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