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