]> granicus.if.org Git - imagemagick/blob - PerlMagick/Magick.xs
(no commit message)
[imagemagick] / PerlMagick / Magick.xs
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                         PPPP   EEEEE  RRRR   L                              %
6 %                         P   P  E      R   R  L                              %
7 %                         PPPP   EEE    RRRR   L                              %
8 %                         P      E      R  R   L                              %
9 %                         P      EEEEE  R   R  LLLLL                          %
10 %                                                                             %
11 %                  M   M   AAA    GGGG  IIIII   CCCC  K   K                   %
12 %                  MM MM  A   A  G        I    C      K  K                    %
13 %                  M M M  AAAAA  G GGG    I    C      KKK                     %
14 %                  M   M  A   A  G   G    I    C      K  K                    %
15 %                  M   M  A   A   GGGG  IIIII   CCCC  K   K                   %
16 %                                                                             %
17 %                                                                             %
18 %                Object-oriented Perl interface to ImageMagick                %
19 %                                                                             %
20 %                            Software Design                                  %
21 %                              Kyle Shorter                                   %
22 %                              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     CompareImages = 1
3069     compare      = 2
3070     compareimage = 3
3071   PPCODE:
3072   {
3073     AV
3074       *av;
3075
3076     char
3077       *attribute;
3078
3079     double
3080       distortion;
3081
3082     ExceptionInfo
3083       *exception;
3084
3085     HV
3086       *hv;
3087
3088     Image
3089       *difference_image,
3090       *image,
3091       *reconstruct_image;
3092
3093     MetricType
3094       metric;
3095
3096     register ssize_t
3097       i;
3098
3099     ssize_t
3100       option;
3101
3102     struct PackageInfo
3103       *info;
3104
3105     SV
3106       *av_reference,
3107       *perl_exception,
3108       *reference,
3109       *rv,
3110       *sv;
3111
3112     PERL_UNUSED_VAR(ref);
3113     PERL_UNUSED_VAR(ix);
3114     exception=AcquireExceptionInfo();
3115     perl_exception=newSVpv("",0);
3116     sv=NULL;
3117     av=NULL;
3118     attribute=NULL;
3119     if (sv_isobject(ST(0)) == 0)
3120       {
3121         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3122           PackageName);
3123         goto PerlException;
3124       }
3125     reference=SvRV(ST(0));
3126     hv=SvSTASH(reference);
3127     av=newAV();
3128     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3129     SvREFCNT_dec(av);
3130     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3131     if (image == (Image *) NULL)
3132       {
3133         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3134           PackageName);
3135         goto PerlException;
3136       }
3137     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3138     /*
3139       Get attribute.
3140     */
3141     reconstruct_image=image;
3142     metric=RootMeanSquaredErrorMetric;
3143     for (i=2; i < items; i+=2)
3144     {
3145       attribute=(char *) SvPV(ST(i-1),na);
3146       switch (*attribute)
3147       {
3148         case 'C':
3149         case 'c':
3150         {
3151           if (LocaleCompare(attribute,"channel") == 0)
3152             {
3153               ssize_t
3154                 option;
3155
3156               option=ParseChannelOption(SvPV(ST(i),na));
3157               if (option < 0)
3158                 {
3159                   ThrowPerlException(exception,OptionError,
3160                     "UnrecognizedType",SvPV(ST(i),na));
3161                   return;
3162                 }
3163               SetPixelComponentMap(image,(ChannelType) option);
3164               break;
3165             }
3166           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3167             attribute);
3168           break;
3169         }
3170         case 'F':
3171         case 'f':
3172         {
3173           if (LocaleCompare(attribute,"fuzz") == 0)
3174             {
3175               image->fuzz=SiPrefixToDouble(SvPV(ST(i),na),100.0);
3176               break;
3177             }
3178           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3179             attribute);
3180           break;
3181         }
3182         case 'I':
3183         case 'i':
3184         {
3185           if (LocaleCompare(attribute,"image") == 0)
3186             {
3187               reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3188                 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3189               break;
3190             }
3191           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3192             attribute);
3193           break;
3194         }
3195         case 'M':
3196         case 'm':
3197         {
3198           if (LocaleCompare(attribute,"metric") == 0)
3199             {
3200               option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3201                 SvPV(ST(i),na));
3202               if (option < 0)
3203                 {
3204                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3205                     SvPV(ST(i),na));
3206                   break;
3207                 }
3208               metric=(MetricType) option;
3209               break;
3210             }
3211           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3212             attribute);
3213           break;
3214         }
3215         default:
3216         {
3217           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3218             attribute);
3219           break;
3220         }
3221       }
3222     }
3223     difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3224       exception);
3225     if (difference_image != (Image *) NULL)
3226       {
3227         difference_image->error.mean_error_per_pixel=distortion;
3228         AddImageToRegistry(sv,difference_image);
3229         rv=newRV(sv);
3230         av_push(av,sv_bless(rv,hv));
3231         SvREFCNT_dec(sv);
3232       }
3233     exception=DestroyExceptionInfo(exception);
3234     ST(0)=av_reference;
3235     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3236     XSRETURN(1);
3237
3238   PerlException:
3239     InheritPerlException(exception,perl_exception);
3240     exception=DestroyExceptionInfo(exception);
3241     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3242     SvPOK_on(perl_exception);
3243     ST(0)=sv_2mortal(perl_exception);
3244     XSRETURN(1);
3245   }
3246 \f
3247 #
3248 ###############################################################################
3249 #                                                                             #
3250 #                                                                             #
3251 #                                                                             #
3252 #   C o m p a r e L a y e r s                                                 #
3253 #                                                                             #
3254 #                                                                             #
3255 #                                                                             #
3256 ###############################################################################
3257 #
3258 #
3259 void
3260 CompareLayers(ref)
3261   Image::Magick ref=NO_INIT
3262   ALIAS:
3263     CompareImagesLayers   = 1
3264     comparelayers        = 2
3265     compareimagelayers   = 3
3266   PPCODE:
3267   {
3268     AV
3269       *av;
3270
3271     char
3272       *attribute;
3273
3274     ExceptionInfo
3275       *exception;
3276
3277     HV
3278       *hv;
3279
3280     Image
3281       *image;
3282
3283     ImageLayerMethod
3284       method;
3285
3286     register ssize_t
3287       i;
3288
3289     ssize_t
3290       option;
3291
3292     struct PackageInfo
3293       *info;
3294
3295     SV
3296       *av_reference,
3297       *perl_exception,
3298       *reference,
3299       *rv,
3300       *sv;
3301
3302     PERL_UNUSED_VAR(ref);
3303     PERL_UNUSED_VAR(ix);
3304     exception=AcquireExceptionInfo();
3305     perl_exception=newSVpv("",0);
3306     sv=NULL;
3307     if (sv_isobject(ST(0)) == 0)
3308       {
3309         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3310           PackageName);
3311         goto PerlException;
3312       }
3313     reference=SvRV(ST(0));
3314     hv=SvSTASH(reference);
3315     av=newAV();
3316     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3317     SvREFCNT_dec(av);
3318     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3319     if (image == (Image *) NULL)
3320       {
3321         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3322           PackageName);
3323         goto PerlException;
3324       }
3325     method=CompareAnyLayer;
3326     for (i=2; i < items; i+=2)
3327     {
3328       attribute=(char *) SvPV(ST(i-1),na);
3329       switch (*attribute)
3330       {
3331         case 'M':
3332         case 'm':
3333         {
3334           if (LocaleCompare(attribute,"method") == 0)
3335             {
3336               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3337                 SvPV(ST(i),na));
3338               if (option < 0)
3339                 {
3340                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3341                     SvPV(ST(i),na));
3342                   break;
3343                 }
3344                method=(ImageLayerMethod) option;
3345               break;
3346             }
3347           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3348             attribute);
3349           break;
3350         }
3351         default:
3352         {
3353           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3354             attribute);
3355           break;
3356         }
3357       }
3358     }
3359     image=CompareImagesLayers(image,method,exception);
3360     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3361       goto PerlException;
3362     for ( ; image; image=image->next)
3363     {
3364       AddImageToRegistry(sv,image);
3365       rv=newRV(sv);
3366       av_push(av,sv_bless(rv,hv));
3367       SvREFCNT_dec(sv);
3368     }
3369     exception=DestroyExceptionInfo(exception);
3370     ST(0)=av_reference;
3371     SvREFCNT_dec(perl_exception);
3372     XSRETURN(1);
3373
3374   PerlException:
3375     InheritPerlException(exception,perl_exception);
3376     exception=DestroyExceptionInfo(exception);
3377     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3378     SvPOK_on(perl_exception);
3379     ST(0)=sv_2mortal(perl_exception);
3380     XSRETURN(1);
3381   }
3382 \f
3383 #
3384 ###############################################################################
3385 #                                                                             #
3386 #                                                                             #
3387 #                                                                             #
3388 #   D e s t r o y                                                             #
3389 #                                                                             #
3390 #                                                                             #
3391 #                                                                             #
3392 ###############################################################################
3393 #
3394 #
3395 void
3396 DESTROY(ref)
3397   Image::Magick ref=NO_INIT
3398   PPCODE:
3399   {
3400     SV
3401       *reference;
3402
3403     PERL_UNUSED_VAR(ref);
3404     if (sv_isobject(ST(0)) == 0)
3405       croak("ReferenceIsNotMyType");
3406     reference=SvRV(ST(0));
3407     switch (SvTYPE(reference))
3408     {
3409       case SVt_PVAV:
3410       {
3411         char
3412           message[MaxTextExtent];
3413
3414         const SV
3415           *key;
3416
3417         HV
3418           *hv;
3419
3420         GV
3421           **gvp;
3422
3423         struct PackageInfo
3424           *info;
3425
3426         SV
3427           *sv;
3428
3429         /*
3430           Array (AV *) reference
3431         */
3432         (void) FormatLocaleString(message,MaxTextExtent,"package%s%p",
3433           XS_VERSION,reference);
3434         hv=gv_stashpv(PackageName, FALSE);
3435         if (!hv)
3436           break;
3437         gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3438         if (!gvp)
3439           break;
3440         sv=GvSV(*gvp);
3441         if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3442           {
3443             info=(struct PackageInfo *) SvIV(sv);
3444             DestroyPackageInfo(info);
3445           }
3446         key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3447         (void) key;
3448         break;
3449       }
3450       case SVt_PVMG:
3451       {
3452         Image
3453           *image;
3454
3455         /*
3456           Blessed scalar = (Image *) SvIV(reference)
3457         */
3458         image=(Image *) SvIV(reference);
3459         if (image != (Image *) NULL)
3460           DeleteImageFromRegistry(reference,image);
3461         break;
3462       }
3463       default:
3464         break;
3465     }
3466   }
3467 \f
3468 #
3469 ###############################################################################
3470 #                                                                             #
3471 #                                                                             #
3472 #                                                                             #
3473 #   D i s p l a y                                                             #
3474 #                                                                             #
3475 #                                                                             #
3476 #                                                                             #
3477 ###############################################################################
3478 #
3479 #
3480 void
3481 Display(ref,...)
3482   Image::Magick ref=NO_INIT
3483   ALIAS:
3484     DisplayImage  = 1
3485     display       = 2
3486     displayimage  = 3
3487   PPCODE:
3488   {
3489     ExceptionInfo
3490       *exception;
3491
3492     Image
3493       *image;
3494
3495     register ssize_t
3496       i;
3497
3498     struct PackageInfo
3499       *info,
3500       *package_info;
3501
3502     SV
3503       *perl_exception,
3504       *reference;
3505
3506     PERL_UNUSED_VAR(ref);
3507     PERL_UNUSED_VAR(ix);
3508     exception=AcquireExceptionInfo();
3509     perl_exception=newSVpv("",0);
3510     package_info=(struct PackageInfo *) NULL;
3511     if (sv_isobject(ST(0)) == 0)
3512       {
3513         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3514           PackageName);
3515         goto PerlException;
3516       }
3517     reference=SvRV(ST(0));
3518     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3519     if (image == (Image *) NULL)
3520       {
3521         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3522           PackageName);
3523         goto PerlException;
3524       }
3525     package_info=ClonePackageInfo(info,exception);
3526     if (items == 2)
3527       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3528     else
3529       if (items > 2)
3530         for (i=2; i < items; i+=2)
3531           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3532             exception);
3533     (void) DisplayImages(package_info->image_info,image);
3534     (void) CatchImageException(image);
3535     InheritException(exception,&image->exception);
3536
3537   PerlException:
3538     if (package_info != (struct PackageInfo *) NULL)
3539       DestroyPackageInfo(package_info);
3540     InheritPerlException(exception,perl_exception);
3541     exception=DestroyExceptionInfo(exception);
3542     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3543     SvPOK_on(perl_exception);
3544     ST(0)=sv_2mortal(perl_exception);
3545     XSRETURN(1);
3546   }
3547 \f
3548 #
3549 ###############################################################################
3550 #                                                                             #
3551 #                                                                             #
3552 #                                                                             #
3553 #   E v a l u a t e I m a g e s                                               #
3554 #                                                                             #
3555 #                                                                             #
3556 #                                                                             #
3557 ###############################################################################
3558 #
3559 #
3560 void
3561 EvaluateImages(ref)
3562   Image::Magick ref=NO_INIT
3563   ALIAS:
3564     EvaluateImages   = 1
3565     evaluateimages   = 2
3566   PPCODE:
3567   {
3568     AV
3569       *av;
3570
3571     char
3572       *attribute,
3573       *p;
3574
3575     ExceptionInfo
3576       *exception;
3577
3578     HV
3579       *hv;
3580
3581     Image
3582       *image;
3583
3584     MagickEvaluateOperator
3585       op;
3586
3587     register ssize_t
3588       i;
3589
3590     struct PackageInfo
3591       *info;
3592
3593     SV
3594       *perl_exception,
3595       *reference,
3596       *rv,
3597       *sv;
3598
3599     PERL_UNUSED_VAR(ref);
3600     PERL_UNUSED_VAR(ix);
3601     exception=AcquireExceptionInfo();
3602     perl_exception=newSVpv("",0);
3603     sv=NULL;
3604     if (sv_isobject(ST(0)) == 0)
3605       {
3606         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3607           PackageName);
3608         goto PerlException;
3609       }
3610     reference=SvRV(ST(0));
3611     hv=SvSTASH(reference);
3612     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3613     if (image == (Image *) NULL)
3614       {
3615         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3616           PackageName);
3617         goto PerlException;
3618       }
3619     op=MeanEvaluateOperator;
3620     if (items == 2)
3621       {
3622         ssize_t
3623           in;
3624
3625         in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
3626           SvPV(ST(1),na));
3627         if (in < 0)
3628           {
3629             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3630               SvPV(ST(1),na));
3631             return;
3632           }
3633         op=(MagickEvaluateOperator) in;
3634       }
3635     else
3636       for (i=2; i < items; i+=2)
3637       {
3638         attribute=(char *) SvPV(ST(i-1),na);
3639         switch (*attribute)
3640         {
3641           case 'O':
3642           case 'o':
3643           {
3644             if (LocaleCompare(attribute,"operator") == 0)
3645               {
3646                 ssize_t
3647                   in;
3648
3649                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3650                   MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
3651                 if (in < 0)
3652                   {
3653                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3654                       SvPV(ST(i),na));
3655                     return;
3656                   }
3657                 op=(MagickEvaluateOperator) in;
3658                 break;
3659               }
3660             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3661               attribute);
3662             break;
3663           }
3664           default:
3665           {
3666             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3667               attribute);
3668             break;
3669           }
3670         }
3671       }
3672     image=EvaluateImages(image,op,exception);
3673     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3674       goto PerlException;
3675     /*
3676       Create blessed Perl array for the returned image.
3677     */
3678     av=newAV();
3679     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3680     SvREFCNT_dec(av);
3681     AddImageToRegistry(sv,image);
3682     rv=newRV(sv);
3683     av_push(av,sv_bless(rv,hv));
3684     SvREFCNT_dec(sv);
3685     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3686     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
3687       "evaluate-%.*s",(int) (MaxTextExtent-9),
3688       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3689     (void) CopyMagickString(image->filename,info->image_info->filename,
3690       MaxTextExtent);
3691     SetImageInfo(info->image_info,0,exception);
3692     exception=DestroyExceptionInfo(exception);
3693     SvREFCNT_dec(perl_exception);
3694     XSRETURN(1);
3695
3696   PerlException:
3697     InheritPerlException(exception,perl_exception);
3698     exception=DestroyExceptionInfo(exception);
3699     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3700     SvPOK_on(perl_exception);
3701     ST(0)=sv_2mortal(perl_exception);
3702     XSRETURN(1);
3703   }
3704 \f
3705 #
3706 ###############################################################################
3707 #                                                                             #
3708 #                                                                             #
3709 #                                                                             #
3710 #   F e a t u r e s                                                           #
3711 #                                                                             #
3712 #                                                                             #
3713 #                                                                             #
3714 ###############################################################################
3715 #
3716 #
3717 void
3718 Features(ref,...)
3719   Image::Magick ref=NO_INIT
3720   ALIAS:
3721     FeaturesImage = 1
3722     features      = 2
3723     featuresimage = 3
3724   PPCODE:
3725   {
3726 #define ChannelFeatures(channel,direction) \
3727 { \
3728   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3729     channel_features[channel].angular_second_moment[direction]); \
3730   PUSHs(sv_2mortal(newSVpv(message,0))); \
3731   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3732     channel_features[channel].contrast[direction]); \
3733   PUSHs(sv_2mortal(newSVpv(message,0))); \
3734   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3735     channel_features[channel].contrast[direction]); \
3736   PUSHs(sv_2mortal(newSVpv(message,0))); \
3737   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3738     channel_features[channel].variance_sum_of_squares[direction]); \
3739   PUSHs(sv_2mortal(newSVpv(message,0))); \
3740   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3741     channel_features[channel].inverse_difference_moment[direction]); \
3742   PUSHs(sv_2mortal(newSVpv(message,0))); \
3743   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3744     channel_features[channel].sum_average[direction]); \
3745   PUSHs(sv_2mortal(newSVpv(message,0))); \
3746   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3747     channel_features[channel].sum_variance[direction]); \
3748   PUSHs(sv_2mortal(newSVpv(message,0))); \
3749   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3750     channel_features[channel].sum_entropy[direction]); \
3751   PUSHs(sv_2mortal(newSVpv(message,0))); \
3752   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3753     channel_features[channel].entropy[direction]); \
3754   PUSHs(sv_2mortal(newSVpv(message,0))); \
3755   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3756     channel_features[channel].difference_variance[direction]); \
3757   PUSHs(sv_2mortal(newSVpv(message,0))); \
3758   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3759     channel_features[channel].difference_entropy[direction]); \
3760   PUSHs(sv_2mortal(newSVpv(message,0))); \
3761   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3762     channel_features[channel].measure_of_correlation_1[direction]); \
3763   PUSHs(sv_2mortal(newSVpv(message,0))); \
3764   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3765     channel_features[channel].measure_of_correlation_2[direction]); \
3766   PUSHs(sv_2mortal(newSVpv(message,0))); \
3767   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3768     channel_features[channel].maximum_correlation_coefficient[direction]); \
3769   PUSHs(sv_2mortal(newSVpv(message,0))); \
3770 }
3771
3772     AV
3773       *av;
3774
3775     char
3776       *attribute,
3777       message[MaxTextExtent];
3778
3779     ChannelFeatures
3780       *channel_features;
3781
3782     double
3783       distance;
3784
3785     ExceptionInfo
3786       *exception;
3787
3788     Image
3789       *image;
3790
3791     register ssize_t
3792       i;
3793
3794     ssize_t
3795       count;
3796
3797     struct PackageInfo
3798       *info;
3799
3800     SV
3801       *perl_exception,
3802       *reference;
3803
3804     PERL_UNUSED_VAR(ref);
3805     PERL_UNUSED_VAR(ix);
3806     exception=AcquireExceptionInfo();
3807     perl_exception=newSVpv("",0);
3808     av=NULL;
3809     if (sv_isobject(ST(0)) == 0)
3810       {
3811         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3812           PackageName);
3813         goto PerlException;
3814       }
3815     reference=SvRV(ST(0));
3816     av=newAV();
3817     SvREFCNT_dec(av);
3818     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3819     if (image == (Image *) NULL)
3820       {
3821         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3822           PackageName);
3823         goto PerlException;
3824       }
3825     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3826     distance=1;
3827     for (i=2; i < items; i+=2)
3828     {
3829       attribute=(char *) SvPV(ST(i-1),na);
3830       switch (*attribute)
3831       {
3832         case 'D':
3833         case 'd':
3834         {
3835           if (LocaleCompare(attribute,"distance") == 0)
3836             {
3837               distance=StringToLong((char *) SvPV(ST(1),na));
3838               break;
3839             }
3840           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3841             attribute);
3842           break;
3843         }
3844         default:
3845         {
3846           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3847             attribute);
3848           break;
3849         }
3850       }
3851     }
3852     count=0;
3853     for ( ; image; image=image->next)
3854     {
3855       channel_features=GetImageChannelFeatures(image,distance,
3856         &image->exception);
3857       if (channel_features == (ChannelFeatures *) NULL)
3858         continue;
3859       count++;
3860       EXTEND(sp,75*count);
3861       for (i=0; i < 4; i++)
3862       {
3863         ChannelFeatures(RedChannel,i);
3864         ChannelFeatures(GreenChannel,i);
3865         ChannelFeatures(BlueChannel,i);
3866         if (image->colorspace == CMYKColorspace)
3867           ChannelFeatures(BlackChannel,i);
3868         if (image->matte != MagickFalse)
3869           ChannelFeatures(AlphaChannel,i);
3870       }
3871       channel_features=(ChannelFeatures *)
3872         RelinquishMagickMemory(channel_features);
3873     }
3874
3875   PerlException:
3876     InheritPerlException(exception,perl_exception);
3877     exception=DestroyExceptionInfo(exception);
3878     SvREFCNT_dec(perl_exception);
3879   }
3880 \f
3881 #
3882 ###############################################################################
3883 #                                                                             #
3884 #                                                                             #
3885 #                                                                             #
3886 #   F l a t t e n                                                             #
3887 #                                                                             #
3888 #                                                                             #
3889 #                                                                             #
3890 ###############################################################################
3891 #
3892 #
3893 void
3894 Flatten(ref)
3895   Image::Magick ref=NO_INIT
3896   ALIAS:
3897     FlattenImage   = 1
3898     flatten        = 2
3899     flattenimage   = 3
3900   PPCODE:
3901   {
3902     AV
3903       *av;
3904
3905     char
3906       *attribute,
3907       *p;
3908
3909     ExceptionInfo
3910       *exception;
3911
3912     HV
3913       *hv;
3914
3915     Image
3916       *image;
3917
3918     PixelPacket
3919       background_color;
3920
3921     register ssize_t
3922       i;
3923
3924     struct PackageInfo
3925       *info;
3926
3927     SV
3928       *perl_exception,
3929       *reference,
3930       *rv,
3931       *sv;
3932
3933     PERL_UNUSED_VAR(ref);
3934     PERL_UNUSED_VAR(ix);
3935     exception=AcquireExceptionInfo();
3936     perl_exception=newSVpv("",0);
3937     sv=NULL;
3938     if (sv_isobject(ST(0)) == 0)
3939       {
3940         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3941           PackageName);
3942         goto PerlException;
3943       }
3944     reference=SvRV(ST(0));
3945     hv=SvSTASH(reference);
3946     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3947     if (image == (Image *) NULL)
3948       {
3949         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3950           PackageName);
3951         goto PerlException;
3952       }
3953     background_color=image->background_color;
3954     if (items == 2)
3955       (void) QueryColorDatabase((char *) SvPV(ST(1),na),&background_color,
3956         exception);
3957     else
3958       for (i=2; i < items; i+=2)
3959       {
3960         attribute=(char *) SvPV(ST(i-1),na);
3961         switch (*attribute)
3962         {
3963           case 'B':
3964           case 'b':
3965           {
3966             if (LocaleCompare(attribute,"background") == 0)
3967               {
3968                 (void) QueryColorDatabase((char *) SvPV(ST(1),na),
3969                   &background_color,exception);
3970                 break;
3971               }
3972             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3973               attribute);
3974             break;
3975           }
3976           default:
3977           {
3978             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3979               attribute);
3980             break;
3981           }
3982         }
3983       }
3984     image->background_color=background_color;
3985     image=MergeImageLayers(image,FlattenLayer,exception);
3986     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3987       goto PerlException;
3988     /*
3989       Create blessed Perl array for the returned image.
3990     */
3991     av=newAV();
3992     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3993     SvREFCNT_dec(av);
3994     AddImageToRegistry(sv,image);
3995     rv=newRV(sv);
3996     av_push(av,sv_bless(rv,hv));
3997     SvREFCNT_dec(sv);
3998     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3999     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
4000       "flatten-%.*s",(int) (MaxTextExtent-9),
4001       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4002     (void) CopyMagickString(image->filename,info->image_info->filename,
4003       MaxTextExtent);
4004     SetImageInfo(info->image_info,0,exception);
4005     exception=DestroyExceptionInfo(exception);
4006     SvREFCNT_dec(perl_exception);
4007     XSRETURN(1);
4008
4009   PerlException:
4010     InheritPerlException(exception,perl_exception);
4011     exception=DestroyExceptionInfo(exception);
4012     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4013     SvPOK_on(perl_exception);  /* return messages in string context */
4014     ST(0)=sv_2mortal(perl_exception);
4015     XSRETURN(1);
4016   }
4017 \f
4018 #
4019 ###############################################################################
4020 #                                                                             #
4021 #                                                                             #
4022 #                                                                             #
4023 #   F x                                                                       #
4024 #                                                                             #
4025 #                                                                             #
4026 #                                                                             #
4027 ###############################################################################
4028 #
4029 #
4030 void
4031 Fx(ref,...)
4032   Image::Magick ref=NO_INIT
4033   ALIAS:
4034     FxImage  = 1
4035     fx       = 2
4036     fximage  = 3
4037   PPCODE:
4038   {
4039     AV
4040       *av;
4041
4042     char
4043       *attribute,
4044       expression[MaxTextExtent];
4045
4046     ChannelType
4047       channel;
4048
4049     ExceptionInfo
4050       *exception;
4051
4052     HV
4053       *hv;
4054
4055     Image
4056       *image;
4057
4058     register ssize_t
4059       i;
4060
4061     struct PackageInfo
4062       *info;
4063
4064     SV
4065       *av_reference,
4066       *perl_exception,
4067       *reference,
4068       *rv,
4069       *sv;
4070
4071     PERL_UNUSED_VAR(ref);
4072     PERL_UNUSED_VAR(ix);
4073     exception=AcquireExceptionInfo();
4074     perl_exception=newSVpv("",0);
4075     sv=NULL;
4076     attribute=NULL;
4077     av=NULL;
4078     if (sv_isobject(ST(0)) == 0)
4079       {
4080         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4081           PackageName);
4082         goto PerlException;
4083       }
4084     reference=SvRV(ST(0));
4085     hv=SvSTASH(reference);
4086     av=newAV();
4087     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4088     SvREFCNT_dec(av);
4089     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4090     if (image == (Image *) NULL)
4091       {
4092         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4093           PackageName);
4094         goto PerlException;
4095       }
4096     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4097     /*
4098       Get options.
4099     */
4100     channel=DefaultChannels;
4101     (void) CopyMagickString(expression,"u",MaxTextExtent);
4102     if (items == 2)
4103       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MaxTextExtent);
4104     else
4105       for (i=2; i < items; i+=2)
4106       {
4107         attribute=(char *) SvPV(ST(i-1),na);
4108         switch (*attribute)
4109         {
4110           case 'C':
4111           case 'c':
4112           {
4113             if (LocaleCompare(attribute,"channel") == 0)
4114               {
4115                 ssize_t
4116                   option;
4117
4118                 option=ParseChannelOption(SvPV(ST(i),na));
4119                 if (option < 0)
4120                   {
4121                     ThrowPerlException(exception,OptionError,
4122                       "UnrecognizedType",SvPV(ST(i),na));
4123                     return;
4124                   }
4125                 channel=(ChannelType) option;
4126                 break;
4127               }
4128             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4129               attribute);
4130             break;
4131           }
4132           case 'E':
4133           case 'e':
4134           {
4135             if (LocaleCompare(attribute,"expression") == 0)
4136               {
4137                 (void) CopyMagickString(expression,SvPV(ST(i),na),
4138                   MaxTextExtent);
4139                 break;
4140               }
4141             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4142               attribute);
4143             break;
4144           }
4145           default:
4146           {
4147             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4148               attribute);
4149             break;
4150           }
4151         }
4152       }
4153     image=FxImageChannel(image,channel,expression,exception);
4154     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
4155       goto PerlException;
4156     for ( ; image; image=image->next)
4157     {
4158       AddImageToRegistry(sv,image);
4159       rv=newRV(sv);
4160       av_push(av,sv_bless(rv,hv));
4161       SvREFCNT_dec(sv);
4162     }
4163     exception=DestroyExceptionInfo(exception);
4164     ST(0)=av_reference;
4165     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4166     XSRETURN(1);
4167
4168   PerlException:
4169     InheritPerlException(exception,perl_exception);
4170     exception=DestroyExceptionInfo(exception);
4171     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4172     SvPOK_on(perl_exception);
4173     ST(0)=sv_2mortal(perl_exception);
4174     XSRETURN(1);
4175   }
4176 \f
4177 #
4178 ###############################################################################
4179 #                                                                             #
4180 #                                                                             #
4181 #                                                                             #
4182 #   G e t                                                                     #
4183 #                                                                             #
4184 #                                                                             #
4185 #                                                                             #
4186 ###############################################################################
4187 #
4188 #
4189 void
4190 Get(ref,...)
4191   Image::Magick ref=NO_INIT
4192   ALIAS:
4193     GetAttributes = 1
4194     GetAttribute  = 2
4195     get           = 3
4196     getattributes = 4
4197     getattribute  = 5
4198   PPCODE:
4199   {
4200     char
4201       *attribute,
4202       color[MaxTextExtent];
4203
4204     const char
4205       *value;
4206
4207     ExceptionInfo
4208       *exception;
4209
4210     Image
4211       *image;
4212
4213     long
4214       j;
4215
4216     register ssize_t
4217       i;
4218
4219     struct PackageInfo
4220       *info;
4221
4222     SV
4223       *perl_exception,
4224       *reference,
4225       *s;
4226
4227     PERL_UNUSED_VAR(ref);
4228     PERL_UNUSED_VAR(ix);
4229     exception=AcquireExceptionInfo();
4230     perl_exception=newSVpv("",0);
4231     if (sv_isobject(ST(0)) == 0)
4232       {
4233         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4234           PackageName);
4235         XSRETURN_EMPTY;
4236       }
4237     reference=SvRV(ST(0));
4238     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4239     if (image == (Image *) NULL && !info)
4240       XSRETURN_EMPTY;
4241     EXTEND(sp,items);
4242     for (i=1; i < items; i++)
4243     {
4244       attribute=(char *) SvPV(ST(i),na);
4245       s=NULL;
4246       switch (*attribute)
4247       {
4248         case 'A':
4249         case 'a':
4250         {
4251           if (LocaleCompare(attribute,"adjoin") == 0)
4252             {
4253               if (info)
4254                 s=newSViv((ssize_t) info->image_info->adjoin);
4255               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4256               continue;
4257             }
4258           if (LocaleCompare(attribute,"antialias") == 0)
4259             {
4260               if (info)
4261                 s=newSViv((ssize_t) info->image_info->antialias);
4262               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4263               continue;
4264             }
4265           if (LocaleCompare(attribute,"area") == 0)
4266             {
4267               s=newSViv(GetMagickResource(AreaResource));
4268               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4269               continue;
4270             }
4271           if (LocaleCompare(attribute,"attenuate") == 0)
4272             {
4273               const char
4274                 *value;
4275
4276               value=GetImageProperty(image,attribute);
4277               if (value != (const char *) NULL)
4278                 s=newSVpv(value,0);
4279               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4280               continue;
4281             }
4282           if (LocaleCompare(attribute,"authenticate") == 0)
4283             {
4284               if (info)
4285                 s=newSVpv(info->image_info->authenticate,0);
4286               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4287               continue;
4288             }
4289           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4290             attribute);
4291           break;
4292         }
4293         case 'B':
4294         case 'b':
4295         {
4296           if (LocaleCompare(attribute,"background") == 0)
4297             {
4298               if (image == (Image *) NULL)
4299                 break;
4300               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4301                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4302                 image->background_color.red,image->background_color.green,
4303                 image->background_color.blue,image->background_color.alpha);
4304               s=newSVpv(color,0);
4305               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4306               continue;
4307             }
4308           if (LocaleCompare(attribute,"base-columns") == 0)
4309             {
4310               if (image != (Image *) NULL)
4311                 s=newSViv((ssize_t) image->magick_columns);
4312               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4313               continue;
4314             }
4315           if (LocaleCompare(attribute,"base-filename") == 0)
4316             {
4317               if (image != (Image *) NULL)
4318                 s=newSVpv(image->magick_filename,0);
4319               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4320               continue;
4321             }
4322           if (LocaleCompare(attribute,"base-height") == 0)
4323             {
4324               if (image != (Image *) NULL)
4325                 s=newSViv((ssize_t) image->magick_rows);
4326               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4327               continue;
4328             }
4329           if (LocaleCompare(attribute,"base-rows") == 0)
4330             {
4331               if (image != (Image *) NULL)
4332                 s=newSViv((ssize_t) image->magick_rows);
4333               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4334               continue;
4335             }
4336           if (LocaleCompare(attribute,"base-width") == 0)
4337             {
4338               if (image != (Image *) NULL)
4339                 s=newSViv((ssize_t) image->magick_columns);
4340               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4341               continue;
4342             }
4343           if (LocaleCompare(attribute,"bias") == 0)
4344             {
4345               if (image != (Image *) NULL)
4346                 s=newSVnv(image->bias);
4347               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4348               continue;
4349             }
4350           if (LocaleCompare(attribute,"blue-primary") == 0)
4351             {
4352               if (image == (Image *) NULL)
4353                 break;
4354               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4355                 image->chromaticity.blue_primary.x,
4356                 image->chromaticity.blue_primary.y);
4357               s=newSVpv(color,0);
4358               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4359               continue;
4360             }
4361           if (LocaleCompare(attribute,"bordercolor") == 0)
4362             {
4363               if (image == (Image *) NULL)
4364                 break;
4365               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4366                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4367                 image->border_color.red,image->border_color.green,
4368                 image->border_color.blue,image->border_color.alpha);
4369               s=newSVpv(color,0);
4370               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4371               continue;
4372             }
4373           if (LocaleCompare(attribute,"bounding-box") == 0)
4374             {
4375               char
4376                 geometry[MaxTextExtent];
4377
4378               RectangleInfo
4379                 page;
4380
4381               if (image == (Image *) NULL)
4382                 break;
4383               page=GetImageBoundingBox(image,&image->exception);
4384               (void) FormatLocaleString(geometry,MaxTextExtent,
4385                 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4386                 page.height,(double) page.x,(double) page.y);
4387               s=newSVpv(geometry,0);
4388               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4389               continue;
4390             }
4391           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4392             attribute);
4393           break;
4394         }
4395         case 'C':
4396         case 'c':
4397         {
4398           if (LocaleCompare(attribute,"class") == 0)
4399             {
4400               if (image == (Image *) NULL)
4401                 break;
4402               s=newSViv(image->storage_class);
4403               (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4404                 image->storage_class));
4405               SvIOK_on(s);
4406               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4407               continue;
4408             }
4409           if (LocaleCompare(attribute,"clip-mask") == 0)
4410             {
4411               if (image != (Image *) NULL)
4412                 {
4413                   SV
4414                     *sv;
4415
4416                   sv=NULL;
4417                   if (image->mask == (Image *) NULL)
4418                     ClipImage(image);
4419                   if (image->mask != (Image *) NULL)
4420                     {
4421                       AddImageToRegistry(sv,image->mask);
4422                       s=sv_bless(newRV(sv),SvSTASH(reference));
4423                     }
4424                 }
4425               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4426               continue;
4427             }
4428           if (LocaleCompare(attribute,"clip-path") == 0)
4429             {
4430               if (image != (Image *) NULL)
4431                 {
4432                   SV
4433                     *sv;
4434
4435                   sv=NULL;
4436                   if (image->clip_mask == (Image *) NULL)
4437                     ClipImage(image);
4438                   if (image->clip_mask != (Image *) NULL)
4439                     {
4440                       AddImageToRegistry(sv,image->clip_mask);
4441                       s=sv_bless(newRV(sv),SvSTASH(reference));
4442                     }
4443                 }
4444               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4445               continue;
4446             }
4447           if (LocaleCompare(attribute,"compression") == 0)
4448             {
4449               j=info ? info->image_info->compression : image ?
4450                 image->compression : UndefinedCompression;
4451               if (info)
4452                 if (info->image_info->compression == UndefinedCompression)
4453                   j=image->compression;
4454               s=newSViv(j);
4455               (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4456                 j));
4457               SvIOK_on(s);
4458               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4459               continue;
4460             }
4461           if (LocaleCompare(attribute,"colorspace") == 0)
4462             {
4463               j=image ? image->colorspace : RGBColorspace;
4464               s=newSViv(j);
4465               (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4466                 j));
4467               SvIOK_on(s);
4468               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4469               continue;
4470             }
4471           if (LocaleCompare(attribute,"colors") == 0)
4472             {
4473               if (image != (Image *) NULL)
4474                 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4475                   &image->exception));
4476               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4477               continue;
4478             }
4479           if (LocaleNCompare(attribute,"colormap",8) == 0)
4480             {
4481               int
4482                 items;
4483
4484               if (image == (Image *) NULL || !image->colormap)
4485                 break;
4486               j=0;
4487               items=sscanf(attribute,"%*[^[][%ld",&j);
4488               (void) items;
4489               if (j > (ssize_t) image->colors)
4490                 j%=image->colors;
4491               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4492                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4493                 image->colormap[j].red,image->colormap[j].green,
4494                 image->colormap[j].blue,image->colormap[j].alpha);
4495               s=newSVpv(color,0);
4496               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4497               continue;
4498             }
4499           if (LocaleCompare(attribute,"columns") == 0)
4500             {
4501               if (image != (Image *) NULL)
4502                 s=newSViv((ssize_t) image->columns);
4503               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4504               continue;
4505             }
4506           if (LocaleCompare(attribute,"comment") == 0)
4507             {
4508               const char
4509                 *value;
4510
4511               value=GetImageProperty(image,attribute);
4512               if (value != (const char *) NULL)
4513                 s=newSVpv(value,0);
4514               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4515               continue;
4516             }
4517           if (LocaleCompare(attribute,"copyright") == 0)
4518             {
4519               s=newSVpv(GetMagickCopyright(),0);
4520               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4521               continue;
4522             }
4523           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4524             attribute);
4525           break;
4526         }
4527         case 'D':
4528         case 'd':
4529         {
4530           if (LocaleCompare(attribute,"density") == 0)
4531             {
4532               char
4533                 geometry[MaxTextExtent];
4534
4535               if (image == (Image *) NULL)
4536                 break;
4537               (void) FormatLocaleString(geometry,MaxTextExtent,"%.15gx%.15g",
4538                 image->x_resolution,image->y_resolution);
4539               s=newSVpv(geometry,0);
4540               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4541               continue;
4542             }
4543           if (LocaleCompare(attribute,"delay") == 0)
4544             {
4545               if (image != (Image *) NULL)
4546                 s=newSViv((ssize_t) image->delay);
4547               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4548               continue;
4549             }
4550           if (LocaleCompare(attribute,"depth") == 0)
4551             {
4552               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4553               if (image != (Image *) NULL)
4554                 s=newSViv((ssize_t) GetImageDepth(image,&image->exception));
4555               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4556               continue;
4557             }
4558           if (LocaleCompare(attribute,"directory") == 0)
4559             {
4560               if (image && image->directory)
4561                 s=newSVpv(image->directory,0);
4562               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4563               continue;
4564             }
4565           if (LocaleCompare(attribute,"dispose") == 0)
4566             {
4567               if (image == (Image *) NULL)
4568                 break;
4569
4570               s=newSViv(image->dispose);
4571               (void) sv_setpv(s,
4572                 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
4573               SvIOK_on(s);
4574               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4575               continue;
4576             }
4577           if (LocaleCompare(attribute,"disk") == 0)
4578             {
4579               s=newSViv(GetMagickResource(DiskResource));
4580               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4581               continue;
4582             }
4583           if (LocaleCompare(attribute,"dither") == 0)
4584             {
4585               if (info)
4586                 s=newSViv((ssize_t) info->image_info->dither);
4587               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4588               continue;
4589             }
4590           if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4591             {
4592               if (info && info->image_info->server_name)
4593                 s=newSVpv(info->image_info->server_name,0);
4594               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4595               continue;
4596             }
4597           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4598             attribute);
4599           break;
4600         }
4601         case 'E':
4602         case 'e':
4603         {
4604           if (LocaleCompare(attribute,"elapsed-time") == 0)
4605             {
4606               if (image != (Image *) NULL)
4607                 s=newSVnv(GetElapsedTime(&image->timer));
4608               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4609               continue;
4610             }
4611           if (LocaleCompare(attribute,"endian") == 0)
4612             {
4613               j=info ? info->image_info->endian : image ? image->endian :
4614                 UndefinedEndian;
4615               s=newSViv(j);
4616               (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
4617               SvIOK_on(s);
4618               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4619               continue;
4620             }
4621           if (LocaleCompare(attribute,"error") == 0)
4622             {
4623               if (image != (Image *) NULL)
4624                 s=newSVnv(image->error.mean_error_per_pixel);
4625               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4626               continue;
4627             }
4628           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4629             attribute);
4630           break;
4631         }
4632         case 'F':
4633         case 'f':
4634         {
4635           if (LocaleCompare(attribute,"filesize") == 0)
4636             {
4637               if (image != (Image *) NULL)
4638                 s=newSViv((ssize_t) GetBlobSize(image));
4639               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4640               continue;
4641             }
4642           if (LocaleCompare(attribute,"filename") == 0)
4643             {
4644               if (info && info->image_info->filename &&
4645                   *info->image_info->filename)
4646                 s=newSVpv(info->image_info->filename,0);
4647               if (image != (Image *) NULL)
4648                 s=newSVpv(image->filename,0);
4649               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4650               continue;
4651             }
4652           if (LocaleCompare(attribute,"filter") == 0)
4653             {
4654               s=image ? newSViv(image->filter) : newSViv(0);
4655               (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
4656                 image->filter));
4657               SvIOK_on(s);
4658               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4659               continue;
4660             }
4661           if (LocaleCompare(attribute,"font") == 0)
4662             {
4663               if (info && info->image_info->font)
4664                 s=newSVpv(info->image_info->font,0);
4665               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4666               continue;
4667             }
4668           if (LocaleCompare(attribute,"foreground") == 0)
4669             continue;
4670           if (LocaleCompare(attribute,"format") == 0)
4671             {
4672               const MagickInfo
4673                 *magick_info;
4674
4675               magick_info=(const MagickInfo *) NULL;
4676               if (info && (*info->image_info->magick != '\0'))
4677                 magick_info=GetMagickInfo(info->image_info->magick,exception);
4678               if (image != (Image *) NULL)
4679                 magick_info=GetMagickInfo(image->magick,&image->exception);
4680               if ((magick_info != (const MagickInfo *) NULL) &&
4681                   (*magick_info->description != '\0'))
4682                 s=newSVpv((char *) magick_info->description,0);
4683               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4684               continue;
4685             }
4686           if (LocaleCompare(attribute,"fuzz") == 0)
4687             {
4688               if (info)
4689                 s=newSVnv(info->image_info->fuzz);
4690               if (image != (Image *) NULL)
4691                 s=newSVnv(image->fuzz);
4692               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4693               continue;
4694             }
4695           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4696             attribute);
4697           break;
4698         }
4699         case 'G':
4700         case 'g':
4701         {
4702           if (LocaleCompare(attribute,"gamma") == 0)
4703             {
4704               if (image != (Image *) NULL)
4705                 s=newSVnv(image->gamma);
4706               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4707               continue;
4708             }
4709           if (LocaleCompare(attribute,"geometry") == 0)
4710             {
4711               if (image && image->geometry)
4712                 s=newSVpv(image->geometry,0);
4713               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4714               continue;
4715             }
4716           if (LocaleCompare(attribute,"gravity") == 0)
4717             {
4718               s=image ? newSViv(image->gravity) : newSViv(0);
4719               (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
4720                 image->gravity));
4721               SvIOK_on(s);
4722               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4723               continue;
4724             }
4725           if (LocaleCompare(attribute,"green-primary") == 0)
4726             {
4727               if (image == (Image *) NULL)
4728                 break;
4729               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4730                 image->chromaticity.green_primary.x,
4731                 image->chromaticity.green_primary.y);
4732               s=newSVpv(color,0);
4733               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4734               continue;
4735             }
4736           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4737             attribute);
4738           break;
4739         }
4740         case 'H':
4741         case 'h':
4742         {
4743           if (LocaleCompare(attribute,"height") == 0)
4744             {
4745               if (image != (Image *) NULL)
4746                 s=newSViv((ssize_t) image->rows);
4747               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4748               continue;
4749             }
4750           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4751             attribute);
4752           break;
4753         }
4754         case 'I':
4755         case 'i':
4756         {
4757           if (LocaleCompare(attribute,"icc") == 0)
4758             {
4759               if (image != (Image *) NULL)
4760                 {
4761                   const StringInfo
4762                     *profile;
4763
4764                   profile=GetImageProfile(image,"icc");
4765                   if (profile != (StringInfo *) NULL)
4766                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4767                       GetStringInfoLength(profile));
4768                 }
4769               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4770               continue;
4771             }
4772           if (LocaleCompare(attribute,"icm") == 0)
4773             {
4774               if (image != (Image *) NULL)
4775                 {
4776                   const StringInfo
4777                     *profile;
4778
4779                   profile=GetImageProfile(image,"icm");
4780                   if (profile != (const StringInfo *) NULL)
4781                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4782                       GetStringInfoLength(profile));
4783                 }
4784               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4785               continue;
4786             }
4787           if (LocaleCompare(attribute,"id") == 0)
4788             {
4789               if (image != (Image *) NULL)
4790                 {
4791                   char
4792                     key[MaxTextExtent];
4793
4794                   MagickBooleanType
4795                     status;
4796
4797                   static ssize_t
4798                     id = 0;
4799
4800                   (void) FormatLocaleString(key,MaxTextExtent,"%.20g\n",(double)
4801                     id);
4802                   status=SetImageRegistry(ImageRegistryType,key,image,
4803                     &image->exception);
4804                   (void) status;
4805                   s=newSViv(id++);
4806                 }
4807               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4808               continue;
4809             }
4810           if (LocaleNCompare(attribute,"index",5) == 0)
4811             {
4812               char
4813                 name[MaxTextExtent];
4814
4815               int
4816                 items;
4817
4818               long
4819                 x,
4820                 y;
4821
4822               register const Quantum
4823                 *p;
4824
4825               CacheView
4826                 *image_view;
4827
4828               if (image == (Image *) NULL)
4829                 break;
4830               if (image->storage_class != PseudoClass)
4831                 break;
4832               x=0;
4833               y=0;
4834               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
4835               (void) items;
4836               image_view=AcquireCacheView(image);
4837               p=GetCacheViewVirtualPixels(image_view,x,y,1,1,&image->exception);
4838               if (p != (const Quantum *) NULL)
4839                 {
4840                   (void) FormatLocaleString(name,MaxTextExtent,QuantumFormat,
4841                     GetPixelIndex(image,p));
4842                   s=newSVpv(name,0);
4843                   PUSHs(s ? sv_2mortal(s) : &sv_undef);
4844                 }
4845               image_view=DestroyCacheView(image_view);
4846               continue;
4847             }
4848           if (LocaleCompare(attribute,"iptc") == 0)
4849             {
4850               if (image != (Image *) NULL)
4851                 {
4852                   const StringInfo
4853                     *profile;
4854
4855                   profile=GetImageProfile(image,"iptc");
4856                   if (profile != (const StringInfo *) NULL)
4857                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4858                       GetStringInfoLength(profile));
4859                 }
4860               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4861               continue;
4862             }
4863           if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
4864             {
4865               if (image != (Image *) NULL)
4866                 s=newSViv((ssize_t) image->iterations);
4867               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4868               continue;
4869             }
4870           if (LocaleCompare(attribute,"interlace") == 0)
4871             {
4872               j=info ? info->image_info->interlace : image ? image->interlace :
4873                 UndefinedInterlace;
4874               s=newSViv(j);
4875               (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
4876                 j));
4877               SvIOK_on(s);
4878               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4879               continue;
4880             }
4881           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4882             attribute);
4883           break;
4884         }
4885         case 'L':
4886         case 'l':
4887         {
4888           if (LocaleCompare(attribute,"label") == 0)
4889             {
4890               const char
4891                 *value;
4892
4893               if (image == (Image *) NULL)
4894                 break;
4895               value=GetImageProperty(image,"Label");
4896               if (value != (const char *) NULL)
4897                 s=newSVpv(value,0);
4898               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4899               continue;
4900             }
4901           if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
4902             {
4903               if (image != (Image *) NULL)
4904                 s=newSViv((ssize_t) image->iterations);
4905               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4906               continue;
4907             }
4908           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4909             attribute);
4910           break;
4911         }
4912         case 'M':
4913         case 'm':
4914         {
4915           if (LocaleCompare(attribute,"magick") == 0)
4916             {
4917               if (info && *info->image_info->magick)
4918                 s=newSVpv(info->image_info->magick,0);
4919               if (image != (Image *) NULL)
4920                 s=newSVpv(image->magick,0);
4921               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4922               continue;
4923             }
4924           if (LocaleCompare(attribute,"map") == 0)
4925             {
4926               s=newSViv(GetMagickResource(MapResource));
4927               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4928               continue;
4929             }
4930           if (LocaleCompare(attribute,"maximum-error") == 0)
4931             {
4932               if (image != (Image *) NULL)
4933                 s=newSVnv(image->error.normalized_maximum_error);
4934               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4935               continue;
4936             }
4937           if (LocaleCompare(attribute,"memory") == 0)
4938             {
4939               s=newSViv(GetMagickResource(MemoryResource));
4940               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4941               continue;
4942             }
4943           if (LocaleCompare(attribute,"mean-error") == 0)
4944             {
4945               if (image != (Image *) NULL)
4946                 s=newSVnv(image->error.normalized_mean_error);
4947               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4948               continue;
4949             }
4950           if (LocaleCompare(attribute,"mime") == 0)
4951             {
4952               if (info && *info->image_info->magick)
4953                 s=newSVpv(MagickToMime(info->image_info->magick),0);
4954               if (image != (Image *) NULL)
4955                 s=newSVpv(MagickToMime(image->magick),0);
4956               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4957               continue;
4958             }
4959           if (LocaleCompare(attribute,"mattecolor") == 0)
4960             {
4961               if (image == (Image *) NULL)
4962                 break;
4963               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4964                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4965                 image->matte_color.red,image->matte_color.green,
4966                 image->matte_color.blue,image->matte_color.alpha);
4967               s=newSVpv(color,0);
4968               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4969               continue;
4970             }
4971           if (LocaleCompare(attribute,"matte") == 0)
4972             {
4973               if (image != (Image *) NULL)
4974                 s=newSViv((ssize_t) image->matte);
4975               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4976               continue;
4977             }
4978           if (LocaleCompare(attribute,"mime") == 0)
4979             {
4980               const char
4981                 *magick;
4982
4983               magick=NULL;
4984               if (info && *info->image_info->magick)
4985                 magick=info->image_info->magick;
4986               if (image != (Image *) NULL)
4987                 magick=image->magick;
4988               if (magick)
4989                 {
4990                   char
4991                     *mime;
4992
4993                   mime=MagickToMime(magick);
4994                   s=newSVpv(mime,0);
4995                   mime=(char *) RelinquishMagickMemory(mime);
4996                 }
4997               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4998               continue;
4999             }
5000           if (LocaleCompare(attribute,"monochrome") == 0)
5001             {
5002               if (image == (Image *) NULL)
5003                 continue;
5004               j=info ? info->image_info->monochrome :
5005                 IsImageMonochrome(image,&image->exception);
5006               s=newSViv(j);
5007               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5008               continue;
5009             }
5010           if (LocaleCompare(attribute,"montage") == 0)
5011             {
5012               if (image && image->montage)
5013                 s=newSVpv(image->montage,0);
5014               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5015               continue;
5016             }
5017           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5018             attribute);
5019           break;
5020         }
5021         case 'O':
5022         case 'o':
5023         {
5024           if (LocaleCompare(attribute,"orientation") == 0)
5025             {
5026               j=info ? info->image_info->orientation : image ?
5027                 image->orientation : UndefinedOrientation;
5028               s=newSViv(j);
5029               (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5030                 j));
5031               SvIOK_on(s);
5032               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5033               continue;
5034             }
5035           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5036             attribute);
5037           break;
5038         }
5039         case 'P':
5040         case 'p':
5041         {
5042           if (LocaleCompare(attribute,"page") == 0)
5043             {
5044               if (info && info->image_info->page)
5045                 s=newSVpv(info->image_info->page,0);
5046               if (image != (Image *) NULL)
5047                 {
5048                   char
5049                     geometry[MaxTextExtent];
5050
5051                   (void) FormatLocaleString(geometry,MaxTextExtent,
5052                     "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5053                     (double) image->page.height,(double) image->page.x,(double)
5054                     image->page.y);
5055                   s=newSVpv(geometry,0);
5056                 }
5057               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5058               continue;
5059             }
5060           if (LocaleCompare(attribute,"page.x") == 0)
5061             {
5062               if (image != (Image *) NULL)
5063                 s=newSViv((ssize_t) image->page.x);
5064               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5065               continue;
5066             }
5067           if (LocaleCompare(attribute,"page.y") == 0)
5068             {
5069               if (image != (Image *) NULL)
5070                 s=newSViv((ssize_t) image->page.y);
5071               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5072               continue;
5073             }
5074           if (LocaleNCompare(attribute,"pixel",5) == 0)
5075             {
5076               char
5077                 tuple[MaxTextExtent];
5078
5079               int
5080                 items;
5081
5082               long
5083                 x,
5084                 y;
5085
5086               register const Quantum
5087                 *p;
5088
5089               if (image == (Image *) NULL)
5090                 break;
5091               x=0;
5092               y=0;
5093               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5094               (void) items;
5095               p=GetVirtualPixels(image,x,y,1,1,exception);
5096               if (image->colorspace != CMYKColorspace)
5097                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5098                   QuantumFormat "," QuantumFormat "," QuantumFormat,
5099                   GetPixelRed(image,p),GetPixelGreen(image,p),
5100                   GetPixelBlue(image,p),GetPixelAlpha(image,p));
5101               else
5102                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5103                   QuantumFormat "," QuantumFormat "," QuantumFormat ","
5104                   QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5105                   GetPixelBlue(image,p),GetPixelBlack(image,p),
5106                   GetPixelAlpha(image,p));
5107               s=newSVpv(tuple,0);
5108               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5109               continue;
5110             }
5111           if (LocaleCompare(attribute,"pointsize") == 0)
5112             {
5113               if (info)
5114                 s=newSViv((ssize_t) info->image_info->pointsize);
5115               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5116               continue;
5117             }
5118           if (LocaleCompare(attribute,"preview") == 0)
5119             {
5120               s=newSViv(info->image_info->preview_type);
5121               (void) sv_setpv(s,CommandOptionToMnemonic(MagickPreviewOptions,
5122                 info->image_info->preview_type));
5123               SvIOK_on(s);
5124               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5125               continue;
5126             }
5127           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5128             attribute);
5129           break;
5130         }
5131         case 'Q':
5132         case 'q':
5133         {
5134           if (LocaleCompare(attribute,"quality") == 0)
5135             {
5136               if (info)
5137                 s=newSViv((ssize_t) info->image_info->quality);
5138               if (image != (Image *) NULL)
5139                 s=newSViv((ssize_t) image->quality);
5140               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5141               continue;
5142             }
5143           if (LocaleCompare(attribute,"quantum") == 0)
5144             {
5145               if (info)
5146                 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5147               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5148               continue;
5149             }
5150           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5151             attribute);
5152           break;
5153         }
5154         case 'R':
5155         case 'r':
5156         {
5157           if (LocaleCompare(attribute,"rendering-intent") == 0)
5158             {
5159               s=newSViv(image->rendering_intent);
5160               (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5161                 image->rendering_intent));
5162               SvIOK_on(s);
5163               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5164               continue;
5165             }
5166           if (LocaleCompare(attribute,"red-primary") == 0)
5167             {
5168               if (image == (Image *) NULL)
5169                 break;
5170               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5171                 image->chromaticity.red_primary.x,
5172                 image->chromaticity.red_primary.y);
5173               s=newSVpv(color,0);
5174               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5175               continue;
5176             }
5177           if (LocaleCompare(attribute,"rows") == 0)
5178             {
5179               if (image != (Image *) NULL)
5180                 s=newSViv((ssize_t) image->rows);
5181               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5182               continue;
5183             }
5184           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5185             attribute);
5186           break;
5187         }
5188         case 'S':
5189         case 's':
5190         {
5191           if (LocaleCompare(attribute,"sampling-factor") == 0)
5192             {
5193               if (info && info->image_info->sampling_factor)
5194                 s=newSVpv(info->image_info->sampling_factor,0);
5195               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5196               continue;
5197             }
5198           if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5199             {
5200               if (info && info->image_info->server_name)
5201                 s=newSVpv(info->image_info->server_name,0);
5202               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5203               continue;
5204             }
5205           if (LocaleCompare(attribute,"size") == 0)
5206             {
5207               if (info && info->image_info->size)
5208                 s=newSVpv(info->image_info->size,0);
5209               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5210               continue;
5211             }
5212           if (LocaleCompare(attribute,"scene") == 0)
5213             {
5214               if (image != (Image *) NULL)
5215                 s=newSViv((ssize_t) image->scene);
5216               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5217               continue;
5218             }
5219           if (LocaleCompare(attribute,"scenes") == 0)
5220             {
5221               if (image != (Image *) NULL)
5222                 s=newSViv((ssize_t) info->image_info->number_scenes);
5223               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5224               continue;
5225             }
5226           if (LocaleCompare(attribute,"signature") == 0)
5227             {
5228               const char
5229                 *value;
5230
5231               if (image == (Image *) NULL)
5232                 break;
5233               (void) SignatureImage(image);
5234               value=GetImageProperty(image,"Signature");
5235               if (value != (const char *) NULL)
5236                 s=newSVpv(value,0);
5237               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5238               continue;
5239             }
5240           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5241             attribute);
5242           break;
5243         }
5244         case 'T':
5245         case 't':
5246         {
5247           if (LocaleCompare(attribute,"taint") == 0)
5248             {
5249               if (image != (Image *) NULL)
5250                 s=newSViv((ssize_t) IsTaintImage(image));
5251               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5252               continue;
5253             }
5254           if (LocaleCompare(attribute,"texture") == 0)
5255             {
5256               if (info && info->image_info->texture)
5257                 s=newSVpv(info->image_info->texture,0);
5258               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5259               continue;
5260             }
5261           if (LocaleCompare(attribute,"total-ink-density") == 0)
5262             {
5263               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5264               if (image != (Image *) NULL)
5265                 s=newSVnv(GetImageTotalInkDensity(image));
5266               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5267               continue;
5268             }
5269           if (LocaleCompare(attribute,"transparent-color") == 0)
5270             {
5271               if (image == (Image *) NULL)
5272                 break;
5273               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
5274                 QuantumFormat "," QuantumFormat "," QuantumFormat,
5275                 image->transparent_color.red,image->transparent_color.green,
5276                 image->transparent_color.blue,image->transparent_color.alpha);
5277               s=newSVpv(color,0);
5278               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5279               continue;
5280             }
5281           if (LocaleCompare(attribute,"type") == 0)
5282             {
5283               if (image == (Image *) NULL)
5284                 break;
5285               j=(ssize_t) GetImageType(image,&image->exception);
5286               s=newSViv(j);
5287               (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5288               SvIOK_on(s);
5289               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5290               continue;
5291             }
5292           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5293             attribute);
5294           break;
5295         }
5296         case 'U':
5297         case 'u':
5298         {
5299           if (LocaleCompare(attribute,"units") == 0)
5300             {
5301               j=info ? info->image_info->units : image ? image->units :
5302                 UndefinedResolution;
5303               if (info && (info->image_info->units == UndefinedResolution))
5304                 if (image)
5305                   j=image->units;
5306               if (j == UndefinedResolution)
5307                 s=newSVpv("undefined units",0);
5308               else
5309                 if (j == PixelsPerInchResolution)
5310                   s=newSVpv("pixels / inch",0);
5311                 else
5312                   s=newSVpv("pixels / centimeter",0);
5313               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5314               continue;
5315             }
5316           if (LocaleCompare(attribute,"user-time") == 0)
5317             {
5318               if (image != (Image *) NULL)
5319                 s=newSVnv(GetUserTime(&image->timer));
5320               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5321               continue;
5322             }
5323           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5324             attribute);
5325           break;
5326         }
5327         case 'V':
5328         case 'v':
5329         {
5330           if (LocaleCompare(attribute,"verbose") == 0)
5331             {
5332               if (info)
5333                 s=newSViv((ssize_t) info->image_info->verbose);
5334               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5335               continue;
5336             }
5337           if (LocaleCompare(attribute,"version") == 0)
5338             {
5339               s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5340               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5341               continue;
5342             }
5343           if (LocaleCompare(attribute,"view") == 0)
5344             {
5345               if (info && info->image_info->view)
5346                 s=newSVpv(info->image_info->view,0);
5347               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5348               continue;
5349             }
5350           if (LocaleCompare(attribute,"virtual-pixel") == 0)
5351             {
5352               if (image == (Image *) NULL)
5353                 break;
5354               j=(ssize_t) GetImageVirtualPixelMethod(image);
5355               s=newSViv(j);
5356               (void) sv_setpv(s,CommandOptionToMnemonic(
5357                 MagickVirtualPixelOptions,j));
5358               SvIOK_on(s);
5359               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5360               continue;
5361             }
5362           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5363             attribute);
5364           break;
5365         }
5366         case 'W':
5367         case 'w':
5368         {
5369           if (LocaleCompare(attribute,"white-point") == 0)
5370             {
5371               if (image == (Image *) NULL)
5372                 break;
5373               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5374                 image->chromaticity.white_point.x,
5375                 image->chromaticity.white_point.y);
5376               s=newSVpv(color,0);
5377               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5378               continue;
5379             }
5380           if (LocaleCompare(attribute,"width") == 0)
5381             {
5382               if (image != (Image *) NULL)
5383                 s=newSViv((ssize_t) image->columns);
5384               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5385               continue;
5386             }
5387           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5388              attribute);
5389           break;
5390         }
5391         case 'X':
5392         case 'x':
5393         {
5394           if (LocaleCompare(attribute,"x-resolution") == 0)
5395             {
5396               if (image != (Image *) NULL)
5397                 s=newSVnv(image->x_resolution);
5398               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5399               continue;
5400             }
5401           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5402             attribute);
5403           break;
5404         }
5405         case 'Y':
5406         case 'y':
5407         {
5408           if (LocaleCompare(attribute,"y-resolution") == 0)
5409             {
5410               if (image != (Image *) NULL)
5411                 s=newSVnv(image->y_resolution);
5412               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5413               continue;
5414             }
5415           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5416             attribute);
5417           break;
5418         }
5419         default:
5420           break;
5421       }
5422       if (image == (Image *) NULL)
5423         ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5424           attribute)
5425       else
5426         {
5427           value=GetImageProperty(image,attribute);
5428           if (value != (const char *) NULL)
5429             {
5430               s=newSVpv(value,0);
5431               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5432             }
5433           else
5434             if (*attribute != '%')
5435               ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5436                 attribute)
5437             else
5438               {
5439                  char
5440                    *meta;
5441
5442                  meta=InterpretImageProperties(info ? info->image_info :
5443                    (ImageInfo *) NULL,image,attribute);
5444                  s=newSVpv(meta,0);
5445                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5446                  meta=(char *) RelinquishMagickMemory(meta);
5447               }
5448         }
5449     }
5450     exception=DestroyExceptionInfo(exception);
5451     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5452   }
5453 \f
5454 #
5455 ###############################################################################
5456 #                                                                             #
5457 #                                                                             #
5458 #                                                                             #
5459 #   G e t A u t h e n t i c P i x e l s                                       #
5460 #                                                                             #
5461 #                                                                             #
5462 #                                                                             #
5463 ###############################################################################
5464 #
5465 #
5466 void *
5467 GetAuthenticPixels(ref,...)
5468   Image::Magick ref = NO_INIT
5469   ALIAS:
5470     getauthenticpixels = 1
5471     GetImagePixels = 2
5472     getimagepixels = 3
5473   CODE:
5474   {
5475     char
5476       *attribute;
5477
5478     ExceptionInfo
5479       *exception;
5480
5481     Image
5482       *image;
5483
5484     RectangleInfo
5485       region;
5486
5487     ssize_t
5488       i;
5489
5490     struct PackageInfo
5491       *info;
5492
5493     SV
5494       *perl_exception,
5495       *reference;
5496
5497     void
5498       *blob = NULL;
5499
5500     PERL_UNUSED_VAR(ref);
5501     PERL_UNUSED_VAR(ix);
5502     exception=AcquireExceptionInfo();
5503     perl_exception=newSVpv("",0);
5504     if (sv_isobject(ST(0)) == 0)
5505       {
5506         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5507           PackageName);
5508         goto PerlException;
5509       }
5510     reference=SvRV(ST(0));
5511
5512     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5513     if (image == (Image *) NULL)
5514       {
5515         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5516           PackageName);
5517         goto PerlException;
5518       }
5519
5520     region.x=0;
5521     region.y=0;
5522     region.width=image->columns;
5523     region.height=1;
5524     if (items == 1)
5525       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5526     for (i=2; i < items; i+=2)
5527     {
5528       attribute=(char *) SvPV(ST(i-1),na);
5529       switch (*attribute)
5530       {
5531         case 'g':
5532         case 'G':
5533         {
5534           if (LocaleCompare(attribute,"geometry") == 0)
5535             {
5536               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5537               break;
5538             }
5539           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5540             attribute);
5541           break;
5542         }
5543         case 'H':
5544         case 'h':
5545         {
5546           if (LocaleCompare(attribute,"height") == 0)
5547             {
5548               region.height=SvIV(ST(i));
5549               continue;
5550             }
5551           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5552             attribute);
5553           break;
5554         }
5555         case 'X':
5556         case 'x':
5557         {
5558           if (LocaleCompare(attribute,"x") == 0)
5559             {
5560               region.x=SvIV(ST(i));
5561               continue;
5562             }
5563           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5564             attribute);
5565           break;
5566         }
5567         case 'Y':
5568         case 'y':
5569         {
5570           if (LocaleCompare(attribute,"y") == 0)
5571             {
5572               region.y=SvIV(ST(i));
5573               continue;
5574             }
5575           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5576             attribute);
5577           break;
5578         }
5579         case 'W':
5580         case 'w':
5581         {
5582           if (LocaleCompare(attribute,"width") == 0)
5583             {
5584               region.width=SvIV(ST(i));
5585               continue;
5586             }
5587           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5588             attribute);
5589           break;
5590         }
5591       }
5592     }
5593     blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5594       region.height,exception);
5595     if (blob != (void *) NULL)
5596       goto PerlEnd;
5597
5598   PerlException:
5599     InheritPerlException(exception,perl_exception);
5600     exception=DestroyExceptionInfo(exception);
5601     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5602
5603   PerlEnd:
5604     RETVAL = blob;
5605   }
5606   OUTPUT:
5607     RETVAL
5608 \f
5609 #
5610 ###############################################################################
5611 #                                                                             #
5612 #                                                                             #
5613 #                                                                             #
5614 #   G e t V i r t u a l P i x e l s                                           #
5615 #                                                                             #
5616 #                                                                             #
5617 #                                                                             #
5618 ###############################################################################
5619 #
5620 #
5621 void *
5622 GetVirtualPixels(ref,...)
5623   Image::Magick ref = NO_INIT
5624   ALIAS:
5625     getvirtualpixels = 1
5626     AcquireImagePixels = 2
5627     acquireimagepixels = 3
5628   CODE:
5629   {
5630     char
5631       *attribute;
5632
5633     const void
5634       *blob = NULL;
5635
5636     ExceptionInfo
5637       *exception;
5638
5639     Image
5640       *image;
5641
5642     RectangleInfo
5643       region;
5644
5645     ssize_t
5646       i;
5647
5648     struct PackageInfo
5649       *info;
5650
5651     SV
5652       *perl_exception,
5653       *reference;
5654
5655     PERL_UNUSED_VAR(ref);
5656     PERL_UNUSED_VAR(ix);
5657     exception=AcquireExceptionInfo();
5658     perl_exception=newSVpv("",0);
5659     if (sv_isobject(ST(0)) == 0)
5660       {
5661         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5662           PackageName);
5663         goto PerlException;
5664       }
5665     reference=SvRV(ST(0));
5666
5667     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5668     if (image == (Image *) NULL)
5669       {
5670         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5671           PackageName);
5672         goto PerlException;
5673       }
5674
5675     region.x=0;
5676     region.y=0;
5677     region.width=image->columns;
5678     region.height=1;
5679     if (items == 1)
5680       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5681     for (i=2; i < items; i+=2)
5682     {
5683       attribute=(char *) SvPV(ST(i-1),na);
5684       switch (*attribute)
5685       {
5686         case 'g':
5687         case 'G':
5688         {
5689           if (LocaleCompare(attribute,"geometry") == 0)
5690             {
5691               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5692               break;
5693             }
5694           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5695             attribute);
5696           break;
5697         }
5698         case 'H':
5699         case 'h':
5700         {
5701           if (LocaleCompare(attribute,"height") == 0)
5702             {
5703               region.height=SvIV(ST(i));
5704               continue;
5705             }
5706           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5707             attribute);
5708           break;
5709         }
5710         case 'X':
5711         case 'x':
5712         {
5713           if (LocaleCompare(attribute,"x") == 0)
5714             {
5715               region.x=SvIV(ST(i));
5716               continue;
5717             }
5718           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5719             attribute);
5720           break;
5721         }
5722         case 'Y':
5723         case 'y':
5724         {
5725           if (LocaleCompare(attribute,"y") == 0)
5726             {
5727               region.y=SvIV(ST(i));
5728               continue;
5729             }
5730           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5731             attribute);
5732           break;
5733         }
5734         case 'W':
5735         case 'w':
5736         {
5737           if (LocaleCompare(attribute,"width") == 0)
5738             {
5739               region.width=SvIV(ST(i));
5740               continue;
5741             }
5742           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5743             attribute);
5744           break;
5745         }
5746       }
5747     }
5748     blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
5749       region.height,exception);
5750     if (blob != (void *) NULL)
5751       goto PerlEnd;
5752
5753   PerlException:
5754     InheritPerlException(exception,perl_exception);
5755     exception=DestroyExceptionInfo(exception);
5756     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5757
5758   PerlEnd:
5759     RETVAL = (void *) blob;
5760   }
5761   OUTPUT:
5762     RETVAL
5763 \f
5764 #
5765 ###############################################################################
5766 #                                                                             #
5767 #                                                                             #
5768 #                                                                             #
5769 #   G e t A u t h e n t i c M e t a c o n t e n t                             #
5770 #                                                                             #
5771 #                                                                             #
5772 #                                                                             #
5773 ###############################################################################
5774 #
5775 #
5776 void *
5777 GetAuthenticMetacontent(ref,...)
5778   Image::Magick ref = NO_INIT
5779   ALIAS:
5780     getauthenticmetacontent = 1
5781     GetMetacontent = 2
5782     getmetacontent = 3
5783   CODE:
5784   {
5785     ExceptionInfo
5786       *exception;
5787
5788     Image
5789       *image;
5790
5791     struct PackageInfo
5792       *info;
5793
5794     SV
5795       *perl_exception,
5796       *reference;
5797
5798     void
5799       *blob = NULL;
5800
5801     PERL_UNUSED_VAR(ref);
5802     PERL_UNUSED_VAR(ix);
5803     exception=AcquireExceptionInfo();
5804     perl_exception=newSVpv("",0);
5805     if (sv_isobject(ST(0)) == 0)
5806       {
5807         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5808           PackageName);
5809         goto PerlException;
5810       }
5811     reference=SvRV(ST(0));
5812
5813     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5814     if (image == (Image *) NULL)
5815       {
5816         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5817           PackageName);
5818         goto PerlException;
5819       }
5820
5821     blob=(void *) GetAuthenticMetacontent(image);
5822     if (blob != (void *) NULL)
5823       goto PerlEnd;
5824
5825   PerlException:
5826     InheritPerlException(exception,perl_exception);
5827     exception=DestroyExceptionInfo(exception);
5828     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5829
5830   PerlEnd:
5831     RETVAL = blob;
5832   }
5833   OUTPUT:
5834     RETVAL
5835 \f
5836 #
5837 ###############################################################################
5838 #                                                                             #
5839 #                                                                             #
5840 #                                                                             #
5841 #   G e t V i r t u a l M e t a c o n t e n t                                 #
5842 #                                                                             #
5843 #                                                                             #
5844 #                                                                             #
5845 ###############################################################################
5846 #
5847 #
5848 void *
5849 GetVirtualMetacontent(ref,...)
5850   Image::Magick ref = NO_INIT
5851   ALIAS:
5852     getvirtualmetacontent = 1
5853   CODE:
5854   {
5855     ExceptionInfo
5856       *exception;
5857
5858     Image
5859       *image;
5860
5861     struct PackageInfo
5862       *info;
5863
5864     SV
5865       *perl_exception,
5866       *reference;
5867
5868     void
5869       *blob = NULL;
5870
5871     PERL_UNUSED_VAR(ref);
5872     PERL_UNUSED_VAR(ix);
5873     exception=AcquireExceptionInfo();
5874     perl_exception=newSVpv("",0);
5875     if (sv_isobject(ST(0)) == 0)
5876       {
5877         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5878           PackageName);
5879         goto PerlException;
5880       }
5881     reference=SvRV(ST(0));
5882
5883     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5884     if (image == (Image *) NULL)
5885       {
5886         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5887           PackageName);
5888         goto PerlException;
5889       }
5890
5891     blob=(void *) GetVirtualMetacontent(image);
5892     if (blob != (void *) NULL)
5893       goto PerlEnd;
5894
5895   PerlException:
5896     InheritPerlException(exception,perl_exception);
5897     exception=DestroyExceptionInfo(exception);
5898     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5899
5900   PerlEnd:
5901     RETVAL = blob;
5902   }
5903   OUTPUT:
5904     RETVAL
5905 \f
5906 #
5907 ###############################################################################
5908 #                                                                             #
5909 #                                                                             #
5910 #                                                                             #
5911 #   H i s t o g r a m                                                         #
5912 #                                                                             #
5913 #                                                                             #
5914 #                                                                             #
5915 ###############################################################################
5916 #
5917 #
5918 void
5919 Histogram(ref,...)
5920   Image::Magick ref=NO_INIT
5921   ALIAS:
5922     HistogramImage = 1
5923     histogram      = 2
5924     histogramimage = 3
5925   PPCODE:
5926   {
5927     AV
5928       *av;
5929
5930     char
5931       message[MaxTextExtent];
5932
5933     PixelPacket
5934       *histogram;
5935
5936     ExceptionInfo
5937       *exception;
5938
5939     Image
5940       *image;
5941
5942     register ssize_t
5943       i;
5944
5945     ssize_t
5946       count;
5947
5948     struct PackageInfo
5949       *info;
5950
5951     SV
5952       *perl_exception,
5953       *reference;
5954
5955     size_t
5956       number_colors;
5957
5958     PERL_UNUSED_VAR(ref);
5959     PERL_UNUSED_VAR(ix);
5960     exception=AcquireExceptionInfo();
5961     perl_exception=newSVpv("",0);
5962     av=NULL;
5963     if (sv_isobject(ST(0)) == 0)
5964       {
5965         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5966           PackageName);
5967         goto PerlException;
5968       }
5969     reference=SvRV(ST(0));
5970     av=newAV();
5971     SvREFCNT_dec(av);
5972     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5973     if (image == (Image *) NULL)
5974       {
5975         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5976           PackageName);
5977         goto PerlException;
5978       }
5979     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
5980     count=0;
5981     for ( ; image; image=image->next)
5982     {
5983       histogram=GetImageHistogram(image,&number_colors,&image->exception);
5984       if (histogram == (PixelPacket *) NULL)
5985         continue;
5986       count+=(ssize_t) number_colors;
5987       EXTEND(sp,6*count);
5988       for (i=0; i < (ssize_t) number_colors; i++)
5989       {
5990         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
5991           histogram[i].red);
5992         PUSHs(sv_2mortal(newSVpv(message,0)));
5993         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
5994           histogram[i].green);
5995         PUSHs(sv_2mortal(newSVpv(message,0)));
5996         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
5997           histogram[i].blue);
5998         PUSHs(sv_2mortal(newSVpv(message,0)));
5999         if (image->colorspace == CMYKColorspace)
6000           {
6001             (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
6002               histogram[i].black);
6003             PUSHs(sv_2mortal(newSVpv(message,0)));
6004           }
6005         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
6006           histogram[i].alpha);
6007         PUSHs(sv_2mortal(newSVpv(message,0)));
6008         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
6009           histogram[i].count);
6010         PUSHs(sv_2mortal(newSVpv(message,0)));
6011       }
6012       histogram=(PixelPacket *) RelinquishMagickMemory(histogram);
6013     }
6014
6015   PerlException:
6016     InheritPerlException(exception,perl_exception);
6017     exception=DestroyExceptionInfo(exception);
6018     SvREFCNT_dec(perl_exception);
6019   }
6020 \f
6021 #
6022 ###############################################################################
6023 #                                                                             #
6024 #                                                                             #
6025 #                                                                             #
6026 #   G e t P i x e l                                                           #
6027 #                                                                             #
6028 #                                                                             #
6029 #                                                                             #
6030 ###############################################################################
6031 #
6032 #
6033 void
6034 GetPixel(ref,...)
6035   Image::Magick ref=NO_INIT
6036   ALIAS:
6037     getpixel = 1
6038     getPixel = 2
6039   PPCODE:
6040   {
6041     AV
6042       *av;
6043
6044     char
6045       *attribute;
6046
6047     ExceptionInfo
6048       *exception;
6049
6050     Image
6051       *image;
6052
6053     MagickBooleanType
6054       normalize;
6055
6056     RectangleInfo
6057       region;
6058
6059     register const Quantum
6060       *p;
6061
6062     register ssize_t
6063       i;
6064
6065     ssize_t
6066       option;
6067
6068     struct PackageInfo
6069       *info;
6070
6071     SV
6072       *perl_exception,
6073       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6074
6075     PERL_UNUSED_VAR(ref);
6076     PERL_UNUSED_VAR(ix);
6077     exception=AcquireExceptionInfo();
6078     perl_exception=newSVpv("",0);
6079     reference=SvRV(ST(0));
6080     av=(AV *) reference;
6081     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6082       exception);
6083     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6084     if (image == (Image *) NULL)
6085       {
6086         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6087           PackageName);
6088         goto PerlException;
6089       }
6090     normalize=MagickTrue;
6091     region.x=0;
6092     region.y=0;
6093     region.width=image->columns;
6094     region.height=1;
6095     if (items == 1)
6096       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6097     for (i=2; i < items; i+=2)
6098     {
6099       attribute=(char *) SvPV(ST(i-1),na);
6100       switch (*attribute)
6101       {
6102         case 'C':
6103         case 'c':
6104         {
6105           if (LocaleCompare(attribute,"channel") == 0)
6106             {
6107               ssize_t
6108                 option;
6109
6110               option=ParseChannelOption(SvPV(ST(i),na));
6111               if (option < 0)
6112                 {
6113                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6114                     SvPV(ST(i),na));
6115                   return;
6116                 }
6117               SetPixelComponentMap(image,(ChannelType) option);
6118               break;
6119             }
6120           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6121             attribute);
6122           break;
6123         }
6124         case 'g':
6125         case 'G':
6126         {
6127           if (LocaleCompare(attribute,"geometry") == 0)
6128             {
6129               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6130               break;
6131             }
6132           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6133             attribute);
6134           break;
6135         }
6136         case 'N':
6137         case 'n':
6138         {
6139           if (LocaleCompare(attribute,"normalize") == 0)
6140             {
6141               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6142                 SvPV(ST(i),na));
6143               if (option < 0)
6144                 {
6145                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6146                     SvPV(ST(i),na));
6147                   break;
6148                 }
6149              normalize=option != 0 ? MagickTrue : MagickFalse;
6150              break;
6151             }
6152           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6153             attribute);
6154           break;
6155         }
6156         case 'x':
6157         case 'X':
6158         {
6159           if (LocaleCompare(attribute,"x") == 0)
6160             {
6161               region.x=SvIV(ST(i));
6162               break;
6163             }
6164           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6165             attribute);
6166           break;
6167         }
6168         case 'y':
6169         case 'Y':
6170         {
6171           if (LocaleCompare(attribute,"y") == 0)
6172             {
6173               region.y=SvIV(ST(i));
6174               break;
6175             }
6176           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6177             attribute);
6178           break;
6179         }
6180         default:
6181         {
6182           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6183             attribute);
6184           break;
6185         }
6186       }
6187     }
6188     p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6189     if (p == (const Quantum *) NULL)
6190       PUSHs(&sv_undef);
6191     else
6192       {
6193         double
6194           scale;
6195
6196         scale=1.0;
6197         if (normalize != MagickFalse)
6198           scale=1.0/QuantumRange;
6199         if ((GetPixelRedTraits(image) & ActivePixelTrait) != 0)
6200           PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6201         if ((GetPixelGreenTraits(image) & ActivePixelTrait) != 0)
6202           PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6203         if ((GetPixelBlueTraits(image) & ActivePixelTrait) != 0)
6204           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6205         if (((GetPixelBlackTraits(image) & ActivePixelTrait) != 0) &&
6206             (image->colorspace == CMYKColorspace))
6207           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6208         if ((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0)
6209           PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6210       }
6211
6212   PerlException:
6213     InheritPerlException(exception,perl_exception);
6214     exception=DestroyExceptionInfo(exception);
6215     SvREFCNT_dec(perl_exception);
6216   }
6217 \f
6218 #
6219 ###############################################################################
6220 #                                                                             #
6221 #                                                                             #
6222 #                                                                             #
6223 #   G e t P i x e l s                                                         #
6224 #                                                                             #
6225 #                                                                             #
6226 #                                                                             #
6227 ###############################################################################
6228 #
6229 #
6230 void
6231 GetPixels(ref,...)
6232   Image::Magick ref=NO_INIT
6233   ALIAS:
6234     getpixels = 1
6235     getPixels = 2
6236   PPCODE:
6237   {
6238     AV
6239       *av;
6240
6241     char
6242       *attribute;
6243
6244     const char
6245       *map;
6246
6247     ExceptionInfo
6248       *exception;
6249
6250     Image
6251       *image;
6252
6253     MagickBooleanType
6254       normalize,
6255       status;
6256
6257     RectangleInfo
6258       region;
6259
6260     register ssize_t
6261       i;
6262
6263     ssize_t
6264       option;
6265
6266     struct PackageInfo
6267       *info;
6268
6269     SV
6270       *perl_exception,
6271       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6272
6273     PERL_UNUSED_VAR(ref);
6274     PERL_UNUSED_VAR(ix);
6275     exception=AcquireExceptionInfo();
6276     perl_exception=newSVpv("",0);
6277     reference=SvRV(ST(0));
6278     av=(AV *) reference;
6279     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6280       exception);
6281     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6282     if (image == (Image *) NULL)
6283       {
6284         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6285           PackageName);
6286         goto PerlException;
6287       }
6288     map="RGB";
6289     if (image->matte != MagickFalse)
6290       map="RGBA";
6291     if (image->colorspace == CMYKColorspace)
6292       {
6293         map="CMYK";
6294         if (image->matte != MagickFalse)
6295           map="CMYKA";
6296       }
6297     normalize=MagickFalse;
6298     region.x=0;
6299     region.y=0;
6300     region.width=image->columns;
6301     region.height=1;
6302     if (items == 1)
6303       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6304     for (i=2; i < items; i+=2)
6305     {
6306       attribute=(char *) SvPV(ST(i-1),na);
6307       switch (*attribute)
6308       {
6309         case 'g':
6310         case 'G':
6311         {
6312           if (LocaleCompare(attribute,"geometry") == 0)
6313             {
6314               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6315               break;
6316             }
6317           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6318             attribute);
6319           break;
6320         }
6321         case 'H':
6322         case 'h':
6323         {
6324           if (LocaleCompare(attribute,"height") == 0)
6325             {
6326               region.height=SvIV(ST(i));
6327               break;
6328             }
6329           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6330             attribute);
6331           break;
6332         }
6333         case 'M':
6334         case 'm':
6335         {
6336           if (LocaleCompare(attribute,"map") == 0)
6337             {
6338               map=SvPV(ST(i),na);
6339               break;
6340             }
6341           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6342             attribute);
6343           break;
6344         }
6345         case 'N':
6346         case 'n':
6347         {
6348           if (LocaleCompare(attribute,"normalize") == 0)
6349             {
6350               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6351                 SvPV(ST(i),na));
6352               if (option < 0)
6353                 {
6354                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6355                     SvPV(ST(i),na));
6356                   break;
6357                 }
6358              normalize=option != 0 ? MagickTrue : MagickFalse;
6359              break;
6360             }
6361           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6362             attribute);
6363           break;
6364         }
6365         case 'W':
6366         case 'w':
6367         {
6368           if (LocaleCompare(attribute,"width") == 0)
6369             {
6370               region.width=SvIV(ST(i));
6371               break;
6372             }
6373           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6374             attribute);
6375           break;
6376         }
6377         case 'x':
6378         case 'X':
6379         {
6380           if (LocaleCompare(attribute,"x") == 0)
6381             {
6382               region.x=SvIV(ST(i));
6383               break;
6384             }
6385           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6386             attribute);
6387           break;
6388         }
6389         case 'y':
6390         case 'Y':
6391         {
6392           if (LocaleCompare(attribute,"y") == 0)
6393             {
6394               region.y=SvIV(ST(i));
6395               break;
6396             }
6397           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6398             attribute);
6399           break;
6400         }
6401         default:
6402         {
6403           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6404             attribute);
6405           break;
6406         }
6407       }
6408     }
6409     if (normalize != MagickFalse)
6410       {
6411         float
6412           *pixels;
6413
6414         pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6415           region.height*sizeof(*pixels));
6416         if (pixels == (float *) NULL)
6417           {
6418             ThrowPerlException(exception,ResourceLimitError,
6419               "MemoryAllocationFailed",PackageName);
6420             goto PerlException;
6421           }
6422         status=ExportImagePixels(image,region.x,region.y,region.width,
6423           region.height,map,FloatPixel,pixels,exception);
6424         if (status == MagickFalse)
6425           PUSHs(&sv_undef);
6426         else
6427           {
6428             EXTEND(sp,strlen(map)*region.width*region.height);
6429             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6430               PUSHs(sv_2mortal(newSVnv(pixels[i])));
6431           }
6432         pixels=(float *) RelinquishMagickMemory(pixels);
6433       }
6434     else
6435       {
6436         Quantum
6437           *pixels;
6438
6439         pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6440           region.height*sizeof(*pixels));
6441         if (pixels == (Quantum *) NULL)
6442           {
6443             ThrowPerlException(exception,ResourceLimitError,
6444               "MemoryAllocationFailed",PackageName);
6445             goto PerlException;
6446           }
6447         status=ExportImagePixels(image,region.x,region.y,region.width,
6448           region.height,map,QuantumPixel,pixels,exception);
6449         if (status == MagickFalse)
6450           PUSHs(&sv_undef);
6451         else
6452           {
6453             EXTEND(sp,strlen(map)*region.width*region.height);
6454             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6455               PUSHs(sv_2mortal(newSViv(pixels[i])));
6456           }
6457         pixels=(Quantum *) RelinquishMagickMemory(pixels);
6458       }
6459
6460   PerlException:
6461     InheritPerlException(exception,perl_exception);
6462     exception=DestroyExceptionInfo(exception);
6463     SvREFCNT_dec(perl_exception);
6464   }
6465 \f
6466 #
6467 ###############################################################################
6468 #                                                                             #
6469 #                                                                             #
6470 #                                                                             #
6471 #   I m a g e T o B l o b                                                     #
6472 #                                                                             #
6473 #                                                                             #
6474 #                                                                             #
6475 ###############################################################################
6476 #
6477 #
6478 void
6479 ImageToBlob(ref,...)
6480   Image::Magick ref=NO_INIT
6481   ALIAS:
6482     ImageToBlob  = 1
6483     imagetoblob  = 2
6484     toblob       = 3
6485     blob         = 4
6486   PPCODE:
6487   {
6488     char
6489       filename[MaxTextExtent];
6490
6491     ExceptionInfo
6492       *exception;
6493
6494     Image
6495       *image,
6496       *next;
6497
6498     register ssize_t
6499       i;
6500
6501     struct PackageInfo
6502       *info,
6503       *package_info;
6504
6505     size_t
6506       length;
6507
6508     ssize_t
6509       scene;
6510
6511     SV
6512       *perl_exception,
6513       *reference;
6514
6515     void
6516       *blob;
6517
6518     PERL_UNUSED_VAR(ref);
6519     PERL_UNUSED_VAR(ix);
6520     exception=AcquireExceptionInfo();
6521     perl_exception=newSVpv("",0);
6522     package_info=(struct PackageInfo *) NULL;
6523     if (sv_isobject(ST(0)) == 0)
6524       {
6525         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6526           PackageName);
6527         goto PerlException;
6528       }
6529     reference=SvRV(ST(0));
6530     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6531     if (image == (Image *) NULL)
6532       {
6533         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6534           PackageName);
6535         goto PerlException;
6536       }
6537     package_info=ClonePackageInfo(info,exception);
6538     for (i=2; i < items; i+=2)
6539       SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6540     (void) CopyMagickString(filename,package_info->image_info->filename,
6541       MaxTextExtent);
6542     scene=0;
6543     for (next=image; next; next=next->next)
6544     {
6545       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
6546       next->scene=scene++;
6547     }
6548     SetImageInfo(package_info->image_info,(unsigned int)
6549       GetImageListLength(image),&image->exception);
6550     EXTEND(sp,(ssize_t) GetImageListLength(image));
6551     for ( ; image; image=image->next)
6552     {
6553       length=0;
6554       blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6555       if (blob != (char *) NULL)
6556         {
6557           PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6558           blob=(unsigned char *) RelinquishMagickMemory(blob);
6559         }
6560       if (package_info->image_info->adjoin)
6561         break;
6562     }
6563
6564   PerlException:
6565     if (package_info != (struct PackageInfo *) NULL)
6566       DestroyPackageInfo(package_info);
6567     InheritPerlException(exception,perl_exception);
6568     exception=DestroyExceptionInfo(exception);
6569     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6570   }
6571 \f
6572 #
6573 ###############################################################################
6574 #                                                                             #
6575 #                                                                             #
6576 #                                                                             #
6577 #   L a y e r s                                                               #
6578 #                                                                             #
6579 #                                                                             #
6580 #                                                                             #
6581 ###############################################################################
6582 #
6583 #
6584 void
6585 Layers(ref,...)
6586   Image::Magick ref=NO_INIT
6587   ALIAS:
6588     Layers                = 1
6589     layers           = 2
6590     OptimizeImageLayers   = 3
6591     optimizelayers        = 4
6592     optimizeimagelayers   = 5
6593   PPCODE:
6594   {
6595     AV
6596       *av;
6597
6598     char
6599       *attribute;
6600
6601     CompositeOperator
6602       compose;
6603
6604     ExceptionInfo
6605       *exception;
6606
6607     HV
6608       *hv;
6609
6610     Image
6611       *image,
6612       *layers;
6613
6614     ImageLayerMethod
6615       method;
6616
6617     register ssize_t
6618       i;
6619
6620     ssize_t
6621       option,
6622       sp;
6623
6624     struct PackageInfo
6625       *info;
6626
6627     SV
6628       *av_reference,
6629       *perl_exception,
6630       *reference,
6631       *rv,
6632       *sv;
6633
6634     PERL_UNUSED_VAR(ref);
6635     PERL_UNUSED_VAR(ix);
6636     exception=AcquireExceptionInfo();
6637     perl_exception=newSVpv("",0);
6638     sv=NULL;
6639     if (sv_isobject(ST(0)) == 0)
6640       {
6641         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6642           PackageName);
6643         goto PerlException;
6644       }
6645     reference=SvRV(ST(0));
6646     hv=SvSTASH(reference);
6647     av=newAV();
6648     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
6649     SvREFCNT_dec(av);
6650     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6651     if (image == (Image *) NULL)
6652       {
6653         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6654           PackageName);
6655         goto PerlException;
6656       }
6657     compose=image->compose;
6658     method=OptimizeLayer;
6659     for (i=2; i < items; i+=2)
6660     {
6661       attribute=(char *) SvPV(ST(i-1),na);
6662       switch (*attribute)
6663       {
6664         case 'C':
6665         case 'c':
6666         {
6667           if (LocaleCompare(attribute,"compose") == 0)
6668             {
6669               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
6670                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
6671               if (sp < 0)
6672                 {
6673                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6674                     SvPV(ST(i),na));
6675                   break;
6676                 }
6677               compose=(CompositeOperator) sp;
6678               break;
6679             }
6680           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6681             attribute);
6682           break;
6683         }
6684         case 'M':
6685         case 'm':
6686         {
6687           if (LocaleCompare(attribute,"method") == 0)
6688             {
6689               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
6690                 SvPV(ST(i),na));
6691               if (option < 0)
6692                 {
6693                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6694                     SvPV(ST(i),na));
6695                   break;
6696                 }
6697               method=(ImageLayerMethod) option;
6698               break;
6699             }
6700           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6701             attribute);
6702           break;
6703         }
6704         default:
6705         {
6706           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6707             attribute);
6708           break;
6709         }
6710       }
6711     }
6712     layers=(Image *) NULL;
6713     switch (method)
6714     {
6715       case CompareAnyLayer:
6716       case CompareClearLayer:
6717       case CompareOverlayLayer:
6718       default:
6719       {
6720         layers=CompareImagesLayers(image,method,exception);
6721         break;
6722       }
6723       case MergeLayer:
6724       case FlattenLayer:
6725       case MosaicLayer:
6726       {
6727         layers=MergeImageLayers(image,method,exception);
6728         break;
6729       }
6730       case DisposeLayer:
6731       {
6732         layers=DisposeImages(image,exception);
6733         break;
6734       }
6735       case OptimizeImageLayer:
6736       {
6737         layers=OptimizeImageLayers(image,exception);
6738         break;
6739       }
6740       case OptimizePlusLayer:
6741       {
6742         layers=OptimizePlusImageLayers(image,exception);
6743         break;
6744       }
6745       case OptimizeTransLayer:
6746       {
6747         OptimizeImageTransparency(image,exception);
6748         InheritException(&(image->exception),exception);
6749         break;
6750       }
6751       case RemoveDupsLayer:
6752       {
6753         RemoveDuplicateLayers(&image,exception);
6754         InheritException(&(image->exception),exception);
6755         break;
6756       }
6757       case RemoveZeroLayer:
6758       {
6759         RemoveZeroDelayLayers(&image,exception);
6760         InheritException(&(image->exception),exception);
6761         break;
6762       }
6763       case OptimizeLayer:
6764       {
6765         QuantizeInfo
6766           *quantize_info;
6767
6768         /*
6769           General Purpose, GIF Animation Optimizer.
6770         */
6771         layers=CoalesceImages(image,exception);
6772         if (layers == (Image *) NULL)
6773           break;
6774         InheritException(&(layers->exception),exception);
6775         image=layers;
6776         layers=OptimizeImageLayers(image,exception);
6777         if (layers == (Image *) NULL)
6778           break;
6779         InheritException(&(layers->exception),exception);
6780         image=DestroyImageList(image);
6781         image=layers;
6782         layers=(Image *) NULL;
6783         OptimizeImageTransparency(image,exception);
6784         InheritException(&(image->exception),exception);
6785         quantize_info=AcquireQuantizeInfo(info->image_info);
6786         (void) RemapImages(quantize_info,image,(Image *) NULL);
6787         quantize_info=DestroyQuantizeInfo(quantize_info);
6788         break;
6789       }
6790       case CompositeLayer:
6791       {
6792         Image
6793           *source;
6794
6795         RectangleInfo
6796           geometry;
6797
6798         /*
6799           Split image sequence at the first 'NULL:' image.
6800         */
6801         source=image;
6802         while (source != (Image *) NULL)
6803         {
6804           source=GetNextImageInList(source);
6805           if ((source != (Image *) NULL) &&
6806               (LocaleCompare(source->magick,"NULL") == 0))
6807             break;
6808         }
6809         if (source != (Image *) NULL)
6810           {
6811             if ((GetPreviousImageInList(source) == (Image *) NULL) ||
6812                 (GetNextImageInList(source) == (Image *) NULL))
6813               source=(Image *) NULL;
6814             else
6815               {
6816                 /*
6817                   Separate the two lists, junk the null: image.
6818                 */
6819                 source=SplitImageList(source->previous);
6820                 DeleteImageFromList(&source);
6821               }
6822           }
6823         if (source == (Image *) NULL)
6824           {
6825             (void) ThrowMagickException(exception,GetMagickModule(),
6826               OptionError,"MissingNullSeparator","layers Composite");
6827             break;
6828           }
6829         /*
6830           Adjust offset with gravity and virtual canvas.
6831         */
6832         SetGeometry(image,&geometry);
6833         (void) ParseAbsoluteGeometry(image->geometry,&geometry);
6834         geometry.width=source->page.width != 0 ? source->page.width :
6835           source->columns;
6836         geometry.height=source->page.height != 0 ? source->page.height :
6837           source->rows;
6838         GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
6839           image->columns,image->page.height != 0 ? image->page.height :
6840           image->rows,image->gravity,&geometry);
6841         CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
6842         source=DestroyImageList(source);
6843         InheritException(&(image->exception),exception);
6844         break;
6845       }
6846     }
6847     if (layers != (Image *) NULL)
6848       {
6849         InheritException(&(layers->exception),exception);
6850         image=layers;
6851       }
6852     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
6853       goto PerlException;
6854     for ( ; image; image=image->next)
6855     {
6856       AddImageToRegistry(sv,image);
6857       rv=newRV(sv);
6858       av_push(av,sv_bless(rv,hv));
6859       SvREFCNT_dec(sv);
6860     }
6861     exception=DestroyExceptionInfo(exception);
6862     ST(0)=av_reference;
6863     SvREFCNT_dec(perl_exception);
6864     XSRETURN(1);
6865
6866   PerlException:
6867     InheritPerlException(exception,perl_exception);
6868     exception=DestroyExceptionInfo(exception);
6869     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
6870     SvPOK_on(perl_exception);
6871     ST(0)=sv_2mortal(perl_exception);
6872     XSRETURN(1);
6873   }
6874 \f
6875 #
6876 ###############################################################################
6877 #                                                                             #
6878 #                                                                             #
6879 #                                                                             #
6880 #   M a g i c k T o M i m e                                                   #
6881 #                                                                             #
6882 #                                                                             #
6883 #                                                                             #
6884 ###############################################################################
6885 #
6886 #
6887 SV *
6888 MagickToMime(ref,name)
6889   Image::Magick ref=NO_INIT
6890   char *name
6891   ALIAS:
6892     magicktomime = 1
6893   CODE:
6894   {
6895     char
6896       *mime;
6897
6898     PERL_UNUSED_VAR(ref);
6899     PERL_UNUSED_VAR(ix);
6900     mime=MagickToMime(name);
6901     RETVAL=newSVpv(mime,0);
6902     mime=(char *) RelinquishMagickMemory(mime);
6903   }
6904   OUTPUT:
6905     RETVAL
6906 \f
6907 #
6908 ###############################################################################
6909 #                                                                             #
6910 #                                                                             #
6911 #                                                                             #
6912 #   M o g r i f y                                                             #
6913 #                                                                             #
6914 #                                                                             #
6915 #                                                                             #
6916 ###############################################################################
6917 #
6918 #
6919 void
6920 Mogrify(ref,...)
6921   Image::Magick ref=NO_INIT
6922   ALIAS:
6923     Comment            =   1
6924     CommentImage       =   2
6925     Label              =   3
6926     LabelImage         =   4
6927     AddNoise           =   5
6928     AddNoiseImage      =   6
6929     Colorize           =   7
6930     ColorizeImage      =   8
6931     Border             =   9
6932     BorderImage        =  10
6933     Blur               =  11
6934     BlurImage          =  12
6935     Chop               =  13
6936     ChopImage          =  14
6937     Crop               =  15
6938     CropImage          =  16
6939     Despeckle          =  17
6940     DespeckleImage     =  18
6941     Edge               =  19
6942     EdgeImage          =  20
6943     Emboss             =  21
6944     EmbossImage        =  22
6945     Enhance            =  23
6946     EnhanceImage       =  24
6947     Flip               =  25
6948     FlipImage          =  26
6949     Flop               =  27
6950     FlopImage          =  28
6951     Frame              =  29
6952     FrameImage         =  30
6953     Implode            =  31
6954     ImplodeImage       =  32
6955     Magnify            =  33
6956     MagnifyImage       =  34
6957     MedianFilter       =  35
6958     MedianFilterImage  =  36
6959     Minify             =  37
6960     MinifyImage        =  38
6961     OilPaint           =  39
6962     OilPaintImage      =  40
6963     ReduceNoise        =  41
6964     ReduceNoiseImage   =  42
6965     Roll               =  43
6966     RollImage          =  44
6967     Rotate             =  45
6968     RotateImage        =  46
6969     Sample             =  47
6970     SampleImage        =  48
6971     Scale              =  49
6972     ScaleImage         =  50
6973     Shade              =  51
6974     ShadeImage         =  52
6975     Sharpen            =  53
6976     SharpenImage       =  54
6977     Shear              =  55
6978     ShearImage         =  56
6979     Spread             =  57
6980     SpreadImage        =  58
6981     Swirl              =  59
6982     SwirlImage         =  60
6983     Resize             =  61
6984     ResizeImage        =  62
6985     Zoom               =  63
6986     ZoomImage          =  64
6987     Annotate           =  65
6988     AnnotateImage      =  66
6989     ColorFloodfill     =  67
6990     ColorFloodfillImage=  68
6991     Composite          =  69
6992     CompositeImage     =  70
6993     Contrast           =  71
6994     ContrastImage      =  72
6995     CycleColormap      =  73
6996     CycleColormapImage =  74
6997     Draw               =  75
6998     DrawImage          =  76
6999     Equalize           =  77
7000     EqualizeImage      =  78
7001     Gamma              =  79
7002     GammaImage         =  80
7003     Map                =  81
7004     MapImage           =  82
7005     MatteFloodfill     =  83
7006     MatteFloodfillImage=  84
7007     Modulate           =  85
7008     ModulateImage      =  86
7009     Negate             =  87
7010     NegateImage        =  88
7011     Normalize          =  89
7012     NormalizeImage     =  90
7013     NumberColors       =  91
7014     NumberColorsImage  =  92
7015     Opaque             =  93
7016     OpaqueImage        =  94
7017     Quantize           =  95
7018     QuantizeImage      =  96
7019     Raise              =  97
7020     RaiseImage         =  98
7021     Segment            =  99
7022     SegmentImage       = 100
7023     Signature          = 101
7024     SignatureImage     = 102
7025     Solarize           = 103
7026     SolarizeImage      = 104
7027     Sync               = 105
7028     SyncImage          = 106
7029     Texture            = 107
7030     TextureImage       = 108
7031     Evaluate           = 109
7032     EvaluateImage      = 110
7033     Transparent        = 111
7034     TransparentImage   = 112
7035     Threshold          = 113
7036     ThresholdImage     = 114
7037     Charcoal           = 115
7038     CharcoalImage      = 116
7039     Trim               = 117
7040     TrimImage          = 118
7041     Wave               = 119
7042     WaveImage          = 120
7043     Separate           = 121
7044     SeparateImage      = 122
7045     Stereo             = 125
7046     StereoImage        = 126
7047     Stegano            = 127
7048     SteganoImage       = 128
7049     Deconstruct        = 129
7050     DeconstructImage   = 130
7051     GaussianBlur       = 131
7052     GaussianBlurImage  = 132
7053     Convolve           = 133
7054     ConvolveImage      = 134
7055     Profile            = 135
7056     ProfileImage       = 136
7057     UnsharpMask        = 137
7058     UnsharpMaskImage   = 138
7059     MotionBlur         = 139
7060     MotionBlurImage    = 140
7061     OrderedDither      = 141
7062     OrderedDitherImage = 142
7063     Shave              = 143
7064     ShaveImage         = 144
7065     Level              = 145
7066     LevelImage         = 146
7067     Clip               = 147
7068     ClipImage          = 148
7069     AffineTransform    = 149
7070     AffineTransformImage = 150
7071     Difference         = 151
7072     DifferenceImage    = 152
7073     AdaptiveThreshold  = 153
7074     AdaptiveThresholdImage = 154
7075     Resample           = 155
7076     ResampleImage      = 156
7077     Describe           = 157
7078     DescribeImage      = 158
7079     BlackThreshold     = 159
7080     BlackThresholdImage= 160
7081     WhiteThreshold     = 161
7082     WhiteThresholdImage= 162
7083     RadialBlur         = 163
7084     RadialBlurImage    = 164
7085     Thumbnail          = 165
7086     ThumbnailImage     = 166
7087     Strip              = 167
7088     StripImage         = 168
7089     Tint               = 169
7090     TintImage          = 170
7091     Channel            = 171
7092     ChannelImage       = 172
7093     Splice             = 173
7094     SpliceImage        = 174
7095     Posterize          = 175
7096     PosterizeImage     = 176
7097     Shadow             = 177
7098     ShadowImage        = 178
7099     Identify           = 179
7100     IdentifyImage      = 180
7101     SepiaTone          = 181
7102     SepiaToneImage     = 182
7103     SigmoidalContrast  = 183
7104     SigmoidalContrastImage = 184
7105     Extent             = 185
7106     ExtentImage        = 186
7107     Vignette           = 187
7108     VignetteImage      = 188
7109     ContrastStretch    = 189
7110     ContrastStretchImage = 190
7111     Sans0              = 191
7112     Sans0Image         = 192
7113     Sans1              = 193
7114     Sans1Image         = 194
7115     AdaptiveSharpen    = 195
7116     AdaptiveSharpenImage = 196
7117     Transpose          = 197
7118     TransposeImage     = 198
7119     Transverse         = 199
7120     TransverseImage    = 200
7121     AutoOrient         = 201
7122     AutoOrientImage    = 202
7123     AdaptiveBlur       = 203
7124     AdaptiveBlurImage  = 204
7125     Sketch             = 205
7126     SketchImage        = 206
7127     UniqueColors       = 207
7128     UniqueColorsImage  = 208
7129     AdaptiveResize     = 209
7130     AdaptiveResizeImage= 210
7131     ClipMask           = 211
7132     ClipMaskImage      = 212
7133     LinearStretch      = 213
7134     LinearStretchImage = 214
7135     RecolorImage       = 215
7136     Recolor            = 216
7137     Mask               = 217
7138     MaskImage          = 218
7139     Polaroid           = 219
7140     PolaroidImage      = 220
7141     FloodfillPaint     = 221
7142     FloodfillPaintImage= 222
7143     Distort            = 223
7144     DistortImage       = 224
7145     Clut               = 225
7146     ClutImage          = 226
7147     LiquidRescale      = 227
7148     LiquidRescaleImage = 228
7149     Encipher           = 229
7150     EncipherImage      = 230
7151     Decipher           = 231
7152     DecipherImage      = 232
7153     Deskew             = 233
7154     DeskewImage        = 234
7155     Remap              = 235
7156     RemapImage         = 236
7157     SparseColor        = 237
7158     SparseColorImage   = 238
7159     Function           = 239
7160     FunctionImage      = 240
7161     SelectiveBlur      = 241
7162     SelectiveBlurImage = 242
7163     HaldClut           = 243
7164     HaldClutImage      = 244
7165     BlueShift          = 245
7166     BlueShiftImage     = 246
7167     ForwardFourierTransform  = 247
7168     ForwardFourierTransformImage = 248
7169     InverseFourierTransform = 249
7170     InverseFourierTransformImage = 250
7171     ColorDecisionList  = 251
7172     ColorDecisionListImage = 252
7173     AutoGamma          = 253
7174     AutoGammaImage     = 254
7175     AutoLevel          = 255
7176     AutoLevelImage     = 256
7177     LevelColors        = 257
7178     LevelColorsImage   = 258
7179     Clamp              = 259
7180     ClampImage         = 260
7181     Filter             = 261
7182     FilterImage        = 262
7183     BrightnessContrast = 263
7184     BrightnessContrastImage = 264
7185     Morphology         = 265
7186     MorphologyImage    = 266
7187     ColorMatrix        = 267
7188     ColorMatrixImage   = 268
7189     Color              = 269
7190     ColorImage         = 270
7191     Mode               = 271
7192     ModeImage          = 272
7193     Statistic          = 273
7194     StatisticImage     = 274
7195     MogrifyRegion      = 666
7196   PPCODE:
7197   {
7198     AffineMatrix
7199       affine,
7200       current;
7201
7202     char
7203       attribute_flag[MaxArguments],
7204       message[MaxTextExtent];
7205
7206     ChannelType
7207       channel;
7208
7209     CompositeOperator
7210       compose;
7211
7212     const char
7213       *attribute,
7214       *value;
7215
7216     double
7217       angle;
7218
7219     ExceptionInfo
7220       *exception;
7221
7222     GeometryInfo
7223       geometry_info;
7224
7225     Image
7226       *image,
7227       *next,
7228       *region_image;
7229
7230     MagickBooleanType
7231       status;
7232
7233     MagickStatusType
7234       flags;
7235
7236     PixelPacket
7237       fill_color;
7238
7239     RectangleInfo
7240       geometry,
7241       region_info;
7242
7243     register ssize_t
7244       i;
7245
7246     ssize_t
7247       base,
7248       j,
7249       number_images;
7250
7251     struct Methods
7252       *rp;
7253
7254     struct PackageInfo
7255       *info;
7256
7257     SV
7258       *perl_exception,
7259       **pv,
7260       *reference,
7261       **reference_vector;
7262
7263     struct ArgumentList
7264       argument_list[MaxArguments];
7265
7266     PERL_UNUSED_VAR(ref);
7267     PERL_UNUSED_VAR(ix);
7268     exception=AcquireExceptionInfo();
7269     perl_exception=newSVpv("",0);
7270     reference_vector=NULL;
7271     region_image=NULL;
7272     number_images=0;
7273     base=2;
7274     if (sv_isobject(ST(0)) == 0)
7275       {
7276         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7277           PackageName);
7278         goto PerlException;
7279       }
7280     reference=SvRV(ST(0));
7281     region_info.width=0;
7282     region_info.height=0;
7283     region_info.x=0;
7284     region_info.y=0;
7285     region_image=(Image *) NULL;
7286     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7287     if (ix && (ix != 666))
7288       {
7289         /*
7290           Called as Method(...)
7291         */
7292         ix=(ix+1)/2;
7293         rp=(&Methods[ix-1]);
7294         attribute=rp->name;
7295       }
7296     else
7297       {
7298         /*
7299           Called as Mogrify("Method",...)
7300         */
7301         attribute=(char *) SvPV(ST(1),na);
7302         if (ix)
7303           {
7304             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7305             attribute=(char *) SvPV(ST(2),na);
7306             base++;
7307           }
7308         for (rp=Methods; ; rp++)
7309         {
7310           if (rp >= EndOf(Methods))
7311             {
7312               ThrowPerlException(exception,OptionError,
7313                 "UnrecognizedPerlMagickMethod",attribute);
7314               goto PerlException;
7315             }
7316           if (strEQcase(attribute,rp->name))
7317             break;
7318         }
7319         ix=rp-Methods+1;
7320         base++;
7321       }
7322     if (image == (Image *) NULL)
7323       {
7324         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7325         goto PerlException;
7326       }
7327     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7328     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7329     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7330     {
7331       Arguments
7332         *pp,
7333         *qq;
7334
7335       ssize_t
7336         ssize_test;
7337
7338       struct ArgumentList
7339         *al;
7340
7341       SV
7342         *sv;
7343
7344       sv=NULL;
7345       ssize_test=0;
7346       pp=(Arguments *) NULL;
7347       qq=rp->arguments;
7348       if (i == items)
7349         {
7350           pp=rp->arguments,
7351           sv=ST(i-1);
7352         }
7353       else
7354         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7355         {
7356           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7357             break;
7358           if (strEQcase(attribute,qq->method) > ssize_test)
7359             {
7360               pp=qq;
7361               ssize_test=strEQcase(attribute,qq->method);
7362             }
7363         }
7364       if (pp == (Arguments *) NULL)
7365         {
7366           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7367             attribute);
7368           goto continue_outer_loop;
7369         }
7370       al=(&argument_list[pp-rp->arguments]);
7371       switch (pp->type)
7372       {
7373         case ArrayReference:
7374         {
7375           if (SvTYPE(sv) != SVt_RV)
7376             {
7377               (void) FormatLocaleString(message,MaxTextExtent,
7378                 "invalid %.60s value",pp->method);
7379               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7380               goto continue_outer_loop;
7381             }
7382           al->array_reference=SvRV(sv);
7383           break;
7384         }
7385         case RealReference:
7386         {
7387           al->real_reference=SvNV(sv);
7388           break;
7389         }
7390         case FileReference:
7391         {
7392           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7393           break;
7394         }
7395         case ImageReference:
7396         {
7397           if (!sv_isobject(sv) ||
7398               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7399                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7400             {
7401               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7402                 PackageName);
7403               goto PerlException;
7404             }
7405           break;
7406         }
7407         case IntegerReference:
7408         {
7409           al->integer_reference=SvIV(sv);
7410           break;
7411         }
7412         case StringReference:
7413         {
7414           al->string_reference=(char *) SvPV(sv,al->length);
7415           if (sv_isobject(sv))
7416             al->image_reference=SetupList(aTHX_ SvRV(sv),
7417               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7418           break;
7419         }
7420         default:
7421         {
7422           /*
7423             Is a string; look up name.
7424           */
7425           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7426             {
7427               al->string_reference=(char *) SvPV(sv,al->length);
7428               al->integer_reference=(-1);
7429               break;
7430             }
7431           al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7432             MagickFalse,SvPV(sv,na));
7433           if (pp->type == MagickChannelOptions)
7434             al->integer_reference=ParseChannelOption(SvPV(sv,na));
7435           if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7436             {
7437               (void) FormatLocaleString(message,MaxTextExtent,
7438                 "invalid %.60s value",pp->method);
7439               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7440               goto continue_outer_loop;
7441             }
7442           break;
7443         }
7444       }
7445       attribute_flag[pp-rp->arguments]++;
7446       continue_outer_loop: ;
7447     }
7448     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7449     pv=reference_vector;
7450     SetGeometryInfo(&geometry_info);
7451     channel=DefaultChannels;
7452     for (next=image; next; next=next->next)
7453     {
7454       image=next;
7455       SetGeometry(image,&geometry);
7456       if ((region_info.width*region_info.height) != 0)
7457         {
7458           region_image=image;
7459           image=CropImage(image,&region_info,exception);
7460         }
7461       switch (ix)
7462       {
7463         default:
7464         {
7465           (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double) ix);
7466           ThrowPerlException(exception,OptionError,
7467             "UnrecognizedPerlMagickMethod",message);
7468           goto PerlException;
7469         }
7470         case 1:  /* Comment */
7471         {
7472           if (attribute_flag[0] == 0)
7473             argument_list[0].string_reference=(char *) NULL;
7474           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7475             info ? info->image_info : (ImageInfo *) NULL,image,
7476             argument_list[0].string_reference));
7477           break;
7478         }
7479         case 2:  /* Label */
7480         {
7481           if (attribute_flag[0] == 0)
7482             argument_list[0].string_reference=(char *) NULL;
7483           (void) SetImageProperty(image,"label",InterpretImageProperties(
7484             info ? info->image_info : (ImageInfo *) NULL,image,
7485             argument_list[0].string_reference));
7486           break;
7487         }
7488         case 3:  /* AddNoise */
7489         {
7490           if (attribute_flag[0] == 0)
7491             argument_list[0].integer_reference=UniformNoise;
7492           if (attribute_flag[1] != 0)
7493             channel=(ChannelType) argument_list[1].integer_reference;
7494           image=AddNoiseImageChannel(image,channel,(NoiseType)
7495             argument_list[0].integer_reference,exception);
7496           break;
7497         }
7498         case 4:  /* Colorize */
7499         {
7500           PixelPacket
7501             target;
7502
7503           (void) GetOneVirtualPixel(image,0,0,&target,exception);
7504           if (attribute_flag[0] != 0)
7505             (void) QueryColorDatabase(argument_list[0].string_reference,&target,
7506               exception);
7507           if (attribute_flag[1] == 0)
7508             argument_list[1].string_reference="100%";
7509           image=ColorizeImage(image,argument_list[1].string_reference,target,
7510             exception);
7511           break;
7512         }
7513         case 5:  /* Border */
7514         {
7515           geometry.width=0;
7516           geometry.height=0;
7517           if (attribute_flag[0] != 0)
7518             {
7519               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7520                 &geometry,exception);
7521               if ((flags & HeightValue) == 0)
7522                 geometry.height=geometry.width;
7523             }
7524           if (attribute_flag[1] != 0)
7525             geometry.width=argument_list[1].integer_reference;
7526           if (attribute_flag[2] != 0)
7527             geometry.height=argument_list[2].integer_reference;
7528           if (attribute_flag[3] != 0)
7529             QueryColorDatabase(argument_list[3].string_reference,
7530               &image->border_color,exception);
7531           if (attribute_flag[4] != 0)
7532             QueryColorDatabase(argument_list[4].string_reference,
7533               &image->border_color,exception);
7534           if (attribute_flag[5] != 0)
7535             QueryColorDatabase(argument_list[5].string_reference,
7536               &image->border_color,exception);
7537           if (attribute_flag[6] != 0)
7538             image->compose=(CompositeOperator) argument_list[6].integer_reference;
7539           image=BorderImage(image,&geometry,exception);
7540           break;
7541         }
7542         case 6:  /* Blur */
7543         {
7544           if (attribute_flag[0] != 0)
7545             {
7546               flags=ParseGeometry(argument_list[0].string_reference,
7547                 &geometry_info);
7548               if ((flags & SigmaValue) == 0)
7549                 geometry_info.sigma=1.0;
7550             }
7551           if (attribute_flag[1] != 0)
7552             geometry_info.rho=argument_list[1].real_reference;
7553           if (attribute_flag[2] != 0)
7554             geometry_info.sigma=argument_list[2].real_reference;
7555           if (attribute_flag[3] != 0)
7556             channel=(ChannelType) argument_list[3].integer_reference;
7557           image=BlurImageChannel(image,channel,geometry_info.rho,
7558             geometry_info.sigma,exception);
7559           break;
7560         }
7561         case 7:  /* Chop */
7562         {
7563           if (attribute_flag[0] != 0)
7564             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7565               &geometry,exception);
7566           if (attribute_flag[1] != 0)
7567             geometry.width=argument_list[1].integer_reference;
7568           if (attribute_flag[2] != 0)
7569             geometry.height=argument_list[2].integer_reference;
7570           if (attribute_flag[3] != 0)
7571             geometry.x=argument_list[3].integer_reference;
7572           if (attribute_flag[4] != 0)
7573             geometry.y=argument_list[4].integer_reference;
7574           image=ChopImage(image,&geometry,exception);
7575           break;
7576         }
7577         case 8:  /* Crop */
7578         {
7579           if (attribute_flag[6] != 0)
7580             image->gravity=(GravityType) argument_list[6].integer_reference;
7581           if (attribute_flag[0] != 0)
7582             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7583               &geometry,exception);
7584           if (attribute_flag[1] != 0)
7585             geometry.width=argument_list[1].integer_reference;
7586           if (attribute_flag[2] != 0)
7587             geometry.height=argument_list[2].integer_reference;
7588           if (attribute_flag[3] != 0)
7589             geometry.x=argument_list[3].integer_reference;
7590           if (attribute_flag[4] != 0)
7591             geometry.y=argument_list[4].integer_reference;
7592           if (attribute_flag[5] != 0)
7593             image->fuzz=
7594               SiPrefixToDouble(argument_list[5].string_reference,QuantumRange);
7595           image=CropImage(image,&geometry,exception);
7596           break;
7597         }
7598         case 9:  /* Despeckle */
7599         {
7600           image=DespeckleImage(image,exception);
7601           break;
7602         }
7603         case 10:  /* Edge */
7604         {
7605           if (attribute_flag[0] != 0)
7606             geometry_info.rho=argument_list[0].real_reference;
7607           image=EdgeImage(image,geometry_info.rho,exception);
7608           break;
7609         }
7610         case 11:  /* Emboss */
7611         {
7612           if (attribute_flag[0] != 0)
7613             {
7614               flags=ParseGeometry(argument_list[0].string_reference,
7615                 &geometry_info);
7616               if ((flags & SigmaValue) == 0)
7617                 geometry_info.sigma=1.0;
7618             }
7619           if (attribute_flag[1] != 0)
7620             geometry_info.rho=argument_list[1].real_reference;
7621           if (attribute_flag[2] != 0)
7622             geometry_info.sigma=argument_list[2].real_reference;
7623           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
7624             exception);
7625           break;
7626         }
7627         case 12:  /* Enhance */
7628         {
7629           image=EnhanceImage(image,exception);
7630           break;
7631         }
7632         case 13:  /* Flip */
7633         {
7634           image=FlipImage(image,exception);
7635           break;
7636         }
7637         case 14:  /* Flop */
7638         {
7639           image=FlopImage(image,exception);
7640           break;
7641         }
7642         case 15:  /* Frame */
7643         {
7644           FrameInfo
7645             frame_info;
7646
7647           if (attribute_flag[0] != 0)
7648             {
7649               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7650                 &geometry,exception);
7651               if ((flags & HeightValue) == 0)
7652                 geometry.height=geometry.width;
7653               frame_info.width=geometry.width;
7654               frame_info.height=geometry.height;
7655               frame_info.outer_bevel=geometry.x;
7656               frame_info.inner_bevel=geometry.y;
7657             }
7658           if (attribute_flag[1] != 0)
7659             frame_info.width=argument_list[1].integer_reference;
7660           if (attribute_flag[2] != 0)
7661             frame_info.height=argument_list[2].integer_reference;
7662           if (attribute_flag[3] != 0)
7663             frame_info.inner_bevel=argument_list[3].integer_reference;
7664           if (attribute_flag[4] != 0)
7665             frame_info.outer_bevel=argument_list[4].integer_reference;
7666           if (attribute_flag[5] != 0)
7667             QueryColorDatabase(argument_list[5].string_reference,&fill_color,
7668               exception);
7669           if (attribute_flag[6] != 0)
7670             QueryColorDatabase(argument_list[6].string_reference,&fill_color,
7671               exception);
7672           frame_info.x=(ssize_t) frame_info.width;
7673           frame_info.y=(ssize_t) frame_info.height;
7674           frame_info.width=image->columns+2*frame_info.x;
7675           frame_info.height=image->rows+2*frame_info.y;
7676           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
7677             image->matte_color=fill_color;
7678           if (attribute_flag[7] != 0)
7679             image->compose=(CompositeOperator) argument_list[7].integer_reference;
7680           image=FrameImage(image,&frame_info,exception);
7681           break;
7682         }
7683         case 16:  /* Implode */
7684         {
7685           if (attribute_flag[0] == 0)
7686             argument_list[0].real_reference=0.5;
7687           if (attribute_flag[1] != 0)
7688             image->interpolate=(InterpolatePixelMethod)
7689               argument_list[1].integer_reference;
7690           image=ImplodeImage(image,argument_list[0].real_reference,
7691             exception);
7692           break;
7693         }
7694         case 17:  /* Magnify */
7695         {
7696           image=MagnifyImage(image,exception);
7697           break;
7698         }
7699         case 18:  /* MedianFilter */
7700         {
7701           if (attribute_flag[0] != 0)
7702             {
7703               flags=ParseGeometry(argument_list[0].string_reference,
7704                 &geometry_info);
7705               if ((flags & SigmaValue) == 0)
7706                 geometry_info.sigma=1.0;
7707             }
7708           if (attribute_flag[1] != 0)
7709             geometry_info.rho=argument_list[1].real_reference;
7710           if (attribute_flag[2] != 0)
7711             geometry_info.sigma=argument_list[2].real_reference;
7712           if (attribute_flag[3] != 0)
7713             channel=(ChannelType) argument_list[3].integer_reference;
7714           image=StatisticImageChannel(image,channel,MedianStatistic,
7715             (size_t) geometry_info.rho,(size_t) geometry_info.sigma,exception);
7716           break;
7717         }
7718         case 19:  /* Minify */
7719         {
7720           image=MinifyImage(image,exception);
7721           break;
7722         }
7723         case 20:  /* OilPaint */
7724         {
7725           if (attribute_flag[0] == 0)
7726             argument_list[0].real_reference=0.0;
7727           image=OilPaintImage(image,argument_list[0].real_reference,
7728             exception);
7729           break;
7730         }
7731         case 21:  /* ReduceNoise */
7732         {
7733           if (attribute_flag[0] != 0)
7734             {
7735               flags=ParseGeometry(argument_list[0].string_reference,
7736                 &geometry_info);
7737               if ((flags & SigmaValue) == 0)
7738                 geometry_info.sigma=1.0;
7739             }
7740           if (attribute_flag[1] != 0)
7741             geometry_info.rho=argument_list[1].real_reference;
7742           if (attribute_flag[2] != 0)
7743             geometry_info.sigma=argument_list[2].real_reference;
7744           if (attribute_flag[3] != 0)
7745             channel=(ChannelType) argument_list[3].integer_reference;
7746           image=StatisticImageChannel(image,channel,NonpeakStatistic,
7747             (size_t) geometry_info.rho,(size_t) geometry_info.sigma,exception);
7748           break;
7749         }
7750         case 22:  /* Roll */
7751         {
7752           if (attribute_flag[0] != 0)
7753             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7754               &geometry,exception);
7755           if (attribute_flag[1] != 0)
7756             geometry.x=argument_list[1].integer_reference;
7757           if (attribute_flag[2] != 0)
7758             geometry.y=argument_list[2].integer_reference;
7759           image=RollImage(image,geometry.x,geometry.y,exception);
7760           break;
7761         }
7762         case 23:  /* Rotate */
7763         {
7764           if (attribute_flag[0] == 0)
7765             argument_list[0].real_reference=90.0;
7766           if (attribute_flag[1] != 0)
7767             QueryColorDatabase(argument_list[1].string_reference,
7768               &image->background_color,exception);
7769           if (attribute_flag[2] != 0)
7770             QueryColorDatabase(argument_list[2].string_reference,
7771               &image->background_color,exception);
7772           if (attribute_flag[3] != 0)
7773             QueryColorDatabase(argument_list[3].string_reference,
7774               &image->background_color,exception);
7775           image=RotateImage(image,argument_list[0].real_reference,exception);
7776           break;
7777         }
7778         case 24:  /* Sample */
7779         {
7780           if (attribute_flag[0] != 0)
7781             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7782               &geometry,exception);
7783           if (attribute_flag[1] != 0)
7784             geometry.width=argument_list[1].integer_reference;
7785           if (attribute_flag[2] != 0)
7786             geometry.height=argument_list[2].integer_reference;
7787           image=SampleImage(image,geometry.width,geometry.height,exception);
7788           break;
7789         }
7790         case 25:  /* Scale */
7791         {
7792           if (attribute_flag[0] != 0)
7793             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7794               &geometry,exception);
7795           if (attribute_flag[1] != 0)
7796             geometry.width=argument_list[1].integer_reference;
7797           if (attribute_flag[2] != 0)
7798             geometry.height=argument_list[2].integer_reference;
7799           image=ScaleImage(image,geometry.width,geometry.height,exception);
7800           break;
7801         }
7802         case 26:  /* Shade */
7803         {
7804           if (attribute_flag[0] != 0)
7805             {
7806               flags=ParseGeometry(argument_list[0].string_reference,
7807                 &geometry_info);
7808               if ((flags & SigmaValue) == 0)
7809                 geometry_info.sigma=0.0;
7810             }
7811           if (attribute_flag[1] != 0)
7812             geometry_info.rho=argument_list[1].real_reference;
7813           if (attribute_flag[2] != 0)
7814             geometry_info.sigma=argument_list[2].real_reference;
7815           image=ShadeImage(image,
7816             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
7817             geometry_info.rho,geometry_info.sigma,exception);
7818           break;
7819         }
7820         case 27:  /* Sharpen */
7821         {
7822           if (attribute_flag[0] != 0)
7823             {
7824               flags=ParseGeometry(argument_list[0].string_reference,
7825                 &geometry_info);
7826               if ((flags & SigmaValue) == 0)
7827                 geometry_info.sigma=1.0;
7828             }
7829           if (attribute_flag[1] != 0)
7830             geometry_info.rho=argument_list[1].real_reference;
7831           if (attribute_flag[2] != 0)
7832             geometry_info.sigma=argument_list[2].real_reference;
7833           if (attribute_flag[3] != 0)
7834             channel=(ChannelType) argument_list[3].integer_reference;
7835           image=SharpenImageChannel(image,channel,geometry_info.rho,
7836             geometry_info.sigma,exception);
7837           break;
7838         }
7839         case 28:  /* Shear */
7840         {
7841           if (attribute_flag[0] != 0)
7842             {
7843               flags=ParseGeometry(argument_list[0].string_reference,
7844                 &geometry_info);
7845               if ((flags & SigmaValue) == 0)
7846                 geometry_info.sigma=geometry_info.rho;
7847             }
7848           if (attribute_flag[1] != 0)
7849             geometry_info.rho=argument_list[1].real_reference;
7850           if (attribute_flag[2] != 0)
7851             geometry_info.sigma=argument_list[2].real_reference;
7852           if (attribute_flag[3] != 0)
7853             QueryColorDatabase(argument_list[3].string_reference,
7854               &image->background_color,exception);
7855           if (attribute_flag[4] != 0)
7856             QueryColorDatabase(argument_list[4].string_reference,
7857               &image->background_color,exception);
7858           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
7859             exception);
7860           break;
7861         }
7862         case 29:  /* Spread */
7863         {
7864           if (attribute_flag[0] == 0)
7865             argument_list[0].real_reference=1.0;
7866           image=SpreadImage(image,argument_list[0].real_reference,exception);
7867           break;
7868         }
7869         case 30:  /* Swirl */
7870         {
7871           if (attribute_flag[0] == 0)
7872             argument_list[0].real_reference=50.0;
7873           if (attribute_flag[1] != 0)
7874             image->interpolate=(InterpolatePixelMethod)
7875               argument_list[1].integer_reference;
7876           image=SwirlImage(image,argument_list[0].real_reference,exception);
7877           break;
7878         }
7879         case 31:  /* Resize */
7880         case 32:  /* Zoom */
7881         {
7882           if (attribute_flag[0] != 0)
7883             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7884               &geometry,exception);
7885           if (attribute_flag[1] != 0)
7886             geometry.width=argument_list[1].integer_reference;
7887           if (attribute_flag[2] != 0)
7888             geometry.height=argument_list[2].integer_reference;
7889           if (attribute_flag[3] == 0)
7890             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
7891           if (attribute_flag[4] != 0)
7892             SetImageArtifact(image,"filter:support",
7893               argument_list[4].string_reference);
7894           if (attribute_flag[5] == 0)
7895             argument_list[5].real_reference=1.0;
7896           image=ResizeImage(image,geometry.width,geometry.height,
7897             (FilterTypes) argument_list[3].integer_reference,
7898             argument_list[5].real_reference,exception);
7899           break;
7900         }
7901         case 33:  /* Annotate */
7902         {
7903           DrawInfo
7904             *draw_info;
7905
7906           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
7907             (DrawInfo *) NULL);
7908           if (attribute_flag[0] != 0)
7909             {
7910               char
7911                 *text;
7912
7913               text=InterpretImageProperties(info ? info->image_info :
7914                 (ImageInfo *) NULL,image,argument_list[0].string_reference);
7915               (void) CloneString(&draw_info->text,text);
7916               text=DestroyString(text);
7917             }
7918           if (attribute_flag[1] != 0)
7919             (void) CloneString(&draw_info->font,
7920               argument_list[1].string_reference);
7921           if (attribute_flag[2] != 0)
7922             draw_info->pointsize=argument_list[2].real_reference;
7923           if (attribute_flag[3] != 0)
7924             (void) CloneString(&draw_info->density,
7925               argument_list[3].string_reference);
7926           if (attribute_flag[4] != 0)
7927             (void) QueryColorDatabase(argument_list[4].string_reference,
7928               &draw_info->undercolor,exception);
7929           if (attribute_flag[5] != 0)
7930             {
7931               (void) QueryColorDatabase(argument_list[5].string_reference,
7932                 &draw_info->stroke,exception);
7933               if (argument_list[5].image_reference != (Image *) NULL)
7934                 draw_info->stroke_pattern=CloneImage(
7935                   argument_list[5].image_reference,0,0,MagickTrue,exception);
7936             }
7937           if (attribute_flag[6] != 0)
7938             {
7939               (void) QueryColorDatabase(argument_list[6].string_reference,
7940                 &draw_info->fill,exception);
7941               if (argument_list[6].image_reference != (Image *) NULL)
7942                 draw_info->fill_pattern=CloneImage(
7943                   argument_list[6].image_reference,0,0,MagickTrue,exception);
7944             }
7945           if (attribute_flag[7] != 0)
7946             {
7947               (void) CloneString(&draw_info->geometry,
7948                 argument_list[7].string_reference);
7949               flags=ParsePageGeometry(image,argument_list[7].string_reference,
7950                 &geometry,exception);
7951               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
7952                 geometry_info.sigma=geometry_info.xi;
7953             }
7954           if (attribute_flag[8] != 0)
7955             (void) QueryColorDatabase(argument_list[8].string_reference,
7956               &draw_info->fill,exception);
7957           if (attribute_flag[11] != 0)
7958             draw_info->gravity=(GravityType) argument_list[11].integer_reference;
7959           if (attribute_flag[25] != 0)
7960             {
7961               AV
7962                 *av;
7963
7964               av=(AV *) argument_list[25].array_reference;
7965               if ((av_len(av) != 3) && (av_len(av) != 5))
7966                 {
7967                   ThrowPerlException(exception,OptionError,
7968                     "affine matrix must have 4 or 6 elements",PackageName);
7969                   goto PerlException;
7970                 }
7971               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
7972               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
7973               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
7974               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
7975               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
7976                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
7977                 {
7978                   ThrowPerlException(exception,OptionError,
7979                     "affine matrix is singular",PackageName);
7980                    goto PerlException;
7981                 }
7982               if (av_len(av) == 5)
7983                 {
7984                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
7985                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
7986                 }
7987             }
7988           for (j=12; j < 17; j++)
7989           {
7990             if (attribute_flag[j] == 0)
7991               continue;
7992             value=argument_list[j].string_reference;
7993             angle=argument_list[j].real_reference;
7994             current=draw_info->affine;
7995             GetAffineMatrix(&affine);
7996             switch (j)
7997             {
7998               case 12:
7999               {
8000                 /*
8001                   Translate.
8002                 */
8003                 flags=ParseGeometry(value,&geometry_info);
8004                 affine.tx=geometry_info.xi;
8005                 affine.ty=geometry_info.psi;
8006                 if ((flags & PsiValue) == 0)
8007                   affine.ty=affine.tx;
8008                 break;
8009               }
8010               case 13:
8011               {
8012                 /*
8013                   Scale.
8014                 */
8015                 flags=ParseGeometry(value,&geometry_info);
8016                 affine.sx=geometry_info.rho;
8017                 affine.sy=geometry_info.sigma;
8018                 if ((flags & SigmaValue) == 0)
8019                   affine.sy=affine.sx;
8020                 break;
8021               }
8022               case 14:
8023               {
8024                 /*
8025                   Rotate.
8026                 */
8027                 if (angle == 0.0)
8028                   break;
8029                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8030                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8031                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8032                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8033                 break;
8034               }
8035               case 15:
8036               {
8037                 /*
8038                   SkewX.
8039                 */
8040                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8041                 break;
8042               }
8043               case 16:
8044               {
8045                 /*
8046                   SkewY.
8047                 */
8048                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8049                 break;
8050               }
8051             }
8052             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8053             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8054             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8055             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8056             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8057               current.tx;
8058             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8059               current.ty;
8060           }
8061           if (attribute_flag[9] == 0)
8062             argument_list[9].real_reference=0.0;
8063           if (attribute_flag[10] == 0)
8064             argument_list[10].real_reference=0.0;
8065           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8066             {
8067               char
8068                 geometry[MaxTextExtent];
8069
8070               (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
8071                 (double) argument_list[9].real_reference+draw_info->affine.tx,
8072                 (double) argument_list[10].real_reference+draw_info->affine.ty);
8073               (void) CloneString(&draw_info->geometry,geometry);
8074             }
8075           if (attribute_flag[17] != 0)
8076             draw_info->stroke_width=argument_list[17].real_reference;
8077           if (attribute_flag[18] != 0)
8078             {
8079               draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8080                 MagickTrue : MagickFalse;
8081               draw_info->stroke_antialias=draw_info->text_antialias;
8082             }
8083           if (attribute_flag[19] != 0)
8084             (void) CloneString(&draw_info->family,
8085               argument_list[19].string_reference);
8086           if (attribute_flag[20] != 0)
8087             draw_info->style=(StyleType) argument_list[20].integer_reference;
8088           if (attribute_flag[21] != 0)
8089             draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8090           if (attribute_flag[22] != 0)
8091             draw_info->weight=argument_list[22].integer_reference;
8092           if (attribute_flag[23] != 0)
8093             draw_info->align=(AlignType) argument_list[23].integer_reference;
8094           if (attribute_flag[24] != 0)
8095             (void) CloneString(&draw_info->encoding,
8096               argument_list[24].string_reference);
8097           if (attribute_flag[25] != 0)
8098             draw_info->fill_pattern=CloneImage(
8099               argument_list[25].image_reference,0,0,MagickTrue,exception);
8100           if (attribute_flag[26] != 0)
8101             draw_info->fill_pattern=CloneImage(
8102               argument_list[26].image_reference,0,0,MagickTrue,exception);
8103           if (attribute_flag[27] != 0)
8104             draw_info->stroke_pattern=CloneImage(
8105               argument_list[27].image_reference,0,0,MagickTrue,exception);
8106           if (attribute_flag[29] != 0)
8107             draw_info->kerning=argument_list[29].real_reference;
8108           if (attribute_flag[30] != 0)
8109             draw_info->interline_spacing=argument_list[30].real_reference;
8110           if (attribute_flag[31] != 0)
8111             draw_info->interword_spacing=argument_list[31].real_reference;
8112           if (attribute_flag[32] != 0)
8113             draw_info->direction=(DirectionType)
8114               argument_list[32].integer_reference;
8115           (void) AnnotateImage(image,draw_info);
8116           draw_info=DestroyDrawInfo(draw_info);
8117           break;
8118         }
8119         case 34:  /* ColorFloodfill */
8120         {
8121           DrawInfo
8122             *draw_info;
8123
8124           MagickBooleanType
8125             invert;
8126
8127           PixelInfo
8128             target;
8129
8130           draw_info=CloneDrawInfo(info ? info->image_info :
8131             (ImageInfo *) NULL,(DrawInfo *) NULL);
8132           if (attribute_flag[0] != 0)
8133             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8134               &geometry,exception);
8135           if (attribute_flag[1] != 0)
8136             geometry.x=argument_list[1].integer_reference;
8137           if (attribute_flag[2] != 0)
8138             geometry.y=argument_list[2].integer_reference;
8139           if (attribute_flag[3] != 0)
8140             (void) QueryColorDatabase(argument_list[3].string_reference,
8141               &draw_info->fill,exception);
8142           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
8143             exception);
8144           invert=MagickFalse;
8145           if (attribute_flag[4] != 0)
8146             {
8147               QueryMagickColor(argument_list[4].string_reference,&target,
8148                 exception);
8149               invert=MagickTrue;
8150             }
8151           if (attribute_flag[5] != 0)
8152             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
8153               QuantumRange);
8154           if (attribute_flag[6] != 0)
8155             invert=(MagickBooleanType) argument_list[6].integer_reference;
8156           (void) FloodfillPaintImage(image,DefaultChannels,draw_info,&target,
8157             geometry.x,geometry.y,invert);
8158           draw_info=DestroyDrawInfo(draw_info);
8159           break;
8160         }
8161         case 35:  /* Composite */
8162         {
8163           char
8164             composite_geometry[MaxTextExtent];
8165
8166           Image
8167             *composite_image,
8168             *rotate_image;
8169
8170           compose=OverCompositeOp;
8171           if (attribute_flag[0] != 0)
8172             composite_image=argument_list[0].image_reference;
8173           else
8174             {
8175               ThrowPerlException(exception,OptionError,
8176                 "CompositeImageRequired",PackageName);
8177               goto PerlException;
8178             }
8179           /*
8180             Parameter Handling used for BOTH normal and tiled composition.
8181           */
8182           if (attribute_flag[1] != 0) /* compose */
8183             compose=(CompositeOperator) argument_list[1].integer_reference;
8184           if (attribute_flag[6] != 0) /* opacity  */
8185             {
8186               if (compose != DissolveCompositeOp)
8187                 (void) SetImageOpacity(composite_image,(Quantum)
8188                   SiPrefixToDouble(argument_list[6].string_reference,
8189                   QuantumRange));
8190               else
8191                 {
8192                   CacheView
8193                     *composite_view;
8194
8195                   double
8196                     opacity;
8197
8198                   MagickBooleanType
8199                     sync;
8200
8201                   register ssize_t
8202                     x;
8203
8204                   register Quantum
8205                     *q;
8206
8207                   ssize_t
8208                     y;
8209
8210                   /*
8211                     Handle dissolve composite operator (patch by
8212                     Kevin A. McGrail).
8213                   */
8214                   (void) CloneString(&image->geometry,
8215                     argument_list[6].string_reference);
8216                   opacity=(Quantum) SiPrefixToDouble(
8217                     argument_list[6].string_reference,QuantumRange);
8218                   if (composite_image->matte != MagickTrue)
8219                     (void) SetImageOpacity(composite_image,OpaqueAlpha);
8220                   composite_view=AcquireCacheView(composite_image);
8221                   for (y=0; y < (ssize_t) composite_image->rows ; y++)
8222                   {
8223                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8224                       composite_image->columns,1,exception);
8225                     for (x=0; x < (ssize_t) composite_image->columns; x++)
8226                     {
8227                       if (GetPixelAlpha(image,q) == OpaqueAlpha)
8228                         SetPixelAlpha(composite_image,ClampToQuantum(opacity),q);
8229                       q+=GetPixelChannels(composite_image);
8230                     }
8231                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8232                     if (sync == MagickFalse)
8233                       break;
8234                   }
8235                   composite_view=DestroyCacheView(composite_view);
8236                 }
8237             }
8238           if (attribute_flag[9] != 0)    /* "color=>" */
8239             QueryColorDatabase(argument_list[9].string_reference,
8240               &composite_image->background_color,exception);
8241           if (attribute_flag[12] != 0) /* "interpolate=>" */
8242             image->interpolate=(InterpolatePixelMethod)
8243               argument_list[12].integer_reference;
8244           if (attribute_flag[13] != 0)   /* "args=>" */
8245             (void) SetImageArtifact(composite_image,"compose:args",
8246               argument_list[13].string_reference);
8247           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8248             (void) SetImageArtifact(composite_image,"compose:args",
8249               argument_list[14].string_reference);
8250           /*
8251             Tiling Composition (with orthogonal rotate).
8252           */
8253           rotate_image=(Image *) NULL;
8254           if (attribute_flag[8] != 0)   /* "rotate=>" */
8255             {
8256                /*
8257                  Rotate image.
8258                */
8259                rotate_image=RotateImage(composite_image,
8260                  argument_list[8].real_reference,exception);
8261                if (rotate_image == (Image *) NULL)
8262                  break;
8263             }
8264           if (attribute_flag[7] && argument_list[7].integer_reference) /* tile */
8265             {
8266               ssize_t
8267                 x,
8268                 y;
8269
8270               /*
8271                 Tile the composite image.
8272               */
8273              if (attribute_flag[8] != 0)   /* "tile=>" */
8274                (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8275                  "false");
8276              else
8277                (void) SetImageArtifact(composite_image,
8278                  "compose:outside-overlay","false");
8279              for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8280                 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8281                 {
8282                   if (attribute_flag[8] != 0) /* rotate */
8283                     (void) CompositeImage(image,compose,rotate_image,x,y);
8284                   else
8285                     (void) CompositeImage(image,compose,composite_image,x,y);
8286                 }
8287               if (attribute_flag[8] != 0) /* rotate */
8288                 rotate_image=DestroyImage(rotate_image);
8289               break;
8290             }
8291           /*
8292             Parameter Handling used used ONLY for normal composition.
8293           */
8294           if (attribute_flag[5] != 0) /* gravity */
8295             image->gravity=(GravityType) argument_list[5].integer_reference;
8296           if (attribute_flag[2] != 0) /* geometry offset */
8297             {
8298               SetGeometry(image,&geometry);
8299               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8300                 &geometry);
8301               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8302                 &geometry);
8303             }
8304           if (attribute_flag[3] != 0) /* x offset */
8305             geometry.x=argument_list[3].integer_reference;
8306           if (attribute_flag[4] != 0) /* y offset */
8307             geometry.y=argument_list[4].integer_reference;
8308           if (attribute_flag[10] != 0) /* mask */
8309             {
8310               if ((image->compose == DisplaceCompositeOp) ||
8311                   (image->compose == DistortCompositeOp))
8312                 {
8313                   /*
8314                     Merge Y displacement into X displacement image.
8315                   */
8316                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8317                     &image->exception);
8318                   (void) CompositeImage(composite_image,CopyGreenCompositeOp,
8319                     argument_list[10].image_reference,0,0);
8320                 }
8321               else
8322                 {
8323                   /*
8324                     Set a blending mask for the composition.
8325                   */
8326                   image->mask=CloneImage(argument_list[10].image_reference,0,0,
8327                     MagickTrue,&image->exception);
8328                   (void) NegateImage(image->mask,MagickFalse);
8329                 }
8330             }
8331           if (attribute_flag[11] != 0) /* channel */
8332             channel=(ChannelType) argument_list[11].integer_reference;
8333           /*
8334             Composite two images (normal composition).
8335           */
8336           (void) FormatLocaleString(composite_geometry,MaxTextExtent,
8337             "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8338             (double) composite_image->rows,(double) geometry.x,(double)
8339             geometry.y);
8340           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8341             exception);
8342           if (attribute_flag[8] == 0) /* no rotate */
8343             CompositeImageChannel(image,channel,compose,composite_image,
8344               geometry.x,geometry.y);
8345           else
8346             {
8347               /*
8348                 Position adjust rotated image then composite.
8349               */
8350               geometry.x-=(ssize_t) (rotate_image->columns-
8351                 composite_image->columns)/2;
8352               geometry.y-=(ssize_t) (rotate_image->rows-
8353                 composite_image->rows)/2;
8354               CompositeImageChannel(image,channel,compose,rotate_image,
8355                 geometry.x,geometry.y);
8356               rotate_image=DestroyImage(rotate_image);
8357             }
8358           if (attribute_flag[10] != 0) /* mask */
8359             {
8360               if ((image->compose == DisplaceCompositeOp) ||
8361                   (image->compose == DistortCompositeOp))
8362                 composite_image=DestroyImage(composite_image);
8363               else
8364                 image->mask=DestroyImage(image->mask);
8365             }
8366           break;
8367         }
8368         case 36:  /* Contrast */
8369         {
8370           if (attribute_flag[0] == 0)
8371             argument_list[0].integer_reference=0;
8372           (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8373             MagickTrue : MagickFalse);
8374           break;
8375         }
8376         case 37:  /* CycleColormap */
8377         {
8378           if (attribute_flag[0] == 0)
8379             argument_list[0].integer_reference=6;
8380           (void) CycleColormapImage(image,argument_list[0].integer_reference);
8381           break;
8382         }
8383         case 38:  /* Draw */
8384         {
8385           DrawInfo
8386             *draw_info;
8387
8388           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8389             (DrawInfo *) NULL);
8390           (void) CloneString(&draw_info->primitive,"point");
8391           if (attribute_flag[0] != 0)
8392             {
8393               if (argument_list[0].integer_reference < 0)
8394                 (void) CloneString(&draw_info->primitive,
8395                   argument_list[0].string_reference);
8396               else
8397                 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8398                   MagickPrimitiveOptions,argument_list[0].integer_reference));
8399             }
8400           if (attribute_flag[1] != 0)
8401             {
8402               if (LocaleCompare(draw_info->primitive,"path") == 0)
8403                 {
8404                   (void) ConcatenateString(&draw_info->primitive," '");
8405                   ConcatenateString(&draw_info->primitive,
8406                     argument_list[1].string_reference);
8407                   (void) ConcatenateString(&draw_info->primitive,"'");
8408                 }
8409               else
8410                 {
8411                   (void) ConcatenateString(&draw_info->primitive," ");
8412                   ConcatenateString(&draw_info->primitive,
8413                     argument_list[1].string_reference);
8414                 }
8415             }
8416           if (attribute_flag[2] != 0)
8417             {
8418               (void) ConcatenateString(&draw_info->primitive," ");
8419               (void) ConcatenateString(&draw_info->primitive,
8420                 CommandOptionToMnemonic(MagickMethodOptions,
8421                 argument_list[2].integer_reference));
8422             }
8423           if (attribute_flag[3] != 0)
8424             {
8425               (void) QueryColorDatabase(argument_list[3].string_reference,
8426                 &draw_info->stroke,exception);
8427               if (argument_list[3].image_reference != (Image *) NULL)
8428                 draw_info->stroke_pattern=CloneImage(
8429                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8430             }
8431           if (attribute_flag[4] != 0)
8432             {
8433               (void) QueryColorDatabase(argument_list[4].string_reference,
8434                 &draw_info->fill,exception);
8435               if (argument_list[4].image_reference != (Image *) NULL)
8436                 draw_info->fill_pattern=CloneImage(
8437                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8438             }
8439           if (attribute_flag[5] != 0)
8440             draw_info->stroke_width=argument_list[5].real_reference;
8441           if (attribute_flag[6] != 0)
8442             (void) CloneString(&draw_info->font,
8443               argument_list[6].string_reference);
8444           if (attribute_flag[7] != 0)
8445             (void) QueryColorDatabase(argument_list[7].string_reference,
8446               &draw_info->border_color,exception);
8447           if (attribute_flag[8] != 0)
8448             draw_info->affine.tx=argument_list[8].real_reference;
8449           if (attribute_flag[9] != 0)
8450             draw_info->affine.ty=argument_list[9].real_reference;
8451           if (attribute_flag[20] != 0)
8452             {
8453               AV
8454                 *av;
8455
8456               av=(AV *) argument_list[20].array_reference;
8457               if ((av_len(av) != 3) && (av_len(av) != 5))
8458                 {
8459                   ThrowPerlException(exception,OptionError,
8460                     "affine matrix must have 4 or 6 elements",PackageName);
8461                   goto PerlException;
8462                 }
8463               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8464               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8465               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8466               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8467               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8468                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8469                 {
8470                   ThrowPerlException(exception,OptionError,
8471                     "affine matrix is singular",PackageName);
8472                    goto PerlException;
8473                 }
8474               if (av_len(av) == 5)
8475                 {
8476                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8477                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8478                 }
8479             }
8480           for (j=10; j < 15; j++)
8481           {
8482             if (attribute_flag[j] == 0)
8483               continue;
8484             value=argument_list[j].string_reference;
8485             angle=argument_list[j].real_reference;
8486             current=draw_info->affine;
8487             GetAffineMatrix(&affine);
8488             switch (j)
8489             {
8490               case 10:
8491               {
8492                 /*
8493                   Translate.
8494                 */
8495                 flags=ParseGeometry(value,&geometry_info);
8496                 affine.tx=geometry_info.xi;
8497                 affine.ty=geometry_info.psi;
8498                 if ((flags & PsiValue) == 0)
8499                   affine.ty=affine.tx;
8500                 break;
8501               }
8502               case 11:
8503               {
8504                 /*
8505                   Scale.
8506                 */
8507                 flags=ParseGeometry(value,&geometry_info);
8508                 affine.sx=geometry_info.rho;
8509                 affine.sy=geometry_info.sigma;
8510                 if ((flags & SigmaValue) == 0)
8511                   affine.sy=affine.sx;
8512                 break;
8513               }
8514               case 12:
8515               {
8516                 /*
8517                   Rotate.
8518                 */
8519                 if (angle == 0.0)
8520                   break;
8521                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8522                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8523                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8524                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8525                 break;
8526               }
8527               case 13:
8528               {
8529                 /*
8530                   SkewX.
8531                 */
8532                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8533                 break;
8534               }
8535               case 14:
8536               {
8537                 /*
8538                   SkewY.
8539                 */
8540                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8541                 break;
8542               }
8543             }
8544             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8545             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8546             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8547             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8548             draw_info->affine.tx=
8549               current.sx*affine.tx+current.ry*affine.ty+current.tx;
8550             draw_info->affine.ty=
8551               current.rx*affine.tx+current.sy*affine.ty+current.ty;
8552           }
8553           if (attribute_flag[15] != 0)
8554             draw_info->fill_pattern=CloneImage(
8555               argument_list[15].image_reference,0,0,MagickTrue,exception);
8556           if (attribute_flag[16] != 0)
8557             draw_info->pointsize=argument_list[16].real_reference;
8558           if (attribute_flag[17] != 0)
8559             {
8560               draw_info->stroke_antialias=argument_list[17].integer_reference != 0
8561                 ? MagickTrue : MagickFalse;
8562               draw_info->text_antialias=draw_info->stroke_antialias;
8563             }
8564           if (attribute_flag[18] != 0)
8565             (void) CloneString(&draw_info->density,
8566               argument_list[18].string_reference);
8567           if (attribute_flag[19] != 0)
8568             draw_info->stroke_width=argument_list[19].real_reference;
8569           if (attribute_flag[21] != 0)
8570             draw_info->dash_offset=argument_list[21].real_reference;
8571           if (attribute_flag[22] != 0)
8572             {
8573               AV
8574                 *av;
8575
8576               av=(AV *) argument_list[22].array_reference;
8577               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
8578                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
8579               if (draw_info->dash_pattern != (double *) NULL)
8580                 {
8581                   for (i=0; i <= av_len(av); i++)
8582                     draw_info->dash_pattern[i]=(double)
8583                       SvNV(*(av_fetch(av,i,0)));
8584                   draw_info->dash_pattern[i]=0.0;
8585                 }
8586             }
8587           if (attribute_flag[23] != 0)
8588             image->interpolate=(InterpolatePixelMethod)
8589               argument_list[23].integer_reference;
8590           if ((attribute_flag[24] != 0) &&
8591               (draw_info->fill_pattern != (Image *) NULL))
8592             flags=ParsePageGeometry(draw_info->fill_pattern,
8593               argument_list[24].string_reference,
8594               &draw_info->fill_pattern->tile_offset,exception);
8595           if (attribute_flag[25] != 0)
8596             {
8597               (void) ConcatenateString(&draw_info->primitive," '");
8598               (void) ConcatenateString(&draw_info->primitive,
8599                 argument_list[25].string_reference);
8600               (void) ConcatenateString(&draw_info->primitive,"'");
8601             }
8602           if (attribute_flag[26] != 0)
8603             draw_info->fill_pattern=CloneImage(
8604               argument_list[26].image_reference,0,0,MagickTrue,exception);
8605           if (attribute_flag[27] != 0)
8606             draw_info->stroke_pattern=CloneImage(
8607               argument_list[27].image_reference,0,0,MagickTrue,exception);
8608           if (attribute_flag[28] != 0)
8609             (void) CloneString(&draw_info->primitive,
8610               argument_list[28].string_reference);
8611           if (attribute_flag[29] != 0)
8612             draw_info->kerning=argument_list[29].real_reference;
8613           if (attribute_flag[30] != 0)
8614             draw_info->interline_spacing=argument_list[30].real_reference;
8615           if (attribute_flag[31] != 0)
8616             draw_info->interword_spacing=argument_list[31].real_reference;
8617           if (attribute_flag[32] != 0)
8618             draw_info->direction=(DirectionType)
8619               argument_list[32].integer_reference;
8620           DrawImage(image,draw_info);
8621           draw_info=DestroyDrawInfo(draw_info);
8622           break;
8623         }
8624         case 39:  /* Equalize */
8625         {
8626           if (attribute_flag[0] != 0)
8627             channel=(ChannelType) argument_list[0].integer_reference;
8628           EqualizeImageChannel(image,channel);
8629           break;
8630         }
8631         case 40:  /* Gamma */
8632         {
8633           if (attribute_flag[1] != 0)
8634             channel=(ChannelType) argument_list[1].integer_reference;
8635           if (attribute_flag[2] == 0)
8636             argument_list[2].real_reference=1.0;
8637           if (attribute_flag[3] == 0)
8638             argument_list[3].real_reference=1.0;
8639           if (attribute_flag[4] == 0)
8640             argument_list[4].real_reference=1.0;
8641           if (attribute_flag[0] == 0)
8642             {
8643               (void) FormatLocaleString(message,MaxTextExtent,
8644                 "%.15g,%.15g,%.15g",(double) argument_list[2].real_reference,
8645                 (double) argument_list[3].real_reference,
8646                 (double) argument_list[4].real_reference);
8647               argument_list[0].string_reference=message;
8648             }
8649           if (strchr(argument_list[0].string_reference,',') != (char *) NULL)
8650             (void) GammaImage(image,argument_list[0].string_reference);
8651           else
8652             (void) GammaImageChannel(image,channel,InterpretLocaleValue(
8653               argument_list[0].string_reference,(char **) NULL));
8654           break;
8655         }
8656         case 41:  /* Map */
8657         {
8658           QuantizeInfo
8659             *quantize_info;
8660
8661           if (attribute_flag[0] == 0)
8662             {
8663               ThrowPerlException(exception,OptionError,"MapImageRequired",
8664                 PackageName);
8665               goto PerlException;
8666             }
8667           quantize_info=AcquireQuantizeInfo(info->image_info);
8668           if (attribute_flag[1] != 0)
8669             quantize_info->dither=(MagickBooleanType)
8670               argument_list[1].integer_reference;
8671           if (attribute_flag[2] != 0)
8672             quantize_info->dither_method=(DitherMethod)
8673               argument_list[2].integer_reference;
8674           (void) RemapImages(quantize_info,image,
8675             argument_list[0].image_reference);
8676           quantize_info=DestroyQuantizeInfo(quantize_info);
8677           break;
8678         }
8679         case 42:  /* MatteFloodfill */
8680         {
8681           DrawInfo
8682             *draw_info;
8683
8684           MagickBooleanType
8685             invert;
8686
8687           PixelInfo
8688             target;
8689
8690           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8691             (DrawInfo *) NULL);
8692           if (attribute_flag[0] != 0)
8693             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8694               &geometry,exception);
8695           if (attribute_flag[1] != 0)
8696             geometry.x=argument_list[1].integer_reference;
8697           if (attribute_flag[2] != 0)
8698             geometry.y=argument_list[2].integer_reference;
8699           if (image->matte == MagickFalse)
8700             (void) SetImageOpacity(image,OpaqueAlpha);
8701           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
8702             exception);
8703           if (attribute_flag[4] != 0)
8704             QueryMagickColor(argument_list[4].string_reference,&target,
8705               exception);
8706           if (attribute_flag[3] != 0)
8707             target.alpha=SiPrefixToDouble(argument_list[3].string_reference,
8708               QuantumRange);
8709           if (attribute_flag[5] != 0)
8710             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
8711               QuantumRange);
8712           invert=MagickFalse;
8713           if (attribute_flag[6] != 0)
8714             invert=(MagickBooleanType) argument_list[6].integer_reference;
8715           SetPixelComponentMap(image,AlphaChannel);
8716           (void) FloodfillPaintImage(image,AlphaChannel,draw_info,&target,
8717             geometry.x,geometry.y,invert);
8718           StandardPixelComponentMap(image);
8719           draw_info=DestroyDrawInfo(draw_info);
8720           break;
8721         }
8722         case 43:  /* Modulate */
8723         {
8724           char
8725             modulate[MaxTextExtent];
8726
8727           geometry_info.rho=100.0;
8728           geometry_info.sigma=100.0;
8729           geometry_info.xi=100.0;
8730           if (attribute_flag[0] != 0)
8731             (void)ParseGeometry(argument_list[0].string_reference,
8732               &geometry_info);
8733           if (attribute_flag[1] != 0)
8734             geometry_info.xi=argument_list[1].real_reference;
8735           if (attribute_flag[2] != 0)
8736             geometry_info.sigma=argument_list[2].real_reference;
8737           if (attribute_flag[3] != 0)
8738             {
8739               geometry_info.sigma=argument_list[3].real_reference;
8740               SetImageArtifact(image,"modulate:colorspace","HWB");
8741             }
8742           if (attribute_flag[4] != 0)
8743             {
8744               geometry_info.rho=argument_list[4].real_reference;
8745               SetImageArtifact(image,"modulate:colorspace","HSB");
8746             }
8747           if (attribute_flag[5] != 0)
8748             {
8749               geometry_info.sigma=argument_list[5].real_reference;
8750               SetImageArtifact(image,"modulate:colorspace","HSL");
8751             }
8752           if (attribute_flag[6] != 0)
8753             {
8754               geometry_info.rho=argument_list[6].real_reference;
8755               SetImageArtifact(image,"modulate:colorspace","HWB");
8756             }
8757           (void) FormatLocaleString(modulate,MaxTextExtent,"%.15g,%.15g,%.15g",
8758             geometry_info.rho,geometry_info.sigma,geometry_info.xi);
8759           (void) ModulateImage(image,modulate);
8760           break;
8761         }
8762         case 44:  /* Negate */
8763         {
8764           if (attribute_flag[0] == 0)
8765             argument_list[0].integer_reference=0;
8766           if (attribute_flag[1] != 0)
8767             channel=(ChannelType) argument_list[1].integer_reference;
8768           (void) NegateImageChannel(image,channel,
8769             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse);
8770           break;
8771         }
8772         case 45:  /* Normalize */
8773         {
8774           if (attribute_flag[0] != 0)
8775             channel=(ChannelType) argument_list[0].integer_reference;
8776           NormalizeImageChannel(image,channel);
8777           break;
8778         }
8779         case 46:  /* NumberColors */
8780           break;
8781         case 47:  /* Opaque */
8782         {
8783           MagickBooleanType
8784             invert;
8785
8786           PixelInfo
8787             fill_color,
8788             target;
8789
8790           (void) QueryMagickColor("none",&target,exception);
8791           (void) QueryMagickColor("none",&fill_color,exception);
8792           if (attribute_flag[0] != 0)
8793             (void) QueryMagickColor(argument_list[0].string_reference,
8794               &target,exception);
8795           if (attribute_flag[1] != 0)
8796             (void) QueryMagickColor(argument_list[1].string_reference,
8797               &fill_color,exception);
8798           if (attribute_flag[2] != 0)
8799             image->fuzz=SiPrefixToDouble(argument_list[2].string_reference,
8800               QuantumRange);
8801           if (attribute_flag[3] != 0)
8802             channel=(ChannelType) argument_list[3].integer_reference;
8803           invert=MagickFalse;
8804           if (attribute_flag[4] != 0)
8805             invert=(MagickBooleanType) argument_list[4].integer_reference;
8806           (void) OpaquePaintImageChannel(image,channel,&target,&fill_color,
8807             invert);
8808           break;
8809         }
8810         case 48:  /* Quantize */
8811         {
8812           QuantizeInfo
8813             *quantize_info;
8814
8815           quantize_info=AcquireQuantizeInfo(info->image_info);
8816           if (attribute_flag[0] != 0)
8817             quantize_info->number_colors=(size_t)
8818               argument_list[0].integer_reference;
8819           if (attribute_flag[1] != 0)
8820             quantize_info->tree_depth=(size_t)
8821               argument_list[1].integer_reference;
8822           if (attribute_flag[2] != 0)
8823             quantize_info->colorspace=(ColorspaceType)
8824               argument_list[2].integer_reference;
8825           if (attribute_flag[3] != 0)
8826             quantize_info->dither=argument_list[3].integer_reference != 0 ?
8827               MagickTrue : MagickFalse;
8828           if (attribute_flag[4] != 0)
8829             quantize_info->measure_error=
8830               argument_list[4].integer_reference != 0 ? MagickTrue : MagickFalse;
8831           if (attribute_flag[5] != 0)
8832             (void) QueryColorDatabase(argument_list[5].string_reference,
8833               &image->transparent_color,exception);
8834           if (attribute_flag[5] && argument_list[5].integer_reference)
8835             {
8836               (void) QuantizeImages(quantize_info,image);
8837               goto PerlException;
8838             }
8839           if (attribute_flag[6] != 0)
8840             quantize_info->dither_method=(DitherMethod)
8841               argument_list[6].integer_reference;
8842           if ((image->storage_class == DirectClass) ||
8843               (image->colors > quantize_info->number_colors) ||
8844               (quantize_info->colorspace == GRAYColorspace))
8845             (void) QuantizeImage(quantize_info,image);
8846           else
8847             CompressImageColormap(image);
8848           quantize_info=DestroyQuantizeInfo(quantize_info);
8849           break;
8850         }
8851         case 49:  /* Raise */
8852         {
8853           if (attribute_flag[0] != 0)
8854             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8855               &geometry,exception);
8856           if (attribute_flag[1] != 0)
8857             geometry.width=argument_list[1].integer_reference;
8858           if (attribute_flag[2] != 0)
8859             geometry.height=argument_list[2].integer_reference;
8860           if (attribute_flag[3] == 0)
8861             argument_list[3].integer_reference=1;
8862           (void) RaiseImage(image,&geometry,argument_list[3].integer_reference !=
8863             0 ? MagickTrue : MagickFalse);
8864           break;
8865         }
8866         case 50:  /* Segment */
8867         {
8868           ColorspaceType
8869             colorspace;
8870
8871           double
8872             cluster_threshold,
8873             smoothing_threshold;
8874
8875           MagickBooleanType
8876             verbose;
8877
8878           cluster_threshold=1.0;
8879           smoothing_threshold=1.5;
8880           colorspace=RGBColorspace;
8881           verbose=MagickFalse;
8882           if (attribute_flag[0] != 0)
8883             {
8884               flags=ParseGeometry(argument_list[0].string_reference,
8885                 &geometry_info);
8886               cluster_threshold=geometry_info.rho;
8887               if (flags & SigmaValue)
8888                 smoothing_threshold=geometry_info.sigma;
8889             }
8890           if (attribute_flag[1] != 0)
8891             cluster_threshold=argument_list[1].real_reference;
8892           if (attribute_flag[2] != 0)
8893             smoothing_threshold=argument_list[2].real_reference;
8894           if (attribute_flag[3] != 0)
8895             colorspace=(ColorspaceType) argument_list[3].integer_reference;
8896           if (attribute_flag[4] != 0)
8897             verbose=argument_list[4].integer_reference != 0 ?
8898               MagickTrue : MagickFalse;
8899           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
8900             smoothing_threshold);
8901           break;
8902         }
8903         case 51:  /* Signature */
8904         {
8905           (void) SignatureImage(image);
8906           break;
8907         }
8908         case 52:  /* Solarize */
8909         {
8910           geometry_info.rho=QuantumRange/2.0;
8911           if (attribute_flag[0] != 0)
8912             flags=ParseGeometry(argument_list[0].string_reference,
8913               &geometry_info);
8914           if (attribute_flag[1] != 0)
8915             geometry_info.rho=SiPrefixToDouble(argument_list[1].string_reference,
8916              QuantumRange);
8917           (void) SolarizeImage(image,geometry_info.rho);
8918           break;
8919         }
8920         case 53:  /* Sync */
8921         {
8922           (void) SyncImage(image);
8923           break;
8924         }
8925         case 54:  /* Texture */
8926         {
8927           if (attribute_flag[0] == 0)
8928             break;
8929           TextureImage(image,argument_list[0].image_reference);
8930           break;
8931         }
8932         case 55:  /* Evalute */
8933         {
8934           MagickEvaluateOperator
8935             op;
8936
8937           op=SetEvaluateOperator;
8938           if (attribute_flag[0] == MagickFalse)
8939             argument_list[0].real_reference=0.0;
8940           if (attribute_flag[1] != MagickFalse)
8941             op=(MagickEvaluateOperator) argument_list[1].integer_reference;
8942           if (attribute_flag[2] != MagickFalse)
8943             channel=(ChannelType) argument_list[2].integer_reference;
8944           (void) EvaluateImageChannel(image,channel,op,
8945             argument_list[0].real_reference,exception);
8946           break;
8947         }
8948         case 56:  /* Transparent */
8949         {
8950           double
8951             opacity;
8952
8953           MagickBooleanType
8954             invert;
8955
8956           PixelInfo
8957             target;
8958
8959           (void) QueryMagickColor("none",&target,exception);
8960           if (attribute_flag[0] != 0)
8961             (void) QueryMagickColor(argument_list[0].string_reference,&target,
8962               exception);
8963           opacity=TransparentAlpha;
8964           if (attribute_flag[1] != 0)
8965             opacity=SiPrefixToDouble(argument_list[1].string_reference,
8966               QuantumRange);
8967           if (attribute_flag[2] != 0)
8968             image->fuzz=SiPrefixToDouble(argument_list[2].string_reference,
8969               QuantumRange);
8970           if (attribute_flag[3] == 0)
8971             argument_list[3].integer_reference=0;
8972           invert=MagickFalse;
8973           if (attribute_flag[3] != 0)
8974             invert=(MagickBooleanType) argument_list[3].integer_reference;
8975           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
8976             invert);
8977           break;
8978         }
8979         case 57:  /* Threshold */
8980         {
8981           double
8982             threshold;
8983
8984           if (attribute_flag[0] == 0)
8985             argument_list[0].string_reference="50%";
8986           if (attribute_flag[1] != 0)
8987             channel=(ChannelType) argument_list[1].integer_reference;
8988           threshold=SiPrefixToDouble(argument_list[0].string_reference,
8989             QuantumRange);
8990           (void) BilevelImageChannel(image,channel,threshold);
8991           break;
8992         }
8993         case 58:  /* Charcoal */
8994         {
8995           if (attribute_flag[0] != 0)
8996             {
8997               flags=ParseGeometry(argument_list[0].string_reference,
8998                 &geometry_info);
8999               if ((flags & SigmaValue) == 0)
9000                 geometry_info.sigma=1.0;
9001             }
9002           if (attribute_flag[1] != 0)
9003             geometry_info.rho=argument_list[1].real_reference;
9004           if (attribute_flag[2] != 0)
9005             geometry_info.sigma=argument_list[2].real_reference;
9006           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9007             exception);
9008           break;
9009         }
9010         case 59:  /* Trim */
9011         {
9012           if (attribute_flag[0] != 0)
9013             image->fuzz=SiPrefixToDouble(argument_list[0].string_reference,
9014               QuantumRange);
9015           image=TrimImage(image,exception);
9016           break;
9017         }
9018         case 60:  /* Wave */
9019         {
9020           if (attribute_flag[0] != 0)
9021             {
9022               flags=ParseGeometry(argument_list[0].string_reference,
9023                 &geometry_info);
9024               if ((flags & SigmaValue) == 0)
9025                 geometry_info.sigma=1.0;
9026             }
9027           if (attribute_flag[1] != 0)
9028             geometry_info.rho=argument_list[1].real_reference;
9029           if (attribute_flag[2] != 0)
9030             geometry_info.sigma=argument_list[2].real_reference;
9031           if (attribute_flag[3] != 0)
9032             image->interpolate=(InterpolatePixelMethod)
9033               argument_list[3].integer_reference;
9034           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9035             exception);
9036           break;
9037         }
9038         case 61:  /* Separate */
9039         {
9040           if (attribute_flag[0] != 0)
9041             channel=(ChannelType) argument_list[0].integer_reference;
9042           (void) SeparateImageChannel(image,channel);
9043           break;
9044         }
9045         case 63:  /* Stereo */
9046         {
9047           if (attribute_flag[0] == 0)
9048             {
9049               ThrowPerlException(exception,OptionError,"StereoImageRequired",
9050                 PackageName);
9051               goto PerlException;
9052             }
9053           if (attribute_flag[1] != 0)
9054             geometry.x=argument_list[1].integer_reference;
9055           if (attribute_flag[2] != 0)
9056             geometry.y=argument_list[2].integer_reference;
9057           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9058             geometry.x,geometry.y,exception);
9059           break;
9060         }
9061         case 64:  /* Stegano */
9062         {
9063           if (attribute_flag[0] == 0)
9064             {
9065               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9066                 PackageName);
9067               goto PerlException;
9068             }
9069           if (attribute_flag[1] == 0)
9070             argument_list[1].integer_reference=0;
9071           image->offset=argument_list[1].integer_reference;
9072           image=SteganoImage(image,argument_list[0].image_reference,exception);
9073           break;
9074         }
9075         case 65:  /* Deconstruct */
9076         {
9077           image=CompareImagesLayers(image,CompareAnyLayer,exception);
9078           break;
9079         }
9080         case 66:  /* GaussianBlur */
9081         {
9082           if (attribute_flag[0] != 0)
9083             {
9084               flags=ParseGeometry(argument_list[0].string_reference,
9085                 &geometry_info);
9086               if ((flags & SigmaValue) == 0)
9087                 geometry_info.sigma=1.0;
9088             }
9089           if (attribute_flag[1] != 0)
9090             geometry_info.rho=argument_list[1].real_reference;
9091           if (attribute_flag[2] != 0)
9092             geometry_info.sigma=argument_list[2].real_reference;
9093           if (attribute_flag[3] != 0)
9094             channel=(ChannelType) argument_list[3].integer_reference;
9095           image=GaussianBlurImageChannel(image,channel,geometry_info.rho,
9096             geometry_info.sigma,exception);
9097           break;
9098         }
9099         case 67:  /* Convolve */
9100         {
9101           AV
9102             *av;
9103
9104           double
9105             *kernel;
9106
9107           size_t
9108             order;
9109
9110           if (attribute_flag[0] == 0)
9111             break;
9112           if (attribute_flag[1] != 0)
9113             channel=(ChannelType) argument_list[1].integer_reference;
9114           if (attribute_flag[2] != 0)
9115             image->bias=SiPrefixToDouble(argument_list[2].string_reference,
9116               QuantumRange);
9117           av=(AV *) argument_list[0].array_reference;
9118           order=(size_t) sqrt(av_len(av)+1);
9119           kernel=(double *) AcquireQuantumMemory(order,order*sizeof(*kernel));
9120           if (kernel == (double *) NULL)
9121             {
9122               ThrowPerlException(exception,ResourceLimitFatalError,
9123                 "MemoryAllocationFailed",PackageName);
9124               goto PerlException;
9125             }
9126           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9127             kernel[j]=(double) SvNV(*(av_fetch(av,j,0)));
9128           for ( ; j < (ssize_t) (order*order); j++)
9129             kernel[j]=0.0;
9130           image=ConvolveImageChannel(image,channel,order,kernel,exception);
9131           kernel=(double *) RelinquishMagickMemory(kernel);
9132           break;
9133         }
9134         case 68:  /* Profile */
9135         {
9136           const char
9137             *name;
9138
9139           Image
9140             *profile_image;
9141
9142           ImageInfo
9143             *profile_info;
9144
9145           StringInfo
9146             *profile;
9147
9148           name="*";
9149           if (attribute_flag[0] != 0)
9150             name=argument_list[0].string_reference;
9151           if (attribute_flag[2] != 0)
9152             image->rendering_intent=(RenderingIntent)
9153               argument_list[2].integer_reference;
9154           if (attribute_flag[3] != 0)
9155             image->black_point_compensation=
9156               argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9157           if (attribute_flag[1] != 0)
9158             {
9159               if (argument_list[1].length == 0)
9160                 {
9161                   /*
9162                     Remove a profile from the image.
9163                   */
9164                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9165                     MagickTrue);
9166                   break;
9167                 }
9168               /*
9169                 Associate user supplied profile with the image.
9170               */
9171               profile=AcquireStringInfo(argument_list[1].length);
9172               SetStringInfoDatum(profile,(const unsigned char *)
9173                 argument_list[1].string_reference);
9174               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9175                 (size_t) GetStringInfoLength(profile),MagickFalse);
9176               profile=DestroyStringInfo(profile);
9177               break;
9178             }
9179           /*
9180             Associate a profile with the image.
9181           */
9182           profile_info=
9183             CloneImageInfo(info ? info->image_info : (ImageInfo *) NULL);
9184           (void) CopyMagickString(profile_info->filename,name,MaxTextExtent);
9185           profile_image=ReadImages(profile_info,&image->exception);
9186           if (profile_image == (Image *) NULL)
9187             break;
9188           ResetImageProfileIterator(profile_image);
9189           name=GetNextImageProfile(profile_image);
9190           while (name != (const char *) NULL)
9191           {
9192             const StringInfo
9193               *profile;
9194
9195             profile=GetImageProfile(profile_image,name);
9196             if (profile != (const StringInfo *) NULL)
9197               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9198                 (size_t) GetStringInfoLength(profile),MagickFalse);
9199             name=GetNextImageProfile(profile_image);
9200           }
9201           profile_image=DestroyImage(profile_image);
9202           profile_info=DestroyImageInfo(profile_info);
9203           break;
9204         }
9205         case 69:  /* UnsharpMask */
9206         {
9207           if (attribute_flag[0] != 0)
9208             {
9209               flags=ParseGeometry(argument_list[0].string_reference,
9210                 &geometry_info);
9211               if ((flags & SigmaValue) == 0)
9212                 geometry_info.sigma=1.0;
9213               if ((flags & XiValue) == 0)
9214                 geometry_info.xi=1.0;
9215               if ((flags & PsiValue) == 0)
9216                 geometry_info.psi=0.5;
9217             }
9218           if (attribute_flag[1] != 0)
9219             geometry_info.rho=argument_list[1].real_reference;
9220           if (attribute_flag[2] != 0)
9221             geometry_info.sigma=argument_list[2].real_reference;
9222           if (attribute_flag[3] != 0)
9223             geometry_info.xi=argument_list[3].real_reference;
9224           if (attribute_flag[4] != 0)
9225             geometry_info.psi=argument_list[4].real_reference;
9226           if (attribute_flag[5] != 0)
9227             channel=(ChannelType) argument_list[5].integer_reference;
9228           image=UnsharpMaskImageChannel(image,channel,geometry_info.rho,
9229             geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
9230           break;
9231         }
9232         case 70:  /* MotionBlur */
9233         {
9234           if (attribute_flag[0] != 0)
9235             {
9236               flags=ParseGeometry(argument_list[0].string_reference,
9237                 &geometry_info);
9238               if ((flags & SigmaValue) == 0)
9239                 geometry_info.sigma=1.0;
9240               if ((flags & XiValue) == 0)
9241                 geometry_info.xi=1.0;
9242             }
9243           if (attribute_flag[1] != 0)
9244             geometry_info.rho=argument_list[1].real_reference;
9245           if (attribute_flag[2] != 0)
9246             geometry_info.sigma=argument_list[2].real_reference;
9247           if (attribute_flag[3] != 0)
9248             geometry_info.xi=argument_list[3].real_reference;
9249           if (attribute_flag[4] != 0)
9250             channel=(ChannelType) argument_list[4].integer_reference;
9251           image=MotionBlurImageChannel(image,channel,geometry_info.rho,
9252             geometry_info.sigma,geometry_info.xi,exception);
9253           break;
9254         }
9255         case 71:  /* OrderedDither */
9256         {
9257           if (attribute_flag[0] == 0)
9258             argument_list[0].string_reference="o8x8";
9259           if (attribute_flag[1] != 0)
9260             channel=(ChannelType) argument_list[1].integer_reference;
9261           (void) OrderedPosterizeImageChannel(image,channel,
9262             argument_list[0].string_reference,exception);
9263           break;
9264         }
9265         case 72:  /* Shave */
9266         {
9267           if (attribute_flag[0] != 0)
9268             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9269               &geometry,exception);
9270           if (attribute_flag[1] != 0)
9271             geometry.width=argument_list[1].integer_reference;
9272           if (attribute_flag[2] != 0)
9273             geometry.height=argument_list[2].integer_reference;
9274           image=ShaveImage(image,&geometry,exception);
9275           break;
9276         }
9277         case 73:  /* Level */
9278         {
9279           double
9280             black_point,
9281             gamma,
9282             white_point;
9283
9284           black_point=0.0;
9285           white_point=(MagickRealType) image->columns*image->rows;
9286           gamma=1.0;
9287           if (attribute_flag[0] != 0)
9288             {
9289               flags=ParseGeometry(argument_list[0].string_reference,
9290                 &geometry_info);
9291               black_point=geometry_info.rho;
9292               if ((flags & SigmaValue) != 0)
9293                 white_point=geometry_info.sigma;
9294               if ((flags & XiValue) != 0)
9295                 gamma=geometry_info.xi;
9296               if ((flags & PercentValue) != 0)
9297                 {
9298                   black_point*=(double) (QuantumRange/100.0);
9299                   white_point*=(double) (QuantumRange/100.0);
9300                 }
9301               if ((flags & SigmaValue) == 0)
9302                 white_point=(double) QuantumRange-black_point;
9303             }
9304           if (attribute_flag[1] != 0)
9305             black_point=argument_list[1].real_reference;
9306           if (attribute_flag[2] != 0)
9307             white_point=argument_list[2].real_reference;
9308           if (attribute_flag[3] != 0)
9309             gamma=argument_list[3].real_reference;
9310           if (attribute_flag[4] != 0)
9311             {
9312               channel=(ChannelType) argument_list[4].integer_reference;
9313               SetPixelComponentMap(image,channel);
9314             }
9315           if (attribute_flag[5] != 0)
9316             {
9317               argument_list[0].real_reference=argument_list[5].real_reference;
9318               attribute_flag[0]=attribute_flag[5];
9319             }
9320           (void) LevelImage(image,black_point,white_point,gamma);
9321           break;
9322         }
9323         case 74:  /* Clip */
9324         {
9325           if (attribute_flag[0] == 0)
9326             argument_list[0].string_reference="#1";
9327           if (attribute_flag[1] == 0)
9328             argument_list[1].integer_reference=MagickTrue;
9329           (void) ClipImagePath(image,argument_list[0].string_reference,
9330             argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse);
9331           break;
9332         }
9333         case 75:  /* AffineTransform */
9334         {
9335           DrawInfo
9336             *draw_info;
9337
9338           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9339             (DrawInfo *) NULL);
9340           if (attribute_flag[0] != 0)
9341             {
9342               AV
9343                 *av;
9344
9345               av=(AV *) argument_list[0].array_reference;
9346               if ((av_len(av) != 3) && (av_len(av) != 5))
9347                 {
9348                   ThrowPerlException(exception,OptionError,
9349                     "affine matrix must have 4 or 6 elements",PackageName);
9350                   goto PerlException;
9351                 }
9352               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9353               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9354               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9355               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9356               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9357                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9358                 {
9359                   ThrowPerlException(exception,OptionError,
9360                     "affine matrix is singular",PackageName);
9361                    goto PerlException;
9362                 }
9363               if (av_len(av) == 5)
9364                 {
9365                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9366                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9367                 }
9368             }
9369           for (j=1; j < 6; j++)
9370           {
9371             if (attribute_flag[j] == 0)
9372               continue;
9373             value=argument_list[j].string_reference;
9374             angle=argument_list[j].real_reference;
9375             current=draw_info->affine;
9376             GetAffineMatrix(&affine);
9377             switch (j)
9378             {
9379               case 1:
9380               {
9381                 /*
9382                   Translate.
9383                 */
9384                 flags=ParseGeometry(value,&geometry_info);
9385                 affine.tx=geometry_info.xi;
9386                 affine.ty=geometry_info.psi;
9387                 if ((flags & PsiValue) == 0)
9388                   affine.ty=affine.tx;
9389                 break;
9390               }
9391               case 2:
9392               {
9393                 /*
9394                   Scale.
9395                 */
9396                 flags=ParseGeometry(value,&geometry_info);
9397                 affine.sx=geometry_info.rho;
9398                 affine.sy=geometry_info.sigma;
9399                 if ((flags & SigmaValue) == 0)
9400                   affine.sy=affine.sx;
9401                 break;
9402               }
9403               case 3:
9404               {
9405                 /*
9406                   Rotate.
9407                 */
9408                 if (angle == 0.0)
9409                   break;
9410                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9411                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9412                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9413                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9414                 break;
9415               }
9416               case 4:
9417               {
9418                 /*
9419                   SkewX.
9420                 */
9421                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9422                 break;
9423               }
9424               case 5:
9425               {
9426                 /*
9427                   SkewY.
9428                 */
9429                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9430                 break;
9431               }
9432             }
9433             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9434             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9435             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9436             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9437             draw_info->affine.tx=
9438               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9439             draw_info->affine.ty=
9440               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9441           }
9442           if (attribute_flag[6] != 0)
9443             image->interpolate=(InterpolatePixelMethod)
9444               argument_list[6].integer_reference;
9445           if (attribute_flag[7] != 0)
9446             QueryColorDatabase(argument_list[7].string_reference,
9447               &image->background_color,exception);
9448           image=AffineTransformImage(image,&draw_info->affine,exception);
9449           draw_info=DestroyDrawInfo(draw_info);
9450           break;
9451         }
9452         case 76:  /* Difference */
9453         {
9454           if (attribute_flag[0] == 0)
9455             {
9456               ThrowPerlException(exception,OptionError,
9457                 "ReferenceImageRequired",PackageName);
9458               goto PerlException;
9459             }
9460           if (attribute_flag[1] != 0)
9461             image->fuzz=SiPrefixToDouble(argument_list[1].string_reference,
9462               QuantumRange);
9463           (void) IsImagesEqual(image,argument_list[0].image_reference);
9464           break;
9465         }
9466         case 77:  /* AdaptiveThreshold */
9467         {
9468           if (attribute_flag[0] != 0)
9469             {
9470               flags=ParseGeometry(argument_list[0].string_reference,
9471                 &geometry_info);
9472               if ((flags & PercentValue) != 0)
9473                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9474             }
9475           if (attribute_flag[1] != 0)
9476             geometry_info.rho=argument_list[1].integer_reference;
9477           if (attribute_flag[2] != 0)
9478             geometry_info.sigma=argument_list[2].integer_reference;
9479           if (attribute_flag[3] != 0)
9480             geometry_info.xi=argument_list[3].integer_reference;;
9481           image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
9482             (size_t) geometry_info.sigma,(ssize_t) geometry_info.xi,
9483             exception);
9484           break;
9485         }
9486         case 78:  /* Resample */
9487         {
9488           size_t
9489             height,
9490             width;
9491
9492           if (attribute_flag[0] != 0)
9493             {
9494               flags=ParseGeometry(argument_list[0].string_reference,
9495                 &geometry_info);
9496               if ((flags & SigmaValue) == 0)
9497                 geometry_info.sigma=geometry_info.rho;
9498             }
9499           if (attribute_flag[1] != 0)
9500             geometry_info.rho=argument_list[1].real_reference;
9501           if (attribute_flag[2] != 0)
9502             geometry_info.sigma=argument_list[2].real_reference;
9503           if (attribute_flag[3] == 0)
9504             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
9505           if (attribute_flag[4] == 0)
9506             SetImageArtifact(image,"filter:support",
9507               argument_list[4].string_reference);
9508           if (attribute_flag[5] != 0)
9509             argument_list[5].real_reference=1.0;
9510           width=(size_t) (geometry_info.rho*image->columns/
9511             (image->x_resolution == 0.0 ? 72.0 : image->x_resolution)+0.5);
9512           height=(size_t) (geometry_info.sigma*image->rows/
9513             (image->y_resolution == 0.0 ? 72.0 : image->y_resolution)+0.5);
9514           image=ResizeImage(image,width,height,(FilterTypes)
9515             argument_list[3].integer_reference,argument_list[5].real_reference,
9516             exception);
9517           if (image != (Image *) NULL)
9518             {
9519               image->x_resolution=geometry_info.rho;
9520               image->y_resolution=geometry_info.sigma;
9521             }
9522           break;
9523         }
9524         case 79:  /* Describe */
9525         {
9526           if (attribute_flag[0] == 0)
9527             argument_list[0].file_reference=(FILE *) NULL;
9528           if (attribute_flag[1] != 0)
9529             (void) SetImageArtifact(image,"identify:features",
9530               argument_list[1].string_reference);
9531           (void) IdentifyImage(image,argument_list[0].file_reference,
9532             MagickTrue);
9533           break;
9534         }
9535         case 80:  /* BlackThreshold */
9536         {
9537           if (attribute_flag[0] == 0)
9538             argument_list[0].string_reference="50%";
9539           if (attribute_flag[2] != 0)
9540             channel=(ChannelType) argument_list[2].integer_reference;
9541           BlackThresholdImageChannel(image,channel,
9542             argument_list[0].string_reference,exception);
9543           break;
9544         }
9545         case 81:  /* WhiteThreshold */
9546         {
9547           if (attribute_flag[0] == 0)
9548             argument_list[0].string_reference="50%";
9549           if (attribute_flag[2] != 0)
9550             channel=(ChannelType) argument_list[2].integer_reference;
9551           WhiteThresholdImageChannel(image,channel,
9552             argument_list[0].string_reference,exception);
9553           break;
9554         }
9555         case 82:  /* RadialBlur */
9556         {
9557           if (attribute_flag[0] != 0)
9558             {
9559               flags=ParseGeometry(argument_list[0].string_reference,
9560                 &geometry_info);
9561               if ((flags & SigmaValue) == 0)
9562                 geometry_info.sigma=1.0;
9563             }
9564           if (attribute_flag[1] != 0)
9565             geometry_info.rho=argument_list[1].real_reference;
9566           if (attribute_flag[2] != 0)
9567             channel=(ChannelType) argument_list[2].integer_reference;
9568           image=RadialBlurImageChannel(image,channel,geometry_info.rho,
9569             exception);
9570           break;
9571         }
9572         case 83:  /* Thumbnail */
9573         {
9574           if (attribute_flag[0] != 0)
9575             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
9576               &geometry,exception);
9577           if (attribute_flag[1] != 0)
9578             geometry.width=argument_list[1].integer_reference;
9579           if (attribute_flag[2] != 0)
9580             geometry.height=argument_list[2].integer_reference;
9581           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
9582           break;
9583         }
9584         case 84:  /* Strip */
9585         {
9586           (void) StripImage(image);
9587           break;
9588         }
9589         case 85:  /* Tint */
9590         {
9591           PixelPacket
9592             target;
9593
9594           (void) GetOneVirtualPixel(image,0,0,&target,exception);
9595           if (attribute_flag[0] != 0)
9596             (void) QueryColorDatabase(argument_list[0].string_reference,&target,
9597               exception);
9598           if (attribute_flag[1] == 0)
9599             argument_list[1].string_reference="100";
9600           image=TintImage(image,argument_list[1].string_reference,target,
9601             exception);
9602           break;
9603         }
9604         case 86:  /* Channel */
9605         {
9606           if (attribute_flag[0] != 0)
9607             channel=(ChannelType) argument_list[0].integer_reference;
9608           (void) SeparateImageChannel(image,channel);
9609           break;
9610         }
9611         case 87:  /* Splice */
9612         {
9613           if (attribute_flag[0] != 0)
9614             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
9615               &geometry,exception);
9616           if (attribute_flag[1] != 0)
9617             geometry.width=argument_list[1].integer_reference;
9618           if (attribute_flag[2] != 0)
9619             geometry.height=argument_list[2].integer_reference;
9620           if (attribute_flag[3] != 0)
9621             geometry.x=argument_list[3].integer_reference;
9622           if (attribute_flag[4] != 0)
9623             geometry.y=argument_list[4].integer_reference;
9624           if (attribute_flag[5] != 0)
9625             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
9626               QuantumRange);
9627           if (attribute_flag[6] != 0)
9628             (void) QueryColorDatabase(argument_list[6].string_reference,
9629               &image->background_color,exception);
9630           if (attribute_flag[7] != 0)
9631             image->gravity=(GravityType) argument_list[7].integer_reference;
9632           image=SpliceImage(image,&geometry,exception);
9633           break;
9634         }
9635         case 88:  /* Posterize */
9636         {
9637           if (attribute_flag[0] == 0)
9638             argument_list[0].integer_reference=3;
9639           if (attribute_flag[1] == 0)
9640             argument_list[1].integer_reference=0;
9641           (void) PosterizeImage(image,argument_list[0].integer_reference,
9642             argument_list[1].integer_reference ? MagickTrue : MagickFalse);
9643           break;
9644         }
9645         case 89:  /* Shadow */
9646         {
9647           if (attribute_flag[0] != 0)
9648             {
9649               flags=ParseGeometry(argument_list[0].string_reference,
9650                 &geometry_info);
9651               if ((flags & SigmaValue) == 0)
9652                 geometry_info.sigma=1.0;
9653               if ((flags & XiValue) == 0)
9654                 geometry_info.xi=4.0;
9655               if ((flags & PsiValue) == 0)
9656                 geometry_info.psi=4.0;
9657             }
9658           if (attribute_flag[1] != 0)
9659             geometry_info.rho=argument_list[1].real_reference;
9660           if (attribute_flag[2] != 0)
9661             geometry_info.sigma=argument_list[2].real_reference;
9662           if (attribute_flag[3] != 0)
9663             geometry_info.xi=argument_list[3].integer_reference;
9664           if (attribute_flag[4] != 0)
9665             geometry_info.psi=argument_list[4].integer_reference;
9666           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
9667             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-
9668             0.5),exception);
9669           break;
9670         }
9671         case 90:  /* Identify */
9672         {
9673           if (attribute_flag[0] == 0)
9674             argument_list[0].file_reference=(FILE *) NULL;
9675           if (attribute_flag[1] != 0)
9676             (void) SetImageArtifact(image,"identify:features",
9677               argument_list[1].string_reference);
9678           if ((attribute_flag[2] != 0) &&
9679               (argument_list[2].integer_reference != 0))
9680             (void) SetImageArtifact(image,"identify:unique","true");
9681           (void) IdentifyImage(image,argument_list[0].file_reference,
9682             MagickTrue);
9683           break;
9684         }
9685         case 91:  /* SepiaTone */
9686         {
9687           if (attribute_flag[0] == 0)
9688             argument_list[0].real_reference=80.0*QuantumRange/100.0;
9689           image=SepiaToneImage(image,argument_list[0].real_reference,
9690             exception);
9691           break;
9692         }
9693         case 92:  /* SigmoidalContrast */
9694         {
9695           MagickBooleanType
9696             sharpen;
9697
9698           if (attribute_flag[0] != 0)
9699             {
9700               flags=ParseGeometry(argument_list[0].string_reference,
9701                 &geometry_info);
9702               if ((flags & SigmaValue) == 0)
9703                 geometry_info.sigma=QuantumRange/2.0;
9704               if ((flags & PercentValue) != 0)
9705                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
9706             }
9707           if (attribute_flag[1] != 0)
9708             geometry_info.rho=argument_list[1].real_reference;
9709           if (attribute_flag[2] != 0)
9710             geometry_info.sigma=argument_list[2].real_reference;
9711           if (attribute_flag[3] != 0)
9712             {
9713               channel=(ChannelType) argument_list[3].integer_reference;
9714               SetPixelComponentMap(image,channel);
9715             }
9716           sharpen=MagickTrue;
9717           if (attribute_flag[4] != 0)
9718             sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
9719               MagickFalse;
9720           (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
9721             geometry_info.sigma);
9722           break;
9723         }
9724         case 93:  /* Extent */
9725         {
9726           if (attribute_flag[7] != 0)
9727             image->gravity=(GravityType) argument_list[7].integer_reference;
9728           if (attribute_flag[0] != 0)
9729             {
9730               int
9731                 flags;
9732
9733               flags=ParseGravityGeometry(image,
9734                 argument_list[0].string_reference,&geometry,exception);
9735               (void) flags;
9736               if (geometry.width == 0)
9737                 geometry.width=image->columns;
9738               if (geometry.height == 0)
9739                 geometry.height=image->rows;
9740             }
9741           if (attribute_flag[1] != 0)
9742             geometry.width=argument_list[1].integer_reference;
9743           if (attribute_flag[2] != 0)
9744             geometry.height=argument_list[2].integer_reference;
9745           if (attribute_flag[3] != 0)
9746             geometry.x=argument_list[3].integer_reference;
9747           if (attribute_flag[4] != 0)
9748             geometry.y=argument_list[4].integer_reference;
9749           if (attribute_flag[5] != 0)
9750             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
9751               QuantumRange);
9752           if (attribute_flag[6] != 0)
9753             (void) QueryColorDatabase(argument_list[6].string_reference,
9754               &image->background_color,exception);
9755           image=ExtentImage(image,&geometry,exception);
9756           break;
9757         }
9758         case 94:  /* Vignette */
9759         {
9760           if (attribute_flag[0] != 0)
9761             {
9762               flags=ParseGeometry(argument_list[0].string_reference,
9763                 &geometry_info);
9764               if ((flags & SigmaValue) == 0)
9765                 geometry_info.sigma=1.0;
9766               if ((flags & XiValue) == 0)
9767                 geometry_info.xi=0.1*image->columns;
9768               if ((flags & PsiValue) == 0)
9769                 geometry_info.psi=0.1*image->rows;
9770             }
9771           if (attribute_flag[1] != 0)
9772             geometry_info.rho=argument_list[1].real_reference;
9773           if (attribute_flag[2] != 0)
9774             geometry_info.sigma=argument_list[2].real_reference;
9775           if (attribute_flag[3] != 0)
9776             geometry_info.xi=argument_list[3].integer_reference;
9777           if (attribute_flag[4] != 0)
9778             geometry_info.psi=argument_list[4].integer_reference;
9779           if (attribute_flag[5] != 0)
9780             (void) QueryColorDatabase(argument_list[5].string_reference,
9781               &image->background_color,exception);
9782           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
9783             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-
9784             0.5),exception);
9785           break;
9786         }
9787         case 95:  /* ContrastStretch */
9788         {
9789           double
9790             black_point,
9791             white_point;
9792
9793           black_point=0.0;
9794           white_point=(MagickRealType) image->columns*image->rows;
9795           if (attribute_flag[0] != 0)
9796             {
9797               flags=ParseGeometry(argument_list[0].string_reference,
9798                 &geometry_info);
9799               black_point=geometry_info.rho;
9800               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
9801                 black_point;
9802               if ((flags & PercentValue) != 0)
9803                 {
9804                   black_point*=(double) image->columns*image->rows/100.0;
9805                   white_point*=(double) image->columns*image->rows/100.0;
9806                 }
9807               white_point=(MagickRealType) image->columns*image->rows-
9808                 white_point;
9809             }
9810           if (attribute_flag[1] != 0)
9811             black_point=argument_list[1].real_reference;
9812           if (attribute_flag[2] != 0)
9813             white_point=argument_list[2].real_reference;
9814           if (attribute_flag[4] != 0)
9815             channel=(ChannelType) argument_list[4].integer_reference;
9816           (void) ContrastStretchImageChannel(image,channel,black_point,
9817             white_point);
9818           break;
9819         }
9820         case 96:  /* Sans0 */
9821         {
9822           break;
9823         }
9824         case 97:  /* Sans1 */
9825         {
9826           break;
9827         }
9828         case 98:  /* AdaptiveSharpen */
9829         {
9830           if (attribute_flag[0] != 0)
9831             {
9832               flags=ParseGeometry(argument_list[0].string_reference,
9833                 &geometry_info);
9834               if ((flags & SigmaValue) == 0)
9835                 geometry_info.sigma=1.0;
9836             }
9837           if (attribute_flag[1] != 0)
9838             geometry_info.rho=argument_list[1].real_reference;
9839           if (attribute_flag[2] != 0)
9840             geometry_info.sigma=argument_list[2].real_reference;
9841           if (attribute_flag[3] != 0)
9842             channel=(ChannelType) argument_list[3].integer_reference;
9843           image=AdaptiveSharpenImageChannel(image,channel,geometry_info.rho,
9844             geometry_info.sigma,exception);
9845           break;
9846         }
9847         case 99:  /* Transpose */
9848         {
9849           image=TransposeImage(image,exception);
9850           break;
9851         }
9852         case 100:  /* Tranverse */
9853         {
9854           image=TransverseImage(image,exception);
9855           break;
9856         }
9857         case 101:  /* AutoOrient */
9858         {
9859           switch (image->orientation)
9860           {
9861             case TopRightOrientation:
9862             {
9863               image=FlopImage(image,exception);
9864               break;
9865             }
9866             case BottomRightOrientation:
9867             {
9868               image=RotateImage(image,180.0,exception);
9869               break;
9870             }
9871             case BottomLeftOrientation:
9872             {
9873               image=FlipImage(image,exception);
9874               break;
9875             }
9876             case LeftTopOrientation:
9877             {
9878               image=TransposeImage(image,exception);
9879               break;
9880             }
9881             case RightTopOrientation:
9882             {
9883               image=RotateImage(image,90.0,exception);
9884               break;
9885             }
9886             case RightBottomOrientation:
9887             {
9888               image=TransverseImage(image,exception);
9889               break;
9890             }
9891             case LeftBottomOrientation:
9892             {
9893               image=RotateImage(image,270.0,exception);
9894               break;
9895             }
9896             default:
9897               break;
9898           }
9899           break;
9900         }
9901         case 102:  /* AdaptiveBlur */
9902         {
9903           if (attribute_flag[0] != 0)
9904             {
9905               flags=ParseGeometry(argument_list[0].string_reference,
9906                 &geometry_info);
9907               if ((flags & SigmaValue) == 0)
9908                 geometry_info.sigma=1.0;
9909             }
9910           if (attribute_flag[1] != 0)
9911             geometry_info.rho=argument_list[1].real_reference;
9912           if (attribute_flag[2] != 0)
9913             geometry_info.sigma=argument_list[2].real_reference;
9914           if (attribute_flag[3] != 0)
9915             channel=(ChannelType) argument_list[3].integer_reference;
9916           image=AdaptiveBlurImageChannel(image,channel,geometry_info.rho,
9917             geometry_info.sigma,exception);
9918           break;
9919         }
9920         case 103:  /* Sketch */
9921         {
9922           if (attribute_flag[0] != 0)
9923             {
9924               flags=ParseGeometry(argument_list[0].string_reference,
9925                 &geometry_info);
9926               if ((flags & SigmaValue) == 0)
9927                 geometry_info.sigma=1.0;
9928               if ((flags & XiValue) == 0)
9929                 geometry_info.xi=1.0;
9930             }
9931           if (attribute_flag[1] != 0)
9932             geometry_info.rho=argument_list[1].real_reference;
9933           if (attribute_flag[2] != 0)
9934             geometry_info.sigma=argument_list[2].real_reference;
9935           if (attribute_flag[3] != 0)
9936             geometry_info.xi=argument_list[3].real_reference;
9937           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
9938             geometry_info.xi,exception);
9939           break;
9940         }
9941         case 104:  /* UniqueColors */
9942         {
9943           image=UniqueImageColors(image,exception);
9944           break;
9945         }
9946         case 105:  /* AdaptiveResize */
9947         {
9948           if (attribute_flag[0] != 0)
9949             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
9950               &geometry,exception);
9951           if (attribute_flag[1] != 0)
9952             geometry.width=argument_list[1].integer_reference;
9953           if (attribute_flag[2] != 0)
9954             geometry.height=argument_list[2].integer_reference;
9955           if (attribute_flag[3] != 0)
9956             image->filter=(FilterTypes) argument_list[4].integer_reference;
9957           if (attribute_flag[4] != 0)
9958             SetImageArtifact(image,"filter:support",
9959               argument_list[4].string_reference);
9960           if (attribute_flag[5] != 0)
9961             image->blur=argument_list[5].real_reference;
9962           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
9963             exception);
9964           break;
9965         }
9966         case 106:  /* ClipMask */
9967         {
9968           if (attribute_flag[0] == 0)
9969             {
9970               ThrowPerlException(exception,OptionError,"MaskImageRequired",
9971                 PackageName);
9972               goto PerlException;
9973             }
9974           image->clip_mask=CloneImage(argument_list[0].image_reference,0,0,
9975             MagickTrue,exception);
9976           (void) NegateImage(image->clip_mask,MagickFalse);
9977           break;
9978         }
9979         case 107:  /* LinearStretch */
9980         {
9981            double
9982              black_point,
9983              white_point;
9984
9985            black_point=0.0;
9986            white_point=(MagickRealType) image->columns*image->rows;
9987            if (attribute_flag[0] != 0)
9988              {
9989                flags=ParseGeometry(argument_list[0].string_reference,
9990                  &geometry_info);
9991                if ((flags & SigmaValue) != 0)
9992                   white_point=geometry_info.sigma;
9993                if ((flags & PercentValue) != 0)
9994                  {
9995                    black_point*=(double) image->columns*image->rows/100.0;
9996                    white_point*=(double) image->columns*image->rows/100.0;
9997                  }
9998                if ((flags & SigmaValue) == 0)
9999                  white_point=(double) image->columns*image->rows-black_point;
10000              }
10001           if (attribute_flag[1] != 0)
10002             black_point=argument_list[1].real_reference;
10003           if (attribute_flag[2] != 0)
10004             white_point=argument_list[2].real_reference;
10005           (void) LinearStretchImage(image,black_point,white_point);
10006           break;
10007         }
10008         case 109:  /* Mask */
10009         {
10010           if (attribute_flag[0] == 0)
10011             {
10012               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10013                 PackageName);
10014               goto PerlException;
10015             }
10016           image->mask=CloneImage(argument_list[0].image_reference,0,0,
10017             MagickTrue,exception);
10018           (void) NegateImage(image->mask,MagickFalse);
10019           break;
10020         }
10021         case 110:  /* Polaroid */
10022         {
10023           DrawInfo
10024             *draw_info;
10025
10026           double
10027             angle;
10028
10029           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10030             (DrawInfo *) NULL);
10031           if (attribute_flag[0] != 0)
10032             (void) SetImageProperty(image,"caption",InterpretImageProperties(
10033               info ? info->image_info : (ImageInfo *) NULL,image,
10034               argument_list[0].string_reference));
10035           angle=0.0;
10036           if (attribute_flag[1] != 0)
10037             angle=argument_list[1].real_reference;
10038           if (attribute_flag[2] != 0)
10039             (void) CloneString(&draw_info->font,
10040               argument_list[2].string_reference);
10041           if (attribute_flag[3] != 0)
10042             (void) QueryColorDatabase(argument_list[3].string_reference,
10043               &draw_info->stroke,exception);
10044           if (attribute_flag[4] != 0)
10045             (void) QueryColorDatabase(argument_list[4].string_reference,
10046               &draw_info->fill,exception);
10047           if (attribute_flag[5] != 0)
10048             draw_info->stroke_width=argument_list[5].real_reference;
10049           if (attribute_flag[6] != 0)
10050             draw_info->pointsize=argument_list[6].real_reference;
10051           if (attribute_flag[7] != 0)
10052             draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10053           if (attribute_flag[8] != 0)
10054             (void) QueryColorDatabase(argument_list[8].string_reference,
10055               &image->background_color,exception);
10056           image=PolaroidImage(image,draw_info,angle,exception);
10057           draw_info=DestroyDrawInfo(draw_info);
10058           break;
10059         }
10060         case 111:  /* FloodfillPaint */
10061         {
10062           DrawInfo
10063             *draw_info;
10064
10065           MagickBooleanType
10066             invert;
10067
10068           PixelInfo
10069             target;
10070
10071           draw_info=CloneDrawInfo(info ? info->image_info :
10072             (ImageInfo *) NULL,(DrawInfo *) NULL);
10073           if (attribute_flag[0] != 0)
10074             flags=ParsePageGeometry(image,argument_list[0].string_reference,
10075               &geometry,exception);
10076           if (attribute_flag[1] != 0)
10077             geometry.x=argument_list[1].integer_reference;
10078           if (attribute_flag[2] != 0)
10079             geometry.y=argument_list[2].integer_reference;
10080           if (attribute_flag[3] != 0)
10081             (void) QueryColorDatabase(argument_list[3].string_reference,
10082               &draw_info->fill,exception);
10083           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
10084             exception);
10085           if (attribute_flag[4] != 0)
10086             QueryMagickColor(argument_list[4].string_reference,&target,
10087               exception);
10088           if (attribute_flag[5] != 0)
10089             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
10090               QuantumRange);
10091           if (attribute_flag[6] != 0)
10092             channel=(ChannelType) argument_list[6].integer_reference;
10093           invert=MagickFalse;
10094           if (attribute_flag[7] != 0)
10095             invert=(MagickBooleanType) argument_list[7].integer_reference;
10096           (void) FloodfillPaintImage(image,channel,draw_info,&target,geometry.x,
10097             geometry.y,invert);
10098           draw_info=DestroyDrawInfo(draw_info);
10099           break;
10100         }
10101         case 112:  /* Distort */
10102         {
10103           AV
10104             *av;
10105
10106           double
10107             *coordinates;
10108
10109           DistortImageMethod
10110             method;
10111
10112           size_t
10113             number_coordinates;
10114
10115           VirtualPixelMethod
10116             virtual_pixel;
10117
10118           if (attribute_flag[0] == 0)
10119             break;
10120           method=UndefinedDistortion;
10121           if (attribute_flag[1] != 0)
10122             method=(DistortImageMethod) argument_list[1].integer_reference;
10123           av=(AV *) argument_list[0].array_reference;
10124           number_coordinates=(size_t) av_len(av)+1;
10125           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10126             sizeof(*coordinates));
10127           if (coordinates == (double *) NULL)
10128             {
10129               ThrowPerlException(exception,ResourceLimitFatalError,
10130                 "MemoryAllocationFailed",PackageName);
10131               goto PerlException;
10132             }
10133           for (j=0; j < (ssize_t) number_coordinates; j++)
10134             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10135           virtual_pixel=UndefinedVirtualPixelMethod;
10136           if (attribute_flag[2] != 0)
10137             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10138               argument_list[2].integer_reference);
10139           image=DistortImage(image,method,number_coordinates,coordinates,
10140             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10141             exception);
10142           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10143             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10144           coordinates=(double *) RelinquishMagickMemory(coordinates);
10145           break;
10146         }
10147         case 113:  /* Clut */
10148         {
10149           if (attribute_flag[0] == 0)
10150             {
10151               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10152                 PackageName);
10153               goto PerlException;
10154             }
10155           if (attribute_flag[1] != 0)
10156             channel=(ChannelType) argument_list[1].integer_reference;
10157           (void) ClutImage(image,channel,
10158             argument_list[0].image_reference);
10159           break;
10160         }
10161         case 114:  /* LiquidRescale */
10162         {
10163           if (attribute_flag[0] != 0)
10164             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10165               &geometry,exception);
10166           if (attribute_flag[1] != 0)
10167             geometry.width=argument_list[1].integer_reference;
10168           if (attribute_flag[2] != 0)
10169             geometry.height=argument_list[2].integer_reference;
10170           if (attribute_flag[3] == 0)
10171             argument_list[3].real_reference=1.0;
10172           if (attribute_flag[4] == 0)
10173             argument_list[4].real_reference=0.0;
10174           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10175             argument_list[3].real_reference,argument_list[4].real_reference,
10176             exception);
10177           break;
10178         }
10179         case 115:  /* EncipherImage */
10180         {
10181           (void) EncipherImage(image,argument_list[0].string_reference,
10182             exception);
10183           break;
10184         }
10185         case 116:  /* DecipherImage */
10186         {
10187           (void) DecipherImage(image,argument_list[0].string_reference,
10188             exception);
10189           break;
10190         }
10191         case 117:  /* Deskew */
10192         {
10193           geometry_info.rho=QuantumRange/2.0;
10194           if (attribute_flag[0] != 0)
10195             flags=ParseGeometry(argument_list[0].string_reference,
10196               &geometry_info);
10197           if (attribute_flag[1] != 0)
10198             geometry_info.rho=SiPrefixToDouble(
10199               argument_list[1].string_reference,QuantumRange);
10200           image=DeskewImage(image,geometry_info.rho,exception);
10201           break;
10202         }
10203         case 118:  /* Remap */
10204         {
10205           QuantizeInfo
10206             *quantize_info;
10207
10208           if (attribute_flag[0] == 0)
10209             {
10210               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10211                 PackageName);
10212               goto PerlException;
10213             }
10214           quantize_info=AcquireQuantizeInfo(info->image_info);
10215           if (attribute_flag[1] != 0)
10216             quantize_info->dither=(MagickBooleanType)
10217               argument_list[1].integer_reference;
10218           if (attribute_flag[2] != 0)
10219             quantize_info->dither_method=(DitherMethod)
10220               argument_list[2].integer_reference;
10221           (void) RemapImages(quantize_info,image,
10222             argument_list[0].image_reference);
10223           quantize_info=DestroyQuantizeInfo(quantize_info);
10224           break;
10225         }
10226         case 119:  /* SparseColor */
10227         {
10228           AV
10229             *av;
10230
10231           double
10232             *coordinates;
10233
10234           SparseColorMethod
10235             method;
10236
10237           size_t
10238             number_coordinates;
10239
10240           VirtualPixelMethod
10241             virtual_pixel;
10242
10243           if (attribute_flag[0] == 0)
10244             break;
10245           method=UndefinedColorInterpolate;
10246           if (attribute_flag[1] != 0)
10247             method=(SparseColorMethod) argument_list[1].integer_reference;
10248           av=(AV *) argument_list[0].array_reference;
10249           number_coordinates=(size_t) av_len(av)+1;
10250           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10251             sizeof(*coordinates));
10252           if (coordinates == (double *) NULL)
10253             {
10254               ThrowPerlException(exception,ResourceLimitFatalError,
10255                 "MemoryAllocationFailed",PackageName);
10256               goto PerlException;
10257             }
10258           for (j=0; j < (ssize_t) number_coordinates; j++)
10259             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10260           virtual_pixel=UndefinedVirtualPixelMethod;
10261           if (attribute_flag[2] != 0)
10262             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10263               argument_list[2].integer_reference);
10264           if (attribute_flag[3] != 0)
10265             channel=(ChannelType) argument_list[3].integer_reference;
10266           image=SparseColorImage(image,channel,method,number_coordinates,
10267             coordinates,exception);
10268           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10269             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10270           coordinates=(double *) RelinquishMagickMemory(coordinates);
10271           break;
10272         }
10273         case 120:  /* Function */
10274         {
10275           AV
10276             *av;
10277
10278           double
10279             *parameters;
10280
10281           MagickFunction
10282             function;
10283
10284           size_t
10285             number_parameters;
10286
10287           VirtualPixelMethod
10288             virtual_pixel;
10289
10290           if (attribute_flag[0] == 0)
10291             break;
10292           function=UndefinedFunction;
10293           if (attribute_flag[1] != 0)
10294             function=(MagickFunction) argument_list[1].integer_reference;
10295           av=(AV *) argument_list[0].array_reference;
10296           number_parameters=(size_t) av_len(av)+1;
10297           parameters=(double *) AcquireQuantumMemory(number_parameters,
10298             sizeof(*parameters));
10299           if (parameters == (double *) NULL)
10300             {
10301               ThrowPerlException(exception,ResourceLimitFatalError,
10302                 "MemoryAllocationFailed",PackageName);
10303               goto PerlException;
10304             }
10305           for (j=0; j < (ssize_t) number_parameters; j++)
10306             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10307           virtual_pixel=UndefinedVirtualPixelMethod;
10308           if (attribute_flag[2] != 0)
10309             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10310               argument_list[2].integer_reference);
10311           (void) FunctionImage(image,function,number_parameters,parameters,
10312             exception);
10313           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10314             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10315           parameters=(double *) RelinquishMagickMemory(parameters);
10316           break;
10317         }
10318         case 121:  /* SelectiveBlur */
10319         {
10320           if (attribute_flag[0] != 0)
10321             {
10322               flags=ParseGeometry(argument_list[0].string_reference,
10323                 &geometry_info);
10324               if ((flags & SigmaValue) == 0)
10325                 geometry_info.sigma=1.0;
10326               if ((flags & PercentValue) != 0)
10327                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10328             }
10329           if (attribute_flag[1] != 0)
10330             geometry_info.rho=argument_list[1].real_reference;
10331           if (attribute_flag[2] != 0)
10332             geometry_info.sigma=argument_list[2].real_reference;
10333           if (attribute_flag[3] != 0)
10334             geometry_info.xi=argument_list[3].integer_reference;;
10335           if (attribute_flag[4] != 0)
10336             channel=(ChannelType) argument_list[4].integer_reference;
10337           image=SelectiveBlurImageChannel(image,channel,geometry_info.rho,
10338             geometry_info.sigma,geometry_info.xi,exception);
10339           break;
10340         }
10341         case 122:  /* HaldClut */
10342         {
10343           if (attribute_flag[0] == 0)
10344             {
10345               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10346                 PackageName);
10347               goto PerlException;
10348             }
10349           if (attribute_flag[1] != 0)
10350             {
10351               channel=(ChannelType) argument_list[1].integer_reference;
10352               SetPixelComponentMap(image,channel);
10353             }
10354           (void) HaldClutImage(image,argument_list[0].image_reference);
10355           break;
10356         }
10357         case 123:  /* BlueShift */
10358         {
10359           if (attribute_flag[0] != 0)
10360             (void) ParseGeometry(argument_list[0].string_reference,
10361               &geometry_info);
10362           image=BlueShiftImage(image,geometry_info.rho,exception);
10363           break;
10364         }
10365         case 124:  /* ForwardFourierTransformImage */
10366         {
10367           image=ForwardFourierTransformImage(image,
10368             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10369             exception);
10370           break;
10371         }
10372         case 125:  /* InverseFourierTransformImage */
10373         {
10374           image=InverseFourierTransformImage(image,image->next,
10375             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10376             exception);
10377           break;
10378         }
10379         case 126:  /* ColorDecisionList */
10380         {
10381           if (attribute_flag[0] == 0)
10382             argument_list[0].string_reference=(char *) NULL;
10383           (void) ColorDecisionListImage(image,
10384             argument_list[0].string_reference);
10385           break;
10386         }
10387         case 127:  /* AutoGamma */
10388         {
10389           if (attribute_flag[0] != 0)
10390             {
10391               channel=(ChannelType) argument_list[0].integer_reference;
10392               SetPixelComponentMap(image,channel);
10393             }
10394           (void) AutoGammaImage(image);
10395           break;
10396         }
10397         case 128:  /* AutoLevel */
10398         {
10399           if (attribute_flag[0] != 0)
10400             {
10401               channel=(ChannelType) argument_list[0].integer_reference;
10402               SetPixelComponentMap(image,channel);
10403             }
10404           (void) AutoLevelImage(image);
10405           break;
10406         }
10407         case 129:  /* LevelColors */
10408         {
10409           PixelInfo
10410             black_point,
10411             white_point;
10412
10413           (void) QueryMagickColor("#000000",&black_point,exception);
10414           (void) QueryMagickColor("#ffffff",&white_point,exception);
10415           if (attribute_flag[1] != 0)
10416              (void) QueryMagickColor(argument_list[1].string_reference,
10417                &black_point,exception);
10418           if (attribute_flag[2] != 0)
10419              (void) QueryMagickColor(argument_list[2].string_reference,
10420                &white_point,exception);
10421           if (attribute_flag[3] != 0)
10422             channel=(ChannelType) argument_list[3].integer_reference;
10423           (void) LevelColorsImageChannel(image,channel,&black_point,
10424             &white_point,argument_list[0].integer_reference != 0 ? MagickTrue :
10425             MagickFalse);
10426           break;
10427         }
10428         case 130:  /* Clamp */
10429         {
10430           if (attribute_flag[0] != 0)
10431             channel=(ChannelType) argument_list[0].integer_reference;
10432           (void) ClampImageChannel(image,channel);
10433           break;
10434         }
10435         case 131:  /* Filter */
10436         {
10437           KernelInfo
10438             *kernel;
10439
10440           if (attribute_flag[0] == 0)
10441             break;
10442           kernel=AcquireKernelInfo(argument_list[0].string_reference);
10443           if (kernel == (KernelInfo *) NULL)
10444             break;
10445           if (attribute_flag[1] != 0)
10446             channel=(ChannelType) argument_list[1].integer_reference;
10447           if (attribute_flag[2] != 0)
10448             image->bias=SiPrefixToDouble(argument_list[2].string_reference,
10449               QuantumRange);
10450           image=FilterImageChannel(image,channel,kernel,exception);
10451           kernel=DestroyKernelInfo(kernel);
10452           break;
10453         }
10454         case 132:  /* BrightnessContrast */
10455         {
10456           double
10457             brightness,
10458             contrast;
10459
10460           brightness=0.0;
10461           contrast=0.0;
10462           if (attribute_flag[0] != 0)
10463             {
10464               flags=ParseGeometry(argument_list[0].string_reference,
10465                 &geometry_info);
10466               brightness=geometry_info.rho;
10467               if ((flags & SigmaValue) == 0)
10468                 contrast=geometry_info.sigma;
10469             }
10470           if (attribute_flag[1] != 0)
10471             brightness=argument_list[1].real_reference;
10472           if (attribute_flag[2] != 0)
10473             contrast=argument_list[2].real_reference;
10474           if (attribute_flag[4] != 0)
10475             {
10476               channel=(ChannelType) argument_list[4].integer_reference;
10477               SetPixelComponentMap(image,channel);
10478             }
10479           (void) BrightnessContrastImage(image,brightness,contrast);
10480           break;
10481         }
10482         case 133:  /* Morphology */
10483         {
10484           KernelInfo
10485             *kernel;
10486
10487           MorphologyMethod
10488             method;
10489
10490           ssize_t
10491             iterations;
10492
10493           if (attribute_flag[0] == 0)
10494             break;
10495           kernel=AcquireKernelInfo(argument_list[0].string_reference);
10496           if (kernel == (KernelInfo *) NULL)
10497             break;
10498           if (attribute_flag[1] != 0)
10499             channel=(ChannelType) argument_list[1].integer_reference;
10500           method=UndefinedMorphology;
10501           if (attribute_flag[2] != 0)
10502             method=argument_list[2].integer_reference;
10503           iterations=1;
10504           if (attribute_flag[3] != 0)
10505             iterations=argument_list[4].integer_reference;
10506           image=MorphologyImageChannel(image,channel,method,iterations,kernel,
10507             exception);
10508           kernel=DestroyKernelInfo(kernel);
10509           break;
10510         }
10511         case 108:  /* Recolor */
10512         case 134:  /* ColorMatrix */
10513         {
10514           AV
10515             *av;
10516
10517           double
10518             *color_matrix;
10519
10520           KernelInfo
10521             *kernel_info;
10522
10523           size_t
10524             order;
10525
10526           if (attribute_flag[0] == 0)
10527             break;
10528           av=(AV *) argument_list[0].array_reference;
10529           order=(size_t) sqrt(av_len(av)+1);
10530           color_matrix=(double *) AcquireQuantumMemory(order,order*
10531             sizeof(*color_matrix));
10532           if (color_matrix == (double *) NULL)
10533             {
10534               ThrowPerlException(exception,ResourceLimitFatalError,
10535                 "MemoryAllocationFailed",PackageName);
10536               goto PerlException;
10537            }
10538           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10539             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10540           for ( ; j < (ssize_t) (order*order); j++)
10541             color_matrix[j]=0.0;
10542           kernel_info=AcquireKernelInfo("1");
10543           if (kernel_info == (KernelInfo *) NULL)
10544             break;
10545           kernel_info->width=order;
10546           kernel_info->height=order;
10547           kernel_info->values=color_matrix;
10548           image=ColorMatrixImage(image,kernel_info,exception);
10549           kernel_info->values=(double *) NULL;
10550           kernel_info=DestroyKernelInfo(kernel_info);
10551           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10552           break;
10553         }
10554         case 135:  /* Color */
10555         {
10556           PixelInfo
10557             color;
10558
10559           (void) QueryMagickColor("none",&color,exception);
10560           if (attribute_flag[0] != 0)
10561             (void) QueryMagickColor(argument_list[0].string_reference,
10562               &color,exception);
10563           (void) SetImageColor(image,&color);
10564           break;
10565         }
10566         case 136:  /* Mode */
10567         {
10568           if (attribute_flag[0] != 0)
10569             {
10570               flags=ParseGeometry(argument_list[0].string_reference,
10571                 &geometry_info);
10572               if ((flags & SigmaValue) == 0)
10573                 geometry_info.sigma=1.0;
10574             }
10575           if (attribute_flag[1] != 0)
10576             geometry_info.rho=argument_list[1].real_reference;
10577           if (attribute_flag[2] != 0)
10578             geometry_info.sigma=argument_list[2].real_reference;
10579           if (attribute_flag[3] != 0)
10580             channel=(ChannelType) argument_list[3].integer_reference;
10581           image=StatisticImageChannel(image,channel,ModeStatistic,
10582             (size_t) geometry_info.rho,(size_t) geometry_info.sigma,exception);
10583           break;
10584         }
10585         case 137:  /* Statistic */
10586         {
10587           StatisticType
10588             statistic;
10589
10590           statistic=UndefinedStatistic;
10591           if (attribute_flag[0] != 0)
10592             {
10593               flags=ParseGeometry(argument_list[0].string_reference,
10594                 &geometry_info);
10595               if ((flags & SigmaValue) == 0)
10596                 geometry_info.sigma=1.0;
10597             }
10598           if (attribute_flag[1] != 0)
10599             geometry_info.rho=argument_list[1].real_reference;
10600           if (attribute_flag[2] != 0)
10601             geometry_info.sigma=argument_list[2].real_reference;
10602           if (attribute_flag[3] != 0)
10603             channel=(ChannelType) argument_list[3].integer_reference;
10604           if (attribute_flag[4] != 0)
10605             statistic=(StatisticType) argument_list[4].integer_reference;
10606           image=StatisticImageChannel(image,channel,statistic,
10607             (size_t) geometry_info.rho,(size_t) geometry_info.sigma,exception);
10608           break;
10609         }
10610       }
10611       if (next != (Image *) NULL)
10612         (void) CatchImageException(next);
10613       if (region_image != (Image *) NULL)
10614         {
10615           /*
10616             Composite region.
10617           */
10618           status=CompositeImage(region_image,CopyCompositeOp,image,
10619             region_info.x,region_info.y);
10620           (void) status;
10621           (void) CatchImageException(region_image);
10622           image=DestroyImage(image);
10623           image=region_image;
10624         }
10625       if (image != (Image *) NULL)
10626         {
10627           number_images++;
10628           if (next && (next != image))
10629             {
10630               image->next=next->next;
10631               DeleteImageFromRegistry(*pv,next);
10632             }
10633           sv_setiv(*pv,(IV) image);
10634           next=image;
10635         }
10636       if (*pv)
10637         pv++;
10638     }
10639
10640   PerlException:
10641     if (reference_vector)
10642       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
10643     InheritPerlException(exception,perl_exception);
10644     exception=DestroyExceptionInfo(exception);
10645     sv_setiv(perl_exception,(IV) number_images);
10646     SvPOK_on(perl_exception);
10647     ST(0)=sv_2mortal(perl_exception);
10648     XSRETURN(1);
10649   }
10650 \f
10651 #
10652 ###############################################################################
10653 #                                                                             #
10654 #                                                                             #
10655 #                                                                             #
10656 #   M o n t a g e                                                             #
10657 #                                                                             #
10658 #                                                                             #
10659 #                                                                             #
10660 ###############################################################################
10661 #
10662 #
10663 void
10664 Montage(ref,...)
10665   Image::Magick ref=NO_INIT
10666   ALIAS:
10667     MontageImage  = 1
10668     montage       = 2
10669     montageimage  = 3
10670   PPCODE:
10671   {
10672     AV
10673       *av;
10674
10675     char
10676       *attribute;
10677
10678     ExceptionInfo
10679       *exception;
10680
10681     HV
10682       *hv;
10683
10684     Image
10685       *image,
10686       *next;
10687
10688     PixelInfo
10689       transparent_color;
10690
10691     MontageInfo
10692       *montage_info;
10693
10694     register ssize_t
10695       i;
10696
10697     ssize_t
10698       sp;
10699
10700     struct PackageInfo
10701       *info;
10702
10703     SV
10704       *av_reference,
10705       *perl_exception,
10706       *reference,
10707       *rv,
10708       *sv;
10709
10710     PERL_UNUSED_VAR(ref);
10711     PERL_UNUSED_VAR(ix);
10712     exception=AcquireExceptionInfo();
10713     perl_exception=newSVpv("",0);
10714     sv=NULL;
10715     attribute=NULL;
10716     if (sv_isobject(ST(0)) == 0)
10717       {
10718         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
10719           PackageName);
10720         goto PerlException;
10721       }
10722     reference=SvRV(ST(0));
10723     hv=SvSTASH(reference);
10724     av=newAV();
10725     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
10726     SvREFCNT_dec(av);
10727     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
10728     if (image == (Image *) NULL)
10729       {
10730         ThrowPerlException(exception,OptionError,"NoImagesDefined",
10731           PackageName);
10732         goto PerlException;
10733       }
10734     /*
10735       Get options.
10736     */
10737     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
10738     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
10739     (void) QueryMagickColor("none",&transparent_color,exception);
10740     for (i=2; i < items; i+=2)
10741     {
10742       attribute=(char *) SvPV(ST(i-1),na);
10743       switch (*attribute)
10744       {
10745         case 'B':
10746         case 'b':
10747         {
10748           if (LocaleCompare(attribute,"background") == 0)
10749             {
10750               (void) QueryColorDatabase(SvPV(ST(i),na),
10751                 &montage_info->background_color,exception);
10752               for (next=image; next; next=next->next)
10753                 next->background_color=montage_info->background_color;
10754               break;
10755             }
10756           if (LocaleCompare(attribute,"border") == 0)
10757             {
10758               montage_info->border_width=SvIV(ST(i));
10759               break;
10760             }
10761           if (LocaleCompare(attribute,"bordercolor") == 0)
10762             {
10763               (void) QueryColorDatabase(SvPV(ST(i),na),
10764                 &montage_info->border_color,exception);
10765               for (next=image; next; next=next->next)
10766                 next->border_color=montage_info->border_color;
10767               break;
10768             }
10769           if (LocaleCompare(attribute,"borderwidth") == 0)
10770             {
10771               montage_info->border_width=SvIV(ST(i));
10772               break;
10773             }
10774           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10775             attribute);
10776           break;
10777         }
10778         case 'C':
10779         case 'c':
10780         {
10781           if (LocaleCompare(attribute,"compose") == 0)
10782             {
10783               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
10784                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
10785               if (sp < 0)
10786                 {
10787                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
10788                     SvPV(ST(i),na));
10789                   break;
10790                 }
10791               for (next=image; next; next=next->next)
10792                 next->compose=(CompositeOperator) sp;
10793               break;
10794             }
10795           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10796             attribute);
10797           break;
10798         }
10799         case 'F':
10800         case 'f':
10801         {
10802           if (LocaleCompare(attribute,"fill") == 0)
10803             {
10804               (void) QueryColorDatabase(SvPV(ST(i),na),&montage_info->fill,
10805                 exception);
10806               break;
10807             }
10808           if (LocaleCompare(attribute,"font") == 0)
10809             {
10810               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
10811               break;
10812             }
10813           if (LocaleCompare(attribute,"frame") == 0)
10814             {
10815               char
10816                 *p;
10817
10818               p=SvPV(ST(i),na);
10819               if (IsGeometry(p) == MagickFalse)
10820                 {
10821                   ThrowPerlException(exception,OptionError,"MissingGeometry",
10822                     p);
10823                   break;
10824                 }
10825               (void) CloneString(&montage_info->frame,p);
10826               if (*p == '\0')
10827                 montage_info->frame=(char *) NULL;
10828               break;
10829             }
10830           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10831             attribute);
10832           break;
10833         }
10834         case 'G':
10835         case 'g':
10836         {
10837           if (LocaleCompare(attribute,"geometry") == 0)
10838             {
10839               char
10840                 *p;
10841
10842               p=SvPV(ST(i),na);
10843               if (IsGeometry(p) == MagickFalse)
10844                 {
10845                   ThrowPerlException(exception,OptionError,"MissingGeometry",
10846                     p);
10847                   break;
10848                 }
10849              (void) CloneString(&montage_info->geometry,p);
10850              if (*p == '\0')
10851                montage_info->geometry=(char *) NULL;
10852              break;
10853            }
10854          if (LocaleCompare(attribute,"gravity") == 0)
10855            {
10856              ssize_t
10857                in;
10858
10859              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
10860                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
10861              if (in < 0)
10862                {
10863                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
10864                    SvPV(ST(i),na));
10865                  return;
10866                }
10867              montage_info->gravity=(GravityType) in;
10868              for (next=image; next; next=next->next)
10869                next->gravity=(GravityType) in;
10870              break;
10871            }
10872           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10873             attribute);
10874           break;
10875         }
10876         case 'L':
10877         case 'l':
10878         {
10879           if (LocaleCompare(attribute,"label") == 0)
10880             {
10881               for (next=image; next; next=next->next)
10882                 (void) SetImageProperty(next,"label",InterpretImageProperties(
10883                   info ? info->image_info : (ImageInfo *) NULL,next,
10884                   SvPV(ST(i),na)));
10885               break;
10886             }
10887           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10888             attribute);
10889           break;
10890         }
10891         case 'M':
10892         case 'm':
10893         {
10894           if (LocaleCompare(attribute,"mattecolor") == 0)
10895             {
10896               (void) QueryColorDatabase(SvPV(ST(i),na),
10897                 &montage_info->matte_color,exception);
10898               for (next=image; next; next=next->next)
10899                 next->matte_color=montage_info->matte_color;
10900               break;
10901             }
10902           if (LocaleCompare(attribute,"mode") == 0)
10903             {
10904               ssize_t
10905                 in;
10906
10907               in=!SvPOK(ST(i)) ? SvIV(ST(i)) :
10908                 ParseCommandOption(MagickModeOptions,MagickFalse,SvPV(ST(i),na));
10909               switch (in)
10910               {
10911                 default:
10912                 {
10913                   ThrowPerlException(exception,OptionError,
10914                     "UnrecognizedModeType",SvPV(ST(i),na));
10915                   break;
10916                 }
10917                 case FrameMode:
10918                 {
10919                   (void) CloneString(&montage_info->frame,"15x15+3+3");
10920                   montage_info->shadow=MagickTrue;
10921                   break;
10922                 }
10923                 case UnframeMode:
10924                 {
10925                   montage_info->frame=(char *) NULL;
10926                   montage_info->shadow=MagickFalse;
10927                   montage_info->border_width=0;
10928                   break;
10929                 }
10930                 case ConcatenateMode:
10931                 {
10932                   montage_info->frame=(char *) NULL;
10933                   montage_info->shadow=MagickFalse;
10934                   (void) CloneString(&montage_info->geometry,"+0+0");
10935                   montage_info->border_width=0;
10936                 }
10937               }
10938               break;
10939             }
10940           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10941             attribute);
10942           break;
10943         }
10944         case 'P':
10945         case 'p':
10946         {
10947           if (LocaleCompare(attribute,"pointsize") == 0)
10948             {
10949               montage_info->pointsize=SvIV(ST(i));
10950               break;
10951             }
10952           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10953             attribute);
10954           break;
10955         }
10956         case 'S':
10957         case 's':
10958         {
10959           if (LocaleCompare(attribute,"shadow") == 0)
10960             {
10961               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
10962                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
10963               if (sp < 0)
10964                 {
10965                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
10966                     SvPV(ST(i),na));
10967                   break;
10968                 }
10969              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
10970              break;
10971             }
10972           if (LocaleCompare(attribute,"stroke") == 0)
10973             {
10974               (void) QueryColorDatabase(SvPV(ST(i),na),&montage_info->stroke,
10975                 exception);
10976               break;
10977             }
10978           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10979             attribute);
10980           break;
10981         }
10982         case 'T':
10983         case 't':
10984         {
10985           if (LocaleCompare(attribute,"texture") == 0)
10986             {
10987               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
10988               break;
10989             }
10990           if (LocaleCompare(attribute,"tile") == 0)
10991             {
10992               char *p=SvPV(ST(i),na);
10993               if (IsGeometry(p) == MagickFalse)
10994                 {
10995                   ThrowPerlException(exception,OptionError,"MissingGeometry",
10996                     p);
10997                   break;
10998                 }
10999               (void) CloneString(&montage_info->tile,p);
11000               if (*p == '\0')
11001                 montage_info->tile=(char *) NULL;
11002               break;
11003             }
11004           if (LocaleCompare(attribute,"title") == 0)
11005             {
11006               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11007               break;
11008             }
11009           if (LocaleCompare(attribute,"transparent") == 0)
11010             {
11011               PixelInfo
11012                 transparent_color;
11013
11014               QueryMagickColor(SvPV(ST(i),na),&transparent_color,exception);
11015               for (next=image; next; next=next->next)
11016                 (void) TransparentPaintImage(next,&transparent_color,
11017                   TransparentAlpha,MagickFalse);
11018               break;
11019             }
11020           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11021             attribute);
11022           break;
11023         }
11024         default:
11025         {
11026           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11027             attribute);
11028           break;
11029         }
11030       }
11031     }
11032     image=MontageImageList(info->image_info,montage_info,image,exception);
11033     montage_info=DestroyMontageInfo(montage_info);
11034     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11035       goto PerlException;
11036     if (transparent_color.alpha != TransparentAlpha)
11037       for (next=image; next; next=next->next)
11038         (void) TransparentPaintImage(next,&transparent_color,
11039           TransparentAlpha,MagickFalse);
11040     for (  ; image; image=image->next)
11041     {
11042       AddImageToRegistry(sv,image);
11043       rv=newRV(sv);
11044       av_push(av,sv_bless(rv,hv));
11045       SvREFCNT_dec(sv);
11046     }
11047     exception=DestroyExceptionInfo(exception);
11048     ST(0)=av_reference;
11049     SvREFCNT_dec(perl_exception);
11050     XSRETURN(1);
11051
11052   PerlException:
11053     InheritPerlException(exception,perl_exception);
11054     exception=DestroyExceptionInfo(exception);
11055     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11056     SvPOK_on(perl_exception);
11057     ST(0)=sv_2mortal(perl_exception);
11058     XSRETURN(1);
11059   }
11060 \f
11061 #
11062 ###############################################################################
11063 #                                                                             #
11064 #                                                                             #
11065 #                                                                             #
11066 #   M o r p h                                                                 #
11067 #                                                                             #
11068 #                                                                             #
11069 #                                                                             #
11070 ###############################################################################
11071 #
11072 #
11073 void
11074 Morph(ref,...)
11075   Image::Magick ref=NO_INIT
11076   ALIAS:
11077     MorphImage  = 1
11078     morph       = 2
11079     morphimage  = 3
11080   PPCODE:
11081   {
11082     AV
11083       *av;
11084
11085     char
11086       *attribute;
11087
11088     ExceptionInfo
11089       *exception;
11090
11091     HV
11092       *hv;
11093
11094     Image
11095       *image;
11096
11097     register ssize_t
11098       i;
11099
11100     ssize_t
11101       number_frames;
11102
11103     struct PackageInfo
11104       *info;
11105
11106     SV
11107       *av_reference,
11108       *perl_exception,
11109       *reference,
11110       *rv,
11111       *sv;
11112
11113     PERL_UNUSED_VAR(ref);
11114     PERL_UNUSED_VAR(ix);
11115     exception=AcquireExceptionInfo();
11116     perl_exception=newSVpv("",0);
11117     sv=NULL;
11118     av=NULL;
11119     attribute=NULL;
11120     if (sv_isobject(ST(0)) == 0)
11121       {
11122         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11123           PackageName);
11124         goto PerlException;
11125       }
11126     reference=SvRV(ST(0));
11127     hv=SvSTASH(reference);
11128     av=newAV();
11129     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11130     SvREFCNT_dec(av);
11131     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11132     if (image == (Image *) NULL)
11133       {
11134         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11135           PackageName);
11136         goto PerlException;
11137       }
11138     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11139     /*
11140       Get attribute.
11141     */
11142     number_frames=30;
11143     for (i=2; i < items; i+=2)
11144     {
11145       attribute=(char *) SvPV(ST(i-1),na);
11146       switch (*attribute)
11147       {
11148         case 'F':
11149         case 'f':
11150         {
11151           if (LocaleCompare(attribute,"frames") == 0)
11152             {
11153               number_frames=SvIV(ST(i));
11154               break;
11155             }
11156           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11157             attribute);
11158           break;
11159         }
11160         default:
11161         {
11162           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11163             attribute);
11164           break;
11165         }
11166       }
11167     }
11168     image=MorphImages(image,number_frames,exception);
11169     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11170       goto PerlException;
11171     for ( ; image; image=image->next)
11172     {
11173       AddImageToRegistry(sv,image);
11174       rv=newRV(sv);
11175       av_push(av,sv_bless(rv,hv));
11176       SvREFCNT_dec(sv);
11177     }
11178     exception=DestroyExceptionInfo(exception);
11179     ST(0)=av_reference;
11180     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11181     XSRETURN(1);
11182
11183   PerlException:
11184     InheritPerlException(exception,perl_exception);
11185     exception=DestroyExceptionInfo(exception);
11186     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11187     SvPOK_on(perl_exception);
11188     ST(0)=sv_2mortal(perl_exception);
11189     XSRETURN(1);
11190   }
11191 \f
11192 #
11193 ###############################################################################
11194 #                                                                             #
11195 #                                                                             #
11196 #                                                                             #
11197 #   M o s a i c                                                               #
11198 #                                                                             #
11199 #                                                                             #
11200 #                                                                             #
11201 ###############################################################################
11202 #
11203 #
11204 void
11205 Mosaic(ref)
11206   Image::Magick ref=NO_INIT
11207   ALIAS:
11208     MosaicImage   = 1
11209     mosaic        = 2
11210     mosaicimage   = 3
11211   PPCODE:
11212   {
11213     AV
11214       *av;
11215
11216     ExceptionInfo
11217       *exception;
11218
11219     HV
11220       *hv;
11221
11222     Image
11223       *image;
11224
11225     struct PackageInfo
11226       *info;
11227
11228     SV
11229       *perl_exception,
11230       *reference,
11231       *rv,
11232       *sv;
11233
11234     PERL_UNUSED_VAR(ref);
11235     PERL_UNUSED_VAR(ix);
11236     exception=AcquireExceptionInfo();
11237     perl_exception=newSVpv("",0);
11238     sv=NULL;
11239     if (sv_isobject(ST(0)) == 0)
11240       {
11241         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11242           PackageName);
11243         goto PerlException;
11244       }
11245     reference=SvRV(ST(0));
11246     hv=SvSTASH(reference);
11247     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11248     if (image == (Image *) NULL)
11249       {
11250         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11251           PackageName);
11252         goto PerlException;
11253       }
11254     image=MergeImageLayers(image,MosaicLayer,exception);
11255     /*
11256       Create blessed Perl array for the returned image.
11257     */
11258     av=newAV();
11259     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11260     SvREFCNT_dec(av);
11261     AddImageToRegistry(sv,image);
11262     rv=newRV(sv);
11263     av_push(av,sv_bless(rv,hv));
11264     SvREFCNT_dec(sv);
11265     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11266     (void) CopyMagickString(image->filename,info->image_info->filename,
11267       MaxTextExtent);
11268     SetImageInfo(info->image_info,0,&image->exception);
11269     exception=DestroyExceptionInfo(exception);
11270     SvREFCNT_dec(perl_exception);
11271     XSRETURN(1);
11272
11273   PerlException:
11274     InheritPerlException(exception,perl_exception);
11275     exception=DestroyExceptionInfo(exception);
11276     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11277     SvPOK_on(perl_exception);  /* return messages in string context */
11278     ST(0)=sv_2mortal(perl_exception);
11279     XSRETURN(1);
11280   }
11281 \f
11282 #
11283 ###############################################################################
11284 #                                                                             #
11285 #                                                                             #
11286 #                                                                             #
11287 #   P i n g                                                                   #
11288 #                                                                             #
11289 #                                                                             #
11290 #                                                                             #
11291 ###############################################################################
11292 #
11293 #
11294 void
11295 Ping(ref,...)
11296   Image::Magick ref=NO_INIT
11297   ALIAS:
11298     PingImage  = 1
11299     ping       = 2
11300     pingimage  = 3
11301   PPCODE:
11302   {
11303     AV
11304       *av;
11305
11306     char
11307       **keep,
11308       **list;
11309
11310     ExceptionInfo
11311       *exception;
11312
11313     Image
11314       *image,
11315       *next;
11316
11317     int
11318       n;
11319
11320     MagickBooleanType
11321       status;
11322
11323     register char
11324       **p;
11325
11326     register ssize_t
11327       i;
11328
11329     ssize_t
11330       ac;
11331
11332     STRLEN
11333       *length;
11334
11335     struct PackageInfo
11336       *info,
11337       *package_info;
11338
11339     SV
11340       *perl_exception,
11341       *reference;
11342
11343     size_t
11344       count;
11345
11346     PERL_UNUSED_VAR(ref);
11347     PERL_UNUSED_VAR(ix);
11348     exception=AcquireExceptionInfo();
11349     perl_exception=newSVpv("",0);
11350     package_info=(struct PackageInfo *) NULL;
11351     ac=(items < 2) ? 1 : items-1;
11352     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
11353     keep=list;
11354     length=(STRLEN *) NULL;
11355     if (list == (char **) NULL)
11356       {
11357         ThrowPerlException(exception,ResourceLimitError,
11358           "MemoryAllocationFailed",PackageName);
11359         goto PerlException;
11360       }
11361     keep=list;
11362     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
11363     if (length == (STRLEN *) NULL)
11364       {
11365         ThrowPerlException(exception,ResourceLimitError,
11366           "MemoryAllocationFailed",PackageName);
11367         goto PerlException;
11368       }
11369     if (sv_isobject(ST(0)) == 0)
11370       {
11371         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11372           PackageName);
11373         goto PerlException;
11374       }
11375     reference=SvRV(ST(0));
11376     if (SvTYPE(reference) != SVt_PVAV)
11377       {
11378         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11379           PackageName);
11380         goto PerlException;
11381       }
11382     av=(AV *) reference;
11383     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11384       exception);
11385     package_info=ClonePackageInfo(info,exception);
11386     n=1;
11387     if (items <= 1)
11388       *list=(char *) (*package_info->image_info->filename ?
11389         package_info->image_info->filename : "XC:black");
11390     else
11391       for (n=0, i=0; i < ac; i++)
11392       {
11393         list[n]=(char *) SvPV(ST(i+1),length[n]);
11394         if ((items >= 3) && strEQcase(list[n],"blob"))
11395           {
11396             void
11397               *blob;
11398
11399             i++;
11400             blob=(void *) (SvPV(ST(i+1),length[n]));
11401             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
11402           }
11403         if ((items >= 3) && strEQcase(list[n],"filename"))
11404           continue;
11405         if ((items >= 3) && strEQcase(list[n],"file"))
11406           {
11407             FILE
11408               *file;
11409
11410             PerlIO
11411               *io_info;
11412
11413             i++;
11414             io_info=IoIFP(sv_2io(ST(i+1)));
11415             if (io_info == (PerlIO *) NULL)
11416               {
11417                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11418                   PackageName);
11419                 continue;
11420               }
11421             file=PerlIO_findFILE(io_info);
11422             if (file == (FILE *) NULL)
11423               {
11424                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11425                   PackageName);
11426                 continue;
11427               }
11428             SetImageInfoFile(package_info->image_info,file);
11429           }
11430         if ((items >= 3) && strEQcase(list[n],"magick"))
11431           continue;
11432         n++;
11433       }
11434     list[n]=(char *) NULL;
11435     keep=list;
11436     status=ExpandFilenames(&n,&list);
11437     if (status == MagickFalse)
11438       {
11439         ThrowPerlException(exception,ResourceLimitError,
11440           "MemoryAllocationFailed",PackageName);
11441         goto PerlException;
11442       }
11443     count=0;
11444     for (i=0; i < n; i++)
11445     {
11446       (void) CopyMagickString(package_info->image_info->filename,list[i],
11447         MaxTextExtent);
11448       image=PingImage(package_info->image_info,exception);
11449       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11450         break;
11451       if ((package_info->image_info->file != (FILE *) NULL) ||
11452           (package_info->image_info->blob != (void *) NULL))
11453         DisassociateImageStream(image);
11454       count+=GetImageListLength(image);
11455       EXTEND(sp,4*count);
11456       for (next=image; next; next=next->next)
11457       {
11458         PUSHs(sv_2mortal(newSViv(next->columns)));
11459         PUSHs(sv_2mortal(newSViv(next->rows)));
11460         PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
11461         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
11462       }
11463       image=DestroyImageList(image);
11464     }
11465     /*
11466       Free resources.
11467     */
11468     for (i=0; i < n; i++)
11469       if (list[i] != (char *) NULL)
11470         for (p=keep; list[i] != *p++; )
11471           if (*p == NULL)
11472             {
11473               list[i]=(char *) RelinquishMagickMemory(list[i]);
11474               break;
11475             }
11476
11477   PerlException:
11478     if (package_info != (struct PackageInfo *) NULL)
11479       DestroyPackageInfo(package_info);
11480     if (list && (list != keep))
11481       list=(char **) RelinquishMagickMemory(list);
11482     if (keep)
11483       keep=(char **) RelinquishMagickMemory(keep);
11484     if (length)
11485       length=(STRLEN *) RelinquishMagickMemory(length);
11486     InheritPerlException(exception,perl_exception);
11487     exception=DestroyExceptionInfo(exception);
11488     SvREFCNT_dec(perl_exception);  /* throw away all errors */
11489   }
11490 \f
11491 #
11492 ###############################################################################
11493 #                                                                             #
11494 #                                                                             #
11495 #                                                                             #
11496 #   P r e v i e w                                                             #
11497 #                                                                             #
11498 #                                                                             #
11499 #                                                                             #
11500 ###############################################################################
11501 #
11502 #
11503 void
11504 Preview(ref,...)
11505   Image::Magick ref=NO_INIT
11506   ALIAS:
11507     PreviewImage = 1
11508     preview      = 2
11509     previewimage = 3
11510   PPCODE:
11511   {
11512     AV
11513       *av;
11514
11515     ExceptionInfo
11516       *exception;
11517
11518     HV
11519       *hv;
11520
11521     Image
11522       *image,
11523       *preview_image;
11524
11525     PreviewType
11526       preview_type;
11527
11528     struct PackageInfo
11529       *info;
11530
11531     SV
11532       *av_reference,
11533       *perl_exception,
11534       *reference,
11535       *rv,
11536       *sv;
11537
11538     PERL_UNUSED_VAR(ref);
11539     PERL_UNUSED_VAR(ix);
11540     exception=AcquireExceptionInfo();
11541     perl_exception=newSVpv("",0);
11542     sv=NULL;
11543     av=NULL;
11544     if (sv_isobject(ST(0)) == 0)
11545       {
11546         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11547           PackageName);
11548         goto PerlException;
11549       }
11550     reference=SvRV(ST(0));
11551     hv=SvSTASH(reference);
11552     av=newAV();
11553     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11554     SvREFCNT_dec(av);
11555     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11556     if (image == (Image *) NULL)
11557       {
11558         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11559           PackageName);
11560         goto PerlException;
11561       }
11562     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11563     preview_type=GammaPreview;
11564     if (items > 1)
11565       preview_type=(PreviewType)
11566         ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
11567     for ( ; image; image=image->next)
11568     {
11569       preview_image=PreviewImage(image,preview_type,exception);
11570       if (preview_image == (Image *) NULL)
11571         goto PerlException;
11572       AddImageToRegistry(sv,preview_image);
11573       rv=newRV(sv);
11574       av_push(av,sv_bless(rv,hv));
11575       SvREFCNT_dec(sv);
11576     }
11577     exception=DestroyExceptionInfo(exception);
11578     ST(0)=av_reference;
11579     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11580     XSRETURN(1);
11581
11582   PerlException:
11583     InheritPerlException(exception,perl_exception);
11584     exception=DestroyExceptionInfo(exception);
11585     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11586     SvPOK_on(perl_exception);
11587     ST(0)=sv_2mortal(perl_exception);
11588     XSRETURN(1);
11589   }
11590 \f
11591 #
11592 ###############################################################################
11593 #                                                                             #
11594 #                                                                             #
11595 #                                                                             #
11596 #   Q u e r y C o l o r                                                       #
11597 #                                                                             #
11598 #                                                                             #
11599 #                                                                             #
11600 ###############################################################################
11601 #
11602 #
11603 void
11604 QueryColor(ref,...)
11605   Image::Magick ref=NO_INIT
11606   ALIAS:
11607     querycolor = 1
11608   PPCODE:
11609   {
11610     char
11611       *name;
11612
11613     ExceptionInfo
11614       *exception;
11615
11616     PixelInfo
11617       color;
11618
11619     register ssize_t
11620       i;
11621
11622     SV
11623       *perl_exception;
11624
11625     PERL_UNUSED_VAR(ref);
11626     PERL_UNUSED_VAR(ix);
11627     exception=AcquireExceptionInfo();
11628     perl_exception=newSVpv("",0);
11629     if (items == 1)
11630       {
11631         const ColorInfo
11632           **colorlist;
11633
11634         size_t
11635           colors;
11636
11637         colorlist=GetColorInfoList("*",&colors,exception);
11638         EXTEND(sp,colors);
11639         for (i=0; i < (ssize_t) colors; i++)
11640         {
11641           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
11642         }
11643         colorlist=(const ColorInfo **)
11644           RelinquishMagickMemory((ColorInfo **) colorlist);
11645         goto PerlException;
11646       }
11647     EXTEND(sp,5*items);
11648     for (i=1; i < items; i++)
11649     {
11650       name=(char *) SvPV(ST(i),na);
11651       if (QueryMagickColor(name,&color,exception) == MagickFalse)
11652         {
11653           PUSHs(&sv_undef);
11654           continue;
11655         }
11656       PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
11657       PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
11658       PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
11659       if (color.colorspace == CMYKColorspace)
11660         PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
11661       if (color.matte != MagickFalse)
11662         PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
11663     }
11664
11665   PerlException:
11666     InheritPerlException(exception,perl_exception);
11667     exception=DestroyExceptionInfo(exception);
11668     SvREFCNT_dec(perl_exception);
11669   }
11670 \f
11671 #
11672 ###############################################################################
11673 #                                                                             #
11674 #                                                                             #
11675 #                                                                             #
11676 #   Q u e r y C o l o r N a m e                                               #
11677 #                                                                             #
11678 #                                                                             #
11679 #                                                                             #
11680 ###############################################################################
11681 #
11682 #
11683 void
11684 QueryColorname(ref,...)
11685   Image::Magick ref=NO_INIT
11686   ALIAS:
11687     querycolorname = 1
11688   PPCODE:
11689   {
11690     AV
11691       *av;
11692
11693     char
11694       message[MaxTextExtent];
11695
11696     ExceptionInfo
11697       *exception;
11698
11699     Image
11700       *image;
11701
11702     PixelPacket
11703       target_color;
11704
11705     register ssize_t
11706       i;
11707
11708     struct PackageInfo
11709       *info;
11710
11711     SV
11712       *perl_exception,
11713       *reference;  /* reference is the SV* of ref=SvIV(reference) */
11714
11715     PERL_UNUSED_VAR(ref);
11716     PERL_UNUSED_VAR(ix);
11717     exception=AcquireExceptionInfo();
11718     perl_exception=newSVpv("",0);
11719     reference=SvRV(ST(0));
11720     av=(AV *) reference;
11721     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11722       exception);
11723     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11724     if (image == (Image *) NULL)
11725       {
11726         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11727           PackageName);
11728         goto PerlException;
11729       }
11730     EXTEND(sp,items);
11731     for (i=1; i < items; i++)
11732     {
11733       (void) QueryColorDatabase(SvPV(ST(i),na),&target_color,exception);
11734       (void) QueryColorname(image,&target_color,SVGCompliance,message,
11735         exception);
11736       PUSHs(sv_2mortal(newSVpv(message,0)));
11737     }
11738
11739   PerlException:
11740     InheritPerlException(exception,perl_exception);
11741     exception=DestroyExceptionInfo(exception);
11742     SvREFCNT_dec(perl_exception);
11743   }
11744 \f
11745 #
11746 ###############################################################################
11747 #                                                                             #
11748 #                                                                             #
11749 #                                                                             #
11750 #   Q u e r y F o n t                                                         #
11751 #                                                                             #
11752 #                                                                             #
11753 #                                                                             #
11754 ###############################################################################
11755 #
11756 #
11757 void
11758 QueryFont(ref,...)
11759   Image::Magick ref=NO_INIT
11760   ALIAS:
11761     queryfont = 1
11762   PPCODE:
11763   {
11764     char
11765       *name,
11766       message[MaxTextExtent];
11767
11768     ExceptionInfo
11769       *exception;
11770
11771     register ssize_t
11772       i;
11773
11774     SV
11775       *perl_exception;
11776
11777     volatile const TypeInfo
11778       *type_info;
11779
11780     PERL_UNUSED_VAR(ref);
11781     PERL_UNUSED_VAR(ix);
11782     exception=AcquireExceptionInfo();
11783     perl_exception=newSVpv("",0);
11784     if (items == 1)
11785       {
11786         const TypeInfo
11787           **typelist;
11788
11789         size_t
11790           types;
11791
11792         typelist=GetTypeInfoList("*",&types,exception);
11793         EXTEND(sp,types);
11794         for (i=0; i < (ssize_t) types; i++)
11795         {
11796           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
11797         }
11798         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
11799           typelist);
11800         goto PerlException;
11801       }
11802     EXTEND(sp,10*items);
11803     for (i=1; i < items; i++)
11804     {
11805       name=(char *) SvPV(ST(i),na);
11806       type_info=GetTypeInfo(name,exception);
11807       if (type_info == (TypeInfo *) NULL)
11808         {
11809           PUSHs(&sv_undef);
11810           continue;
11811         }
11812       if (type_info->name == (char *) NULL)
11813         PUSHs(&sv_undef);
11814       else
11815         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
11816       if (type_info->description == (char *) NULL)
11817         PUSHs(&sv_undef);
11818       else
11819         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
11820       if (type_info->family == (char *) NULL)
11821         PUSHs(&sv_undef);
11822       else
11823         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
11824       if (type_info->style == UndefinedStyle)
11825         PUSHs(&sv_undef);
11826       else
11827         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
11828           type_info->style),0)));
11829       if (type_info->stretch == UndefinedStretch)
11830         PUSHs(&sv_undef);
11831       else
11832         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
11833           type_info->stretch),0)));
11834       (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
11835         type_info->weight);
11836       PUSHs(sv_2mortal(newSVpv(message,0)));
11837       if (type_info->encoding == (char *) NULL)
11838         PUSHs(&sv_undef);
11839       else
11840         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
11841       if (type_info->foundry == (char *) NULL)
11842         PUSHs(&sv_undef);
11843       else
11844         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
11845       if (type_info->format == (char *) NULL)
11846         PUSHs(&sv_undef);
11847       else
11848         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
11849       if (type_info->metrics == (char *) NULL)
11850         PUSHs(&sv_undef);
11851       else
11852         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
11853       if (type_info->glyphs == (char *) NULL)
11854         PUSHs(&sv_undef);
11855       else
11856         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
11857     }
11858
11859   PerlException:
11860     InheritPerlException(exception,perl_exception);
11861     exception=DestroyExceptionInfo(exception);
11862     SvREFCNT_dec(perl_exception);
11863   }
11864 \f
11865 #
11866 ###############################################################################
11867 #                                                                             #
11868 #                                                                             #
11869 #                                                                             #
11870 #   Q u e r y F o n t M e t r i c s                                           #
11871 #                                                                             #
11872 #                                                                             #
11873 #                                                                             #
11874 ###############################################################################
11875 #
11876 #
11877 void
11878 QueryFontMetrics(ref,...)
11879   Image::Magick ref=NO_INIT
11880   ALIAS:
11881     queryfontmetrics = 1
11882   PPCODE:
11883   {
11884     AffineMatrix
11885       affine,
11886       current;
11887
11888     AV
11889       *av;
11890
11891     char
11892       *attribute;
11893
11894     double
11895       x,
11896       y;
11897
11898     DrawInfo
11899       *draw_info;
11900
11901     ExceptionInfo
11902       *exception;
11903
11904     GeometryInfo
11905       geometry_info;
11906
11907     Image
11908       *image;
11909
11910     MagickBooleanType
11911       status;
11912
11913     MagickStatusType
11914       flags;
11915
11916     register ssize_t
11917       i;
11918
11919     ssize_t
11920       type;
11921
11922     struct PackageInfo
11923       *info,
11924       *package_info;
11925
11926     SV
11927       *perl_exception,
11928       *reference;  /* reference is the SV* of ref=SvIV(reference) */
11929
11930     TypeMetric
11931       metrics;
11932
11933     PERL_UNUSED_VAR(ref);
11934     PERL_UNUSED_VAR(ix);
11935     exception=AcquireExceptionInfo();
11936     package_info=(struct PackageInfo *) NULL;
11937     perl_exception=newSVpv("",0);
11938     reference=SvRV(ST(0));
11939     av=(AV *) reference;
11940     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11941       exception);
11942     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11943     if (image == (Image *) NULL)
11944       {
11945         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11946           PackageName);
11947         goto PerlException;
11948       }
11949     package_info=ClonePackageInfo(info,exception);
11950     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
11951     CloneString(&draw_info->text,"");
11952     current=draw_info->affine;
11953     GetAffineMatrix(&affine);
11954     x=0.0;
11955     y=0.0;
11956     EXTEND(sp,7*items);
11957     for (i=2; i < items; i+=2)
11958     {
11959       attribute=(char *) SvPV(ST(i-1),na);
11960       switch (*attribute)
11961       {
11962         case 'A':
11963         case 'a':
11964         {
11965           if (LocaleCompare(attribute,"antialias") == 0)
11966             {
11967               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
11968                 SvPV(ST(i),na));
11969               if (type < 0)
11970                 {
11971                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11972                     SvPV(ST(i),na));
11973                   break;
11974                 }
11975               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
11976               break;
11977             }
11978           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11979             attribute);
11980           break;
11981         }
11982         case 'd':
11983         case 'D':
11984         {
11985           if (LocaleCompare(attribute,"density") == 0)
11986             {
11987               CloneString(&draw_info->density,SvPV(ST(i),na));
11988               break;
11989             }
11990           if (LocaleCompare(attribute,"direction") == 0)
11991             {
11992               draw_info->direction=(DirectionType) ParseCommandOption(
11993                 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
11994               break;
11995             }
11996           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11997             attribute);
11998           break;
11999         }
12000         case 'e':
12001         case 'E':
12002         {
12003           if (LocaleCompare(attribute,"encoding") == 0)
12004             {
12005               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12006               break;
12007             }
12008           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12009             attribute);
12010           break;
12011         }
12012         case 'f':
12013         case 'F':
12014         {
12015           if (LocaleCompare(attribute,"family") == 0)
12016             {
12017               CloneString(&draw_info->family,SvPV(ST(i),na));
12018               break;
12019             }
12020           if (LocaleCompare(attribute,"fill") == 0)
12021             {
12022               if (info)
12023                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->fill,
12024                   &image->exception);
12025               break;
12026             }
12027           if (LocaleCompare(attribute,"font") == 0)
12028             {
12029               CloneString(&draw_info->font,SvPV(ST(i),na));
12030               break;
12031             }
12032           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12033             attribute);
12034           break;
12035         }
12036         case 'g':
12037         case 'G':
12038         {
12039           if (LocaleCompare(attribute,"geometry") == 0)
12040             {
12041               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12042               break;
12043             }
12044           if (LocaleCompare(attribute,"gravity") == 0)
12045             {
12046               draw_info->gravity=(GravityType) ParseCommandOption(
12047                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12048               break;
12049             }
12050           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12051             attribute);
12052           break;
12053         }
12054         case 'i':
12055         case 'I':
12056         {
12057           if (LocaleCompare(attribute,"interline-spacing") == 0)
12058             {
12059               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12060               draw_info->interline_spacing=geometry_info.rho;
12061               break;
12062             }
12063           if (LocaleCompare(attribute,"interword-spacing") == 0)
12064             {
12065               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12066               draw_info->interword_spacing=geometry_info.rho;
12067               break;
12068             }
12069           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12070             attribute);
12071           break;
12072         }
12073         case 'k':
12074         case 'K':
12075         {
12076           if (LocaleCompare(attribute,"kerning") == 0)
12077             {
12078               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12079               draw_info->kerning=geometry_info.rho;
12080               break;
12081             }
12082           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12083             attribute);
12084           break;
12085         }
12086         case 'p':
12087         case 'P':
12088         {
12089           if (LocaleCompare(attribute,"pointsize") == 0)
12090             {
12091               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12092               draw_info->pointsize=geometry_info.rho;
12093               break;
12094             }
12095           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12096             attribute);
12097           break;
12098         }
12099         case 'r':
12100         case 'R':
12101         {
12102           if (LocaleCompare(attribute,"rotate") == 0)
12103             {
12104               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12105               affine.rx=geometry_info.rho;
12106               affine.ry=geometry_info.sigma;
12107               if ((flags & SigmaValue) == 0)
12108                 affine.ry=affine.rx;
12109               break;
12110             }
12111           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12112             attribute);
12113           break;
12114         }
12115         case 's':
12116         case 'S':
12117         {
12118           if (LocaleCompare(attribute,"scale") == 0)
12119             {
12120               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12121               affine.sx=geometry_info.rho;
12122               affine.sy=geometry_info.sigma;
12123               if ((flags & SigmaValue) == 0)
12124                 affine.sy=affine.sx;
12125               break;
12126             }
12127           if (LocaleCompare(attribute,"skew") == 0)
12128             {
12129               double
12130                 x_angle,
12131                 y_angle;
12132
12133               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12134               x_angle=geometry_info.rho;
12135               y_angle=geometry_info.sigma;
12136               if ((flags & SigmaValue) == 0)
12137                 y_angle=x_angle;
12138               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12139               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12140               break;
12141             }
12142           if (LocaleCompare(attribute,"stroke") == 0)
12143             {
12144               if (info)
12145                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->stroke,
12146                   &image->exception);
12147               break;
12148             }
12149           if (LocaleCompare(attribute,"style") == 0)
12150             {
12151               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12152                 SvPV(ST(i),na));
12153               if (type < 0)
12154                 {
12155                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12156                     SvPV(ST(i),na));
12157                   break;
12158                 }
12159               draw_info->style=(StyleType) type;
12160               break;
12161             }
12162           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12163             attribute);
12164           break;
12165         }
12166         case 't':
12167         case 'T':
12168         {
12169           if (LocaleCompare(attribute,"text") == 0)
12170             {
12171               CloneString(&draw_info->text,SvPV(ST(i),na));
12172               break;
12173             }
12174           if (LocaleCompare(attribute,"translate") == 0)
12175             {
12176               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12177               affine.tx=geometry_info.rho;
12178               affine.ty=geometry_info.sigma;
12179               if ((flags & SigmaValue) == 0)
12180                 affine.ty=affine.tx;
12181               break;
12182             }
12183           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12184             attribute);
12185           break;
12186         }
12187         case 'w':
12188         case 'W':
12189         {
12190           if (LocaleCompare(attribute,"weight") == 0)
12191             {
12192               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12193               draw_info->weight=(size_t) geometry_info.rho;
12194               break;
12195             }
12196           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12197             attribute);
12198           break;
12199         }
12200         case 'x':
12201         case 'X':
12202         {
12203           if (LocaleCompare(attribute,"x") == 0)
12204             {
12205               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12206               x=geometry_info.rho;
12207               break;
12208             }
12209           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12210             attribute);
12211           break;
12212         }
12213         case 'y':
12214         case 'Y':
12215         {
12216           if (LocaleCompare(attribute,"y") == 0)
12217             {
12218               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12219               y=geometry_info.rho;
12220               break;
12221             }
12222           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12223             attribute);
12224           break;
12225         }
12226         default:
12227         {
12228           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12229             attribute);
12230           break;
12231         }
12232       }
12233     }
12234     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12235     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12236     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12237     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12238     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12239     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12240     if (draw_info->geometry == (char *) NULL)
12241       {
12242         draw_info->geometry=AcquireString((char *) NULL);
12243         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12244           "%.15g,%.15g",x,y);
12245       }
12246     status=GetTypeMetrics(image,draw_info,&metrics);
12247     (void) CatchImageException(image);
12248     if (status == MagickFalse)
12249       PUSHs(&sv_undef);
12250     else
12251       {
12252         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12253         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12254         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12255         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12256         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12257         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12258         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12259         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12260         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12261         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12262         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12263         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12264         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12265       }
12266     draw_info=DestroyDrawInfo(draw_info);
12267
12268   PerlException:
12269     if (package_info != (struct PackageInfo *) NULL)
12270       DestroyPackageInfo(package_info);
12271     InheritPerlException(exception,perl_exception);
12272     exception=DestroyExceptionInfo(exception);
12273     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12274   }
12275 \f
12276 #
12277 ###############################################################################
12278 #                                                                             #
12279 #                                                                             #
12280 #                                                                             #
12281 #   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                         #
12282 #                                                                             #
12283 #                                                                             #
12284 #                                                                             #
12285 ###############################################################################
12286 #
12287 #
12288 void
12289 QueryMultilineFontMetrics(ref,...)
12290   Image::Magick ref=NO_INIT
12291   ALIAS:
12292     querymultilinefontmetrics = 1
12293   PPCODE:
12294   {
12295     AffineMatrix
12296       affine,
12297       current;
12298
12299     AV
12300       *av;
12301
12302     char
12303       *attribute;
12304
12305     double
12306       x,
12307       y;
12308
12309     DrawInfo
12310       *draw_info;
12311
12312     ExceptionInfo
12313       *exception;
12314
12315     GeometryInfo
12316       geometry_info;
12317
12318     Image
12319       *image;
12320
12321     MagickBooleanType
12322       status;
12323
12324     MagickStatusType
12325       flags;
12326
12327     register ssize_t
12328       i;
12329
12330     ssize_t
12331       type;
12332
12333     struct PackageInfo
12334       *info,
12335       *package_info;
12336
12337     SV
12338       *perl_exception,
12339       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12340
12341     TypeMetric
12342       metrics;
12343
12344     PERL_UNUSED_VAR(ref);
12345     PERL_UNUSED_VAR(ix);
12346     exception=AcquireExceptionInfo();
12347     package_info=(struct PackageInfo *) NULL;
12348     perl_exception=newSVpv("",0);
12349     reference=SvRV(ST(0));
12350     av=(AV *) reference;
12351     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12352       exception);
12353     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12354     if (image == (Image *) NULL)
12355       {
12356         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12357           PackageName);
12358         goto PerlException;
12359       }
12360     package_info=ClonePackageInfo(info,exception);
12361     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12362     CloneString(&draw_info->text,"");
12363     current=draw_info->affine;
12364     GetAffineMatrix(&affine);
12365     x=0.0;
12366     y=0.0;
12367     EXTEND(sp,7*items);
12368     for (i=2; i < items; i+=2)
12369     {
12370       attribute=(char *) SvPV(ST(i-1),na);
12371       switch (*attribute)
12372       {
12373         case 'A':
12374         case 'a':
12375         {
12376           if (LocaleCompare(attribute,"antialias") == 0)
12377             {
12378               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12379                 SvPV(ST(i),na));
12380               if (type < 0)
12381                 {
12382                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12383                     SvPV(ST(i),na));
12384                   break;
12385                 }
12386               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12387               break;
12388             }
12389           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12390             attribute);
12391           break;
12392         }
12393         case 'd':
12394         case 'D':
12395         {
12396           if (LocaleCompare(attribute,"density") == 0)
12397             {
12398               CloneString(&draw_info->density,SvPV(ST(i),na));
12399               break;
12400             }
12401           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12402             attribute);
12403           break;
12404         }
12405         case 'e':
12406         case 'E':
12407         {
12408           if (LocaleCompare(attribute,"encoding") == 0)
12409             {
12410               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12411               break;
12412             }
12413           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12414             attribute);
12415           break;
12416         }
12417         case 'f':
12418         case 'F':
12419         {
12420           if (LocaleCompare(attribute,"family") == 0)
12421             {
12422               CloneString(&draw_info->family,SvPV(ST(i),na));
12423               break;
12424             }
12425           if (LocaleCompare(attribute,"fill") == 0)
12426             {
12427               if (info)
12428                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->fill,
12429                   &image->exception);
12430               break;
12431             }
12432           if (LocaleCompare(attribute,"font") == 0)
12433             {
12434               CloneString(&draw_info->font,SvPV(ST(i),na));
12435               break;
12436             }
12437           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12438             attribute);
12439           break;
12440         }
12441         case 'g':
12442         case 'G':
12443         {
12444           if (LocaleCompare(attribute,"geometry") == 0)
12445             {
12446               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12447               break;
12448             }
12449           if (LocaleCompare(attribute,"gravity") == 0)
12450             {
12451               draw_info->gravity=(GravityType) ParseCommandOption(
12452                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12453               break;
12454             }
12455           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12456             attribute);
12457           break;
12458         }
12459         case 'p':
12460         case 'P':
12461         {
12462           if (LocaleCompare(attribute,"pointsize") == 0)
12463             {
12464               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12465               draw_info->pointsize=geometry_info.rho;
12466               break;
12467             }
12468           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12469             attribute);
12470           break;
12471         }
12472         case 'r':
12473         case 'R':
12474         {
12475           if (LocaleCompare(attribute,"rotate") == 0)
12476             {
12477               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12478               affine.rx=geometry_info.rho;
12479               affine.ry=geometry_info.sigma;
12480               if ((flags & SigmaValue) == 0)
12481                 affine.ry=affine.rx;
12482               break;
12483             }
12484           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12485             attribute);
12486           break;
12487         }
12488         case 's':
12489         case 'S':
12490         {
12491           if (LocaleCompare(attribute,"scale") == 0)
12492             {
12493               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12494               affine.sx=geometry_info.rho;
12495               affine.sy=geometry_info.sigma;
12496               if ((flags & SigmaValue) == 0)
12497                 affine.sy=affine.sx;
12498               break;
12499             }
12500           if (LocaleCompare(attribute,"skew") == 0)
12501             {
12502               double
12503                 x_angle,
12504                 y_angle;
12505
12506               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12507               x_angle=geometry_info.rho;
12508               y_angle=geometry_info.sigma;
12509               if ((flags & SigmaValue) == 0)
12510                 y_angle=x_angle;
12511               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12512               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12513               break;
12514             }
12515           if (LocaleCompare(attribute,"stroke") == 0)
12516             {
12517               if (info)
12518                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->stroke,
12519                   &image->exception);
12520               break;
12521             }
12522           if (LocaleCompare(attribute,"style") == 0)
12523             {
12524               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12525                 SvPV(ST(i),na));
12526               if (type < 0)
12527                 {
12528                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12529                     SvPV(ST(i),na));
12530                   break;
12531                 }
12532               draw_info->style=(StyleType) type;
12533               break;
12534             }
12535           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12536             attribute);
12537           break;
12538         }
12539         case 't':
12540         case 'T':
12541         {
12542           if (LocaleCompare(attribute,"text") == 0)
12543             {
12544               CloneString(&draw_info->text,SvPV(ST(i),na));
12545               break;
12546             }
12547           if (LocaleCompare(attribute,"translate") == 0)
12548             {
12549               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12550               affine.tx=geometry_info.rho;
12551               affine.ty=geometry_info.sigma;
12552               if ((flags & SigmaValue) == 0)
12553                 affine.ty=affine.tx;
12554               break;
12555             }
12556           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12557             attribute);
12558           break;
12559         }
12560         case 'w':
12561         case 'W':
12562         {
12563           if (LocaleCompare(attribute,"weight") == 0)
12564             {
12565               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12566               draw_info->weight=(size_t) geometry_info.rho;
12567               break;
12568             }
12569           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12570             attribute);
12571           break;
12572         }
12573         case 'x':
12574         case 'X':
12575         {
12576           if (LocaleCompare(attribute,"x") == 0)
12577             {
12578               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12579               x=geometry_info.rho;
12580               break;
12581             }
12582           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12583             attribute);
12584           break;
12585         }
12586         case 'y':
12587         case 'Y':
12588         {
12589           if (LocaleCompare(attribute,"y") == 0)
12590             {
12591               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12592               y=geometry_info.rho;
12593               break;
12594             }
12595           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12596             attribute);
12597           break;
12598         }
12599         default:
12600         {
12601           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12602             attribute);
12603           break;
12604         }
12605       }
12606     }
12607     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12608     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12609     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12610     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12611     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12612     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12613     if (draw_info->geometry == (char *) NULL)
12614       {
12615         draw_info->geometry=AcquireString((char *) NULL);
12616         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12617           "%.15g,%.15g",x,y);
12618       }
12619     status=GetMultilineTypeMetrics(image,draw_info,&metrics);
12620     (void) CatchImageException(image);
12621     if (status == MagickFalse)
12622       PUSHs(&sv_undef);
12623     else
12624       {
12625         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12626         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12627         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12628         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12629         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12630         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12631         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12632         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12633         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12634         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12635         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12636         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12637         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12638       }
12639     draw_info=DestroyDrawInfo(draw_info);
12640
12641   PerlException:
12642     if (package_info != (struct PackageInfo *) NULL)
12643       DestroyPackageInfo(package_info);
12644     InheritPerlException(exception,perl_exception);
12645     exception=DestroyExceptionInfo(exception);
12646     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12647   }
12648 \f
12649 #
12650 ###############################################################################
12651 #                                                                             #
12652 #                                                                             #
12653 #                                                                             #
12654 #   Q u e r y F o r m a t                                                     #
12655 #                                                                             #
12656 #                                                                             #
12657 #                                                                             #
12658 ###############################################################################
12659 #
12660 #
12661 void
12662 QueryFormat(ref,...)
12663   Image::Magick ref=NO_INIT
12664   ALIAS:
12665     queryformat = 1
12666   PPCODE:
12667   {
12668     char
12669       *name;
12670
12671     ExceptionInfo
12672       *exception;
12673
12674     register ssize_t
12675       i;
12676
12677     SV
12678       *perl_exception;
12679
12680     volatile const MagickInfo
12681       *magick_info;
12682
12683     PERL_UNUSED_VAR(ref);
12684     PERL_UNUSED_VAR(ix);
12685     exception=AcquireExceptionInfo();
12686     perl_exception=newSVpv("",0);
12687     if (items == 1)
12688       {
12689         char
12690           format[MaxTextExtent];
12691
12692         const MagickInfo
12693           **format_list;
12694
12695         size_t
12696           types;
12697
12698         format_list=GetMagickInfoList("*",&types,exception);
12699         EXTEND(sp,types);
12700         for (i=0; i < (ssize_t) types; i++)
12701         {
12702           (void) CopyMagickString(format,format_list[i]->name,MaxTextExtent);
12703           LocaleLower(format);
12704           PUSHs(sv_2mortal(newSVpv(format,0)));
12705         }
12706         format_list=(const MagickInfo **)
12707           RelinquishMagickMemory((MagickInfo *) format_list);
12708         goto PerlException;
12709       }
12710     EXTEND(sp,8*items);
12711     for (i=1; i < items; i++)
12712     {
12713       name=(char *) SvPV(ST(i),na);
12714       magick_info=GetMagickInfo(name,exception);
12715       if (magick_info == (const MagickInfo *) NULL)
12716         {
12717           PUSHs(&sv_undef);
12718           continue;
12719         }
12720       PUSHs(sv_2mortal(newSViv(magick_info->adjoin)));
12721       PUSHs(sv_2mortal(newSViv(magick_info->blob_support)));
12722       PUSHs(sv_2mortal(newSViv(magick_info->raw)));
12723       PUSHs(sv_2mortal(newSViv((long) magick_info->decoder)));
12724       PUSHs(sv_2mortal(newSViv((long) magick_info->encoder)));
12725       if (magick_info->description == (char *) NULL)
12726         PUSHs(&sv_undef);
12727       else
12728         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
12729       if (magick_info->module == (char *) NULL)
12730         PUSHs(&sv_undef);
12731       else
12732         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
12733     }
12734
12735   PerlException:
12736     InheritPerlException(exception,perl_exception);
12737     exception=DestroyExceptionInfo(exception);
12738     SvREFCNT_dec(perl_exception);
12739   }
12740 \f
12741 #
12742 ###############################################################################
12743 #                                                                             #
12744 #                                                                             #
12745 #                                                                             #
12746 #   Q u e r y O p t i o n                                                     #
12747 #                                                                             #
12748 #                                                                             #
12749 #                                                                             #
12750 ###############################################################################
12751 #
12752 #
12753 void
12754 QueryOption(ref,...)
12755   Image::Magick ref=NO_INIT
12756   ALIAS:
12757     queryoption = 1
12758   PPCODE:
12759   {
12760     char
12761       **options;
12762
12763     ExceptionInfo
12764       *exception;
12765
12766     register ssize_t
12767       i;
12768
12769     ssize_t
12770       j,
12771       option;
12772
12773     SV
12774       *perl_exception;
12775
12776     PERL_UNUSED_VAR(ref);
12777     PERL_UNUSED_VAR(ix);
12778     exception=AcquireExceptionInfo();
12779     perl_exception=newSVpv("",0);
12780     EXTEND(sp,8*items);
12781     for (i=1; i < items; i++)
12782     {
12783       option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
12784         SvPV(ST(i),na));
12785       options=GetCommandOptions((CommandOption) option);
12786       if (options == (char **) NULL)
12787         PUSHs(&sv_undef);
12788       else
12789         {
12790           for (j=0; options[j] != (char *) NULL; j++)
12791             PUSHs(sv_2mortal(newSVpv(options[j],0)));
12792           options=DestroyStringList(options);
12793         }
12794     }
12795
12796     InheritPerlException(exception,perl_exception);
12797     exception=DestroyExceptionInfo(exception);
12798     SvREFCNT_dec(perl_exception);
12799   }
12800 \f
12801 #
12802 ###############################################################################
12803 #                                                                             #
12804 #                                                                             #
12805 #                                                                             #
12806 #   R e a d                                                                   #
12807 #                                                                             #
12808 #                                                                             #
12809 #                                                                             #
12810 ###############################################################################
12811 #
12812 #
12813 void
12814 Read(ref,...)
12815   Image::Magick ref=NO_INIT
12816   ALIAS:
12817     ReadImage  = 1
12818     read       = 2
12819     readimage  = 3
12820   PPCODE:
12821   {
12822     AV
12823       *av;
12824
12825     char
12826       **keep,
12827       **list;
12828
12829     ExceptionInfo
12830       *exception;
12831
12832     HV
12833       *hv;
12834
12835     Image
12836       *image;
12837
12838     int
12839       n;
12840
12841     MagickBooleanType
12842       status;
12843
12844     register char
12845       **p;
12846
12847     register ssize_t
12848       i;
12849
12850     ssize_t
12851       ac,
12852       number_images;
12853
12854     STRLEN
12855       *length;
12856
12857     struct PackageInfo
12858       *info,
12859       *package_info;
12860
12861     SV
12862       *perl_exception,  /* Perl variable for storing messages */
12863       *reference,
12864       *rv,
12865       *sv;
12866
12867     PERL_UNUSED_VAR(ref);
12868     PERL_UNUSED_VAR(ix);
12869     exception=AcquireExceptionInfo();
12870     perl_exception=newSVpv("",0);
12871     sv=NULL;
12872     package_info=(struct PackageInfo *) NULL;
12873     number_images=0;
12874     ac=(items < 2) ? 1 : items-1;
12875     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
12876     keep=list;
12877     length=(STRLEN *) NULL;
12878     if (list == (char **) NULL)
12879       {
12880         ThrowPerlException(exception,ResourceLimitError,
12881           "MemoryAllocationFailed",PackageName);
12882         goto PerlException;
12883       }
12884     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
12885     if (length == (STRLEN *) NULL)
12886       {
12887         ThrowPerlException(exception,ResourceLimitError,
12888           "MemoryAllocationFailed",PackageName);
12889         goto PerlException;
12890       }
12891     if (sv_isobject(ST(0)) == 0)
12892       {
12893         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12894           PackageName);
12895         goto PerlException;
12896       }
12897     reference=SvRV(ST(0));
12898     hv=SvSTASH(reference);
12899     if (SvTYPE(reference) != SVt_PVAV)
12900       {
12901         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12902           PackageName);
12903         goto PerlException;
12904       }
12905     av=(AV *) reference;
12906     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12907       exception);
12908     package_info=ClonePackageInfo(info,exception);
12909     n=1;
12910     if (items <= 1)
12911       *list=(char *) (*package_info->image_info->filename ?
12912         package_info->image_info->filename : "XC:black");
12913     else
12914       for (n=0, i=0; i < ac; i++)
12915       {
12916         list[n]=(char *) SvPV(ST(i+1),length[n]);
12917         if ((items >= 3) && strEQcase(list[n],"blob"))
12918           {
12919             void
12920               *blob;
12921
12922             i++;
12923             blob=(void *) (SvPV(ST(i+1),length[n]));
12924             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
12925           }
12926         if ((items >= 3) && strEQcase(list[n],"filename"))
12927           continue;
12928         if ((items >= 3) && strEQcase(list[n],"file"))
12929           {
12930             FILE
12931               *file;
12932
12933             PerlIO
12934               *io_info;
12935
12936             i++;
12937             io_info=IoIFP(sv_2io(ST(i+1)));
12938             if (io_info == (PerlIO *) NULL)
12939               {
12940                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12941                   PackageName);
12942                 continue;
12943               }
12944             file=PerlIO_findFILE(io_info);
12945             if (file == (FILE *) NULL)
12946               {
12947                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12948                   PackageName);
12949                 continue;
12950               }
12951             SetImageInfoFile(package_info->image_info,file);
12952           }
12953         if ((items >= 3) && strEQcase(list[n],"magick"))
12954           continue;
12955         n++;
12956       }
12957     list[n]=(char *) NULL;
12958     keep=list;
12959     status=ExpandFilenames(&n,&list);
12960     if (status == MagickFalse)
12961       {
12962         ThrowPerlException(exception,ResourceLimitError,
12963           "MemoryAllocationFailed",PackageName);
12964         goto PerlException;
12965       }
12966     number_images=0;
12967     for (i=0; i < n; i++)
12968     {
12969       if ((package_info->image_info->file != (FILE *) NULL) ||
12970           (package_info->image_info->blob != (void *) NULL))
12971         {
12972           image=ReadImages(package_info->image_info,exception);
12973           if (image != (Image *) NULL)
12974             DisassociateImageStream(image);
12975         }
12976       else
12977         {
12978           (void) CopyMagickString(package_info->image_info->filename,list[i],
12979             MaxTextExtent);
12980           image=ReadImages(package_info->image_info,exception);
12981         }
12982       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
12983         break;
12984       for ( ; image; image=image->next)
12985       {
12986         AddImageToRegistry(sv,image);
12987         rv=newRV(sv);
12988         av_push(av,sv_bless(rv,hv));
12989         SvREFCNT_dec(sv);
12990         number_images++;
12991       }
12992     }
12993     /*
12994       Free resources.
12995     */
12996     for (i=0; i < n; i++)
12997       if (list[i] != (char *) NULL)
12998         for (p=keep; list[i] != *p++; )
12999           if (*p == (char *) NULL)
13000             {
13001               list[i]=(char *) RelinquishMagickMemory(list[i]);
13002               break;
13003             }
13004
13005   PerlException:
13006     if (package_info != (struct PackageInfo *) NULL)
13007       DestroyPackageInfo(package_info);
13008     if (list && (list != keep))
13009       list=(char **) RelinquishMagickMemory(list);
13010     if (keep)
13011       keep=(char **) RelinquishMagickMemory(keep);
13012     if (length)
13013       length=(STRLEN *) RelinquishMagickMemory(length);
13014     InheritPerlException(exception,perl_exception);
13015     exception=DestroyExceptionInfo(exception);
13016     sv_setiv(perl_exception,(IV) number_images);
13017     SvPOK_on(perl_exception);
13018     ST(0)=sv_2mortal(perl_exception);
13019     XSRETURN(1);
13020   }
13021 \f
13022 #
13023 ###############################################################################
13024 #                                                                             #
13025 #                                                                             #
13026 #                                                                             #
13027 #   R e m o t e                                                               #
13028 #                                                                             #
13029 #                                                                             #
13030 #                                                                             #
13031 ###############################################################################
13032 #
13033 #
13034 void
13035 Remote(ref,...)
13036   Image::Magick ref=NO_INIT
13037   ALIAS:
13038     RemoteCommand  = 1
13039     remote         = 2
13040     remoteCommand  = 3
13041   PPCODE:
13042   {
13043     AV
13044       *av;
13045
13046     ExceptionInfo
13047       *exception;
13048
13049     register ssize_t
13050       i;
13051
13052     SV
13053       *perl_exception,
13054       *reference;
13055
13056     struct PackageInfo
13057       *info;
13058
13059     PERL_UNUSED_VAR(ref);
13060     PERL_UNUSED_VAR(ix);
13061     exception=AcquireExceptionInfo();
13062     perl_exception=newSVpv("",0);
13063     reference=SvRV(ST(0));
13064     av=(AV *) reference;
13065     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13066       exception);
13067     for (i=1; i < items; i++)
13068       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13069         SvPV(ST(i),na),exception);
13070     InheritPerlException(exception,perl_exception);
13071     exception=DestroyExceptionInfo(exception);
13072     SvREFCNT_dec(perl_exception);    /* throw away all errors */
13073   }
13074 \f
13075 #
13076 ###############################################################################
13077 #                                                                             #
13078 #                                                                             #
13079 #                                                                             #
13080 #   S e t                                                                     #
13081 #                                                                             #
13082 #                                                                             #
13083 #                                                                             #
13084 ###############################################################################
13085 #
13086 #
13087 void
13088 Set(ref,...)
13089   Image::Magick ref=NO_INIT
13090   ALIAS:
13091     SetAttributes  = 1
13092     SetAttribute   = 2
13093     set            = 3
13094     setattributes  = 4
13095     setattribute   = 5
13096   PPCODE:
13097   {
13098     ExceptionInfo
13099       *exception;
13100
13101     Image
13102       *image;
13103
13104     register ssize_t
13105       i;
13106
13107     struct PackageInfo
13108       *info;
13109
13110     SV
13111       *perl_exception,
13112       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13113
13114     PERL_UNUSED_VAR(ref);
13115     PERL_UNUSED_VAR(ix);
13116     exception=AcquireExceptionInfo();
13117     perl_exception=newSVpv("",0);
13118     if (sv_isobject(ST(0)) == 0)
13119       {
13120         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13121           PackageName);
13122         goto PerlException;
13123       }
13124     reference=SvRV(ST(0));
13125     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13126     if (items == 2)
13127       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13128     else
13129       for (i=2; i < items; i+=2)
13130         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13131
13132   PerlException:
13133     InheritPerlException(exception,perl_exception);
13134     exception=DestroyExceptionInfo(exception);
13135     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13136     SvPOK_on(perl_exception);
13137     ST(0)=sv_2mortal(perl_exception);
13138     XSRETURN(1);
13139   }
13140 \f
13141 #
13142 ###############################################################################
13143 #                                                                             #
13144 #                                                                             #
13145 #                                                                             #
13146 #   S e t P i x e l                                                           #
13147 #                                                                             #
13148 #                                                                             #
13149 #                                                                             #
13150 ###############################################################################
13151 #
13152 #
13153 void
13154 SetPixel(ref,...)
13155   Image::Magick ref=NO_INIT
13156   ALIAS:
13157     setpixel = 1
13158     setPixel = 2
13159   PPCODE:
13160   {
13161     AV
13162       *av;
13163
13164     char
13165       *attribute;
13166
13167     ChannelType
13168       channel;
13169
13170     ExceptionInfo
13171       *exception;
13172
13173     Image
13174       *image;
13175
13176     MagickBooleanType
13177       normalize;
13178
13179     RectangleInfo
13180       region;
13181
13182     register ssize_t
13183       i;
13184
13185     register Quantum
13186       *q;
13187
13188     ssize_t
13189       option;
13190
13191     struct PackageInfo
13192       *info;
13193
13194     SV
13195       *perl_exception,
13196       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13197
13198     PERL_UNUSED_VAR(ref);
13199     PERL_UNUSED_VAR(ix);
13200     exception=AcquireExceptionInfo();
13201     perl_exception=newSVpv("",0);
13202     reference=SvRV(ST(0));
13203     av=(AV *) reference;
13204     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13205       exception);
13206     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13207     if (image == (Image *) NULL)
13208       {
13209         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13210           PackageName);
13211         goto PerlException;
13212       }
13213     av=(AV *) NULL;
13214     channel=DefaultChannels;
13215     normalize=MagickTrue;
13216     region.x=0;
13217     region.y=0;
13218     region.width=image->columns;
13219     region.height=1;
13220     if (items == 1)
13221       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13222     for (i=2; i < items; i+=2)
13223     {
13224       attribute=(char *) SvPV(ST(i-1),na);
13225       switch (*attribute)
13226       {
13227         case 'C':
13228         case 'c':
13229         {
13230           if (LocaleCompare(attribute,"channel") == 0)
13231             {
13232               ssize_t
13233                 option;
13234
13235               option=ParseChannelOption(SvPV(ST(i),na));
13236               if (option < 0)
13237                 {
13238                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13239                     SvPV(ST(i),na));
13240                   return;
13241                 }
13242                channel=(ChannelType) option;
13243               break;
13244             }
13245           if (LocaleCompare(attribute,"color") == 0)
13246             {
13247               if (SvTYPE(ST(i)) != SVt_RV)
13248                 {
13249                   char
13250                     message[MaxTextExtent];
13251
13252                   (void) FormatLocaleString(message,MaxTextExtent,
13253                     "invalid %.60s value",attribute);
13254                   ThrowPerlException(exception,OptionError,message,
13255                     SvPV(ST(i),na));
13256                 }
13257               av=(AV *) SvRV(ST(i));
13258               break;
13259             }
13260           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13261             attribute);
13262           break;
13263         }
13264         case 'g':
13265         case 'G':
13266         {
13267           if (LocaleCompare(attribute,"geometry") == 0)
13268             {
13269               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
13270               break;
13271             }
13272           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13273             attribute);
13274           break;
13275         }
13276         case 'N':
13277         case 'n':
13278         {
13279           if (LocaleCompare(attribute,"normalize") == 0)
13280             {
13281               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13282                 SvPV(ST(i),na));
13283               if (option < 0)
13284                 {
13285                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13286                     SvPV(ST(i),na));
13287                   break;
13288                 }
13289              normalize=option != 0 ? MagickTrue : MagickFalse;
13290              break;
13291             }
13292           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13293             attribute);
13294           break;
13295         }
13296         case 'x':
13297         case 'X':
13298         {
13299           if (LocaleCompare(attribute,"x") == 0)
13300             {
13301               region.x=SvIV(ST(i));
13302               break;
13303             }
13304           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13305             attribute);
13306           break;
13307         }
13308         case 'y':
13309         case 'Y':
13310         {
13311           if (LocaleCompare(attribute,"y") == 0)
13312             {
13313               region.y=SvIV(ST(i));
13314               break;
13315             }
13316           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13317             attribute);
13318           break;
13319         }
13320         default:
13321         {
13322           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13323             attribute);
13324           break;
13325         }
13326       }
13327     }
13328     (void) SetImageStorageClass(image,DirectClass);
13329     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
13330     if ((q == (const Quantum *) NULL) || (av == (AV *) NULL) ||
13331         (SvTYPE(av) != SVt_PVAV))
13332       PUSHs(&sv_undef);
13333     else
13334       {
13335         double
13336           scale;
13337
13338         register ssize_t
13339           i;
13340
13341         i=0;
13342         scale=1.0;
13343         if (normalize != MagickFalse)
13344           scale=QuantumRange;
13345         if (((GetPixelRedTraits(image) & ActivePixelTrait) != 0) && (i <= av_len(av)))
13346           {
13347             SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
13348               av_fetch(av,i,0)))),q);
13349             i++;
13350           }
13351         if (((GetPixelGreenTraits(image) & ActivePixelTrait) != 0) && (i <= av_len(av)))
13352           {
13353             SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
13354               av_fetch(av,i,0)))),q);
13355             i++;
13356           }
13357         if (((GetPixelBlueTraits(image) & ActivePixelTrait) != 0) && (i <= av_len(av)))
13358           {
13359             SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
13360               av_fetch(av,i,0)))),q);
13361             i++;
13362           }
13363         if ((((GetPixelBlackTraits(image) & ActivePixelTrait) != 0) &&
13364             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
13365           {
13366             SetPixelBlack(image,ClampToQuantum(scale*
13367               SvNV(*(av_fetch(av,i,0)))),q);
13368             i++;
13369           }
13370         if (((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0) && (i <= av_len(av)))
13371           {
13372             SetPixelAlpha(image,ClampToQuantum(scale*
13373               SvNV(*(av_fetch(av,i,0)))),q);
13374             i++;
13375           }
13376         (void) SyncAuthenticPixels(image,exception);
13377       }
13378
13379   PerlException:
13380     InheritPerlException(exception,perl_exception);
13381     exception=DestroyExceptionInfo(exception);
13382     SvREFCNT_dec(perl_exception);
13383   }
13384 \f
13385 #
13386 ###############################################################################
13387 #                                                                             #
13388 #                                                                             #
13389 #                                                                             #
13390 #   S m u s h                                                                 #
13391 #                                                                             #
13392 #                                                                             #
13393 #                                                                             #
13394 ###############################################################################
13395 #
13396 #
13397 void
13398 Smush(ref,...)
13399   Image::Magick ref=NO_INIT
13400   ALIAS:
13401     SmushImage  = 1
13402     smush       = 2
13403     smushimage  = 3
13404   PPCODE:
13405   {
13406     AV
13407       *av;
13408
13409     char
13410       *attribute;
13411
13412     ExceptionInfo
13413       *exception;
13414
13415     HV
13416       *hv;
13417
13418     Image
13419       *image;
13420
13421     register ssize_t
13422       i;
13423
13424     ssize_t
13425       offset,
13426       stack;
13427
13428     struct PackageInfo
13429       *info;
13430
13431     SV
13432       *av_reference,
13433       *perl_exception,
13434       *reference,
13435       *rv,
13436       *sv;
13437
13438     PERL_UNUSED_VAR(ref);
13439     PERL_UNUSED_VAR(ix);
13440     exception=AcquireExceptionInfo();
13441     perl_exception=newSVpv("",0);
13442     sv=NULL;
13443     attribute=NULL;
13444     av=NULL;
13445     if (sv_isobject(ST(0)) == 0)
13446       {
13447         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13448           PackageName);
13449         goto PerlException;
13450       }
13451     reference=SvRV(ST(0));
13452     hv=SvSTASH(reference);
13453     av=newAV();
13454     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13455     SvREFCNT_dec(av);
13456     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13457     if (image == (Image *) NULL)
13458       {
13459         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13460           PackageName);
13461         goto PerlException;
13462       }
13463     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13464     /*
13465       Get options.
13466     */
13467     offset=0;
13468     stack=MagickTrue;
13469     for (i=2; i < items; i+=2)
13470     {
13471       attribute=(char *) SvPV(ST(i-1),na);
13472       switch (*attribute)
13473       {
13474         case 'O':
13475         case 'o':
13476         {
13477           if (LocaleCompare(attribute,"offset") == 0)
13478             {
13479               offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
13480               break;
13481             }
13482           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13483             attribute);
13484           break;
13485         }
13486         case 'S':
13487         case 's':
13488         {
13489           if (LocaleCompare(attribute,"stack") == 0)
13490             {
13491               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13492                 SvPV(ST(i),na));
13493               if (stack < 0)
13494                 {
13495                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13496                     SvPV(ST(i),na));
13497                   return;
13498                 }
13499               break;
13500             }
13501           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13502             attribute);
13503           break;
13504         }
13505         default:
13506         {
13507           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13508             attribute);
13509           break;
13510         }
13511       }
13512     }
13513     image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
13514       exception);
13515     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
13516       goto PerlException;
13517     for ( ; image; image=image->next)
13518     {
13519       AddImageToRegistry(sv,image);
13520       rv=newRV(sv);
13521       av_push(av,sv_bless(rv,hv));
13522       SvREFCNT_dec(sv);
13523     }
13524     exception=DestroyExceptionInfo(exception);
13525     ST(0)=av_reference;
13526     SvREFCNT_dec(perl_exception);
13527     XSRETURN(1);
13528
13529   PerlException:
13530     InheritPerlException(exception,perl_exception);
13531     exception=DestroyExceptionInfo(exception);
13532     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
13533     SvPOK_on(perl_exception);
13534     ST(0)=sv_2mortal(perl_exception);
13535     XSRETURN(1);
13536   }
13537 \f
13538 #
13539 ###############################################################################
13540 #                                                                             #
13541 #                                                                             #
13542 #                                                                             #
13543 #   S t a t i s t i c s                                                       #
13544 #                                                                             #
13545 #                                                                             #
13546 #                                                                             #
13547 ###############################################################################
13548 #
13549 #
13550 void
13551 Statistics(ref,...)
13552   Image::Magick ref=NO_INIT
13553   ALIAS:
13554     StatisticsImage = 1
13555     statistics      = 2
13556     statisticsimage = 3
13557   PPCODE:
13558   {
13559 #define ChannelStatistics(channel) \
13560 { \
13561   (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
13562     (double) channel_statistics[channel].depth); \
13563   PUSHs(sv_2mortal(newSVpv(message,0))); \
13564   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13565     channel_statistics[channel].minima/scale); \
13566   PUSHs(sv_2mortal(newSVpv(message,0))); \
13567   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13568     channel_statistics[channel].maxima/scale); \
13569   PUSHs(sv_2mortal(newSVpv(message,0))); \
13570   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13571     channel_statistics[channel].mean/scale); \
13572   PUSHs(sv_2mortal(newSVpv(message,0))); \
13573   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13574     channel_statistics[channel].standard_deviation/scale); \
13575   PUSHs(sv_2mortal(newSVpv(message,0))); \
13576   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13577     channel_statistics[channel].kurtosis); \
13578   PUSHs(sv_2mortal(newSVpv(message,0))); \
13579   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13580     channel_statistics[channel].skewness); \
13581   PUSHs(sv_2mortal(newSVpv(message,0))); \
13582 }
13583
13584     AV
13585       *av;
13586
13587     char
13588       message[MaxTextExtent];
13589
13590     ChannelStatistics
13591       *channel_statistics;
13592
13593     double
13594       scale;
13595
13596     ExceptionInfo
13597       *exception;
13598
13599     Image
13600       *image;
13601
13602     ssize_t
13603       count;
13604
13605     struct PackageInfo
13606       *info;
13607
13608     SV
13609       *perl_exception,
13610       *reference;
13611
13612     PERL_UNUSED_VAR(ref);
13613     PERL_UNUSED_VAR(ix);
13614     exception=AcquireExceptionInfo();
13615     perl_exception=newSVpv("",0);
13616     av=NULL;
13617     if (sv_isobject(ST(0)) == 0)
13618       {
13619         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13620           PackageName);
13621         goto PerlException;
13622       }
13623     reference=SvRV(ST(0));
13624     av=newAV();
13625     SvREFCNT_dec(av);
13626     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13627     if (image == (Image *) NULL)
13628       {
13629         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13630           PackageName);
13631         goto PerlException;
13632       }
13633     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13634     count=0;
13635     for ( ; image; image=image->next)
13636     {
13637       channel_statistics=GetImageChannelStatistics(image,&image->exception);
13638       if (channel_statistics == (ChannelStatistics *) NULL)
13639         continue;
13640       count++;
13641       EXTEND(sp,35*count);
13642       scale=(double) QuantumRange;
13643       ChannelStatistics(RedChannel);
13644       ChannelStatistics(GreenChannel);
13645       ChannelStatistics(BlueChannel);
13646       if (image->colorspace == CMYKColorspace)
13647         ChannelStatistics(BlackChannel);
13648       if (image->matte != MagickFalse)
13649         ChannelStatistics(AlphaChannel);
13650       channel_statistics=(ChannelStatistics *)
13651         RelinquishMagickMemory(channel_statistics);
13652     }
13653
13654   PerlException:
13655     InheritPerlException(exception,perl_exception);
13656     exception=DestroyExceptionInfo(exception);
13657     SvREFCNT_dec(perl_exception);
13658   }
13659 \f
13660 #
13661 ###############################################################################
13662 #                                                                             #
13663 #                                                                             #
13664 #                                                                             #
13665 #   S y n c A u t h e n t i c P i x e l s                                     #
13666 #                                                                             #
13667 #                                                                             #
13668 #                                                                             #
13669 ###############################################################################
13670 #
13671 #
13672 void
13673 SyncAuthenticPixels(ref,...)
13674   Image::Magick ref = NO_INIT
13675   ALIAS:
13676     Syncauthenticpixels = 1
13677     SyncImagePixels = 2
13678     syncimagepixels = 3
13679   CODE:
13680   {
13681     ExceptionInfo
13682       *exception;
13683
13684     Image
13685       *image;
13686
13687     MagickBooleanType
13688       status;
13689
13690     struct PackageInfo
13691       *info;
13692
13693     SV
13694       *perl_exception,
13695       *reference;
13696
13697     PERL_UNUSED_VAR(ref);
13698     PERL_UNUSED_VAR(ix);
13699     exception=AcquireExceptionInfo();
13700     perl_exception=newSVpv("",0);
13701     if (sv_isobject(ST(0)) == 0)
13702       {
13703         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13704           PackageName);
13705         goto PerlException;
13706       }
13707
13708     reference=SvRV(ST(0));
13709     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13710     if (image == (Image *) NULL)
13711       {
13712         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13713           PackageName);
13714         goto PerlException;
13715       }
13716
13717     status=SyncAuthenticPixels(image,exception);
13718     if (status != MagickFalse)
13719       return;
13720     InheritException(exception,&image->exception);
13721
13722   PerlException:
13723     InheritPerlException(exception,perl_exception);
13724     exception=DestroyExceptionInfo(exception);
13725     SvREFCNT_dec(perl_exception);  /* throw away all errors */
13726   }
13727 \f
13728 #
13729 ###############################################################################
13730 #                                                                             #
13731 #                                                                             #
13732 #                                                                             #
13733 #   T r a n s f o r m                                                         #
13734 #                                                                             #
13735 #                                                                             #
13736 #                                                                             #
13737 ###############################################################################
13738 #
13739 #
13740 void
13741 Transform(ref,...)
13742   Image::Magick ref=NO_INIT
13743   ALIAS:
13744     TransformImage = 1
13745     transform      = 2
13746     transformimage = 3
13747   PPCODE:
13748   {
13749     AV
13750       *av;
13751
13752     char
13753       *attribute,
13754       *crop_geometry,
13755       *geometry;
13756
13757     ExceptionInfo
13758       *exception;
13759
13760     HV
13761       *hv;
13762
13763     Image
13764       *clone,
13765       *image;
13766
13767     register ssize_t
13768       i;
13769
13770     struct PackageInfo
13771       *info;
13772
13773     SV
13774       *av_reference,
13775       *perl_exception,
13776       *reference,
13777       *rv,
13778       *sv;
13779
13780     PERL_UNUSED_VAR(ref);
13781     PERL_UNUSED_VAR(ix);
13782     exception=AcquireExceptionInfo();
13783     perl_exception=newSVpv("",0);
13784     sv=NULL;
13785     av=NULL;
13786     attribute=NULL;
13787     if (sv_isobject(ST(0)) == 0)
13788       {
13789         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13790           PackageName);
13791         goto PerlException;
13792       }
13793     reference=SvRV(ST(0));
13794     hv=SvSTASH(reference);
13795     av=newAV();
13796     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13797     SvREFCNT_dec(av);
13798     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13799     if (image == (Image *) NULL)
13800       {
13801         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13802           PackageName);
13803         goto PerlException;
13804       }
13805     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13806     /*
13807       Get attribute.
13808     */
13809     crop_geometry=(char *) NULL;
13810     geometry=(char *) NULL;
13811     for (i=2; i < items; i+=2)
13812     {
13813       attribute=(char *) SvPV(ST(i-1),na);
13814       switch (*attribute)
13815       {
13816         case 'c':
13817         case 'C':
13818         {
13819           if (LocaleCompare(attribute,"crop") == 0)
13820             {
13821               crop_geometry=SvPV(ST(i),na);
13822               break;
13823             }
13824           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13825             attribute);
13826           break;
13827         }
13828         case 'g':
13829         case 'G':
13830         {
13831           if (LocaleCompare(attribute,"geometry") == 0)
13832             {
13833               geometry=SvPV(ST(i),na);
13834               break;
13835             }
13836          if (LocaleCompare(attribute,"gravity") == 0)
13837            {
13838              Image
13839                *next;
13840
13841              ssize_t
13842                in;
13843
13844              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
13845                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13846              if (in < 0)
13847                {
13848                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
13849                    SvPV(ST(i),na));
13850                  return;
13851                }
13852              for (next=image; next; next=next->next)
13853                next->gravity=(GravityType) in;
13854              break;
13855            }
13856           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13857             attribute);
13858           break;
13859         }
13860         default:
13861         {
13862           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13863             attribute);
13864           break;
13865         }
13866       }
13867     }
13868     for ( ; image; image=image->next)
13869     {
13870       clone=CloneImage(image,0,0,MagickTrue,exception);
13871       if ((clone == (Image *) NULL) || (exception->severity >= ErrorException))
13872         goto PerlException;
13873       TransformImage(&clone,crop_geometry,geometry);
13874       for ( ; clone; clone=clone->next)
13875       {
13876         AddImageToRegistry(sv,clone);
13877         rv=newRV(sv);
13878         av_push(av,sv_bless(rv,hv));
13879         SvREFCNT_dec(sv);
13880       }
13881     }
13882     exception=DestroyExceptionInfo(exception);
13883     ST(0)=av_reference;
13884     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13885     XSRETURN(1);
13886
13887   PerlException:
13888     InheritPerlException(exception,perl_exception);
13889     exception=DestroyExceptionInfo(exception);
13890     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
13891     SvPOK_on(perl_exception);
13892     ST(0)=sv_2mortal(perl_exception);
13893     XSRETURN(1);
13894   }
13895 \f
13896 #
13897 ###############################################################################
13898 #                                                                             #
13899 #                                                                             #
13900 #                                                                             #
13901 #   W r i t e                                                                 #
13902 #                                                                             #
13903 #                                                                             #
13904 #                                                                             #
13905 ###############################################################################
13906 #
13907 #
13908 void
13909 Write(ref,...)
13910   Image::Magick ref=NO_INIT
13911   ALIAS:
13912     WriteImage    = 1
13913     write         = 2
13914     writeimage    = 3
13915   PPCODE:
13916   {
13917     char
13918       filename[MaxTextExtent];
13919
13920     ExceptionInfo
13921       *exception;
13922
13923     Image
13924       *image,
13925       *next;
13926
13927     register ssize_t
13928       i;
13929
13930     ssize_t
13931       number_images,
13932       scene;
13933
13934     struct PackageInfo
13935       *info,
13936       *package_info;
13937
13938     SV
13939       *perl_exception,
13940       *reference;
13941
13942     PERL_UNUSED_VAR(ref);
13943     PERL_UNUSED_VAR(ix);
13944     exception=AcquireExceptionInfo();
13945     perl_exception=newSVpv("",0);
13946     number_images=0;
13947     package_info=(struct PackageInfo *) NULL;
13948     if (sv_isobject(ST(0)) == 0)
13949       {
13950         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13951           PackageName);
13952         goto PerlException;
13953       }
13954     reference=SvRV(ST(0));
13955     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13956     if (image == (Image *) NULL)
13957       {
13958         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13959           PackageName);
13960         goto PerlException;
13961       }
13962     package_info=ClonePackageInfo(info,exception);
13963     if (items == 2)
13964       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
13965     else
13966       if (items > 2)
13967         for (i=2; i < items; i+=2)
13968           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
13969             exception);
13970     (void) CopyMagickString(filename,package_info->image_info->filename,
13971       MaxTextExtent);
13972     scene=0;
13973     for (next=image; next; next=next->next)
13974     {
13975       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
13976       next->scene=scene++;
13977     }
13978     SetImageInfo(package_info->image_info,(unsigned int)
13979       GetImageListLength(image),&image->exception);
13980     for (next=image; next; next=next->next)
13981     {
13982       (void) WriteImage(package_info->image_info,next);
13983       if (next->exception.severity >= ErrorException)
13984         InheritException(exception,&next->exception);
13985       GetImageException(next,exception);
13986       number_images++;
13987       if (package_info->image_info->adjoin)
13988         break;
13989     }
13990
13991   PerlException:
13992     if (package_info != (struct PackageInfo *) NULL)
13993       DestroyPackageInfo(package_info);
13994     InheritPerlException(exception,perl_exception);
13995     exception=DestroyExceptionInfo(exception);
13996     sv_setiv(perl_exception,(IV) number_images);
13997     SvPOK_on(perl_exception);
13998     ST(0)=sv_2mortal(perl_exception);
13999     XSRETURN(1);
14000   }