]> 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       {"kernel", StringReference} } },
391     { "Profile", { {"name", StringReference}, {"profile", StringReference},
392       { "rendering-intent", MagickIntentOptions},
393       { "black-point-compensation", MagickBooleanOptions} } },
394     { "UnsharpMask", { {"geometry", StringReference},
395       {"radius", RealReference}, {"sigma", RealReference},
396       {"amount", RealReference}, {"threshold", RealReference},
397       {"channel", MagickChannelOptions} } },
398     { "MotionBlur", { {"geometry", StringReference},
399       {"radius", RealReference}, {"sigma", RealReference},
400       {"angle", RealReference}, {"channel", MagickChannelOptions} } },
401     { "OrderedDither", { {"threshold", StringReference},
402       {"channel", MagickChannelOptions} } },
403     { "Shave", { {"geometry", StringReference}, {"width", IntegerReference},
404       {"height", IntegerReference} } },
405     { "Level", { {"levels", StringReference}, {"black-point", RealReference},
406       {"white-point", RealReference}, {"gamma", RealReference},
407       {"channel", MagickChannelOptions}, {"level", StringReference} } },
408     { "Clip", { {"id", StringReference}, {"inside", MagickBooleanOptions} } },
409     { "AffineTransform", { {"affine", ArrayReference},
410       {"translate", StringReference}, {"scale", StringReference},
411       {"rotate", RealReference}, {"skewX", RealReference},
412       {"skewY", RealReference}, {"interpolate", MagickInterpolateOptions},
413       {"background", StringReference} } },
414     { "Difference", { {"image", ImageReference}, {"fuzz", StringReference} } },
415     { "AdaptiveThreshold", { {"geometry", StringReference},
416       {"width", IntegerReference}, {"height", IntegerReference},
417       {"bias", RealReference} } },
418     { "Resample", { {"density", StringReference}, {"x", RealReference},
419       {"y", RealReference}, {"filter", MagickFilterOptions},
420       {"support", RealReference }, {"blur", RealReference } } },
421     { "Describe", { {"file", FileReference} } },
422     { "BlackThreshold", { {"threshold", StringReference},
423       {"channel", MagickChannelOptions} } },
424     { "WhiteThreshold", { {"threshold", StringReference},
425       {"channel", MagickChannelOptions} } },
426     { "RadialBlur", { {"geometry", StringReference}, {"angle", RealReference},
427       {"channel", MagickChannelOptions} } },
428     { "Thumbnail", { {"geometry", StringReference}, {"width", IntegerReference},
429       {"height", IntegerReference} } },
430     { "Strip", },
431     { "Tint", { {"fill", StringReference}, {"opacity", StringReference} } },
432     { "Channel", { {"channel", MagickChannelOptions} } },
433     { "Splice", { {"geometry", StringReference}, {"width", IntegerReference},
434       {"height", IntegerReference}, {"x", IntegerReference},
435       {"y", IntegerReference}, {"fuzz", StringReference},
436       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
437     { "Posterize", { {"levels", IntegerReference},
438       {"dither", MagickBooleanOptions} } },
439     { "Shadow", { {"geometry", StringReference}, {"opacity", RealReference},
440       {"sigma", RealReference}, {"x", IntegerReference},
441       {"y", IntegerReference} } },
442     { "Identify", { {"file", FileReference}, {"features", StringReference},
443       {"unique", MagickBooleanOptions} } },
444     { "SepiaTone", { {"threshold", RealReference} } },
445     { "SigmoidalContrast", { {"geometry", StringReference},
446       {"contrast", RealReference}, {"mid-point", RealReference},
447       {"channel", MagickChannelOptions}, {"sharpen", MagickBooleanOptions} } },
448     { "Extent", { {"geometry", StringReference}, {"width", IntegerReference},
449       {"height", IntegerReference}, {"x", IntegerReference},
450       {"y", IntegerReference}, {"fuzz", StringReference},
451       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
452     { "Vignette", { {"geometry", StringReference}, {"radius", RealReference},
453       {"sigma", RealReference}, {"x", IntegerReference},
454       {"y", IntegerReference}, {"background", StringReference} } },
455     { "ContrastStretch", { {"levels", StringReference},
456       {"black-point", RealReference},{"white-point", RealReference},
457       {"channel", MagickChannelOptions} } },
458     { "Sans0", },
459     { "Sans1", },
460     { "AdaptiveSharpen", { {"geometry", StringReference},
461       {"radius", RealReference}, {"sigma", RealReference},
462       {"channel", MagickChannelOptions} } },
463     { "Transpose", },
464     { "Transverse", },
465     { "AutoOrient", },
466     { "AdaptiveBlur", { {"geometry", StringReference},
467       {"radius", RealReference}, {"sigma", RealReference},
468       {"channel", MagickChannelOptions} } },
469     { "Sketch", { {"geometry", StringReference},
470       {"radius", RealReference}, {"sigma", RealReference},
471       {"angle", RealReference} } },
472     { "UniqueColors", },
473     { "AdaptiveResize", { {"geometry", StringReference},
474       {"width", IntegerReference}, {"height", IntegerReference},
475       {"filter", MagickFilterOptions}, {"support", StringReference },
476       {"blur", RealReference } } },
477     { "ClipMask", { {"mask", ImageReference} } },
478     { "LinearStretch", { {"levels", StringReference},
479       {"black-point", RealReference},{"white-point", RealReference} } },
480     { "Recolor", { {"matrix", ArrayReference} } },
481     { "Mask", { {"mask", ImageReference} } },
482     { "Polaroid", { {"caption", StringReference}, {"angle", RealReference},
483       {"font", StringReference}, {"stroke", StringReference},
484       {"fill", StringReference}, {"strokewidth", RealReference},
485       {"pointsize", RealReference}, {"gravity", MagickGravityOptions},
486       {"background", StringReference} } },
487     { "FloodfillPaint", { {"geometry", StringReference},
488       {"x", IntegerReference}, {"y", IntegerReference},
489       {"fill", StringReference}, {"bordercolor", StringReference},
490       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
491       {"invert", MagickBooleanOptions} } },
492     { "Distort", { {"points", ArrayReference}, {"method", MagickDistortOptions},
493       {"virtual-pixel", MagickVirtualPixelOptions},
494       {"best-fit", MagickBooleanOptions} } },
495     { "Clut", { {"image", ImageReference},
496       {"channel", MagickChannelOptions} } },
497     { "LiquidRescale", { {"geometry", StringReference},
498       {"width", IntegerReference}, {"height", IntegerReference},
499       {"delta-x", RealReference}, {"rigidity", RealReference } } },
500     { "Encipher", { {"passphrase", StringReference} } },
501     { "Decipher", { {"passphrase", StringReference} } },
502     { "Deskew", { {"geometry", StringReference},
503       {"threshold", StringReference} } },
504     { "Remap", { {"image", ImageReference}, {"dither", MagickBooleanOptions},
505       {"dither-method", MagickDitherOptions} } },
506     { "SparseColor", { {"points", ArrayReference},
507       {"method", MagickSparseColorOptions},
508       {"virtual-pixel", MagickVirtualPixelOptions},
509       {"channel", MagickChannelOptions} } },
510     { "Function", { {"parameters", ArrayReference},
511       {"function", MagickFunctionOptions},
512       {"virtual-pixel", MagickVirtualPixelOptions} } },
513     { "SelectiveBlur", { {"geometry", StringReference},
514       {"radius", RealReference}, {"sigma", RealReference},
515       {"threshold", RealReference}, {"channel", MagickChannelOptions} } },
516     { "HaldClut", { {"image", ImageReference},
517       {"channel", MagickChannelOptions} } },
518     { "BlueShift", { {"factor", StringReference} } },
519     { "ForwardFourierTransform", { {"magnitude", MagickBooleanOptions} } },
520     { "InverseFourierTransform", { {"magnitude", MagickBooleanOptions} } },
521     { "ColorDecisionList", {
522       {"color-correction-collection", StringReference} } },
523     { "AutoGamma", { {"channel", MagickChannelOptions} } },
524     { "AutoLevel", { {"channel", MagickChannelOptions} } },
525     { "LevelColors", { {"invert", MagickBooleanOptions},
526       {"black-point", StringReference}, {"white-point", StringReference},
527       {"channel", MagickChannelOptions}, {"invert", MagickBooleanOptions} } },
528     { "Clamp", { {"channel", MagickChannelOptions} } },
529     { "BrightnessContrast", { {"levels", StringReference},
530       {"brightness", RealReference},{"contrast", RealReference},
531       {"channel", MagickChannelOptions} } },
532     { "Morphology", { {"kernel", StringReference},
533       {"channel", MagickChannelOptions}, {"method", MagickMorphologyOptions},
534       {"iterations", IntegerReference} } },
535     { "ColorMatrix", { {"matrix", ArrayReference} } },
536     { "Color", { {"color", StringReference} } },
537     { "Mode", { {"geometry", StringReference},
538       {"width", IntegerReference},{"height", IntegerReference},
539       {"channel", MagickChannelOptions} } },
540     { "Statistic", { {"geometry", StringReference},
541       {"width", IntegerReference},{"height", IntegerReference},
542       {"channel", MagickChannelOptions}, {"type", MagickStatisticOptions} } }
543   };
544
545 static SplayTreeInfo
546   *magick_registry = (SplayTreeInfo *) NULL;
547 \f
548 /*
549   Forward declarations.
550 */
551 static Image
552   *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
553
554 static ssize_t
555   strEQcase(const char *,const char *);
556 \f
557 /*
558 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
559 %                                                                             %
560 %                                                                             %
561 %                                                                             %
562 %   C l o n e P a c k a g e I n f o                                           %
563 %                                                                             %
564 %                                                                             %
565 %                                                                             %
566 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
567 %
568 %  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
569 %  a new one.
570 %
571 %  The format of the ClonePackageInfo routine is:
572 %
573 %      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
574 %        exception)
575 %
576 %  A description of each parameter follows:
577 %
578 %    o info: a structure of type info.
579 %
580 %    o exception: Return any errors or warnings in this structure.
581 %
582 */
583 static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
584   ExceptionInfo *exception)
585 {
586   struct PackageInfo
587     *clone_info;
588
589   clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
590   if (clone_info == (struct PackageInfo *) NULL)
591     {
592       ThrowPerlException(exception,ResourceLimitError,
593         "UnableToClonePackageInfo",PackageName);
594       return((struct PackageInfo *) NULL);
595     }
596   if (info == (struct PackageInfo *) NULL)
597     {
598       clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
599       return(clone_info);
600     }
601   *clone_info=(*info);
602   clone_info->image_info=CloneImageInfo(info->image_info);
603   return(clone_info);
604 }
605 \f
606 /*
607 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
608 %                                                                             %
609 %                                                                             %
610 %                                                                             %
611 %   c o n s t a n t                                                           %
612 %                                                                             %
613 %                                                                             %
614 %                                                                             %
615 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
616 %
617 %  constant() returns a double value for the specified name.
618 %
619 %  The format of the constant routine is:
620 %
621 %      double constant(char *name,ssize_t sans)
622 %
623 %  A description of each parameter follows:
624 %
625 %    o value: Method constant returns a double value for the specified name.
626 %
627 %    o name: The name of the constant.
628 %
629 %    o sans: This integer value is not used.
630 %
631 */
632 static double constant(char *name,ssize_t sans)
633 {
634   (void) sans;
635   errno=0;
636   switch (*name)
637   {
638     case 'B':
639     {
640       if (strEQ(name,"BlobError"))
641         return(BlobError);
642       if (strEQ(name,"BlobWarning"))
643         return(BlobWarning);
644       break;
645     }
646     case 'C':
647     {
648       if (strEQ(name,"CacheError"))
649         return(CacheError);
650       if (strEQ(name,"CacheWarning"))
651         return(CacheWarning);
652       if (strEQ(name,"CoderError"))
653         return(CoderError);
654       if (strEQ(name,"CoderWarning"))
655         return(CoderWarning);
656       if (strEQ(name,"ConfigureError"))
657         return(ConfigureError);
658       if (strEQ(name,"ConfigureWarning"))
659         return(ConfigureWarning);
660       if (strEQ(name,"CorruptImageError"))
661         return(CorruptImageError);
662       if (strEQ(name,"CorruptImageWarning"))
663         return(CorruptImageWarning);
664       break;
665     }
666     case 'D':
667     {
668       if (strEQ(name,"DelegateError"))
669         return(DelegateError);
670       if (strEQ(name,"DelegateWarning"))
671         return(DelegateWarning);
672       if (strEQ(name,"DrawError"))
673         return(DrawError);
674       if (strEQ(name,"DrawWarning"))
675         return(DrawWarning);
676       break;
677     }
678     case 'E':
679     {
680       if (strEQ(name,"ErrorException"))
681         return(ErrorException);
682       if (strEQ(name,"ExceptionError"))
683         return(CoderError);
684       if (strEQ(name,"ExceptionWarning"))
685         return(CoderWarning);
686       break;
687     }
688     case 'F':
689     {
690       if (strEQ(name,"FatalErrorException"))
691         return(FatalErrorException);
692       if (strEQ(name,"FileOpenError"))
693         return(FileOpenError);
694       if (strEQ(name,"FileOpenWarning"))
695         return(FileOpenWarning);
696       break;
697     }
698     case 'I':
699     {
700       if (strEQ(name,"ImageError"))
701         return(ImageError);
702       if (strEQ(name,"ImageWarning"))
703         return(ImageWarning);
704       break;
705     }
706     case 'M':
707     {
708       if (strEQ(name,"MaxRGB"))
709         return(QuantumRange);
710       if (strEQ(name,"MissingDelegateError"))
711         return(MissingDelegateError);
712       if (strEQ(name,"MissingDelegateWarning"))
713         return(MissingDelegateWarning);
714       if (strEQ(name,"ModuleError"))
715         return(ModuleError);
716       if (strEQ(name,"ModuleWarning"))
717         return(ModuleWarning);
718       break;
719     }
720     case 'O':
721     {
722       if (strEQ(name,"Opaque"))
723         return(OpaqueAlpha);
724       if (strEQ(name,"OptionError"))
725         return(OptionError);
726       if (strEQ(name,"OptionWarning"))
727         return(OptionWarning);
728       break;
729     }
730     case 'Q':
731     {
732       if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
733         return(MAGICKCORE_QUANTUM_DEPTH);
734       if (strEQ(name,"QuantumDepth"))
735         return(MAGICKCORE_QUANTUM_DEPTH);
736       if (strEQ(name,"QuantumRange"))
737         return(QuantumRange);
738       break;
739     }
740     case 'R':
741     {
742       if (strEQ(name,"ResourceLimitError"))
743         return(ResourceLimitError);
744       if (strEQ(name,"ResourceLimitWarning"))
745         return(ResourceLimitWarning);
746       if (strEQ(name,"RegistryError"))
747         return(RegistryError);
748       if (strEQ(name,"RegistryWarning"))
749         return(RegistryWarning);
750       break;
751     }
752     case 'S':
753     {
754       if (strEQ(name,"StreamError"))
755         return(StreamError);
756       if (strEQ(name,"StreamWarning"))
757         return(StreamWarning);
758       if (strEQ(name,"Success"))
759         return(0);
760       break;
761     }
762     case 'T':
763     {
764       if (strEQ(name,"Transparent"))
765         return(TransparentAlpha);
766       if (strEQ(name,"TypeError"))
767         return(TypeError);
768       if (strEQ(name,"TypeWarning"))
769         return(TypeWarning);
770       break;
771     }
772     case 'W':
773     {
774       if (strEQ(name,"WarningException"))
775         return(WarningException);
776       break;
777     }
778     case 'X':
779     {
780       if (strEQ(name,"XServerError"))
781         return(XServerError);
782       if (strEQ(name,"XServerWarning"))
783         return(XServerWarning);
784       break;
785     }
786   }
787   errno=EINVAL;
788   return(0);
789 }
790 \f
791 /*
792 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
793 %                                                                             %
794 %                                                                             %
795 %                                                                             %
796 %   D e s t r o y P a c k a g e I n f o                                       %
797 %                                                                             %
798 %                                                                             %
799 %                                                                             %
800 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
801 %
802 %  Method DestroyPackageInfo frees a previously created info structure.
803 %
804 %  The format of the DestroyPackageInfo routine is:
805 %
806 %      DestroyPackageInfo(struct PackageInfo *info)
807 %
808 %  A description of each parameter follows:
809 %
810 %    o info: a structure of type info.
811 %
812 */
813 static void DestroyPackageInfo(struct PackageInfo *info)
814 {
815   info->image_info=DestroyImageInfo(info->image_info);
816   info=(struct PackageInfo *) RelinquishMagickMemory(info);
817 }
818 \f
819 /*
820 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
821 %                                                                             %
822 %                                                                             %
823 %                                                                             %
824 %   G e t L i s t                                                             %
825 %                                                                             %
826 %                                                                             %
827 %                                                                             %
828 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
829 %
830 %  Method GetList is recursively called by SetupList to traverse the
831 %  Image__Magick reference.  If building an reference_vector (see SetupList),
832 %  *current is the current position in *reference_vector and *last is the final
833 %  entry in *reference_vector.
834 %
835 %  The format of the GetList routine is:
836 %
837 %      GetList(info)
838 %
839 %  A description of each parameter follows:
840 %
841 %    o info: a structure of type info.
842 %
843 */
844 static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
845   ssize_t *current,ssize_t *last,ExceptionInfo *exception)
846 {
847   Image
848     *image;
849
850   if (reference == (SV *) NULL)
851     return(NULL);
852   switch (SvTYPE(reference))
853   {
854     case SVt_PVAV:
855     {
856       AV
857         *av;
858
859       Image
860         *head,
861         *previous;
862
863       register ssize_t
864         i;
865
866       ssize_t
867         n;
868
869       /*
870         Array of images.
871       */
872       previous=(Image *) NULL;
873       head=(Image *) NULL;
874       av=(AV *) reference;
875       n=av_len(av);
876       for (i=0; i <= n; i++)
877       {
878         SV
879           **rv;
880
881         rv=av_fetch(av,i,0);
882         if (rv && *rv && sv_isobject(*rv))
883           {
884             image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
885               exception);
886             if (image == (Image *) NULL)
887               continue;
888             if (image == previous)
889               {
890                 image=CloneImage(image,0,0,MagickTrue,exception);
891                 if (image == (Image *) NULL)
892                   return(NULL);
893               }
894             image->previous=previous;
895             *(previous ? &previous->next : &head)=image;
896             for (previous=image; previous->next; previous=previous->next) ;
897           }
898       }
899       return(head);
900     }
901     case SVt_PVMG:
902     {
903       /*
904         Blessed scalar, one image.
905       */
906       image=(Image *) SvIV(reference);
907       if (image == (Image *) NULL)
908         return(NULL);
909       image->previous=(Image *) NULL;
910       image->next=(Image *) NULL;
911       if (reference_vector)
912         {
913           if (*current == *last)
914             {
915               *last+=256;
916               if (*reference_vector == (SV **) NULL)
917                 *reference_vector=(SV **) AcquireQuantumMemory(*last,
918                   sizeof(*reference_vector));
919               else
920                 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
921                   *last,sizeof(*reference_vector));
922             }
923           if (*reference_vector == (SV **) NULL)
924             {
925               ThrowPerlException(exception,ResourceLimitError,
926                 "MemoryAllocationFailed",PackageName);
927               return((Image *) NULL);
928             }
929           (*reference_vector)[*current]=reference;
930           (*reference_vector)[++(*current)]=NULL;
931         }
932       return(image);
933     }
934     default:
935       break;
936   }
937   (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
938     (double) SvTYPE(reference));
939   return((Image *) NULL);
940 }
941 \f
942 /*
943 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
944 %                                                                             %
945 %                                                                             %
946 %                                                                             %
947 %   G e t P a c k a g e I n f o                                               %
948 %                                                                             %
949 %                                                                             %
950 %                                                                             %
951 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
952 %
953 %  Method GetPackageInfo looks up or creates an info structure for the given
954 %  Image__Magick reference.  If it does create a new one, the information in
955 %  package_info is used to initialize it.
956 %
957 %  The format of the GetPackageInfo routine is:
958 %
959 %      struct PackageInfo *GetPackageInfo(void *reference,
960 %        struct PackageInfo *package_info,ExceptionInfo *exception)
961 %
962 %  A description of each parameter follows:
963 %
964 %    o info: a structure of type info.
965 %
966 %    o exception: Return any errors or warnings in this structure.
967 %
968 */
969 static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
970   struct PackageInfo *package_info,ExceptionInfo *exception)
971 {
972   char
973     message[MaxTextExtent];
974
975   struct PackageInfo
976     *clone_info;
977
978   SV
979     *sv;
980
981   (void) FormatLocaleString(message,MaxTextExtent,"%s::package%s%p",
982     PackageName,XS_VERSION,reference);
983   sv=perl_get_sv(message,(TRUE | 0x02));
984   if (sv == (SV *) NULL)
985     {
986       ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
987         message);
988       return(package_info);
989     }
990   if (SvREFCNT(sv) == 0)
991     (void) SvREFCNT_inc(sv);
992   if (SvIOKp(sv) && (clone_info=(struct PackageInfo *) SvIV(sv)))
993     return(clone_info);
994   clone_info=ClonePackageInfo(package_info,exception);
995   sv_setiv(sv,(IV) clone_info);
996   return(clone_info);
997 }
998 \f
999 /*
1000 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1001 %                                                                             %
1002 %                                                                             %
1003 %                                                                             %
1004 %   S e t A t t r i b u t e                                                   %
1005 %                                                                             %
1006 %                                                                             %
1007 %                                                                             %
1008 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1009 %
1010 %  SetAttribute() sets the attribute to the value in sval.  This can change
1011 %  either or both of image or info.
1012 %
1013 %  The format of the SetAttribute routine is:
1014 %
1015 %      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1016 %        SV *sval,ExceptionInfo *exception)
1017 %
1018 %  A description of each parameter follows:
1019 %
1020 %    o list: a list of strings.
1021 %
1022 %    o string: a character string.
1023 %
1024 */
1025
1026 static double SiPrefixToDouble(const char *string,const double interval)
1027 {
1028   char
1029     *q;
1030
1031   double
1032     scale,
1033     value;
1034
1035   value=InterpretLocaleValue(string,&q);
1036   scale=1000.0;
1037   if ((*q != '\0') && (tolower((int) ((unsigned char) *(q+1))) == 'i'))
1038     scale=1024.0;
1039   switch (tolower((int) ((unsigned char) *q)))
1040   {
1041     case '%': value*=pow(scale,0)*interval/100.0; break;
1042     case 'k': value*=pow(scale,1); break;
1043     case 'm': value*=pow(scale,2); break;
1044     case 'g': value*=pow(scale,3); break;
1045     case 't': value*=pow(scale,4); break;
1046     case 'p': value*=pow(scale,5); break;
1047     case 'e': value*=pow(scale,6); break;
1048     case 'z': value*=pow(scale,7); break;
1049     case 'y': value*=pow(scale,8); break;
1050     default:  break;
1051   }
1052   return(value);
1053 }
1054
1055 static inline ssize_t StringToLong(const char *value)
1056 {
1057   return(strtol(value,(char **) NULL,10));
1058 }
1059
1060 static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1061   const char *attribute,SV *sval,ExceptionInfo *exception)
1062 {
1063   GeometryInfo
1064     geometry_info;
1065
1066   long
1067     x,
1068     y;
1069
1070   PixelInfo
1071     pixel;
1072
1073   MagickStatusType
1074     flags;
1075
1076   PixelPacket
1077     *color,
1078     target_color;
1079
1080   ssize_t
1081     sp;
1082
1083   switch (*attribute)
1084   {
1085     case 'A':
1086     case 'a':
1087     {
1088       if (LocaleCompare(attribute,"adjoin") == 0)
1089         {
1090           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1091             SvPV(sval,na)) : SvIV(sval);
1092           if (sp < 0)
1093             {
1094               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1095                 SvPV(sval,na));
1096               break;
1097             }
1098           if (info)
1099             info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1100           break;
1101         }
1102       if (LocaleCompare(attribute,"alpha") == 0)
1103         {
1104           sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaOptions,MagickFalse,
1105             SvPV(sval,na)) : SvIV(sval);
1106           if (sp < 0)
1107             {
1108               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1109                 SvPV(sval,na));
1110               break;
1111             }
1112           for ( ; image; image=image->next)
1113             (void) SetImageAlphaChannel(image,(AlphaChannelType) sp,exception);
1114           break;
1115         }
1116       if (LocaleCompare(attribute,"antialias") == 0)
1117         {
1118           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1119             SvPV(sval,na)) : SvIV(sval);
1120           if (sp < 0)
1121             {
1122               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1123                 SvPV(sval,na));
1124               break;
1125             }
1126           if (info)
1127             info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1128           break;
1129         }
1130       if (LocaleCompare(attribute,"area-limit") == 0)
1131         {
1132           MagickSizeType
1133             limit;
1134
1135           limit=MagickResourceInfinity;
1136           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1137             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1138           (void) SetMagickResourceLimit(AreaResource,limit);
1139           break;
1140         }
1141       if (LocaleCompare(attribute,"attenuate") == 0)
1142         {
1143           if (info)
1144             (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1145           break;
1146         }
1147       if (LocaleCompare(attribute,"authenticate") == 0)
1148         {
1149           if (info)
1150             (void) CloneString(&info->image_info->authenticate,SvPV(sval,na));
1151           break;
1152         }
1153       if (info)
1154         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1155       for ( ; image; image=image->next)
1156         SetImageProperty(image,attribute,SvPV(sval,na));
1157       break;
1158     }
1159     case 'B':
1160     case 'b':
1161     {
1162       if (LocaleCompare(attribute,"background") == 0)
1163         {
1164           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1165           if (info)
1166             info->image_info->background_color=target_color;
1167           for ( ; image; image=image->next)
1168             image->background_color=target_color;
1169           break;
1170         }
1171       if (LocaleCompare(attribute,"bias") == 0)
1172         {
1173           for ( ; image; image=image->next)
1174             image->bias=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1175           break;
1176         }
1177       if (LocaleCompare(attribute,"blue-primary") == 0)
1178         {
1179           for ( ; image; image=image->next)
1180           {
1181             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1182             image->chromaticity.blue_primary.x=geometry_info.rho;
1183             image->chromaticity.blue_primary.y=geometry_info.sigma;
1184             if ((flags & SigmaValue) == 0)
1185               image->chromaticity.blue_primary.y=
1186                 image->chromaticity.blue_primary.x;
1187           }
1188           break;
1189         }
1190       if (LocaleCompare(attribute,"bordercolor") == 0)
1191         {
1192           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1193           if (info)
1194             info->image_info->border_color=target_color;
1195           for ( ; image; image=image->next)
1196             image->border_color=target_color;
1197           break;
1198         }
1199       if (info)
1200         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1201       for ( ; image; image=image->next)
1202         SetImageProperty(image,attribute,SvPV(sval,na));
1203       break;
1204     }
1205     case 'C':
1206     case 'c':
1207     {
1208       if (LocaleCompare(attribute,"cache-threshold") == 0)
1209         {
1210           (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1211             SiPrefixToDouble(SvPV(sval,na),100.0));
1212           (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1213             (2*SiPrefixToDouble(SvPV(sval,na),100.0)));
1214           break;
1215         }
1216       if (LocaleCompare(attribute,"clip-mask") == 0)
1217         {
1218           Image
1219             *clip_mask;
1220
1221           clip_mask=(Image *) NULL;
1222           if (SvPOK(sval))
1223             clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1224           for ( ; image; image=image->next)
1225             SetImageClipMask(image,clip_mask);
1226           break;
1227         }
1228       if (LocaleNCompare(attribute,"colormap",8) == 0)
1229         {
1230           for ( ; image; image=image->next)
1231           {
1232             int
1233               items;
1234
1235             long
1236               i;
1237
1238             if (image->storage_class == DirectClass)
1239               continue;
1240             i=0;
1241             items=sscanf(attribute,"%*[^[][%ld",&i);
1242             (void) items;
1243             if (i > (ssize_t) image->colors)
1244               i%=image->colors;
1245             if ((strchr(SvPV(sval,na),',') == 0) ||
1246                 (strchr(SvPV(sval,na),')') != 0))
1247               QueryColorDatabase(SvPV(sval,na),image->colormap+i,exception);
1248             else
1249               {
1250                 color=image->colormap+i;
1251                 pixel.red=color->red;
1252                 pixel.green=color->green;
1253                 pixel.blue=color->blue;
1254                 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1255                 pixel.red=geometry_info.rho;
1256                 pixel.green=geometry_info.sigma;
1257                 pixel.blue=geometry_info.xi;
1258                 color->red=ClampToQuantum(pixel.red);
1259                 color->green=ClampToQuantum(pixel.green);
1260                 color->blue=ClampToQuantum(pixel.blue);
1261               }
1262           }
1263           break;
1264         }
1265       if (LocaleCompare(attribute,"colorspace") == 0)
1266         {
1267           sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1268             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1269           if (sp < 0)
1270             {
1271               ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1272                 SvPV(sval,na));
1273               break;
1274             }
1275           for ( ; image; image=image->next)
1276             (void) TransformImageColorspace(image,(ColorspaceType) sp);
1277           break;
1278         }
1279       if (LocaleCompare(attribute,"comment") == 0)
1280         {
1281           for ( ; image; image=image->next)
1282             (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1283               info ? info->image_info : (ImageInfo *) NULL,image,
1284               SvPV(sval,na)));
1285           break;
1286         }
1287       if (LocaleCompare(attribute,"compression") == 0)
1288         {
1289           sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1290             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1291           if (sp < 0)
1292             {
1293               ThrowPerlException(exception,OptionError,
1294                 "UnrecognizedImageCompression",SvPV(sval,na));
1295               break;
1296             }
1297           if (info)
1298             info->image_info->compression=(CompressionType) sp;
1299           for ( ; image; image=image->next)
1300             image->compression=(CompressionType) sp;
1301           break;
1302         }
1303       if (info)
1304         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1305       for ( ; image; image=image->next)
1306         SetImageProperty(image,attribute,SvPV(sval,na));
1307       break;
1308     }
1309     case 'D':
1310     case 'd':
1311     {
1312       if (LocaleCompare(attribute,"debug") == 0)
1313         {
1314           SetLogEventMask(SvPV(sval,na));
1315           break;
1316         }
1317       if (LocaleCompare(attribute,"delay") == 0)
1318         {
1319           flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1320           for ( ; image; image=image->next)
1321           {
1322             image->delay=(size_t) floor(geometry_info.rho+0.5);
1323             if ((flags & SigmaValue) != 0)
1324               image->ticks_per_second=(ssize_t)
1325                 floor(geometry_info.sigma+0.5);
1326           }
1327           break;
1328         }
1329       if (LocaleCompare(attribute,"disk-limit") == 0)
1330         {
1331           MagickSizeType
1332             limit;
1333
1334           limit=MagickResourceInfinity;
1335           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1336             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1337           (void) SetMagickResourceLimit(DiskResource,limit);
1338           break;
1339         }
1340       if (LocaleCompare(attribute,"density") == 0)
1341         {
1342           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1343             {
1344               ThrowPerlException(exception,OptionError,"MissingGeometry",
1345                 SvPV(sval,na));
1346               break;
1347             }
1348           if (info)
1349             (void) CloneString(&info->image_info->density,SvPV(sval,na));
1350           for ( ; image; image=image->next)
1351           {
1352             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1353             image->x_resolution=geometry_info.rho;
1354             image->y_resolution=geometry_info.sigma;
1355             if ((flags & SigmaValue) == 0)
1356               image->y_resolution=image->x_resolution;
1357           }
1358           break;
1359         }
1360       if (LocaleCompare(attribute,"depth") == 0)
1361         {
1362           if (info)
1363             info->image_info->depth=SvIV(sval);
1364           for ( ; image; image=image->next)
1365             (void) SetImageDepth(image,SvIV(sval));
1366           break;
1367         }
1368       if (LocaleCompare(attribute,"dispose") == 0)
1369         {
1370           sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1371             SvPV(sval,na)) : SvIV(sval);
1372           if (sp < 0)
1373             {
1374               ThrowPerlException(exception,OptionError,
1375                 "UnrecognizedDisposeMethod",SvPV(sval,na));
1376               break;
1377             }
1378           for ( ; image; image=image->next)
1379             image->dispose=(DisposeType) sp;
1380           break;
1381         }
1382       if (LocaleCompare(attribute,"dither") == 0)
1383         {
1384           if (info)
1385             {
1386               sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1387                 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1388               if (sp < 0)
1389                 {
1390                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
1391                     SvPV(sval,na));
1392                   break;
1393                 }
1394               info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1395             }
1396           break;
1397         }
1398       if (LocaleCompare(attribute,"display") == 0)
1399         {
1400           display:
1401           if (info)
1402             (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1403           break;
1404         }
1405       if (info)
1406         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1407       for ( ; image; image=image->next)
1408         SetImageProperty(image,attribute,SvPV(sval,na));
1409       break;
1410     }
1411     case 'E':
1412     case 'e':
1413     {
1414       if (LocaleCompare(attribute,"endian") == 0)
1415         {
1416           sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1417             SvPV(sval,na)) : SvIV(sval);
1418           if (sp < 0)
1419             {
1420               ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1421                 SvPV(sval,na));
1422               break;
1423             }
1424           if (info)
1425             info->image_info->endian=(EndianType) sp;
1426           for ( ; image; image=image->next)
1427             image->endian=(EndianType) sp;
1428           break;
1429         }
1430       if (LocaleCompare(attribute,"extract") == 0)
1431         {
1432           /*
1433             Set image extract geometry.
1434           */
1435           (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1436           break;
1437         }
1438       if (info)
1439         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1440       for ( ; image; image=image->next)
1441         SetImageProperty(image,attribute,SvPV(sval,na));
1442       break;
1443     }
1444     case 'F':
1445     case 'f':
1446     {
1447       if (LocaleCompare(attribute,"filename") == 0)
1448         {
1449           if (info)
1450             (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1451               MaxTextExtent);
1452           for ( ; image; image=image->next)
1453             (void) CopyMagickString(image->filename,SvPV(sval,na),
1454               MaxTextExtent);
1455           break;
1456         }
1457       if (LocaleCompare(attribute,"file") == 0)
1458         {
1459           FILE
1460             *file;
1461
1462           PerlIO
1463             *io_info;
1464
1465           if (info == (struct PackageInfo *) NULL)
1466             break;
1467           io_info=IoIFP(sv_2io(sval));
1468           if (io_info == (PerlIO *) NULL)
1469             {
1470               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1471                 PackageName);
1472               break;
1473             }
1474           file=PerlIO_findFILE(io_info);
1475           if (file == (FILE *) NULL)
1476             {
1477               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1478                 PackageName);
1479               break;
1480             }
1481           SetImageInfoFile(info->image_info,file);
1482           break;
1483         }
1484       if (LocaleCompare(attribute,"fill") == 0)
1485         {
1486           if (info)
1487             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1488           break;
1489         }
1490       if (LocaleCompare(attribute,"font") == 0)
1491         {
1492           if (info)
1493             (void) CloneString(&info->image_info->font,SvPV(sval,na));
1494           break;
1495         }
1496       if (LocaleCompare(attribute,"foreground") == 0)
1497         break;
1498       if (LocaleCompare(attribute,"fuzz") == 0)
1499         {
1500           if (info)
1501             info->image_info->fuzz=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1502           for ( ; image; image=image->next)
1503             image->fuzz=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1504           break;
1505         }
1506       if (info)
1507         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1508       for ( ; image; image=image->next)
1509         SetImageProperty(image,attribute,SvPV(sval,na));
1510       break;
1511     }
1512     case 'G':
1513     case 'g':
1514     {
1515       if (LocaleCompare(attribute,"gamma") == 0)
1516         {
1517           for ( ; image; image=image->next)
1518             image->gamma=SvNV(sval);
1519           break;
1520         }
1521       if (LocaleCompare(attribute,"gravity") == 0)
1522         {
1523           sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1524             SvPV(sval,na)) : SvIV(sval);
1525           if (sp < 0)
1526             {
1527               ThrowPerlException(exception,OptionError,
1528                 "UnrecognizedGravityType",SvPV(sval,na));
1529               break;
1530             }
1531           if (info)
1532             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1533           for ( ; image; image=image->next)
1534             image->gravity=(GravityType) sp;
1535           break;
1536         }
1537       if (LocaleCompare(attribute,"green-primary") == 0)
1538         {
1539           for ( ; image; image=image->next)
1540           {
1541             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1542             image->chromaticity.green_primary.x=geometry_info.rho;
1543             image->chromaticity.green_primary.y=geometry_info.sigma;
1544             if ((flags & SigmaValue) == 0)
1545               image->chromaticity.green_primary.y=
1546                 image->chromaticity.green_primary.x;
1547           }
1548           break;
1549         }
1550       if (info)
1551         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1552       for ( ; image; image=image->next)
1553         SetImageProperty(image,attribute,SvPV(sval,na));
1554       break;
1555     }
1556     case 'I':
1557     case 'i':
1558     {
1559       if (LocaleNCompare(attribute,"index",5) == 0)
1560         {
1561           int
1562             items;
1563
1564           long
1565             index;
1566
1567           register Quantum
1568             *q;
1569
1570           CacheView
1571             *image_view;
1572
1573           for ( ; image; image=image->next)
1574           {
1575             if (image->storage_class != PseudoClass)
1576               continue;
1577             x=0;
1578             y=0;
1579             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1580             (void) items;
1581             image_view=AcquireCacheView(image);
1582             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1583             if (q != (Quantum *) NULL)
1584               {
1585                 items=sscanf(SvPV(sval,na),"%ld",&index);
1586                 if ((index >= 0) && (index < (ssize_t) image->colors))
1587                   SetPixelIndex(image,index,q);
1588                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1589               }
1590             image_view=DestroyCacheView(image_view);
1591           }
1592           break;
1593         }
1594       if (LocaleCompare(attribute,"iterations") == 0)
1595         {
1596   iterations:
1597           for ( ; image; image=image->next)
1598             image->iterations=SvIV(sval);
1599           break;
1600         }
1601       if (LocaleCompare(attribute,"interlace") == 0)
1602         {
1603           sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1604             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1605           if (sp < 0)
1606             {
1607               ThrowPerlException(exception,OptionError,
1608                 "UnrecognizedInterlaceType",SvPV(sval,na));
1609               break;
1610             }
1611           if (info)
1612             info->image_info->interlace=(InterlaceType) sp;
1613           for ( ; image; image=image->next)
1614             image->interlace=(InterlaceType) sp;
1615           break;
1616         }
1617       if (info)
1618         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1619       for ( ; image; image=image->next)
1620         SetImageProperty(image,attribute,SvPV(sval,na));
1621       break;
1622     }
1623     case 'L':
1624     case 'l':
1625     {
1626       if (LocaleCompare(attribute,"label") == 0)
1627         {
1628           for ( ; image; image=image->next)
1629             (void) SetImageProperty(image,"label",InterpretImageProperties(
1630               info ? info->image_info : (ImageInfo *) NULL,image,
1631               SvPV(sval,na)));
1632           break;
1633         }
1634       if (LocaleCompare(attribute,"loop") == 0)
1635         goto iterations;
1636       if (info)
1637         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1638       for ( ; image; image=image->next)
1639         SetImageProperty(image,attribute,SvPV(sval,na));
1640       break;
1641     }
1642     case 'M':
1643     case 'm':
1644     {
1645       if (LocaleCompare(attribute,"magick") == 0)
1646         {
1647           if (info)
1648             (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
1649               "%s:",SvPV(sval,na));
1650           for ( ; image; image=image->next)
1651             (void) CopyMagickString(image->magick,SvPV(sval,na),MaxTextExtent);
1652           break;
1653         }
1654       if (LocaleCompare(attribute,"map-limit") == 0)
1655         {
1656           MagickSizeType
1657             limit;
1658
1659           limit=MagickResourceInfinity;
1660           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1661             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1662           (void) SetMagickResourceLimit(MapResource,limit);
1663           break;
1664         }
1665       if (LocaleCompare(attribute,"mask") == 0)
1666         {
1667           Image
1668             *mask;
1669
1670           mask=(Image *) NULL;
1671           if (SvPOK(sval))
1672             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1673           for ( ; image; image=image->next)
1674             SetImageMask(image,mask);
1675           break;
1676         }
1677       if (LocaleCompare(attribute,"mattecolor") == 0)
1678         {
1679           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1680           if (info)
1681             info->image_info->matte_color=target_color;
1682           for ( ; image; image=image->next)
1683             image->matte_color=target_color;
1684           break;
1685         }
1686       if (LocaleCompare(attribute,"matte") == 0)
1687         {
1688           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1689             SvPV(sval,na)) : SvIV(sval);
1690           if (sp < 0)
1691             {
1692               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1693                 SvPV(sval,na));
1694               break;
1695             }
1696           for ( ; image; image=image->next)
1697             image->matte=sp != 0 ? MagickTrue : MagickFalse;
1698           break;
1699         }
1700       if (LocaleCompare(attribute,"memory-limit") == 0)
1701         {
1702           MagickSizeType
1703             limit;
1704
1705           limit=MagickResourceInfinity;
1706           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1707             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1708           (void) SetMagickResourceLimit(MemoryResource,limit);
1709           break;
1710         }
1711       if (LocaleCompare(attribute,"monochrome") == 0)
1712         {
1713           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1714             SvPV(sval,na)) : SvIV(sval);
1715           if (sp < 0)
1716             {
1717               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1718                 SvPV(sval,na));
1719               break;
1720             }
1721           if (info)
1722             info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1723           for ( ; image; image=image->next)
1724             (void) SetImageType(image,BilevelType);
1725           break;
1726         }
1727       if (info)
1728         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1729       for ( ; image; image=image->next)
1730         SetImageProperty(image,attribute,SvPV(sval,na));
1731       break;
1732     }
1733     case 'O':
1734     case 'o':
1735     {
1736       if (LocaleCompare(attribute,"option") == 0)
1737         {
1738           if (info)
1739             DefineImageOption(info->image_info,SvPV(sval,na));
1740           break;
1741         }
1742       if (LocaleCompare(attribute,"orientation") == 0)
1743         {
1744           sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1745             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1746           if (sp < 0)
1747             {
1748               ThrowPerlException(exception,OptionError,
1749                 "UnrecognizedOrientationType",SvPV(sval,na));
1750               break;
1751             }
1752           if (info)
1753             info->image_info->orientation=(OrientationType) sp;
1754           for ( ; image; image=image->next)
1755             image->orientation=(OrientationType) sp;
1756           break;
1757         }
1758       if (info)
1759         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1760       for ( ; image; image=image->next)
1761         SetImageProperty(image,attribute,SvPV(sval,na));
1762       break;
1763     }
1764     case 'P':
1765     case 'p':
1766     {
1767       if (LocaleCompare(attribute,"page") == 0)
1768         {
1769           char
1770             *geometry;
1771
1772           geometry=GetPageGeometry(SvPV(sval,na));
1773           if (info)
1774             (void) CloneString(&info->image_info->page,geometry);
1775           for ( ; image; image=image->next)
1776             (void) ParsePageGeometry(image,geometry,&image->page,exception);
1777           geometry=(char *) RelinquishMagickMemory(geometry);
1778           break;
1779         }
1780       if (LocaleCompare(attribute,"pen") == 0)
1781         {
1782           if (info)
1783             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1784           break;
1785         }
1786       if (LocaleNCompare(attribute,"pixel",5) == 0)
1787         {
1788           int
1789             items;
1790
1791           PixelInfo
1792             pixel;
1793
1794           register Quantum
1795             *q;
1796
1797           CacheView
1798             *image_view;
1799
1800           for ( ; image; image=image->next)
1801           {
1802             if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1803               break;
1804             x=0;
1805             y=0;
1806             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1807             (void) items;
1808             image_view=AcquireCacheView(image);
1809             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1810             if (q != (Quantum *) NULL)
1811               {
1812                 if ((strchr(SvPV(sval,na),',') == 0) ||
1813                     (strchr(SvPV(sval,na),')') != 0))
1814                   QueryMagickColor(SvPV(sval,na),&pixel,exception);
1815                 else
1816                   {
1817                     GetPixelInfo(image,&pixel);
1818                     flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1819                     pixel.red=geometry_info.rho;
1820                     if ((flags & SigmaValue) != 0)
1821                       pixel.green=geometry_info.sigma;
1822                     if ((flags & XiValue) != 0)
1823                       pixel.blue=geometry_info.xi;
1824                     if ((flags & PsiValue) != 0)
1825                       pixel.alpha=geometry_info.psi;
1826                     if ((flags & ChiValue) != 0)
1827                       pixel.black=geometry_info.chi;
1828                   }
1829                 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1830                 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1831                 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1832                 if (image->colorspace == CMYKColorspace)
1833                   SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1834                 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1835                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1836               }
1837             image_view=DestroyCacheView(image_view);
1838           }
1839           break;
1840         }
1841       if (LocaleCompare(attribute,"pointsize") == 0)
1842         {
1843           if (info)
1844             {
1845               (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1846               info->image_info->pointsize=geometry_info.rho;
1847             }
1848           break;
1849         }
1850       if (LocaleCompare(attribute,"preview") == 0)
1851         {
1852           sp=SvPOK(sval) ? ParseCommandOption(MagickPreviewOptions,MagickFalse,
1853             SvPV(sval,na)) : SvIV(sval);
1854           if (sp < 0)
1855             {
1856               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1857                 SvPV(sval,na));
1858               break;
1859             }
1860           if (info)
1861             info->image_info->preview_type=(PreviewType) sp;
1862           break;
1863         }
1864       if (info)
1865         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1866       for ( ; image; image=image->next)
1867         SetImageProperty(image,attribute,SvPV(sval,na));
1868       break;
1869     }
1870     case 'Q':
1871     case 'q':
1872     {
1873       if (LocaleCompare(attribute,"quality") == 0)
1874         {
1875           if (info)
1876             info->image_info->quality=SvIV(sval);
1877           for ( ; image; image=image->next)
1878             image->quality=SvIV(sval);
1879           break;
1880         }
1881       if (info)
1882         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1883       for ( ; image; image=image->next)
1884         SetImageProperty(image,attribute,SvPV(sval,na));
1885       break;
1886     }
1887     case 'R':
1888     case 'r':
1889     {
1890       if (LocaleCompare(attribute,"red-primary") == 0)
1891         {
1892           for ( ; image; image=image->next)
1893           {
1894             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1895             image->chromaticity.red_primary.x=geometry_info.rho;
1896             image->chromaticity.red_primary.y=geometry_info.sigma;
1897             if ((flags & SigmaValue) == 0)
1898               image->chromaticity.red_primary.y=
1899                 image->chromaticity.red_primary.x;
1900           }
1901           break;
1902         }
1903       if (LocaleCompare(attribute,"render") == 0)
1904         {
1905           sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1906             SvPV(sval,na)) : SvIV(sval);
1907           if (sp < 0)
1908             {
1909               ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1910                 SvPV(sval,na));
1911               break;
1912             }
1913          for ( ; image; image=image->next)
1914            image->rendering_intent=(RenderingIntent) sp;
1915          break;
1916        }
1917       if (LocaleCompare(attribute,"repage") == 0)
1918         {
1919           RectangleInfo
1920             geometry;
1921
1922           for ( ; image; image=image->next)
1923           {
1924             flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
1925             if ((flags & WidthValue) != 0)
1926               {
1927                 if ((flags & HeightValue) == 0)
1928                   geometry.height=geometry.width;
1929                 image->page.width=geometry.width;
1930                 image->page.height=geometry.height;
1931               }
1932             if ((flags & AspectValue) != 0)
1933               {
1934                 if ((flags & XValue) != 0)
1935                   image->page.x+=geometry.x;
1936                 if ((flags & YValue) != 0)
1937                   image->page.y+=geometry.y;
1938               }
1939             else
1940               {
1941                 if ((flags & XValue) != 0)
1942                   {
1943                     image->page.x=geometry.x;
1944                     if (((flags & WidthValue) != 0) && (geometry.x > 0))
1945                       image->page.width=image->columns+geometry.x;
1946                   }
1947                 if ((flags & YValue) != 0)
1948                   {
1949                     image->page.y=geometry.y;
1950                     if (((flags & HeightValue) != 0) && (geometry.y > 0))
1951                       image->page.height=image->rows+geometry.y;
1952                   }
1953               }
1954           }
1955           break;
1956         }
1957       if (info)
1958         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1959       for ( ; image; image=image->next)
1960         SetImageProperty(image,attribute,SvPV(sval,na));
1961       break;
1962     }
1963     case 'S':
1964     case 's':
1965     {
1966       if (LocaleCompare(attribute,"sampling-factor") == 0)
1967         {
1968           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1969             {
1970               ThrowPerlException(exception,OptionError,"MissingGeometry",
1971                 SvPV(sval,na));
1972               break;
1973             }
1974           if (info)
1975             (void) CloneString(&info->image_info->sampling_factor,
1976               SvPV(sval,na));
1977           break;
1978         }
1979       if (LocaleCompare(attribute,"scene") == 0)
1980         {
1981           for ( ; image; image=image->next)
1982             image->scene=SvIV(sval);
1983           break;
1984         }
1985       if (LocaleCompare(attribute,"server") == 0)
1986         goto display;
1987       if (LocaleCompare(attribute,"size") == 0)
1988         {
1989           if (info)
1990             {
1991               if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1992                 {
1993                   ThrowPerlException(exception,OptionError,"MissingGeometry",
1994                     SvPV(sval,na));
1995                   break;
1996                 }
1997               (void) CloneString(&info->image_info->size,SvPV(sval,na));
1998             }
1999           break;
2000         }
2001       if (LocaleCompare(attribute,"stroke") == 0)
2002         {
2003           if (info)
2004             (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2005           break;
2006         }
2007       if (info)
2008         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2009       for ( ; image; image=image->next)
2010         SetImageProperty(image,attribute,SvPV(sval,na));
2011       break;
2012     }
2013     case 'T':
2014     case 't':
2015     {
2016       if (LocaleCompare(attribute,"texture") == 0)
2017         {
2018           if (info)
2019             (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2020           break;
2021         }
2022       if (LocaleCompare(attribute,"thread-limit") == 0)
2023         {
2024           MagickSizeType
2025             limit;
2026
2027           limit=MagickResourceInfinity;
2028           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2029             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
2030           (void) SetMagickResourceLimit(ThreadResource,limit);
2031           break;
2032         }
2033       if (LocaleCompare(attribute,"tile-offset") == 0)
2034         {
2035           char
2036             *geometry;
2037
2038           geometry=GetPageGeometry(SvPV(sval,na));
2039           if (info)
2040             (void) CloneString(&info->image_info->page,geometry);
2041           for ( ; image; image=image->next)
2042             (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2043               exception);
2044           geometry=(char *) RelinquishMagickMemory(geometry);
2045           break;
2046         }
2047       if (LocaleCompare(attribute,"time-limit") == 0)
2048         {
2049           MagickSizeType
2050             limit;
2051
2052           limit=MagickResourceInfinity;
2053           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2054             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
2055           (void) SetMagickResourceLimit(TimeResource,limit);
2056           break;
2057         }
2058       if (LocaleCompare(attribute,"transparent-color") == 0)
2059         {
2060           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
2061           if (info)
2062             info->image_info->transparent_color=target_color;
2063           for ( ; image; image=image->next)
2064             image->transparent_color=target_color;
2065           break;
2066         }
2067       if (LocaleCompare(attribute,"type") == 0)
2068         {
2069           sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2070             SvPV(sval,na)) : SvIV(sval);
2071           if (sp < 0)
2072             {
2073               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2074                 SvPV(sval,na));
2075               break;
2076             }
2077           if (info)
2078             info->image_info->type=(ImageType) sp;
2079           for ( ; image; image=image->next)
2080             SetImageType(image,(ImageType) sp);
2081           break;
2082         }
2083       if (info)
2084         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2085       for ( ; image; image=image->next)
2086         SetImageProperty(image,attribute,SvPV(sval,na));
2087       break;
2088     }
2089     case 'U':
2090     case 'u':
2091     {
2092       if (LocaleCompare(attribute,"units") == 0)
2093         {
2094           sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2095             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2096           if (sp < 0)
2097             {
2098               ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2099                 SvPV(sval,na));
2100               break;
2101             }
2102           if (info)
2103             info->image_info->units=(ResolutionType) sp;
2104           for ( ; image; image=image->next)
2105           {
2106             ResolutionType
2107               units;
2108
2109             units=(ResolutionType) sp;
2110             if (image->units != units)
2111               switch (image->units)
2112               {
2113                 case UndefinedResolution:
2114                 case PixelsPerInchResolution:
2115                 {
2116                   if (units == PixelsPerCentimeterResolution)
2117                     {
2118                       image->x_resolution*=2.54;
2119                       image->y_resolution*=2.54;
2120                     }
2121                   break;
2122                 }
2123                 case PixelsPerCentimeterResolution:
2124                 {
2125                   if (units == PixelsPerInchResolution)
2126                     {
2127                       image->x_resolution/=2.54;
2128                       image->y_resolution/=2.54;
2129                     }
2130                   break;
2131                 }
2132               }
2133             image->units=units;
2134           }
2135           break;
2136         }
2137       if (info)
2138         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2139       for ( ; image; image=image->next)
2140         SetImageProperty(image,attribute,SvPV(sval,na));
2141       break;
2142     }
2143     case 'V':
2144     case 'v':
2145     {
2146       if (LocaleCompare(attribute,"verbose") == 0)
2147         {
2148           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2149             SvPV(sval,na)) : SvIV(sval);
2150           if (sp < 0)
2151             {
2152               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2153                 SvPV(sval,na));
2154               break;
2155             }
2156           if (info)
2157             info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2158           break;
2159         }
2160       if (LocaleCompare(attribute,"view") == 0)
2161         {
2162           if (info)
2163             (void) CloneString(&info->image_info->view,SvPV(sval,na));
2164           break;
2165         }
2166       if (LocaleCompare(attribute,"virtual-pixel") == 0)
2167         {
2168           sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2169             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2170           if (sp < 0)
2171             {
2172               ThrowPerlException(exception,OptionError,
2173                 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2174               break;
2175             }
2176           if (info)
2177             info->image_info->virtual_pixel_method=(VirtualPixelMethod) sp;
2178           for ( ; image; image=image->next)
2179             SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp);
2180           break;
2181         }
2182       if (info)
2183         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2184       for ( ; image; image=image->next)
2185         SetImageProperty(image,attribute,SvPV(sval,na));
2186       break;
2187     }
2188     case 'W':
2189     case 'w':
2190     {
2191       if (LocaleCompare(attribute,"white-point") == 0)
2192         {
2193           for ( ; image; image=image->next)
2194           {
2195             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2196             image->chromaticity.white_point.x=geometry_info.rho;
2197             image->chromaticity.white_point.y=geometry_info.sigma;
2198             if ((flags & SigmaValue) == 0)
2199               image->chromaticity.white_point.y=
2200                 image->chromaticity.white_point.x;
2201           }
2202           break;
2203         }
2204       if (info)
2205         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2206       for ( ; image; image=image->next)
2207         SetImageProperty(image,attribute,SvPV(sval,na));
2208       break;
2209     }
2210     default:
2211     {
2212       if (info)
2213         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2214       for ( ; image; image=image->next)
2215         SetImageProperty(image,attribute,SvPV(sval,na));
2216       break;
2217     }
2218   }
2219 }
2220 \f
2221 /*
2222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2223 %                                                                             %
2224 %                                                                             %
2225 %                                                                             %
2226 %   S e t u p L i s t                                                         %
2227 %                                                                             %
2228 %                                                                             %
2229 %                                                                             %
2230 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2231 %
2232 %  Method SetupList returns the list of all the images linked by their
2233 %  image->next and image->previous link lists for use with ImageMagick.  If
2234 %  info is non-NULL, an info structure is returned in *info.  If
2235 %  reference_vector is non-NULL,an array of SV* are returned in
2236 %  *reference_vector.  Reference_vector is used when the images are going to be
2237 %  replaced with new Image*'s.
2238 %
2239 %  The format of the SetupList routine is:
2240 %
2241 %      Image *SetupList(SV *reference,struct PackageInfo **info,
2242 %        SV ***reference_vector,ExceptionInfo *exception)
2243 %
2244 %  A description of each parameter follows:
2245 %
2246 %    o list: a list of strings.
2247 %
2248 %    o string: a character string.
2249 %
2250 %    o exception: Return any errors or warnings in this structure.
2251 %
2252 */
2253 static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2254   SV ***reference_vector,ExceptionInfo *exception)
2255 {
2256   Image
2257     *image;
2258
2259   ssize_t
2260     current,
2261     last;
2262
2263   if (reference_vector)
2264     *reference_vector=NULL;
2265   if (info)
2266     *info=NULL;
2267   current=0;
2268   last=0;
2269   image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2270   if (info && (SvTYPE(reference) == SVt_PVAV))
2271     *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2272       exception);
2273   return(image);
2274 }
2275 \f
2276 /*
2277 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2278 %                                                                             %
2279 %                                                                             %
2280 %                                                                             %
2281 %   s t r E Q c a s e                                                         %
2282 %                                                                             %
2283 %                                                                             %
2284 %                                                                             %
2285 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2286 %
2287 %  strEQcase() compares two strings and returns 0 if they are the
2288 %  same or if the second string runs out first.  The comparison is case
2289 %  insensitive.
2290 %
2291 %  The format of the strEQcase routine is:
2292 %
2293 %      ssize_t strEQcase(const char *p,const char *q)
2294 %
2295 %  A description of each parameter follows:
2296 %
2297 %    o p: a character string.
2298 %
2299 %    o q: a character string.
2300 %
2301 %
2302 */
2303 static ssize_t strEQcase(const char *p,const char *q)
2304 {
2305   char
2306     c;
2307
2308   register ssize_t
2309     i;
2310
2311   for (i=0 ; (c=(*q)) != 0; i++)
2312   {
2313     if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2314         (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2315       return(0);
2316     p++;
2317     q++;
2318   }
2319   return(((*q == 0) && (*p == 0)) ? i : 0);
2320 }
2321 \f
2322 /*
2323 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2324 %                                                                             %
2325 %                                                                             %
2326 %                                                                             %
2327 %   I m a g e : : M a g i c k                                                 %
2328 %                                                                             %
2329 %                                                                             %
2330 %                                                                             %
2331 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2332 %
2333 %
2334 */
2335 MODULE = Image::Magick PACKAGE = Image::Magick
2336
2337 PROTOTYPES: ENABLE
2338
2339 BOOT:
2340   MagickCoreGenesis("PerlMagick",MagickFalse);
2341   SetWarningHandler(NULL);
2342   SetErrorHandler(NULL);
2343   magick_registry=NewSplayTree((int (*)(const void *,const void *))
2344     NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2345
2346 void
2347 UNLOAD()
2348   PPCODE:
2349   {
2350     if (magick_registry != (SplayTreeInfo *) NULL)
2351       magick_registry=DestroySplayTree(magick_registry);
2352     MagickCoreTerminus();
2353   }
2354
2355 double
2356 constant(name,argument)
2357   char *name
2358   ssize_t argument
2359 \f
2360 #
2361 ###############################################################################
2362 #                                                                             #
2363 #                                                                             #
2364 #                                                                             #
2365 #   A n i m a t e                                                             #
2366 #                                                                             #
2367 #                                                                             #
2368 #                                                                             #
2369 ###############################################################################
2370 #
2371 #
2372 void
2373 Animate(ref,...)
2374   Image::Magick ref=NO_INIT
2375   ALIAS:
2376     AnimateImage  = 1
2377     animate       = 2
2378     animateimage  = 3
2379   PPCODE:
2380   {
2381     ExceptionInfo
2382       *exception;
2383
2384     Image
2385       *image;
2386
2387     register ssize_t
2388       i;
2389
2390     struct PackageInfo
2391       *info,
2392       *package_info;
2393
2394     SV
2395       *perl_exception,
2396       *reference;
2397
2398     PERL_UNUSED_VAR(ref);
2399     PERL_UNUSED_VAR(ix);
2400     exception=AcquireExceptionInfo();
2401     perl_exception=newSVpv("",0);
2402     package_info=(struct PackageInfo *) NULL;
2403     if (sv_isobject(ST(0)) == 0)
2404       {
2405         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2406           PackageName);
2407         goto PerlException;
2408       }
2409     reference=SvRV(ST(0));
2410     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2411     if (image == (Image *) NULL)
2412       {
2413         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2414           PackageName);
2415         goto PerlException;
2416       }
2417     package_info=ClonePackageInfo(info,exception);
2418     if (items == 2)
2419       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2420     else
2421       if (items > 2)
2422         for (i=2; i < items; i+=2)
2423           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2424             exception);
2425     (void) AnimateImages(package_info->image_info,image);
2426     (void) CatchImageException(image);
2427     InheritException(exception,&image->exception);
2428
2429   PerlException:
2430     if (package_info != (struct PackageInfo *) NULL)
2431       DestroyPackageInfo(package_info);
2432     InheritPerlException(exception,perl_exception);
2433     exception=DestroyExceptionInfo(exception);
2434     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2435     SvPOK_on(perl_exception);
2436     ST(0)=sv_2mortal(perl_exception);
2437     XSRETURN(1);
2438   }
2439 \f
2440 #
2441 ###############################################################################
2442 #                                                                             #
2443 #                                                                             #
2444 #                                                                             #
2445 #   A p p e n d                                                               #
2446 #                                                                             #
2447 #                                                                             #
2448 #                                                                             #
2449 ###############################################################################
2450 #
2451 #
2452 void
2453 Append(ref,...)
2454   Image::Magick ref=NO_INIT
2455   ALIAS:
2456     AppendImage  = 1
2457     append       = 2
2458     appendimage  = 3
2459   PPCODE:
2460   {
2461     AV
2462       *av;
2463
2464     char
2465       *attribute;
2466
2467     ExceptionInfo
2468       *exception;
2469
2470     HV
2471       *hv;
2472
2473     Image
2474       *image;
2475
2476     register ssize_t
2477       i;
2478
2479     ssize_t
2480       stack;
2481
2482     struct PackageInfo
2483       *info;
2484
2485     SV
2486       *av_reference,
2487       *perl_exception,
2488       *reference,
2489       *rv,
2490       *sv;
2491
2492     PERL_UNUSED_VAR(ref);
2493     PERL_UNUSED_VAR(ix);
2494     exception=AcquireExceptionInfo();
2495     perl_exception=newSVpv("",0);
2496     sv=NULL;
2497     attribute=NULL;
2498     av=NULL;
2499     if (sv_isobject(ST(0)) == 0)
2500       {
2501         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2502           PackageName);
2503         goto PerlException;
2504       }
2505     reference=SvRV(ST(0));
2506     hv=SvSTASH(reference);
2507     av=newAV();
2508     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2509     SvREFCNT_dec(av);
2510     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2511     if (image == (Image *) NULL)
2512       {
2513         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2514           PackageName);
2515         goto PerlException;
2516       }
2517     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2518     /*
2519       Get options.
2520     */
2521     stack=MagickTrue;
2522     for (i=2; i < items; i+=2)
2523     {
2524       attribute=(char *) SvPV(ST(i-1),na);
2525       switch (*attribute)
2526       {
2527         case 'S':
2528         case 's':
2529         {
2530           if (LocaleCompare(attribute,"stack") == 0)
2531             {
2532               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2533                 SvPV(ST(i),na));
2534               if (stack < 0)
2535                 {
2536                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
2537                     SvPV(ST(i),na));
2538                   return;
2539                 }
2540               break;
2541             }
2542           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2543             attribute);
2544           break;
2545         }
2546         default:
2547         {
2548           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2549             attribute);
2550           break;
2551         }
2552       }
2553     }
2554     image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2555     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2556       goto PerlException;
2557     for ( ; image; image=image->next)
2558     {
2559       AddImageToRegistry(sv,image);
2560       rv=newRV(sv);
2561       av_push(av,sv_bless(rv,hv));
2562       SvREFCNT_dec(sv);
2563     }
2564     exception=DestroyExceptionInfo(exception);
2565     ST(0)=av_reference;
2566     SvREFCNT_dec(perl_exception);
2567     XSRETURN(1);
2568
2569   PerlException:
2570     InheritPerlException(exception,perl_exception);
2571     exception=DestroyExceptionInfo(exception);
2572     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2573     SvPOK_on(perl_exception);
2574     ST(0)=sv_2mortal(perl_exception);
2575     XSRETURN(1);
2576   }
2577 \f
2578 #
2579 ###############################################################################
2580 #                                                                             #
2581 #                                                                             #
2582 #                                                                             #
2583 #   A v e r a g e                                                             #
2584 #                                                                             #
2585 #                                                                             #
2586 #                                                                             #
2587 ###############################################################################
2588 #
2589 #
2590 void
2591 Average(ref)
2592   Image::Magick ref=NO_INIT
2593   ALIAS:
2594     AverageImage   = 1
2595     average        = 2
2596     averageimage   = 3
2597   PPCODE:
2598   {
2599     AV
2600       *av;
2601
2602     char
2603       *p;
2604
2605     ExceptionInfo
2606       *exception;
2607
2608     HV
2609       *hv;
2610
2611     Image
2612       *image;
2613
2614     struct PackageInfo
2615       *info;
2616
2617     SV
2618       *perl_exception,
2619       *reference,
2620       *rv,
2621       *sv;
2622
2623     PERL_UNUSED_VAR(ref);
2624     PERL_UNUSED_VAR(ix);
2625     exception=AcquireExceptionInfo();
2626     perl_exception=newSVpv("",0);
2627     sv=NULL;
2628     if (sv_isobject(ST(0)) == 0)
2629       {
2630         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2631           PackageName);
2632         goto PerlException;
2633       }
2634     reference=SvRV(ST(0));
2635     hv=SvSTASH(reference);
2636     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2637     if (image == (Image *) NULL)
2638       {
2639         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2640           PackageName);
2641         goto PerlException;
2642       }
2643     image=EvaluateImages(image,MeanEvaluateOperator,exception);
2644     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2645       goto PerlException;
2646     /*
2647       Create blessed Perl array for the returned image.
2648     */
2649     av=newAV();
2650     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2651     SvREFCNT_dec(av);
2652     AddImageToRegistry(sv,image);
2653     rv=newRV(sv);
2654     av_push(av,sv_bless(rv,hv));
2655     SvREFCNT_dec(sv);
2656     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2657     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
2658       "average-%.*s",(int) (MaxTextExtent-9),
2659       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2660     (void) CopyMagickString(image->filename,info->image_info->filename,
2661       MaxTextExtent);
2662     SetImageInfo(info->image_info,0,exception);
2663     exception=DestroyExceptionInfo(exception);
2664     SvREFCNT_dec(perl_exception);
2665     XSRETURN(1);
2666
2667   PerlException:
2668     InheritPerlException(exception,perl_exception);
2669     exception=DestroyExceptionInfo(exception);
2670     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2671     SvPOK_on(perl_exception);
2672     ST(0)=sv_2mortal(perl_exception);
2673     XSRETURN(1);
2674   }
2675 \f
2676 #
2677 ###############################################################################
2678 #                                                                             #
2679 #                                                                             #
2680 #                                                                             #
2681 #   B l o b T o I m a g e                                                     #
2682 #                                                                             #
2683 #                                                                             #
2684 #                                                                             #
2685 ###############################################################################
2686 #
2687 #
2688 void
2689 BlobToImage(ref,...)
2690   Image::Magick ref=NO_INIT
2691   ALIAS:
2692     BlobToImage  = 1
2693     blobtoimage  = 2
2694     blobto       = 3
2695   PPCODE:
2696   {
2697     AV
2698       *av;
2699
2700     char
2701       **keep,
2702       **list;
2703
2704     ExceptionInfo
2705       *exception;
2706
2707     HV
2708       *hv;
2709
2710     Image
2711       *image;
2712
2713     register char
2714       **p;
2715
2716     register ssize_t
2717       i;
2718
2719     ssize_t
2720       ac,
2721       n,
2722       number_images;
2723
2724     STRLEN
2725       *length;
2726
2727     struct PackageInfo
2728       *info;
2729
2730     SV
2731       *perl_exception,
2732       *reference,
2733       *rv,
2734       *sv;
2735
2736     PERL_UNUSED_VAR(ref);
2737     PERL_UNUSED_VAR(ix);
2738     exception=AcquireExceptionInfo();
2739     perl_exception=newSVpv("",0);
2740     sv=NULL;
2741     number_images=0;
2742     ac=(items < 2) ? 1 : items-1;
2743     length=(STRLEN *) NULL;
2744     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2745     if (list == (char **) NULL)
2746       {
2747         ThrowPerlException(exception,ResourceLimitError,
2748           "MemoryAllocationFailed",PackageName);
2749         goto PerlException;
2750       }
2751     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2752     if (length == (STRLEN *) NULL)
2753       {
2754         ThrowPerlException(exception,ResourceLimitError,
2755           "MemoryAllocationFailed",PackageName);
2756         goto PerlException;
2757       }
2758     if (sv_isobject(ST(0)) == 0)
2759       {
2760         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2761           PackageName);
2762         goto PerlException;
2763       }
2764     reference=SvRV(ST(0));
2765     hv=SvSTASH(reference);
2766     if (SvTYPE(reference) != SVt_PVAV)
2767       {
2768         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2769           PackageName);
2770         goto PerlException;
2771       }
2772     av=(AV *) reference;
2773     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2774       exception);
2775     n=1;
2776     if (items <= 1)
2777       {
2778         ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2779         goto PerlException;
2780       }
2781     for (n=0, i=0; i < ac; i++)
2782     {
2783       list[n]=(char *) (SvPV(ST(i+1),length[n]));
2784       if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2785         {
2786           list[n]=(char *) (SvPV(ST(i+2),length[n]));
2787           continue;
2788         }
2789       n++;
2790     }
2791     list[n]=(char *) NULL;
2792     keep=list;
2793     for (i=number_images=0; i < n; i++)
2794     {
2795       image=BlobToImage(info->image_info,list[i],length[i],exception);
2796       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2797         break;
2798       for ( ; image; image=image->next)
2799       {
2800         AddImageToRegistry(sv,image);
2801         rv=newRV(sv);
2802         av_push(av,sv_bless(rv,hv));
2803         SvREFCNT_dec(sv);
2804         number_images++;
2805       }
2806     }
2807     /*
2808       Free resources.
2809     */
2810     for (i=0; i < n; i++)
2811       if (list[i] != (char *) NULL)
2812         for (p=keep; list[i] != *p++; )
2813           if (*p == (char *) NULL)
2814             {
2815               list[i]=(char *) RelinquishMagickMemory(list[i]);
2816               break;
2817             }
2818
2819   PerlException:
2820     if (list)
2821       list=(char **) RelinquishMagickMemory(list);
2822     if (length)
2823       length=(STRLEN *) RelinquishMagickMemory(length);
2824     InheritPerlException(exception,perl_exception);
2825     exception=DestroyExceptionInfo(exception);
2826     sv_setiv(perl_exception,(IV) number_images);
2827     SvPOK_on(perl_exception);
2828     ST(0)=sv_2mortal(perl_exception);
2829     XSRETURN(1);
2830   }
2831 \f
2832 #
2833 ###############################################################################
2834 #                                                                             #
2835 #                                                                             #
2836 #                                                                             #
2837 #   C l o n e                                                                 #
2838 #                                                                             #
2839 #                                                                             #
2840 #                                                                             #
2841 ###############################################################################
2842 #
2843 #
2844 void
2845 Clone(ref)
2846   Image::Magick ref=NO_INIT
2847   ALIAS:
2848     CopyImage   = 1
2849     copy        = 2
2850     copyimage   = 3
2851     CloneImage  = 4
2852     clone       = 5
2853     cloneimage  = 6
2854     Clone       = 7
2855   PPCODE:
2856   {
2857     AV
2858       *av;
2859
2860     ExceptionInfo
2861       *exception;
2862
2863     HV
2864       *hv;
2865
2866     Image
2867       *clone,
2868       *image;
2869
2870     struct PackageInfo
2871       *info;
2872
2873     SV
2874       *perl_exception,
2875       *reference,
2876       *rv,
2877       *sv;
2878
2879     PERL_UNUSED_VAR(ref);
2880     PERL_UNUSED_VAR(ix);
2881     exception=AcquireExceptionInfo();
2882     perl_exception=newSVpv("",0);
2883     sv=NULL;
2884     if (sv_isobject(ST(0)) == 0)
2885       {
2886         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2887           PackageName);
2888         goto PerlException;
2889       }
2890     reference=SvRV(ST(0));
2891     hv=SvSTASH(reference);
2892     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2893     if (image == (Image *) NULL)
2894       {
2895         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2896           PackageName);
2897         goto PerlException;
2898       }
2899     /*
2900       Create blessed Perl array for the returned image.
2901     */
2902     av=newAV();
2903     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2904     SvREFCNT_dec(av);
2905     for ( ; image; image=image->next)
2906     {
2907       clone=CloneImage(image,0,0,MagickTrue,exception);
2908       if ((clone == (Image *) NULL) || (exception->severity >= ErrorException))
2909         break;
2910       AddImageToRegistry(sv,clone);
2911       rv=newRV(sv);
2912       av_push(av,sv_bless(rv,hv));
2913       SvREFCNT_dec(sv);
2914     }
2915     exception=DestroyExceptionInfo(exception);
2916     SvREFCNT_dec(perl_exception);
2917     XSRETURN(1);
2918
2919   PerlException:
2920     InheritPerlException(exception,perl_exception);
2921     exception=DestroyExceptionInfo(exception);
2922     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2923     SvPOK_on(perl_exception);
2924     ST(0)=sv_2mortal(perl_exception);
2925     XSRETURN(1);
2926   }
2927 \f
2928 #
2929 ###############################################################################
2930 #                                                                             #
2931 #                                                                             #
2932 #                                                                             #
2933 #   C L O N E                                                                 #
2934 #                                                                             #
2935 #                                                                             #
2936 #                                                                             #
2937 ###############################################################################
2938 #
2939 #
2940 void
2941 CLONE(ref,...)
2942   SV *ref;
2943   CODE:
2944   {
2945     PERL_UNUSED_VAR(ref);
2946     if (magick_registry != (SplayTreeInfo *) NULL)
2947       {
2948         register Image
2949           *p;
2950
2951         ResetSplayTreeIterator(magick_registry);
2952         p=(Image *) GetNextKeyInSplayTree(magick_registry);
2953         while (p != (Image *) NULL)
2954         {
2955           ReferenceImage(p);
2956           p=(Image *) GetNextKeyInSplayTree(magick_registry);
2957         }
2958       }
2959   }
2960 \f
2961 #
2962 ###############################################################################
2963 #                                                                             #
2964 #                                                                             #
2965 #                                                                             #
2966 #   C o a l e s c e                                                           #
2967 #                                                                             #
2968 #                                                                             #
2969 #                                                                             #
2970 ###############################################################################
2971 #
2972 #
2973 void
2974 Coalesce(ref)
2975   Image::Magick ref=NO_INIT
2976   ALIAS:
2977     CoalesceImage   = 1
2978     coalesce        = 2
2979     coalesceimage   = 3
2980   PPCODE:
2981   {
2982     AV
2983       *av;
2984
2985     ExceptionInfo
2986       *exception;
2987
2988     HV
2989       *hv;
2990
2991     Image
2992       *image;
2993
2994     struct PackageInfo
2995       *info;
2996
2997     SV
2998       *av_reference,
2999       *perl_exception,
3000       *reference,
3001       *rv,
3002       *sv;
3003
3004     PERL_UNUSED_VAR(ref);
3005     PERL_UNUSED_VAR(ix);
3006     exception=AcquireExceptionInfo();
3007     perl_exception=newSVpv("",0);
3008     sv=NULL;
3009     if (sv_isobject(ST(0)) == 0)
3010       {
3011         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3012           PackageName);
3013         goto PerlException;
3014       }
3015     reference=SvRV(ST(0));
3016     hv=SvSTASH(reference);
3017     av=newAV();
3018     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3019     SvREFCNT_dec(av);
3020     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3021     if (image == (Image *) NULL)
3022       {
3023         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3024           PackageName);
3025         goto PerlException;
3026       }
3027     image=CoalesceImages(image,exception);
3028     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3029       goto PerlException;
3030     for ( ; image; image=image->next)
3031     {
3032       AddImageToRegistry(sv,image);
3033       rv=newRV(sv);
3034       av_push(av,sv_bless(rv,hv));
3035       SvREFCNT_dec(sv);
3036     }
3037     exception=DestroyExceptionInfo(exception);
3038     ST(0)=av_reference;
3039     SvREFCNT_dec(perl_exception);
3040     XSRETURN(1);
3041
3042   PerlException:
3043     InheritPerlException(exception,perl_exception);
3044     exception=DestroyExceptionInfo(exception);
3045     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3046     SvPOK_on(perl_exception);
3047     ST(0)=sv_2mortal(perl_exception);
3048     XSRETURN(1);
3049   }
3050 \f
3051 #
3052 ###############################################################################
3053 #                                                                             #
3054 #                                                                             #
3055 #                                                                             #
3056 #   C o m p a r e                                                             #
3057 #                                                                             #
3058 #                                                                             #
3059 #                                                                             #
3060 ###############################################################################
3061 #
3062 #
3063 void
3064 Compare(ref,...)
3065   Image::Magick ref=NO_INIT
3066   ALIAS:
3067     CompareImages = 1
3068     compare      = 2
3069     compareimage = 3
3070   PPCODE:
3071   {
3072     AV
3073       *av;
3074
3075     char
3076       *attribute;
3077
3078     double
3079       distortion;
3080
3081     ExceptionInfo
3082       *exception;
3083
3084     HV
3085       *hv;
3086
3087     Image
3088       *difference_image,
3089       *image,
3090       *reconstruct_image;
3091
3092     MetricType
3093       metric;
3094
3095     register ssize_t
3096       i;
3097
3098     ssize_t
3099       option;
3100
3101     struct PackageInfo
3102       *info;
3103
3104     SV
3105       *av_reference,
3106       *perl_exception,
3107       *reference,
3108       *rv,
3109       *sv;
3110
3111     PERL_UNUSED_VAR(ref);
3112     PERL_UNUSED_VAR(ix);
3113     exception=AcquireExceptionInfo();
3114     perl_exception=newSVpv("",0);
3115     sv=NULL;
3116     av=NULL;
3117     attribute=NULL;
3118     if (sv_isobject(ST(0)) == 0)
3119       {
3120         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3121           PackageName);
3122         goto PerlException;
3123       }
3124     reference=SvRV(ST(0));
3125     hv=SvSTASH(reference);
3126     av=newAV();
3127     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3128     SvREFCNT_dec(av);
3129     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3130     if (image == (Image *) NULL)
3131       {
3132         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3133           PackageName);
3134         goto PerlException;
3135       }
3136     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3137     /*
3138       Get attribute.
3139     */
3140     reconstruct_image=image;
3141     metric=RootMeanSquaredErrorMetric;
3142     for (i=2; i < items; i+=2)
3143     {
3144       attribute=(char *) SvPV(ST(i-1),na);
3145       switch (*attribute)
3146       {
3147         case 'C':
3148         case 'c':
3149         {
3150           if (LocaleCompare(attribute,"channel") == 0)
3151             {
3152               ssize_t
3153                 option;
3154
3155               option=ParseChannelOption(SvPV(ST(i),na));
3156               if (option < 0)
3157                 {
3158                   ThrowPerlException(exception,OptionError,
3159                     "UnrecognizedType",SvPV(ST(i),na));
3160                   return;
3161                 }
3162               SetPixelChannelMap(image,(ChannelType) option);
3163               break;
3164             }
3165           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3166             attribute);
3167           break;
3168         }
3169         case 'F':
3170         case 'f':
3171         {
3172           if (LocaleCompare(attribute,"fuzz") == 0)
3173             {
3174               image->fuzz=SiPrefixToDouble(SvPV(ST(i),na),100.0);
3175               break;
3176             }
3177           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3178             attribute);
3179           break;
3180         }
3181         case 'I':
3182         case 'i':
3183         {
3184           if (LocaleCompare(attribute,"image") == 0)
3185             {
3186               reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3187                 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3188               break;
3189             }
3190           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3191             attribute);
3192           break;
3193         }
3194         case 'M':
3195         case 'm':
3196         {
3197           if (LocaleCompare(attribute,"metric") == 0)
3198             {
3199               option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3200                 SvPV(ST(i),na));
3201               if (option < 0)
3202                 {
3203                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3204                     SvPV(ST(i),na));
3205                   break;
3206                 }
3207               metric=(MetricType) option;
3208               break;
3209             }
3210           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3211             attribute);
3212           break;
3213         }
3214         default:
3215         {
3216           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3217             attribute);
3218           break;
3219         }
3220       }
3221     }
3222     difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3223       exception);
3224     if (difference_image != (Image *) NULL)
3225       {
3226         difference_image->error.mean_error_per_pixel=distortion;
3227         AddImageToRegistry(sv,difference_image);
3228         rv=newRV(sv);
3229         av_push(av,sv_bless(rv,hv));
3230         SvREFCNT_dec(sv);
3231       }
3232     exception=DestroyExceptionInfo(exception);
3233     ST(0)=av_reference;
3234     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3235     XSRETURN(1);
3236
3237   PerlException:
3238     InheritPerlException(exception,perl_exception);
3239     exception=DestroyExceptionInfo(exception);
3240     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3241     SvPOK_on(perl_exception);
3242     ST(0)=sv_2mortal(perl_exception);
3243     XSRETURN(1);
3244   }
3245 \f
3246 #
3247 ###############################################################################
3248 #                                                                             #
3249 #                                                                             #
3250 #                                                                             #
3251 #   C o m p a r e L a y e r s                                                 #
3252 #                                                                             #
3253 #                                                                             #
3254 #                                                                             #
3255 ###############################################################################
3256 #
3257 #
3258 void
3259 CompareLayers(ref)
3260   Image::Magick ref=NO_INIT
3261   ALIAS:
3262     CompareImagesLayers   = 1
3263     comparelayers        = 2
3264     compareimagelayers   = 3
3265   PPCODE:
3266   {
3267     AV
3268       *av;
3269
3270     char
3271       *attribute;
3272
3273     ExceptionInfo
3274       *exception;
3275
3276     HV
3277       *hv;
3278
3279     Image
3280       *image;
3281
3282     ImageLayerMethod
3283       method;
3284
3285     register ssize_t
3286       i;
3287
3288     ssize_t
3289       option;
3290
3291     struct PackageInfo
3292       *info;
3293
3294     SV
3295       *av_reference,
3296       *perl_exception,
3297       *reference,
3298       *rv,
3299       *sv;
3300
3301     PERL_UNUSED_VAR(ref);
3302     PERL_UNUSED_VAR(ix);
3303     exception=AcquireExceptionInfo();
3304     perl_exception=newSVpv("",0);
3305     sv=NULL;
3306     if (sv_isobject(ST(0)) == 0)
3307       {
3308         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3309           PackageName);
3310         goto PerlException;
3311       }
3312     reference=SvRV(ST(0));
3313     hv=SvSTASH(reference);
3314     av=newAV();
3315     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3316     SvREFCNT_dec(av);
3317     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3318     if (image == (Image *) NULL)
3319       {
3320         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3321           PackageName);
3322         goto PerlException;
3323       }
3324     method=CompareAnyLayer;
3325     for (i=2; i < items; i+=2)
3326     {
3327       attribute=(char *) SvPV(ST(i-1),na);
3328       switch (*attribute)
3329       {
3330         case 'M':
3331         case 'm':
3332         {
3333           if (LocaleCompare(attribute,"method") == 0)
3334             {
3335               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3336                 SvPV(ST(i),na));
3337               if (option < 0)
3338                 {
3339                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3340                     SvPV(ST(i),na));
3341                   break;
3342                 }
3343                method=(ImageLayerMethod) option;
3344               break;
3345             }
3346           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3347             attribute);
3348           break;
3349         }
3350         default:
3351         {
3352           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3353             attribute);
3354           break;
3355         }
3356       }
3357     }
3358     image=CompareImagesLayers(image,method,exception);
3359     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3360       goto PerlException;
3361     for ( ; image; image=image->next)
3362     {
3363       AddImageToRegistry(sv,image);
3364       rv=newRV(sv);
3365       av_push(av,sv_bless(rv,hv));
3366       SvREFCNT_dec(sv);
3367     }
3368     exception=DestroyExceptionInfo(exception);
3369     ST(0)=av_reference;
3370     SvREFCNT_dec(perl_exception);
3371     XSRETURN(1);
3372
3373   PerlException:
3374     InheritPerlException(exception,perl_exception);
3375     exception=DestroyExceptionInfo(exception);
3376     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3377     SvPOK_on(perl_exception);
3378     ST(0)=sv_2mortal(perl_exception);
3379     XSRETURN(1);
3380   }
3381 \f
3382 #
3383 ###############################################################################
3384 #                                                                             #
3385 #                                                                             #
3386 #                                                                             #
3387 #   D e s t r o y                                                             #
3388 #                                                                             #
3389 #                                                                             #
3390 #                                                                             #
3391 ###############################################################################
3392 #
3393 #
3394 void
3395 DESTROY(ref)
3396   Image::Magick ref=NO_INIT
3397   PPCODE:
3398   {
3399     SV
3400       *reference;
3401
3402     PERL_UNUSED_VAR(ref);
3403     if (sv_isobject(ST(0)) == 0)
3404       croak("ReferenceIsNotMyType");
3405     reference=SvRV(ST(0));
3406     switch (SvTYPE(reference))
3407     {
3408       case SVt_PVAV:
3409       {
3410         char
3411           message[MaxTextExtent];
3412
3413         const SV
3414           *key;
3415
3416         HV
3417           *hv;
3418
3419         GV
3420           **gvp;
3421
3422         struct PackageInfo
3423           *info;
3424
3425         SV
3426           *sv;
3427
3428         /*
3429           Array (AV *) reference
3430         */
3431         (void) FormatLocaleString(message,MaxTextExtent,"package%s%p",
3432           XS_VERSION,reference);
3433         hv=gv_stashpv(PackageName, FALSE);
3434         if (!hv)
3435           break;
3436         gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3437         if (!gvp)
3438           break;
3439         sv=GvSV(*gvp);
3440         if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3441           {
3442             info=(struct PackageInfo *) SvIV(sv);
3443             DestroyPackageInfo(info);
3444           }
3445         key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3446         (void) key;
3447         break;
3448       }
3449       case SVt_PVMG:
3450       {
3451         Image
3452           *image;
3453
3454         /*
3455           Blessed scalar = (Image *) SvIV(reference)
3456         */
3457         image=(Image *) SvIV(reference);
3458         if (image != (Image *) NULL)
3459           DeleteImageFromRegistry(reference,image);
3460         break;
3461       }
3462       default:
3463         break;
3464     }
3465   }
3466 \f
3467 #
3468 ###############################################################################
3469 #                                                                             #
3470 #                                                                             #
3471 #                                                                             #
3472 #   D i s p l a y                                                             #
3473 #                                                                             #
3474 #                                                                             #
3475 #                                                                             #
3476 ###############################################################################
3477 #
3478 #
3479 void
3480 Display(ref,...)
3481   Image::Magick ref=NO_INIT
3482   ALIAS:
3483     DisplayImage  = 1
3484     display       = 2
3485     displayimage  = 3
3486   PPCODE:
3487   {
3488     ExceptionInfo
3489       *exception;
3490
3491     Image
3492       *image;
3493
3494     register ssize_t
3495       i;
3496
3497     struct PackageInfo
3498       *info,
3499       *package_info;
3500
3501     SV
3502       *perl_exception,
3503       *reference;
3504
3505     PERL_UNUSED_VAR(ref);
3506     PERL_UNUSED_VAR(ix);
3507     exception=AcquireExceptionInfo();
3508     perl_exception=newSVpv("",0);
3509     package_info=(struct PackageInfo *) NULL;
3510     if (sv_isobject(ST(0)) == 0)
3511       {
3512         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3513           PackageName);
3514         goto PerlException;
3515       }
3516     reference=SvRV(ST(0));
3517     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3518     if (image == (Image *) NULL)
3519       {
3520         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3521           PackageName);
3522         goto PerlException;
3523       }
3524     package_info=ClonePackageInfo(info,exception);
3525     if (items == 2)
3526       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3527     else
3528       if (items > 2)
3529         for (i=2; i < items; i+=2)
3530           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3531             exception);
3532     (void) DisplayImages(package_info->image_info,image);
3533     (void) CatchImageException(image);
3534     InheritException(exception,&image->exception);
3535
3536   PerlException:
3537     if (package_info != (struct PackageInfo *) NULL)
3538       DestroyPackageInfo(package_info);
3539     InheritPerlException(exception,perl_exception);
3540     exception=DestroyExceptionInfo(exception);
3541     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3542     SvPOK_on(perl_exception);
3543     ST(0)=sv_2mortal(perl_exception);
3544     XSRETURN(1);
3545   }
3546 \f
3547 #
3548 ###############################################################################
3549 #                                                                             #
3550 #                                                                             #
3551 #                                                                             #
3552 #   E v a l u a t e I m a g e s                                               #
3553 #                                                                             #
3554 #                                                                             #
3555 #                                                                             #
3556 ###############################################################################
3557 #
3558 #
3559 void
3560 EvaluateImages(ref)
3561   Image::Magick ref=NO_INIT
3562   ALIAS:
3563     EvaluateImages   = 1
3564     evaluateimages   = 2
3565   PPCODE:
3566   {
3567     AV
3568       *av;
3569
3570     char
3571       *attribute,
3572       *p;
3573
3574     ExceptionInfo
3575       *exception;
3576
3577     HV
3578       *hv;
3579
3580     Image
3581       *image;
3582
3583     MagickEvaluateOperator
3584       op;
3585
3586     register ssize_t
3587       i;
3588
3589     struct PackageInfo
3590       *info;
3591
3592     SV
3593       *perl_exception,
3594       *reference,
3595       *rv,
3596       *sv;
3597
3598     PERL_UNUSED_VAR(ref);
3599     PERL_UNUSED_VAR(ix);
3600     exception=AcquireExceptionInfo();
3601     perl_exception=newSVpv("",0);
3602     sv=NULL;
3603     if (sv_isobject(ST(0)) == 0)
3604       {
3605         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3606           PackageName);
3607         goto PerlException;
3608       }
3609     reference=SvRV(ST(0));
3610     hv=SvSTASH(reference);
3611     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3612     if (image == (Image *) NULL)
3613       {
3614         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3615           PackageName);
3616         goto PerlException;
3617       }
3618     op=MeanEvaluateOperator;
3619     if (items == 2)
3620       {
3621         ssize_t
3622           in;
3623
3624         in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
3625           SvPV(ST(1),na));
3626         if (in < 0)
3627           {
3628             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3629               SvPV(ST(1),na));
3630             return;
3631           }
3632         op=(MagickEvaluateOperator) in;
3633       }
3634     else
3635       for (i=2; i < items; i+=2)
3636       {
3637         attribute=(char *) SvPV(ST(i-1),na);
3638         switch (*attribute)
3639         {
3640           case 'O':
3641           case 'o':
3642           {
3643             if (LocaleCompare(attribute,"operator") == 0)
3644               {
3645                 ssize_t
3646                   in;
3647
3648                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3649                   MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
3650                 if (in < 0)
3651                   {
3652                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3653                       SvPV(ST(i),na));
3654                     return;
3655                   }
3656                 op=(MagickEvaluateOperator) in;
3657                 break;
3658               }
3659             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3660               attribute);
3661             break;
3662           }
3663           default:
3664           {
3665             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3666               attribute);
3667             break;
3668           }
3669         }
3670       }
3671     image=EvaluateImages(image,op,exception);
3672     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3673       goto PerlException;
3674     /*
3675       Create blessed Perl array for the returned image.
3676     */
3677     av=newAV();
3678     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3679     SvREFCNT_dec(av);
3680     AddImageToRegistry(sv,image);
3681     rv=newRV(sv);
3682     av_push(av,sv_bless(rv,hv));
3683     SvREFCNT_dec(sv);
3684     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3685     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
3686       "evaluate-%.*s",(int) (MaxTextExtent-9),
3687       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3688     (void) CopyMagickString(image->filename,info->image_info->filename,
3689       MaxTextExtent);
3690     SetImageInfo(info->image_info,0,exception);
3691     exception=DestroyExceptionInfo(exception);
3692     SvREFCNT_dec(perl_exception);
3693     XSRETURN(1);
3694
3695   PerlException:
3696     InheritPerlException(exception,perl_exception);
3697     exception=DestroyExceptionInfo(exception);
3698     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3699     SvPOK_on(perl_exception);
3700     ST(0)=sv_2mortal(perl_exception);
3701     XSRETURN(1);
3702   }
3703 \f
3704 #
3705 ###############################################################################
3706 #                                                                             #
3707 #                                                                             #
3708 #                                                                             #
3709 #   F e a t u r e s                                                           #
3710 #                                                                             #
3711 #                                                                             #
3712 #                                                                             #
3713 ###############################################################################
3714 #
3715 #
3716 void
3717 Features(ref,...)
3718   Image::Magick ref=NO_INIT
3719   ALIAS:
3720     FeaturesImage = 1
3721     features      = 2
3722     featuresimage = 3
3723   PPCODE:
3724   {
3725 #define ChannelFeatures(channel,direction) \
3726 { \
3727   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3728     channel_features[channel].angular_second_moment[direction]); \
3729   PUSHs(sv_2mortal(newSVpv(message,0))); \
3730   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3731     channel_features[channel].contrast[direction]); \
3732   PUSHs(sv_2mortal(newSVpv(message,0))); \
3733   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3734     channel_features[channel].contrast[direction]); \
3735   PUSHs(sv_2mortal(newSVpv(message,0))); \
3736   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3737     channel_features[channel].variance_sum_of_squares[direction]); \
3738   PUSHs(sv_2mortal(newSVpv(message,0))); \
3739   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3740     channel_features[channel].inverse_difference_moment[direction]); \
3741   PUSHs(sv_2mortal(newSVpv(message,0))); \
3742   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3743     channel_features[channel].sum_average[direction]); \
3744   PUSHs(sv_2mortal(newSVpv(message,0))); \
3745   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3746     channel_features[channel].sum_variance[direction]); \
3747   PUSHs(sv_2mortal(newSVpv(message,0))); \
3748   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3749     channel_features[channel].sum_entropy[direction]); \
3750   PUSHs(sv_2mortal(newSVpv(message,0))); \
3751   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3752     channel_features[channel].entropy[direction]); \
3753   PUSHs(sv_2mortal(newSVpv(message,0))); \
3754   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3755     channel_features[channel].difference_variance[direction]); \
3756   PUSHs(sv_2mortal(newSVpv(message,0))); \
3757   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3758     channel_features[channel].difference_entropy[direction]); \
3759   PUSHs(sv_2mortal(newSVpv(message,0))); \
3760   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3761     channel_features[channel].measure_of_correlation_1[direction]); \
3762   PUSHs(sv_2mortal(newSVpv(message,0))); \
3763   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3764     channel_features[channel].measure_of_correlation_2[direction]); \
3765   PUSHs(sv_2mortal(newSVpv(message,0))); \
3766   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3767     channel_features[channel].maximum_correlation_coefficient[direction]); \
3768   PUSHs(sv_2mortal(newSVpv(message,0))); \
3769 }
3770
3771     AV
3772       *av;
3773
3774     char
3775       *attribute,
3776       message[MaxTextExtent];
3777
3778     ChannelFeatures
3779       *channel_features;
3780
3781     double
3782       distance;
3783
3784     ExceptionInfo
3785       *exception;
3786
3787     Image
3788       *image;
3789
3790     register ssize_t
3791       i;
3792
3793     ssize_t
3794       count;
3795
3796     struct PackageInfo
3797       *info;
3798
3799     SV
3800       *perl_exception,
3801       *reference;
3802
3803     PERL_UNUSED_VAR(ref);
3804     PERL_UNUSED_VAR(ix);
3805     exception=AcquireExceptionInfo();
3806     perl_exception=newSVpv("",0);
3807     av=NULL;
3808     if (sv_isobject(ST(0)) == 0)
3809       {
3810         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3811           PackageName);
3812         goto PerlException;
3813       }
3814     reference=SvRV(ST(0));
3815     av=newAV();
3816     SvREFCNT_dec(av);
3817     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3818     if (image == (Image *) NULL)
3819       {
3820         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3821           PackageName);
3822         goto PerlException;
3823       }
3824     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3825     distance=1;
3826     for (i=2; i < items; i+=2)
3827     {
3828       attribute=(char *) SvPV(ST(i-1),na);
3829       switch (*attribute)
3830       {
3831         case 'D':
3832         case 'd':
3833         {
3834           if (LocaleCompare(attribute,"distance") == 0)
3835             {
3836               distance=StringToLong((char *) SvPV(ST(1),na));
3837               break;
3838             }
3839           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3840             attribute);
3841           break;
3842         }
3843         default:
3844         {
3845           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3846             attribute);
3847           break;
3848         }
3849       }
3850     }
3851     count=0;
3852     for ( ; image; image=image->next)
3853     {
3854       channel_features=GetImageFeatures(image,distance,
3855         &image->exception);
3856       if (channel_features == (ChannelFeatures *) NULL)
3857         continue;
3858       count++;
3859       EXTEND(sp,75*count);
3860       for (i=0; i < 4; i++)
3861       {
3862         ChannelFeatures(RedChannel,i);
3863         ChannelFeatures(GreenChannel,i);
3864         ChannelFeatures(BlueChannel,i);
3865         if (image->colorspace == CMYKColorspace)
3866           ChannelFeatures(BlackChannel,i);
3867         if (image->matte != MagickFalse)
3868           ChannelFeatures(AlphaChannel,i);
3869       }
3870       channel_features=(ChannelFeatures *)
3871         RelinquishMagickMemory(channel_features);
3872     }
3873
3874   PerlException:
3875     InheritPerlException(exception,perl_exception);
3876     exception=DestroyExceptionInfo(exception);
3877     SvREFCNT_dec(perl_exception);
3878   }
3879 \f
3880 #
3881 ###############################################################################
3882 #                                                                             #
3883 #                                                                             #
3884 #                                                                             #
3885 #   F l a t t e n                                                             #
3886 #                                                                             #
3887 #                                                                             #
3888 #                                                                             #
3889 ###############################################################################
3890 #
3891 #
3892 void
3893 Flatten(ref)
3894   Image::Magick ref=NO_INIT
3895   ALIAS:
3896     FlattenImage   = 1
3897     flatten        = 2
3898     flattenimage   = 3
3899   PPCODE:
3900   {
3901     AV
3902       *av;
3903
3904     char
3905       *attribute,
3906       *p;
3907
3908     ExceptionInfo
3909       *exception;
3910
3911     HV
3912       *hv;
3913
3914     Image
3915       *image;
3916
3917     PixelPacket
3918       background_color;
3919
3920     register ssize_t
3921       i;
3922
3923     struct PackageInfo
3924       *info;
3925
3926     SV
3927       *perl_exception,
3928       *reference,
3929       *rv,
3930       *sv;
3931
3932     PERL_UNUSED_VAR(ref);
3933     PERL_UNUSED_VAR(ix);
3934     exception=AcquireExceptionInfo();
3935     perl_exception=newSVpv("",0);
3936     sv=NULL;
3937     if (sv_isobject(ST(0)) == 0)
3938       {
3939         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3940           PackageName);
3941         goto PerlException;
3942       }
3943     reference=SvRV(ST(0));
3944     hv=SvSTASH(reference);
3945     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3946     if (image == (Image *) NULL)
3947       {
3948         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3949           PackageName);
3950         goto PerlException;
3951       }
3952     background_color=image->background_color;
3953     if (items == 2)
3954       (void) QueryColorDatabase((char *) SvPV(ST(1),na),&background_color,
3955         exception);
3956     else
3957       for (i=2; i < items; i+=2)
3958       {
3959         attribute=(char *) SvPV(ST(i-1),na);
3960         switch (*attribute)
3961         {
3962           case 'B':
3963           case 'b':
3964           {
3965             if (LocaleCompare(attribute,"background") == 0)
3966               {
3967                 (void) QueryColorDatabase((char *) SvPV(ST(1),na),
3968                   &background_color,exception);
3969                 break;
3970               }
3971             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3972               attribute);
3973             break;
3974           }
3975           default:
3976           {
3977             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3978               attribute);
3979             break;
3980           }
3981         }
3982       }
3983     image->background_color=background_color;
3984     image=MergeImageLayers(image,FlattenLayer,exception);
3985     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3986       goto PerlException;
3987     /*
3988       Create blessed Perl array for the returned image.
3989     */
3990     av=newAV();
3991     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3992     SvREFCNT_dec(av);
3993     AddImageToRegistry(sv,image);
3994     rv=newRV(sv);
3995     av_push(av,sv_bless(rv,hv));
3996     SvREFCNT_dec(sv);
3997     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3998     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
3999       "flatten-%.*s",(int) (MaxTextExtent-9),
4000       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4001     (void) CopyMagickString(image->filename,info->image_info->filename,
4002       MaxTextExtent);
4003     SetImageInfo(info->image_info,0,exception);
4004     exception=DestroyExceptionInfo(exception);
4005     SvREFCNT_dec(perl_exception);
4006     XSRETURN(1);
4007
4008   PerlException:
4009     InheritPerlException(exception,perl_exception);
4010     exception=DestroyExceptionInfo(exception);
4011     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4012     SvPOK_on(perl_exception);  /* return messages in string context */
4013     ST(0)=sv_2mortal(perl_exception);
4014     XSRETURN(1);
4015   }
4016 \f
4017 #
4018 ###############################################################################
4019 #                                                                             #
4020 #                                                                             #
4021 #                                                                             #
4022 #   F x                                                                       #
4023 #                                                                             #
4024 #                                                                             #
4025 #                                                                             #
4026 ###############################################################################
4027 #
4028 #
4029 void
4030 Fx(ref,...)
4031   Image::Magick ref=NO_INIT
4032   ALIAS:
4033     FxImage  = 1
4034     fx       = 2
4035     fximage  = 3
4036   PPCODE:
4037   {
4038     AV
4039       *av;
4040
4041     char
4042       *attribute,
4043       expression[MaxTextExtent];
4044
4045     ChannelType
4046       channel,
4047       channel_mask;
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     channel_mask=SetPixelChannelMask(image,channel);
4154     image=FxImage(image,expression,exception);
4155     if (image != (Image *) NULL)
4156       (void) SetPixelChannelMask(image,channel_mask);
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               SetPixelChannelMap(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) & UpdatePixelTrait) != 0)
6203           PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6204         if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6205           PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6206         if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6207           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6208         if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6209             (image->colorspace == CMYKColorspace))
6210           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6211         if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 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     MedianConvolveImage  =  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     BrightnessContrast = 263
7185     BrightnessContrastImage = 264
7186     Morphology         = 265
7187     MorphologyImage    = 266
7188     ColorMatrix        = 267
7189     ColorMatrixImage   = 268
7190     Color              = 269
7191     ColorImage         = 270
7192     Mode               = 271
7193     ModeImage          = 272
7194     Statistic          = 273
7195     StatisticImage     = 274
7196     MogrifyRegion      = 666
7197   PPCODE:
7198   {
7199     AffineMatrix
7200       affine,
7201       current;
7202
7203     char
7204       attribute_flag[MaxArguments],
7205       message[MaxTextExtent];
7206
7207     ChannelType
7208       channel,
7209       channel_mask;
7210
7211     CompositeOperator
7212       compose;
7213
7214     const char
7215       *attribute,
7216       *value;
7217
7218     double
7219       angle;
7220
7221     ExceptionInfo
7222       *exception;
7223
7224     GeometryInfo
7225       geometry_info;
7226
7227     Image
7228       *image,
7229       *next,
7230       *region_image;
7231
7232     MagickBooleanType
7233       status;
7234
7235     MagickStatusType
7236       flags;
7237
7238     PixelPacket
7239       fill_color;
7240
7241     RectangleInfo
7242       geometry,
7243       region_info;
7244
7245     register ssize_t
7246       i;
7247
7248     ssize_t
7249       base,
7250       j,
7251       number_images;
7252
7253     struct Methods
7254       *rp;
7255
7256     struct PackageInfo
7257       *info;
7258
7259     SV
7260       *perl_exception,
7261       **pv,
7262       *reference,
7263       **reference_vector;
7264
7265     struct ArgumentList
7266       argument_list[MaxArguments];
7267
7268     PERL_UNUSED_VAR(ref);
7269     PERL_UNUSED_VAR(ix);
7270     exception=AcquireExceptionInfo();
7271     perl_exception=newSVpv("",0);
7272     reference_vector=NULL;
7273     region_image=NULL;
7274     number_images=0;
7275     base=2;
7276     if (sv_isobject(ST(0)) == 0)
7277       {
7278         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7279           PackageName);
7280         goto PerlException;
7281       }
7282     reference=SvRV(ST(0));
7283     region_info.width=0;
7284     region_info.height=0;
7285     region_info.x=0;
7286     region_info.y=0;
7287     region_image=(Image *) NULL;
7288     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7289     if (ix && (ix != 666))
7290       {
7291         /*
7292           Called as Method(...)
7293         */
7294         ix=(ix+1)/2;
7295         rp=(&Methods[ix-1]);
7296         attribute=rp->name;
7297       }
7298     else
7299       {
7300         /*
7301           Called as Mogrify("Method",...)
7302         */
7303         attribute=(char *) SvPV(ST(1),na);
7304         if (ix)
7305           {
7306             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7307             attribute=(char *) SvPV(ST(2),na);
7308             base++;
7309           }
7310         for (rp=Methods; ; rp++)
7311         {
7312           if (rp >= EndOf(Methods))
7313             {
7314               ThrowPerlException(exception,OptionError,
7315                 "UnrecognizedPerlMagickMethod",attribute);
7316               goto PerlException;
7317             }
7318           if (strEQcase(attribute,rp->name))
7319             break;
7320         }
7321         ix=rp-Methods+1;
7322         base++;
7323       }
7324     if (image == (Image *) NULL)
7325       {
7326         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7327         goto PerlException;
7328       }
7329     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7330     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7331     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7332     {
7333       Arguments
7334         *pp,
7335         *qq;
7336
7337       ssize_t
7338         ssize_test;
7339
7340       struct ArgumentList
7341         *al;
7342
7343       SV
7344         *sv;
7345
7346       sv=NULL;
7347       ssize_test=0;
7348       pp=(Arguments *) NULL;
7349       qq=rp->arguments;
7350       if (i == items)
7351         {
7352           pp=rp->arguments,
7353           sv=ST(i-1);
7354         }
7355       else
7356         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7357         {
7358           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7359             break;
7360           if (strEQcase(attribute,qq->method) > ssize_test)
7361             {
7362               pp=qq;
7363               ssize_test=strEQcase(attribute,qq->method);
7364             }
7365         }
7366       if (pp == (Arguments *) NULL)
7367         {
7368           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7369             attribute);
7370           goto continue_outer_loop;
7371         }
7372       al=(&argument_list[pp-rp->arguments]);
7373       switch (pp->type)
7374       {
7375         case ArrayReference:
7376         {
7377           if (SvTYPE(sv) != SVt_RV)
7378             {
7379               (void) FormatLocaleString(message,MaxTextExtent,
7380                 "invalid %.60s value",pp->method);
7381               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7382               goto continue_outer_loop;
7383             }
7384           al->array_reference=SvRV(sv);
7385           break;
7386         }
7387         case RealReference:
7388         {
7389           al->real_reference=SvNV(sv);
7390           break;
7391         }
7392         case FileReference:
7393         {
7394           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7395           break;
7396         }
7397         case ImageReference:
7398         {
7399           if (!sv_isobject(sv) ||
7400               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7401                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7402             {
7403               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7404                 PackageName);
7405               goto PerlException;
7406             }
7407           break;
7408         }
7409         case IntegerReference:
7410         {
7411           al->integer_reference=SvIV(sv);
7412           break;
7413         }
7414         case StringReference:
7415         {
7416           al->string_reference=(char *) SvPV(sv,al->length);
7417           if (sv_isobject(sv))
7418             al->image_reference=SetupList(aTHX_ SvRV(sv),
7419               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7420           break;
7421         }
7422         default:
7423         {
7424           /*
7425             Is a string; look up name.
7426           */
7427           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7428             {
7429               al->string_reference=(char *) SvPV(sv,al->length);
7430               al->integer_reference=(-1);
7431               break;
7432             }
7433           al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7434             MagickFalse,SvPV(sv,na));
7435           if (pp->type == MagickChannelOptions)
7436             al->integer_reference=ParseChannelOption(SvPV(sv,na));
7437           if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7438             {
7439               (void) FormatLocaleString(message,MaxTextExtent,
7440                 "invalid %.60s value",pp->method);
7441               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7442               goto continue_outer_loop;
7443             }
7444           break;
7445         }
7446       }
7447       attribute_flag[pp-rp->arguments]++;
7448       continue_outer_loop: ;
7449     }
7450     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7451     pv=reference_vector;
7452     SetGeometryInfo(&geometry_info);
7453     channel=DefaultChannels;
7454     for (next=image; next; next=next->next)
7455     {
7456       image=next;
7457       SetGeometry(image,&geometry);
7458       if ((region_info.width*region_info.height) != 0)
7459         {
7460           region_image=image;
7461           image=CropImage(image,&region_info,exception);
7462         }
7463       switch (ix)
7464       {
7465         default:
7466         {
7467           (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double) ix);
7468           ThrowPerlException(exception,OptionError,
7469             "UnrecognizedPerlMagickMethod",message);
7470           goto PerlException;
7471         }
7472         case 1:  /* Comment */
7473         {
7474           if (attribute_flag[0] == 0)
7475             argument_list[0].string_reference=(char *) NULL;
7476           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7477             info ? info->image_info : (ImageInfo *) NULL,image,
7478             argument_list[0].string_reference));
7479           break;
7480         }
7481         case 2:  /* Label */
7482         {
7483           if (attribute_flag[0] == 0)
7484             argument_list[0].string_reference=(char *) NULL;
7485           (void) SetImageProperty(image,"label",InterpretImageProperties(
7486             info ? info->image_info : (ImageInfo *) NULL,image,
7487             argument_list[0].string_reference));
7488           break;
7489         }
7490         case 3:  /* AddNoise */
7491         {
7492           if (attribute_flag[0] == 0)
7493             argument_list[0].integer_reference=UniformNoise;
7494           if (attribute_flag[1] != 0)
7495             channel=(ChannelType) argument_list[1].integer_reference;
7496           channel_mask=SetPixelChannelMask(image,channel);
7497           image=AddNoiseImage(image,(NoiseType)
7498             argument_list[0].integer_reference,exception);
7499           if (image != (Image *) NULL)
7500             (void) SetPixelChannelMask(image,channel_mask);
7501           break;
7502         }
7503         case 4:  /* Colorize */
7504         {
7505           PixelPacket
7506             target;
7507
7508           (void) GetOneVirtualPixel(image,0,0,&target,exception);
7509           if (attribute_flag[0] != 0)
7510             (void) QueryColorDatabase(argument_list[0].string_reference,&target,
7511               exception);
7512           if (attribute_flag[1] == 0)
7513             argument_list[1].string_reference="100%";
7514           image=ColorizeImage(image,argument_list[1].string_reference,target,
7515             exception);
7516           break;
7517         }
7518         case 5:  /* Border */
7519         {
7520           geometry.width=0;
7521           geometry.height=0;
7522           if (attribute_flag[0] != 0)
7523             {
7524               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7525                 &geometry,exception);
7526               if ((flags & HeightValue) == 0)
7527                 geometry.height=geometry.width;
7528             }
7529           if (attribute_flag[1] != 0)
7530             geometry.width=argument_list[1].integer_reference;
7531           if (attribute_flag[2] != 0)
7532             geometry.height=argument_list[2].integer_reference;
7533           if (attribute_flag[3] != 0)
7534             QueryColorDatabase(argument_list[3].string_reference,
7535               &image->border_color,exception);
7536           if (attribute_flag[4] != 0)
7537             QueryColorDatabase(argument_list[4].string_reference,
7538               &image->border_color,exception);
7539           if (attribute_flag[5] != 0)
7540             QueryColorDatabase(argument_list[5].string_reference,
7541               &image->border_color,exception);
7542           if (attribute_flag[6] != 0)
7543             image->compose=(CompositeOperator) argument_list[6].integer_reference;
7544           image=BorderImage(image,&geometry,exception);
7545           break;
7546         }
7547         case 6:  /* Blur */
7548         {
7549           if (attribute_flag[0] != 0)
7550             {
7551               flags=ParseGeometry(argument_list[0].string_reference,
7552                 &geometry_info);
7553               if ((flags & SigmaValue) == 0)
7554                 geometry_info.sigma=1.0;
7555             }
7556           if (attribute_flag[1] != 0)
7557             geometry_info.rho=argument_list[1].real_reference;
7558           if (attribute_flag[2] != 0)
7559             geometry_info.sigma=argument_list[2].real_reference;
7560           if (attribute_flag[3] != 0)
7561             channel=(ChannelType) argument_list[3].integer_reference;
7562           channel_mask=SetPixelChannelMask(image,channel);
7563           image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
7564             exception);
7565           if (image != (Image *) NULL)
7566             (void) SetPixelChannelMask(image,channel_mask);
7567           break;
7568         }
7569         case 7:  /* Chop */
7570         {
7571           if (attribute_flag[0] != 0)
7572             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7573               &geometry,exception);
7574           if (attribute_flag[1] != 0)
7575             geometry.width=argument_list[1].integer_reference;
7576           if (attribute_flag[2] != 0)
7577             geometry.height=argument_list[2].integer_reference;
7578           if (attribute_flag[3] != 0)
7579             geometry.x=argument_list[3].integer_reference;
7580           if (attribute_flag[4] != 0)
7581             geometry.y=argument_list[4].integer_reference;
7582           image=ChopImage(image,&geometry,exception);
7583           break;
7584         }
7585         case 8:  /* Crop */
7586         {
7587           if (attribute_flag[6] != 0)
7588             image->gravity=(GravityType) argument_list[6].integer_reference;
7589           if (attribute_flag[0] != 0)
7590             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7591               &geometry,exception);
7592           if (attribute_flag[1] != 0)
7593             geometry.width=argument_list[1].integer_reference;
7594           if (attribute_flag[2] != 0)
7595             geometry.height=argument_list[2].integer_reference;
7596           if (attribute_flag[3] != 0)
7597             geometry.x=argument_list[3].integer_reference;
7598           if (attribute_flag[4] != 0)
7599             geometry.y=argument_list[4].integer_reference;
7600           if (attribute_flag[5] != 0)
7601             image->fuzz=
7602               SiPrefixToDouble(argument_list[5].string_reference,QuantumRange);
7603           image=CropImage(image,&geometry,exception);
7604           break;
7605         }
7606         case 9:  /* Despeckle */
7607         {
7608           image=DespeckleImage(image,exception);
7609           break;
7610         }
7611         case 10:  /* Edge */
7612         {
7613           if (attribute_flag[0] != 0)
7614             geometry_info.rho=argument_list[0].real_reference;
7615           image=EdgeImage(image,geometry_info.rho,exception);
7616           break;
7617         }
7618         case 11:  /* Emboss */
7619         {
7620           if (attribute_flag[0] != 0)
7621             {
7622               flags=ParseGeometry(argument_list[0].string_reference,
7623                 &geometry_info);
7624               if ((flags & SigmaValue) == 0)
7625                 geometry_info.sigma=1.0;
7626             }
7627           if (attribute_flag[1] != 0)
7628             geometry_info.rho=argument_list[1].real_reference;
7629           if (attribute_flag[2] != 0)
7630             geometry_info.sigma=argument_list[2].real_reference;
7631           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
7632             exception);
7633           break;
7634         }
7635         case 12:  /* Enhance */
7636         {
7637           image=EnhanceImage(image,exception);
7638           break;
7639         }
7640         case 13:  /* Flip */
7641         {
7642           image=FlipImage(image,exception);
7643           break;
7644         }
7645         case 14:  /* Flop */
7646         {
7647           image=FlopImage(image,exception);
7648           break;
7649         }
7650         case 15:  /* Frame */
7651         {
7652           FrameInfo
7653             frame_info;
7654
7655           if (attribute_flag[0] != 0)
7656             {
7657               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7658                 &geometry,exception);
7659               if ((flags & HeightValue) == 0)
7660                 geometry.height=geometry.width;
7661               frame_info.width=geometry.width;
7662               frame_info.height=geometry.height;
7663               frame_info.outer_bevel=geometry.x;
7664               frame_info.inner_bevel=geometry.y;
7665             }
7666           if (attribute_flag[1] != 0)
7667             frame_info.width=argument_list[1].integer_reference;
7668           if (attribute_flag[2] != 0)
7669             frame_info.height=argument_list[2].integer_reference;
7670           if (attribute_flag[3] != 0)
7671             frame_info.inner_bevel=argument_list[3].integer_reference;
7672           if (attribute_flag[4] != 0)
7673             frame_info.outer_bevel=argument_list[4].integer_reference;
7674           if (attribute_flag[5] != 0)
7675             QueryColorDatabase(argument_list[5].string_reference,&fill_color,
7676               exception);
7677           if (attribute_flag[6] != 0)
7678             QueryColorDatabase(argument_list[6].string_reference,&fill_color,
7679               exception);
7680           frame_info.x=(ssize_t) frame_info.width;
7681           frame_info.y=(ssize_t) frame_info.height;
7682           frame_info.width=image->columns+2*frame_info.x;
7683           frame_info.height=image->rows+2*frame_info.y;
7684           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
7685             image->matte_color=fill_color;
7686           if (attribute_flag[7] != 0)
7687             image->compose=(CompositeOperator) argument_list[7].integer_reference;
7688           image=FrameImage(image,&frame_info,exception);
7689           break;
7690         }
7691         case 16:  /* Implode */
7692         {
7693           if (attribute_flag[0] == 0)
7694             argument_list[0].real_reference=0.5;
7695           if (attribute_flag[1] != 0)
7696             image->interpolate=(InterpolatePixelMethod)
7697               argument_list[1].integer_reference;
7698           image=ImplodeImage(image,argument_list[0].real_reference,
7699             exception);
7700           break;
7701         }
7702         case 17:  /* Magnify */
7703         {
7704           image=MagnifyImage(image,exception);
7705           break;
7706         }
7707         case 18:  /* MedianFilter */
7708         {
7709           if (attribute_flag[0] != 0)
7710             {
7711               flags=ParseGeometry(argument_list[0].string_reference,
7712                 &geometry_info);
7713               if ((flags & SigmaValue) == 0)
7714                 geometry_info.sigma=1.0;
7715             }
7716           if (attribute_flag[1] != 0)
7717             geometry_info.rho=argument_list[1].real_reference;
7718           if (attribute_flag[2] != 0)
7719             geometry_info.sigma=argument_list[2].real_reference;
7720           if (attribute_flag[3] != 0)
7721             channel=(ChannelType) argument_list[3].integer_reference;
7722           channel_mask=SetPixelChannelMask(image,channel);
7723           image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
7724             (size_t) geometry_info.sigma,exception);
7725           if (image != (Image *) NULL)
7726             (void) SetPixelChannelMask(image,channel_mask);
7727           break;
7728         }
7729         case 19:  /* Minify */
7730         {
7731           image=MinifyImage(image,exception);
7732           break;
7733         }
7734         case 20:  /* OilPaint */
7735         {
7736           if (attribute_flag[0] == 0)
7737             argument_list[0].real_reference=0.0;
7738           image=OilPaintImage(image,argument_list[0].real_reference,
7739             exception);
7740           break;
7741         }
7742         case 21:  /* ReduceNoise */
7743         {
7744           if (attribute_flag[0] != 0)
7745             {
7746               flags=ParseGeometry(argument_list[0].string_reference,
7747                 &geometry_info);
7748               if ((flags & SigmaValue) == 0)
7749                 geometry_info.sigma=1.0;
7750             }
7751           if (attribute_flag[1] != 0)
7752             geometry_info.rho=argument_list[1].real_reference;
7753           if (attribute_flag[2] != 0)
7754             geometry_info.sigma=argument_list[2].real_reference;
7755           if (attribute_flag[3] != 0)
7756             channel=(ChannelType) argument_list[3].integer_reference;
7757           channel_mask=SetPixelChannelMask(image,channel);
7758           image=StatisticImage(image,NonpeakStatistic,(size_t)
7759             geometry_info.rho,(size_t) geometry_info.sigma,exception);
7760           if (image != (Image *) NULL)
7761             (void) SetPixelChannelMask(image,channel_mask);
7762           break;
7763         }
7764         case 22:  /* Roll */
7765         {
7766           if (attribute_flag[0] != 0)
7767             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7768               &geometry,exception);
7769           if (attribute_flag[1] != 0)
7770             geometry.x=argument_list[1].integer_reference;
7771           if (attribute_flag[2] != 0)
7772             geometry.y=argument_list[2].integer_reference;
7773           image=RollImage(image,geometry.x,geometry.y,exception);
7774           break;
7775         }
7776         case 23:  /* Rotate */
7777         {
7778           if (attribute_flag[0] == 0)
7779             argument_list[0].real_reference=90.0;
7780           if (attribute_flag[1] != 0)
7781             QueryColorDatabase(argument_list[1].string_reference,
7782               &image->background_color,exception);
7783           if (attribute_flag[2] != 0)
7784             QueryColorDatabase(argument_list[2].string_reference,
7785               &image->background_color,exception);
7786           if (attribute_flag[3] != 0)
7787             QueryColorDatabase(argument_list[3].string_reference,
7788               &image->background_color,exception);
7789           image=RotateImage(image,argument_list[0].real_reference,exception);
7790           break;
7791         }
7792         case 24:  /* Sample */
7793         {
7794           if (attribute_flag[0] != 0)
7795             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7796               &geometry,exception);
7797           if (attribute_flag[1] != 0)
7798             geometry.width=argument_list[1].integer_reference;
7799           if (attribute_flag[2] != 0)
7800             geometry.height=argument_list[2].integer_reference;
7801           image=SampleImage(image,geometry.width,geometry.height,exception);
7802           break;
7803         }
7804         case 25:  /* Scale */
7805         {
7806           if (attribute_flag[0] != 0)
7807             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7808               &geometry,exception);
7809           if (attribute_flag[1] != 0)
7810             geometry.width=argument_list[1].integer_reference;
7811           if (attribute_flag[2] != 0)
7812             geometry.height=argument_list[2].integer_reference;
7813           image=ScaleImage(image,geometry.width,geometry.height,exception);
7814           break;
7815         }
7816         case 26:  /* Shade */
7817         {
7818           if (attribute_flag[0] != 0)
7819             {
7820               flags=ParseGeometry(argument_list[0].string_reference,
7821                 &geometry_info);
7822               if ((flags & SigmaValue) == 0)
7823                 geometry_info.sigma=0.0;
7824             }
7825           if (attribute_flag[1] != 0)
7826             geometry_info.rho=argument_list[1].real_reference;
7827           if (attribute_flag[2] != 0)
7828             geometry_info.sigma=argument_list[2].real_reference;
7829           image=ShadeImage(image,
7830             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
7831             geometry_info.rho,geometry_info.sigma,exception);
7832           break;
7833         }
7834         case 27:  /* Sharpen */
7835         {
7836           if (attribute_flag[0] != 0)
7837             {
7838               flags=ParseGeometry(argument_list[0].string_reference,
7839                 &geometry_info);
7840               if ((flags & SigmaValue) == 0)
7841                 geometry_info.sigma=1.0;
7842             }
7843           if (attribute_flag[1] != 0)
7844             geometry_info.rho=argument_list[1].real_reference;
7845           if (attribute_flag[2] != 0)
7846             geometry_info.sigma=argument_list[2].real_reference;
7847           if (attribute_flag[3] != 0)
7848             channel=(ChannelType) argument_list[3].integer_reference;
7849           channel_mask=SetPixelChannelMask(image,channel);
7850           image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
7851             exception);
7852           if (image != (Image *) NULL)
7853             (void) SetPixelChannelMask(image,channel_mask);
7854           break;
7855         }
7856         case 28:  /* Shear */
7857         {
7858           if (attribute_flag[0] != 0)
7859             {
7860               flags=ParseGeometry(argument_list[0].string_reference,
7861                 &geometry_info);
7862               if ((flags & SigmaValue) == 0)
7863                 geometry_info.sigma=geometry_info.rho;
7864             }
7865           if (attribute_flag[1] != 0)
7866             geometry_info.rho=argument_list[1].real_reference;
7867           if (attribute_flag[2] != 0)
7868             geometry_info.sigma=argument_list[2].real_reference;
7869           if (attribute_flag[3] != 0)
7870             QueryColorDatabase(argument_list[3].string_reference,
7871               &image->background_color,exception);
7872           if (attribute_flag[4] != 0)
7873             QueryColorDatabase(argument_list[4].string_reference,
7874               &image->background_color,exception);
7875           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
7876             exception);
7877           break;
7878         }
7879         case 29:  /* Spread */
7880         {
7881           if (attribute_flag[0] == 0)
7882             argument_list[0].real_reference=1.0;
7883           image=SpreadImage(image,argument_list[0].real_reference,exception);
7884           break;
7885         }
7886         case 30:  /* Swirl */
7887         {
7888           if (attribute_flag[0] == 0)
7889             argument_list[0].real_reference=50.0;
7890           if (attribute_flag[1] != 0)
7891             image->interpolate=(InterpolatePixelMethod)
7892               argument_list[1].integer_reference;
7893           image=SwirlImage(image,argument_list[0].real_reference,exception);
7894           break;
7895         }
7896         case 31:  /* Resize */
7897         case 32:  /* Zoom */
7898         {
7899           if (attribute_flag[0] != 0)
7900             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7901               &geometry,exception);
7902           if (attribute_flag[1] != 0)
7903             geometry.width=argument_list[1].integer_reference;
7904           if (attribute_flag[2] != 0)
7905             geometry.height=argument_list[2].integer_reference;
7906           if (attribute_flag[3] == 0)
7907             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
7908           if (attribute_flag[4] != 0)
7909             SetImageArtifact(image,"filter:support",
7910               argument_list[4].string_reference);
7911           if (attribute_flag[5] == 0)
7912             argument_list[5].real_reference=1.0;
7913           image=ResizeImage(image,geometry.width,geometry.height,
7914             (FilterTypes) argument_list[3].integer_reference,
7915             argument_list[5].real_reference,exception);
7916           break;
7917         }
7918         case 33:  /* Annotate */
7919         {
7920           DrawInfo
7921             *draw_info;
7922
7923           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
7924             (DrawInfo *) NULL);
7925           if (attribute_flag[0] != 0)
7926             {
7927               char
7928                 *text;
7929
7930               text=InterpretImageProperties(info ? info->image_info :
7931                 (ImageInfo *) NULL,image,argument_list[0].string_reference);
7932               (void) CloneString(&draw_info->text,text);
7933               text=DestroyString(text);
7934             }
7935           if (attribute_flag[1] != 0)
7936             (void) CloneString(&draw_info->font,
7937               argument_list[1].string_reference);
7938           if (attribute_flag[2] != 0)
7939             draw_info->pointsize=argument_list[2].real_reference;
7940           if (attribute_flag[3] != 0)
7941             (void) CloneString(&draw_info->density,
7942               argument_list[3].string_reference);
7943           if (attribute_flag[4] != 0)
7944             (void) QueryColorDatabase(argument_list[4].string_reference,
7945               &draw_info->undercolor,exception);
7946           if (attribute_flag[5] != 0)
7947             {
7948               (void) QueryColorDatabase(argument_list[5].string_reference,
7949                 &draw_info->stroke,exception);
7950               if (argument_list[5].image_reference != (Image *) NULL)
7951                 draw_info->stroke_pattern=CloneImage(
7952                   argument_list[5].image_reference,0,0,MagickTrue,exception);
7953             }
7954           if (attribute_flag[6] != 0)
7955             {
7956               (void) QueryColorDatabase(argument_list[6].string_reference,
7957                 &draw_info->fill,exception);
7958               if (argument_list[6].image_reference != (Image *) NULL)
7959                 draw_info->fill_pattern=CloneImage(
7960                   argument_list[6].image_reference,0,0,MagickTrue,exception);
7961             }
7962           if (attribute_flag[7] != 0)
7963             {
7964               (void) CloneString(&draw_info->geometry,
7965                 argument_list[7].string_reference);
7966               flags=ParsePageGeometry(image,argument_list[7].string_reference,
7967                 &geometry,exception);
7968               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
7969                 geometry_info.sigma=geometry_info.xi;
7970             }
7971           if (attribute_flag[8] != 0)
7972             (void) QueryColorDatabase(argument_list[8].string_reference,
7973               &draw_info->fill,exception);
7974           if (attribute_flag[11] != 0)
7975             draw_info->gravity=(GravityType) argument_list[11].integer_reference;
7976           if (attribute_flag[25] != 0)
7977             {
7978               AV
7979                 *av;
7980
7981               av=(AV *) argument_list[25].array_reference;
7982               if ((av_len(av) != 3) && (av_len(av) != 5))
7983                 {
7984                   ThrowPerlException(exception,OptionError,
7985                     "affine matrix must have 4 or 6 elements",PackageName);
7986                   goto PerlException;
7987                 }
7988               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
7989               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
7990               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
7991               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
7992               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
7993                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
7994                 {
7995                   ThrowPerlException(exception,OptionError,
7996                     "affine matrix is singular",PackageName);
7997                    goto PerlException;
7998                 }
7999               if (av_len(av) == 5)
8000                 {
8001                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8002                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8003                 }
8004             }
8005           for (j=12; j < 17; j++)
8006           {
8007             if (attribute_flag[j] == 0)
8008               continue;
8009             value=argument_list[j].string_reference;
8010             angle=argument_list[j].real_reference;
8011             current=draw_info->affine;
8012             GetAffineMatrix(&affine);
8013             switch (j)
8014             {
8015               case 12:
8016               {
8017                 /*
8018                   Translate.
8019                 */
8020                 flags=ParseGeometry(value,&geometry_info);
8021                 affine.tx=geometry_info.xi;
8022                 affine.ty=geometry_info.psi;
8023                 if ((flags & PsiValue) == 0)
8024                   affine.ty=affine.tx;
8025                 break;
8026               }
8027               case 13:
8028               {
8029                 /*
8030                   Scale.
8031                 */
8032                 flags=ParseGeometry(value,&geometry_info);
8033                 affine.sx=geometry_info.rho;
8034                 affine.sy=geometry_info.sigma;
8035                 if ((flags & SigmaValue) == 0)
8036                   affine.sy=affine.sx;
8037                 break;
8038               }
8039               case 14:
8040               {
8041                 /*
8042                   Rotate.
8043                 */
8044                 if (angle == 0.0)
8045                   break;
8046                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8047                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8048                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8049                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8050                 break;
8051               }
8052               case 15:
8053               {
8054                 /*
8055                   SkewX.
8056                 */
8057                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8058                 break;
8059               }
8060               case 16:
8061               {
8062                 /*
8063                   SkewY.
8064                 */
8065                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8066                 break;
8067               }
8068             }
8069             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8070             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8071             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8072             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8073             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8074               current.tx;
8075             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8076               current.ty;
8077           }
8078           if (attribute_flag[9] == 0)
8079             argument_list[9].real_reference=0.0;
8080           if (attribute_flag[10] == 0)
8081             argument_list[10].real_reference=0.0;
8082           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8083             {
8084               char
8085                 geometry[MaxTextExtent];
8086
8087               (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
8088                 (double) argument_list[9].real_reference+draw_info->affine.tx,
8089                 (double) argument_list[10].real_reference+draw_info->affine.ty);
8090               (void) CloneString(&draw_info->geometry,geometry);
8091             }
8092           if (attribute_flag[17] != 0)
8093             draw_info->stroke_width=argument_list[17].real_reference;
8094           if (attribute_flag[18] != 0)
8095             {
8096               draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8097                 MagickTrue : MagickFalse;
8098               draw_info->stroke_antialias=draw_info->text_antialias;
8099             }
8100           if (attribute_flag[19] != 0)
8101             (void) CloneString(&draw_info->family,
8102               argument_list[19].string_reference);
8103           if (attribute_flag[20] != 0)
8104             draw_info->style=(StyleType) argument_list[20].integer_reference;
8105           if (attribute_flag[21] != 0)
8106             draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8107           if (attribute_flag[22] != 0)
8108             draw_info->weight=argument_list[22].integer_reference;
8109           if (attribute_flag[23] != 0)
8110             draw_info->align=(AlignType) argument_list[23].integer_reference;
8111           if (attribute_flag[24] != 0)
8112             (void) CloneString(&draw_info->encoding,
8113               argument_list[24].string_reference);
8114           if (attribute_flag[25] != 0)
8115             draw_info->fill_pattern=CloneImage(
8116               argument_list[25].image_reference,0,0,MagickTrue,exception);
8117           if (attribute_flag[26] != 0)
8118             draw_info->fill_pattern=CloneImage(
8119               argument_list[26].image_reference,0,0,MagickTrue,exception);
8120           if (attribute_flag[27] != 0)
8121             draw_info->stroke_pattern=CloneImage(
8122               argument_list[27].image_reference,0,0,MagickTrue,exception);
8123           if (attribute_flag[29] != 0)
8124             draw_info->kerning=argument_list[29].real_reference;
8125           if (attribute_flag[30] != 0)
8126             draw_info->interline_spacing=argument_list[30].real_reference;
8127           if (attribute_flag[31] != 0)
8128             draw_info->interword_spacing=argument_list[31].real_reference;
8129           if (attribute_flag[32] != 0)
8130             draw_info->direction=(DirectionType)
8131               argument_list[32].integer_reference;
8132           (void) AnnotateImage(image,draw_info);
8133           draw_info=DestroyDrawInfo(draw_info);
8134           break;
8135         }
8136         case 34:  /* ColorFloodfill */
8137         {
8138           DrawInfo
8139             *draw_info;
8140
8141           MagickBooleanType
8142             invert;
8143
8144           PixelInfo
8145             target;
8146
8147           draw_info=CloneDrawInfo(info ? info->image_info :
8148             (ImageInfo *) NULL,(DrawInfo *) NULL);
8149           if (attribute_flag[0] != 0)
8150             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8151               &geometry,exception);
8152           if (attribute_flag[1] != 0)
8153             geometry.x=argument_list[1].integer_reference;
8154           if (attribute_flag[2] != 0)
8155             geometry.y=argument_list[2].integer_reference;
8156           if (attribute_flag[3] != 0)
8157             (void) QueryColorDatabase(argument_list[3].string_reference,
8158               &draw_info->fill,exception);
8159           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
8160             exception);
8161           invert=MagickFalse;
8162           if (attribute_flag[4] != 0)
8163             {
8164               QueryMagickColor(argument_list[4].string_reference,&target,
8165                 exception);
8166               invert=MagickTrue;
8167             }
8168           if (attribute_flag[5] != 0)
8169             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
8170               QuantumRange);
8171           if (attribute_flag[6] != 0)
8172             invert=(MagickBooleanType) argument_list[6].integer_reference;
8173           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8174             geometry.y,invert);
8175           draw_info=DestroyDrawInfo(draw_info);
8176           break;
8177         }
8178         case 35:  /* Composite */
8179         {
8180           char
8181             composite_geometry[MaxTextExtent];
8182
8183           Image
8184             *composite_image,
8185             *rotate_image;
8186
8187           compose=OverCompositeOp;
8188           if (attribute_flag[0] != 0)
8189             composite_image=argument_list[0].image_reference;
8190           else
8191             {
8192               ThrowPerlException(exception,OptionError,
8193                 "CompositeImageRequired",PackageName);
8194               goto PerlException;
8195             }
8196           /*
8197             Parameter Handling used for BOTH normal and tiled composition.
8198           */
8199           if (attribute_flag[1] != 0) /* compose */
8200             compose=(CompositeOperator) argument_list[1].integer_reference;
8201           if (attribute_flag[6] != 0) /* opacity  */
8202             {
8203               if (compose != DissolveCompositeOp)
8204                 (void) SetImageOpacity(composite_image,(Quantum)
8205                   SiPrefixToDouble(argument_list[6].string_reference,
8206                   QuantumRange));
8207               else
8208                 {
8209                   CacheView
8210                     *composite_view;
8211
8212                   double
8213                     opacity;
8214
8215                   MagickBooleanType
8216                     sync;
8217
8218                   register ssize_t
8219                     x;
8220
8221                   register Quantum
8222                     *q;
8223
8224                   ssize_t
8225                     y;
8226
8227                   /*
8228                     Handle dissolve composite operator (patch by
8229                     Kevin A. McGrail).
8230                   */
8231                   (void) CloneString(&image->geometry,
8232                     argument_list[6].string_reference);
8233                   opacity=(Quantum) SiPrefixToDouble(
8234                     argument_list[6].string_reference,QuantumRange);
8235                   if (composite_image->matte != MagickTrue)
8236                     (void) SetImageOpacity(composite_image,OpaqueAlpha);
8237                   composite_view=AcquireCacheView(composite_image);
8238                   for (y=0; y < (ssize_t) composite_image->rows ; y++)
8239                   {
8240                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8241                       composite_image->columns,1,exception);
8242                     for (x=0; x < (ssize_t) composite_image->columns; x++)
8243                     {
8244                       if (GetPixelAlpha(image,q) == OpaqueAlpha)
8245                         SetPixelAlpha(composite_image,ClampToQuantum(opacity),q);
8246                       q+=GetPixelChannels(composite_image);
8247                     }
8248                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8249                     if (sync == MagickFalse)
8250                       break;
8251                   }
8252                   composite_view=DestroyCacheView(composite_view);
8253                 }
8254             }
8255           if (attribute_flag[9] != 0)    /* "color=>" */
8256             QueryColorDatabase(argument_list[9].string_reference,
8257               &composite_image->background_color,exception);
8258           if (attribute_flag[12] != 0) /* "interpolate=>" */
8259             image->interpolate=(InterpolatePixelMethod)
8260               argument_list[12].integer_reference;
8261           if (attribute_flag[13] != 0)   /* "args=>" */
8262             (void) SetImageArtifact(composite_image,"compose:args",
8263               argument_list[13].string_reference);
8264           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8265             (void) SetImageArtifact(composite_image,"compose:args",
8266               argument_list[14].string_reference);
8267           /*
8268             Tiling Composition (with orthogonal rotate).
8269           */
8270           rotate_image=(Image *) NULL;
8271           if (attribute_flag[8] != 0)   /* "rotate=>" */
8272             {
8273                /*
8274                  Rotate image.
8275                */
8276                rotate_image=RotateImage(composite_image,
8277                  argument_list[8].real_reference,exception);
8278                if (rotate_image == (Image *) NULL)
8279                  break;
8280             }
8281           if (attribute_flag[7] && argument_list[7].integer_reference) /* tile */
8282             {
8283               ssize_t
8284                 x,
8285                 y;
8286
8287               /*
8288                 Tile the composite image.
8289               */
8290              if (attribute_flag[8] != 0)   /* "tile=>" */
8291                (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8292                  "false");
8293              else
8294                (void) SetImageArtifact(composite_image,
8295                  "compose:outside-overlay","false");
8296              for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8297                 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8298                 {
8299                   if (attribute_flag[8] != 0) /* rotate */
8300                     (void) CompositeImage(image,compose,rotate_image,x,y);
8301                   else
8302                     (void) CompositeImage(image,compose,composite_image,x,y);
8303                 }
8304               if (attribute_flag[8] != 0) /* rotate */
8305                 rotate_image=DestroyImage(rotate_image);
8306               break;
8307             }
8308           /*
8309             Parameter Handling used used ONLY for normal composition.
8310           */
8311           if (attribute_flag[5] != 0) /* gravity */
8312             image->gravity=(GravityType) argument_list[5].integer_reference;
8313           if (attribute_flag[2] != 0) /* geometry offset */
8314             {
8315               SetGeometry(image,&geometry);
8316               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8317                 &geometry);
8318               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8319                 &geometry);
8320             }
8321           if (attribute_flag[3] != 0) /* x offset */
8322             geometry.x=argument_list[3].integer_reference;
8323           if (attribute_flag[4] != 0) /* y offset */
8324             geometry.y=argument_list[4].integer_reference;
8325           if (attribute_flag[10] != 0) /* mask */
8326             {
8327               if ((image->compose == DisplaceCompositeOp) ||
8328                   (image->compose == DistortCompositeOp))
8329                 {
8330                   /*
8331                     Merge Y displacement into X displacement image.
8332                   */
8333                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8334                     &image->exception);
8335                   (void) CompositeImage(composite_image,CopyGreenCompositeOp,
8336                     argument_list[10].image_reference,0,0);
8337                 }
8338               else
8339                 {
8340                   /*
8341                     Set a blending mask for the composition.
8342                   */
8343                   image->mask=CloneImage(argument_list[10].image_reference,0,0,
8344                     MagickTrue,&image->exception);
8345                   (void) NegateImage(image->mask,MagickFalse,exception);
8346                 }
8347             }
8348           if (attribute_flag[11] != 0) /* channel */
8349             channel=(ChannelType) argument_list[11].integer_reference;
8350           /*
8351             Composite two images (normal composition).
8352           */
8353           (void) FormatLocaleString(composite_geometry,MaxTextExtent,
8354             "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8355             (double) composite_image->rows,(double) geometry.x,(double)
8356             geometry.y);
8357           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8358             exception);
8359           channel_mask=SetPixelChannelMask(image,channel);
8360           if (attribute_flag[8] == 0) /* no rotate */
8361             CompositeImage(image,compose,composite_image,geometry.x,geometry.y);
8362           else
8363             {
8364               /*
8365                 Position adjust rotated image then composite.
8366               */
8367               geometry.x-=(ssize_t) (rotate_image->columns-
8368                 composite_image->columns)/2;
8369               geometry.y-=(ssize_t) (rotate_image->rows-
8370                 composite_image->rows)/2;
8371               CompositeImage(image,compose,rotate_image,geometry.x,geometry.y);
8372               rotate_image=DestroyImage(rotate_image);
8373             }
8374           if (attribute_flag[10] != 0) /* mask */
8375             {
8376               if ((image->compose == DisplaceCompositeOp) ||
8377                   (image->compose == DistortCompositeOp))
8378                 composite_image=DestroyImage(composite_image);
8379               else
8380                 image->mask=DestroyImage(image->mask);
8381             }
8382           (void) SetPixelChannelMask(image,channel_mask);
8383           break;
8384         }
8385         case 36:  /* Contrast */
8386         {
8387           if (attribute_flag[0] == 0)
8388             argument_list[0].integer_reference=0;
8389           (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8390             MagickTrue : MagickFalse,exception);
8391           break;
8392         }
8393         case 37:  /* CycleColormap */
8394         {
8395           if (attribute_flag[0] == 0)
8396             argument_list[0].integer_reference=6;
8397           (void) CycleColormapImage(image,argument_list[0].integer_reference);
8398           break;
8399         }
8400         case 38:  /* Draw */
8401         {
8402           DrawInfo
8403             *draw_info;
8404
8405           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8406             (DrawInfo *) NULL);
8407           (void) CloneString(&draw_info->primitive,"point");
8408           if (attribute_flag[0] != 0)
8409             {
8410               if (argument_list[0].integer_reference < 0)
8411                 (void) CloneString(&draw_info->primitive,
8412                   argument_list[0].string_reference);
8413               else
8414                 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8415                   MagickPrimitiveOptions,argument_list[0].integer_reference));
8416             }
8417           if (attribute_flag[1] != 0)
8418             {
8419               if (LocaleCompare(draw_info->primitive,"path") == 0)
8420                 {
8421                   (void) ConcatenateString(&draw_info->primitive," '");
8422                   ConcatenateString(&draw_info->primitive,
8423                     argument_list[1].string_reference);
8424                   (void) ConcatenateString(&draw_info->primitive,"'");
8425                 }
8426               else
8427                 {
8428                   (void) ConcatenateString(&draw_info->primitive," ");
8429                   ConcatenateString(&draw_info->primitive,
8430                     argument_list[1].string_reference);
8431                 }
8432             }
8433           if (attribute_flag[2] != 0)
8434             {
8435               (void) ConcatenateString(&draw_info->primitive," ");
8436               (void) ConcatenateString(&draw_info->primitive,
8437                 CommandOptionToMnemonic(MagickMethodOptions,
8438                 argument_list[2].integer_reference));
8439             }
8440           if (attribute_flag[3] != 0)
8441             {
8442               (void) QueryColorDatabase(argument_list[3].string_reference,
8443                 &draw_info->stroke,exception);
8444               if (argument_list[3].image_reference != (Image *) NULL)
8445                 draw_info->stroke_pattern=CloneImage(
8446                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8447             }
8448           if (attribute_flag[4] != 0)
8449             {
8450               (void) QueryColorDatabase(argument_list[4].string_reference,
8451                 &draw_info->fill,exception);
8452               if (argument_list[4].image_reference != (Image *) NULL)
8453                 draw_info->fill_pattern=CloneImage(
8454                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8455             }
8456           if (attribute_flag[5] != 0)
8457             draw_info->stroke_width=argument_list[5].real_reference;
8458           if (attribute_flag[6] != 0)
8459             (void) CloneString(&draw_info->font,
8460               argument_list[6].string_reference);
8461           if (attribute_flag[7] != 0)
8462             (void) QueryColorDatabase(argument_list[7].string_reference,
8463               &draw_info->border_color,exception);
8464           if (attribute_flag[8] != 0)
8465             draw_info->affine.tx=argument_list[8].real_reference;
8466           if (attribute_flag[9] != 0)
8467             draw_info->affine.ty=argument_list[9].real_reference;
8468           if (attribute_flag[20] != 0)
8469             {
8470               AV
8471                 *av;
8472
8473               av=(AV *) argument_list[20].array_reference;
8474               if ((av_len(av) != 3) && (av_len(av) != 5))
8475                 {
8476                   ThrowPerlException(exception,OptionError,
8477                     "affine matrix must have 4 or 6 elements",PackageName);
8478                   goto PerlException;
8479                 }
8480               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8481               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8482               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8483               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8484               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8485                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8486                 {
8487                   ThrowPerlException(exception,OptionError,
8488                     "affine matrix is singular",PackageName);
8489                    goto PerlException;
8490                 }
8491               if (av_len(av) == 5)
8492                 {
8493                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8494                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8495                 }
8496             }
8497           for (j=10; j < 15; j++)
8498           {
8499             if (attribute_flag[j] == 0)
8500               continue;
8501             value=argument_list[j].string_reference;
8502             angle=argument_list[j].real_reference;
8503             current=draw_info->affine;
8504             GetAffineMatrix(&affine);
8505             switch (j)
8506             {
8507               case 10:
8508               {
8509                 /*
8510                   Translate.
8511                 */
8512                 flags=ParseGeometry(value,&geometry_info);
8513                 affine.tx=geometry_info.xi;
8514                 affine.ty=geometry_info.psi;
8515                 if ((flags & PsiValue) == 0)
8516                   affine.ty=affine.tx;
8517                 break;
8518               }
8519               case 11:
8520               {
8521                 /*
8522                   Scale.
8523                 */
8524                 flags=ParseGeometry(value,&geometry_info);
8525                 affine.sx=geometry_info.rho;
8526                 affine.sy=geometry_info.sigma;
8527                 if ((flags & SigmaValue) == 0)
8528                   affine.sy=affine.sx;
8529                 break;
8530               }
8531               case 12:
8532               {
8533                 /*
8534                   Rotate.
8535                 */
8536                 if (angle == 0.0)
8537                   break;
8538                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8539                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8540                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8541                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8542                 break;
8543               }
8544               case 13:
8545               {
8546                 /*
8547                   SkewX.
8548                 */
8549                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8550                 break;
8551               }
8552               case 14:
8553               {
8554                 /*
8555                   SkewY.
8556                 */
8557                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8558                 break;
8559               }
8560             }
8561             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8562             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8563             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8564             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8565             draw_info->affine.tx=
8566               current.sx*affine.tx+current.ry*affine.ty+current.tx;
8567             draw_info->affine.ty=
8568               current.rx*affine.tx+current.sy*affine.ty+current.ty;
8569           }
8570           if (attribute_flag[15] != 0)
8571             draw_info->fill_pattern=CloneImage(
8572               argument_list[15].image_reference,0,0,MagickTrue,exception);
8573           if (attribute_flag[16] != 0)
8574             draw_info->pointsize=argument_list[16].real_reference;
8575           if (attribute_flag[17] != 0)
8576             {
8577               draw_info->stroke_antialias=argument_list[17].integer_reference != 0
8578                 ? MagickTrue : MagickFalse;
8579               draw_info->text_antialias=draw_info->stroke_antialias;
8580             }
8581           if (attribute_flag[18] != 0)
8582             (void) CloneString(&draw_info->density,
8583               argument_list[18].string_reference);
8584           if (attribute_flag[19] != 0)
8585             draw_info->stroke_width=argument_list[19].real_reference;
8586           if (attribute_flag[21] != 0)
8587             draw_info->dash_offset=argument_list[21].real_reference;
8588           if (attribute_flag[22] != 0)
8589             {
8590               AV
8591                 *av;
8592
8593               av=(AV *) argument_list[22].array_reference;
8594               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
8595                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
8596               if (draw_info->dash_pattern != (double *) NULL)
8597                 {
8598                   for (i=0; i <= av_len(av); i++)
8599                     draw_info->dash_pattern[i]=(double)
8600                       SvNV(*(av_fetch(av,i,0)));
8601                   draw_info->dash_pattern[i]=0.0;
8602                 }
8603             }
8604           if (attribute_flag[23] != 0)
8605             image->interpolate=(InterpolatePixelMethod)
8606               argument_list[23].integer_reference;
8607           if ((attribute_flag[24] != 0) &&
8608               (draw_info->fill_pattern != (Image *) NULL))
8609             flags=ParsePageGeometry(draw_info->fill_pattern,
8610               argument_list[24].string_reference,
8611               &draw_info->fill_pattern->tile_offset,exception);
8612           if (attribute_flag[25] != 0)
8613             {
8614               (void) ConcatenateString(&draw_info->primitive," '");
8615               (void) ConcatenateString(&draw_info->primitive,
8616                 argument_list[25].string_reference);
8617               (void) ConcatenateString(&draw_info->primitive,"'");
8618             }
8619           if (attribute_flag[26] != 0)
8620             draw_info->fill_pattern=CloneImage(
8621               argument_list[26].image_reference,0,0,MagickTrue,exception);
8622           if (attribute_flag[27] != 0)
8623             draw_info->stroke_pattern=CloneImage(
8624               argument_list[27].image_reference,0,0,MagickTrue,exception);
8625           if (attribute_flag[28] != 0)
8626             (void) CloneString(&draw_info->primitive,
8627               argument_list[28].string_reference);
8628           if (attribute_flag[29] != 0)
8629             draw_info->kerning=argument_list[29].real_reference;
8630           if (attribute_flag[30] != 0)
8631             draw_info->interline_spacing=argument_list[30].real_reference;
8632           if (attribute_flag[31] != 0)
8633             draw_info->interword_spacing=argument_list[31].real_reference;
8634           if (attribute_flag[32] != 0)
8635             draw_info->direction=(DirectionType)
8636               argument_list[32].integer_reference;
8637           DrawImage(image,draw_info);
8638           draw_info=DestroyDrawInfo(draw_info);
8639           break;
8640         }
8641         case 39:  /* Equalize */
8642         {
8643           if (attribute_flag[0] != 0)
8644             channel=(ChannelType) argument_list[0].integer_reference;
8645           channel_mask=SetPixelChannelMask(image,channel);
8646           EqualizeImage(image,exception);
8647           (void) SetPixelChannelMask(image,channel_mask);
8648           break;
8649         }
8650         case 40:  /* Gamma */
8651         {
8652           if (attribute_flag[1] != 0)
8653             channel=(ChannelType) argument_list[1].integer_reference;
8654           if (attribute_flag[2] == 0)
8655             argument_list[2].real_reference=1.0;
8656           if (attribute_flag[3] == 0)
8657             argument_list[3].real_reference=1.0;
8658           if (attribute_flag[4] == 0)
8659             argument_list[4].real_reference=1.0;
8660           if (attribute_flag[0] == 0)
8661             {
8662               (void) FormatLocaleString(message,MaxTextExtent,
8663                 "%.15g,%.15g,%.15g",(double) argument_list[2].real_reference,
8664                 (double) argument_list[3].real_reference,
8665                 (double) argument_list[4].real_reference);
8666               argument_list[0].string_reference=message;
8667             }
8668           (void) GammaImage(image,InterpretLocaleValue(
8669             argument_list[0].string_reference,(char **) NULL),exception);
8670           break;
8671         }
8672         case 41:  /* Map */
8673         {
8674           QuantizeInfo
8675             *quantize_info;
8676
8677           if (attribute_flag[0] == 0)
8678             {
8679               ThrowPerlException(exception,OptionError,"MapImageRequired",
8680                 PackageName);
8681               goto PerlException;
8682             }
8683           quantize_info=AcquireQuantizeInfo(info->image_info);
8684           if (attribute_flag[1] != 0)
8685             quantize_info->dither=(MagickBooleanType)
8686               argument_list[1].integer_reference;
8687           if (attribute_flag[2] != 0)
8688             quantize_info->dither_method=(DitherMethod)
8689               argument_list[2].integer_reference;
8690           (void) RemapImages(quantize_info,image,
8691             argument_list[0].image_reference);
8692           quantize_info=DestroyQuantizeInfo(quantize_info);
8693           break;
8694         }
8695         case 42:  /* MatteFloodfill */
8696         {
8697           DrawInfo
8698             *draw_info;
8699
8700           MagickBooleanType
8701             invert;
8702
8703           PixelInfo
8704             target;
8705
8706           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8707             (DrawInfo *) NULL);
8708           if (attribute_flag[0] != 0)
8709             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8710               &geometry,exception);
8711           if (attribute_flag[1] != 0)
8712             geometry.x=argument_list[1].integer_reference;
8713           if (attribute_flag[2] != 0)
8714             geometry.y=argument_list[2].integer_reference;
8715           if (image->matte == MagickFalse)
8716             (void) SetImageOpacity(image,OpaqueAlpha);
8717           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
8718             exception);
8719           if (attribute_flag[4] != 0)
8720             QueryMagickColor(argument_list[4].string_reference,&target,
8721               exception);
8722           if (attribute_flag[3] != 0)
8723             target.alpha=SiPrefixToDouble(argument_list[3].string_reference,
8724               QuantumRange);
8725           if (attribute_flag[5] != 0)
8726             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
8727               QuantumRange);
8728           invert=MagickFalse;
8729           if (attribute_flag[6] != 0)
8730             invert=(MagickBooleanType) argument_list[6].integer_reference;
8731           channel_mask=SetPixelChannelMask(image,AlphaChannel);
8732           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8733             geometry.y,invert);
8734           (void) SetPixelChannelMask(image,channel_mask);
8735           draw_info=DestroyDrawInfo(draw_info);
8736           break;
8737         }
8738         case 43:  /* Modulate */
8739         {
8740           char
8741             modulate[MaxTextExtent];
8742
8743           geometry_info.rho=100.0;
8744           geometry_info.sigma=100.0;
8745           geometry_info.xi=100.0;
8746           if (attribute_flag[0] != 0)
8747             (void)ParseGeometry(argument_list[0].string_reference,
8748               &geometry_info);
8749           if (attribute_flag[1] != 0)
8750             geometry_info.xi=argument_list[1].real_reference;
8751           if (attribute_flag[2] != 0)
8752             geometry_info.sigma=argument_list[2].real_reference;
8753           if (attribute_flag[3] != 0)
8754             {
8755               geometry_info.sigma=argument_list[3].real_reference;
8756               SetImageArtifact(image,"modulate:colorspace","HWB");
8757             }
8758           if (attribute_flag[4] != 0)
8759             {
8760               geometry_info.rho=argument_list[4].real_reference;
8761               SetImageArtifact(image,"modulate:colorspace","HSB");
8762             }
8763           if (attribute_flag[5] != 0)
8764             {
8765               geometry_info.sigma=argument_list[5].real_reference;
8766               SetImageArtifact(image,"modulate:colorspace","HSL");
8767             }
8768           if (attribute_flag[6] != 0)
8769             {
8770               geometry_info.rho=argument_list[6].real_reference;
8771               SetImageArtifact(image,"modulate:colorspace","HWB");
8772             }
8773           (void) FormatLocaleString(modulate,MaxTextExtent,"%.15g,%.15g,%.15g",
8774             geometry_info.rho,geometry_info.sigma,geometry_info.xi);
8775           (void) ModulateImage(image,modulate);
8776           break;
8777         }
8778         case 44:  /* Negate */
8779         {
8780           if (attribute_flag[0] == 0)
8781             argument_list[0].integer_reference=0;
8782           if (attribute_flag[1] != 0)
8783             channel=(ChannelType) argument_list[1].integer_reference;
8784           channel_mask=SetPixelChannelMask(image,channel);
8785           (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
8786             MagickTrue : MagickFalse,exception);
8787           (void) SetPixelChannelMask(image,channel_mask);
8788           break;
8789         }
8790         case 45:  /* Normalize */
8791         {
8792           if (attribute_flag[0] != 0)
8793             channel=(ChannelType) argument_list[0].integer_reference;
8794           channel_mask=SetPixelChannelMask(image,channel);
8795           NormalizeImage(image,exception);
8796           (void) SetPixelChannelMask(image,channel_mask);
8797           break;
8798         }
8799         case 46:  /* NumberColors */
8800           break;
8801         case 47:  /* Opaque */
8802         {
8803           MagickBooleanType
8804             invert;
8805
8806           PixelInfo
8807             fill_color,
8808             target;
8809
8810           (void) QueryMagickColor("none",&target,exception);
8811           (void) QueryMagickColor("none",&fill_color,exception);
8812           if (attribute_flag[0] != 0)
8813             (void) QueryMagickColor(argument_list[0].string_reference,
8814               &target,exception);
8815           if (attribute_flag[1] != 0)
8816             (void) QueryMagickColor(argument_list[1].string_reference,
8817               &fill_color,exception);
8818           if (attribute_flag[2] != 0)
8819             image->fuzz=SiPrefixToDouble(argument_list[2].string_reference,
8820               QuantumRange);
8821           if (attribute_flag[3] != 0)
8822             channel=(ChannelType) argument_list[3].integer_reference;
8823           invert=MagickFalse;
8824           if (attribute_flag[4] != 0)
8825             invert=(MagickBooleanType) argument_list[4].integer_reference;
8826           channel_mask=SetPixelChannelMask(image,channel);
8827           (void) OpaquePaintImage(image,&target,&fill_color,invert);
8828           (void) SetPixelChannelMask(image,channel_mask);
8829           break;
8830         }
8831         case 48:  /* Quantize */
8832         {
8833           QuantizeInfo
8834             *quantize_info;
8835
8836           quantize_info=AcquireQuantizeInfo(info->image_info);
8837           if (attribute_flag[0] != 0)
8838             quantize_info->number_colors=(size_t)
8839               argument_list[0].integer_reference;
8840           if (attribute_flag[1] != 0)
8841             quantize_info->tree_depth=(size_t)
8842               argument_list[1].integer_reference;
8843           if (attribute_flag[2] != 0)
8844             quantize_info->colorspace=(ColorspaceType)
8845               argument_list[2].integer_reference;
8846           if (attribute_flag[3] != 0)
8847             quantize_info->dither=argument_list[3].integer_reference != 0 ?
8848               MagickTrue : MagickFalse;
8849           if (attribute_flag[4] != 0)
8850             quantize_info->measure_error=
8851               argument_list[4].integer_reference != 0 ? MagickTrue : MagickFalse;
8852           if (attribute_flag[5] != 0)
8853             (void) QueryColorDatabase(argument_list[5].string_reference,
8854               &image->transparent_color,exception);
8855           if (attribute_flag[5] && argument_list[5].integer_reference)
8856             {
8857               (void) QuantizeImages(quantize_info,image);
8858               goto PerlException;
8859             }
8860           if (attribute_flag[6] != 0)
8861             quantize_info->dither_method=(DitherMethod)
8862               argument_list[6].integer_reference;
8863           if ((image->storage_class == DirectClass) ||
8864               (image->colors > quantize_info->number_colors) ||
8865               (quantize_info->colorspace == GRAYColorspace))
8866             (void) QuantizeImage(quantize_info,image);
8867           else
8868             CompressImageColormap(image);
8869           quantize_info=DestroyQuantizeInfo(quantize_info);
8870           break;
8871         }
8872         case 49:  /* Raise */
8873         {
8874           if (attribute_flag[0] != 0)
8875             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8876               &geometry,exception);
8877           if (attribute_flag[1] != 0)
8878             geometry.width=argument_list[1].integer_reference;
8879           if (attribute_flag[2] != 0)
8880             geometry.height=argument_list[2].integer_reference;
8881           if (attribute_flag[3] == 0)
8882             argument_list[3].integer_reference=1;
8883           (void) RaiseImage(image,&geometry,argument_list[3].integer_reference !=
8884             0 ? MagickTrue : MagickFalse);
8885           break;
8886         }
8887         case 50:  /* Segment */
8888         {
8889           ColorspaceType
8890             colorspace;
8891
8892           double
8893             cluster_threshold,
8894             smoothing_threshold;
8895
8896           MagickBooleanType
8897             verbose;
8898
8899           cluster_threshold=1.0;
8900           smoothing_threshold=1.5;
8901           colorspace=RGBColorspace;
8902           verbose=MagickFalse;
8903           if (attribute_flag[0] != 0)
8904             {
8905               flags=ParseGeometry(argument_list[0].string_reference,
8906                 &geometry_info);
8907               cluster_threshold=geometry_info.rho;
8908               if (flags & SigmaValue)
8909                 smoothing_threshold=geometry_info.sigma;
8910             }
8911           if (attribute_flag[1] != 0)
8912             cluster_threshold=argument_list[1].real_reference;
8913           if (attribute_flag[2] != 0)
8914             smoothing_threshold=argument_list[2].real_reference;
8915           if (attribute_flag[3] != 0)
8916             colorspace=(ColorspaceType) argument_list[3].integer_reference;
8917           if (attribute_flag[4] != 0)
8918             verbose=argument_list[4].integer_reference != 0 ?
8919               MagickTrue : MagickFalse;
8920           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
8921             smoothing_threshold);
8922           break;
8923         }
8924         case 51:  /* Signature */
8925         {
8926           (void) SignatureImage(image);
8927           break;
8928         }
8929         case 52:  /* Solarize */
8930         {
8931           geometry_info.rho=QuantumRange/2.0;
8932           if (attribute_flag[0] != 0)
8933             flags=ParseGeometry(argument_list[0].string_reference,
8934               &geometry_info);
8935           if (attribute_flag[1] != 0)
8936             geometry_info.rho=SiPrefixToDouble(argument_list[1].string_reference,
8937              QuantumRange);
8938           (void) SolarizeImage(image,geometry_info.rho);
8939           break;
8940         }
8941         case 53:  /* Sync */
8942         {
8943           (void) SyncImage(image);
8944           break;
8945         }
8946         case 54:  /* Texture */
8947         {
8948           if (attribute_flag[0] == 0)
8949             break;
8950           TextureImage(image,argument_list[0].image_reference);
8951           break;
8952         }
8953         case 55:  /* Evalute */
8954         {
8955           MagickEvaluateOperator
8956             op;
8957
8958           op=SetEvaluateOperator;
8959           if (attribute_flag[0] == MagickFalse)
8960             argument_list[0].real_reference=0.0;
8961           if (attribute_flag[1] != MagickFalse)
8962             op=(MagickEvaluateOperator) argument_list[1].integer_reference;
8963           if (attribute_flag[2] != MagickFalse)
8964             channel=(ChannelType) argument_list[2].integer_reference;
8965           channel_mask=SetPixelChannelMask(image,channel);
8966           (void) EvaluateImage(image,op,argument_list[0].real_reference,
8967             exception);
8968           (void) SetPixelChannelMask(image,channel_mask);
8969           break;
8970         }
8971         case 56:  /* Transparent */
8972         {
8973           double
8974             opacity;
8975
8976           MagickBooleanType
8977             invert;
8978
8979           PixelInfo
8980             target;
8981
8982           (void) QueryMagickColor("none",&target,exception);
8983           if (attribute_flag[0] != 0)
8984             (void) QueryMagickColor(argument_list[0].string_reference,&target,
8985               exception);
8986           opacity=TransparentAlpha;
8987           if (attribute_flag[1] != 0)
8988             opacity=SiPrefixToDouble(argument_list[1].string_reference,
8989               QuantumRange);
8990           if (attribute_flag[2] != 0)
8991             image->fuzz=SiPrefixToDouble(argument_list[2].string_reference,
8992               QuantumRange);
8993           if (attribute_flag[3] == 0)
8994             argument_list[3].integer_reference=0;
8995           invert=MagickFalse;
8996           if (attribute_flag[3] != 0)
8997             invert=(MagickBooleanType) argument_list[3].integer_reference;
8998           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
8999             invert);
9000           break;
9001         }
9002         case 57:  /* Threshold */
9003         {
9004           double
9005             threshold;
9006
9007           if (attribute_flag[0] == 0)
9008             argument_list[0].string_reference="50%";
9009           if (attribute_flag[1] != 0)
9010             channel=(ChannelType) argument_list[1].integer_reference;
9011           threshold=SiPrefixToDouble(argument_list[0].string_reference,
9012             QuantumRange);
9013           channel_mask=SetPixelChannelMask(image,channel);
9014           (void) BilevelImage(image,threshold);
9015           (void) SetPixelChannelMask(image,channel_mask);
9016           break;
9017         }
9018         case 58:  /* Charcoal */
9019         {
9020           if (attribute_flag[0] != 0)
9021             {
9022               flags=ParseGeometry(argument_list[0].string_reference,
9023                 &geometry_info);
9024               if ((flags & SigmaValue) == 0)
9025                 geometry_info.sigma=1.0;
9026             }
9027           if (attribute_flag[1] != 0)
9028             geometry_info.rho=argument_list[1].real_reference;
9029           if (attribute_flag[2] != 0)
9030             geometry_info.sigma=argument_list[2].real_reference;
9031           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9032             exception);
9033           break;
9034         }
9035         case 59:  /* Trim */
9036         {
9037           if (attribute_flag[0] != 0)
9038             image->fuzz=SiPrefixToDouble(argument_list[0].string_reference,
9039               QuantumRange);
9040           image=TrimImage(image,exception);
9041           break;
9042         }
9043         case 60:  /* Wave */
9044         {
9045           if (attribute_flag[0] != 0)
9046             {
9047               flags=ParseGeometry(argument_list[0].string_reference,
9048                 &geometry_info);
9049               if ((flags & SigmaValue) == 0)
9050                 geometry_info.sigma=1.0;
9051             }
9052           if (attribute_flag[1] != 0)
9053             geometry_info.rho=argument_list[1].real_reference;
9054           if (attribute_flag[2] != 0)
9055             geometry_info.sigma=argument_list[2].real_reference;
9056           if (attribute_flag[3] != 0)
9057             image->interpolate=(InterpolatePixelMethod)
9058               argument_list[3].integer_reference;
9059           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9060             exception);
9061           break;
9062         }
9063         case 61:  /* Separate */
9064         {
9065           if (attribute_flag[0] != 0)
9066             channel=(ChannelType) argument_list[0].integer_reference;
9067           channel_mask=SetPixelChannelMask(image,channel);
9068           (void) SeparateImage(image);
9069           (void) SetPixelChannelMask(image,channel_mask);
9070           break;
9071         }
9072         case 63:  /* Stereo */
9073         {
9074           if (attribute_flag[0] == 0)
9075             {
9076               ThrowPerlException(exception,OptionError,"StereoImageRequired",
9077                 PackageName);
9078               goto PerlException;
9079             }
9080           if (attribute_flag[1] != 0)
9081             geometry.x=argument_list[1].integer_reference;
9082           if (attribute_flag[2] != 0)
9083             geometry.y=argument_list[2].integer_reference;
9084           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9085             geometry.x,geometry.y,exception);
9086           break;
9087         }
9088         case 64:  /* Stegano */
9089         {
9090           if (attribute_flag[0] == 0)
9091             {
9092               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9093                 PackageName);
9094               goto PerlException;
9095             }
9096           if (attribute_flag[1] == 0)
9097             argument_list[1].integer_reference=0;
9098           image->offset=argument_list[1].integer_reference;
9099           image=SteganoImage(image,argument_list[0].image_reference,exception);
9100           break;
9101         }
9102         case 65:  /* Deconstruct */
9103         {
9104           image=CompareImagesLayers(image,CompareAnyLayer,exception);
9105           break;
9106         }
9107         case 66:  /* GaussianBlur */
9108         {
9109           if (attribute_flag[0] != 0)
9110             {
9111               flags=ParseGeometry(argument_list[0].string_reference,
9112                 &geometry_info);
9113               if ((flags & SigmaValue) == 0)
9114                 geometry_info.sigma=1.0;
9115             }
9116           if (attribute_flag[1] != 0)
9117             geometry_info.rho=argument_list[1].real_reference;
9118           if (attribute_flag[2] != 0)
9119             geometry_info.sigma=argument_list[2].real_reference;
9120           if (attribute_flag[3] != 0)
9121             channel=(ChannelType) argument_list[3].integer_reference;
9122           channel_mask=SetPixelChannelMask(image,channel);
9123           image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9124             exception);
9125           if (image != (Image *) NULL)
9126             (void) SetPixelChannelMask(image,channel_mask);
9127           break;
9128         }
9129         case 67:  /* Convolve */
9130         {
9131           KernelInfo
9132             *kernel;
9133
9134           kernel=(KernelInfo *) NULL;
9135           if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9136             break;
9137           if (attribute_flag[0] != 0)
9138             {
9139               AV
9140                 *av;
9141
9142               size_t
9143                 order;
9144
9145               kernel=AcquireKernelInfo((const char *) NULL);
9146               if (kernel == (KernelInfo *) NULL)
9147                 break;
9148               av=(AV *) argument_list[0].array_reference;
9149               order=(size_t) sqrt(av_len(av)+1);
9150               kernel->width=order;
9151               kernel->height=order;
9152               kernel->values=(double *) AcquireQuantumMemory(order,order*
9153                 sizeof(*kernel->values));
9154               if (kernel->values == (double *) NULL)
9155                 {
9156                   kernel=DestroyKernelInfo(kernel);
9157                   ThrowPerlException(exception,ResourceLimitFatalError,
9158                     "MemoryAllocationFailed",PackageName);
9159                   goto PerlException;
9160                 }
9161               for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9162                 kernel->values[j]=(double) SvNV(*(av_fetch(av,j,0)));
9163               for ( ; j < (ssize_t) (order*order); j++)
9164                 kernel->values[j]=0.0;
9165             }
9166           if (attribute_flag[1] != 0)
9167             channel=(ChannelType) argument_list[1].integer_reference;
9168           if (attribute_flag[2] != 0)
9169             image->bias=SiPrefixToDouble(argument_list[2].string_reference,
9170               QuantumRange);
9171           if (attribute_flag[3] != 0)
9172             {
9173               kernel=AcquireKernelInfo(argument_list[3].string_reference);
9174               if (kernel == (KernelInfo *) NULL)
9175                 break;
9176             }
9177           channel_mask=SetPixelChannelMask(image,channel);
9178           kernel->bias=image->bias;
9179           image=ConvolveImage(image,kernel,exception);
9180           if (image != (Image *) NULL)
9181             (void) SetPixelChannelMask(image,channel_mask);
9182           kernel=DestroyKernelInfo(kernel);
9183           break;
9184         }
9185         case 68:  /* Profile */
9186         {
9187           const char
9188             *name;
9189
9190           Image
9191             *profile_image;
9192
9193           ImageInfo
9194             *profile_info;
9195
9196           StringInfo
9197             *profile;
9198
9199           name="*";
9200           if (attribute_flag[0] != 0)
9201             name=argument_list[0].string_reference;
9202           if (attribute_flag[2] != 0)
9203             image->rendering_intent=(RenderingIntent)
9204               argument_list[2].integer_reference;
9205           if (attribute_flag[3] != 0)
9206             image->black_point_compensation=
9207               argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9208           if (attribute_flag[1] != 0)
9209             {
9210               if (argument_list[1].length == 0)
9211                 {
9212                   /*
9213                     Remove a profile from the image.
9214                   */
9215                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9216                     MagickTrue);
9217                   break;
9218                 }
9219               /*
9220                 Associate user supplied profile with the image.
9221               */
9222               profile=AcquireStringInfo(argument_list[1].length);
9223               SetStringInfoDatum(profile,(const unsigned char *)
9224                 argument_list[1].string_reference);
9225               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9226                 (size_t) GetStringInfoLength(profile),MagickFalse);
9227               profile=DestroyStringInfo(profile);
9228               break;
9229             }
9230           /*
9231             Associate a profile with the image.
9232           */
9233           profile_info=
9234             CloneImageInfo(info ? info->image_info : (ImageInfo *) NULL);
9235           (void) CopyMagickString(profile_info->filename,name,MaxTextExtent);
9236           profile_image=ReadImages(profile_info,&image->exception);
9237           if (profile_image == (Image *) NULL)
9238             break;
9239           ResetImageProfileIterator(profile_image);
9240           name=GetNextImageProfile(profile_image);
9241           while (name != (const char *) NULL)
9242           {
9243             const StringInfo
9244               *profile;
9245
9246             profile=GetImageProfile(profile_image,name);
9247             if (profile != (const StringInfo *) NULL)
9248               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9249                 (size_t) GetStringInfoLength(profile),MagickFalse);
9250             name=GetNextImageProfile(profile_image);
9251           }
9252           profile_image=DestroyImage(profile_image);
9253           profile_info=DestroyImageInfo(profile_info);
9254           break;
9255         }
9256         case 69:  /* UnsharpMask */
9257         {
9258           if (attribute_flag[0] != 0)
9259             {
9260               flags=ParseGeometry(argument_list[0].string_reference,
9261                 &geometry_info);
9262               if ((flags & SigmaValue) == 0)
9263                 geometry_info.sigma=1.0;
9264               if ((flags & XiValue) == 0)
9265                 geometry_info.xi=1.0;
9266               if ((flags & PsiValue) == 0)
9267                 geometry_info.psi=0.5;
9268             }
9269           if (attribute_flag[1] != 0)
9270             geometry_info.rho=argument_list[1].real_reference;
9271           if (attribute_flag[2] != 0)
9272             geometry_info.sigma=argument_list[2].real_reference;
9273           if (attribute_flag[3] != 0)
9274             geometry_info.xi=argument_list[3].real_reference;
9275           if (attribute_flag[4] != 0)
9276             geometry_info.psi=argument_list[4].real_reference;
9277           if (attribute_flag[5] != 0)
9278             channel=(ChannelType) argument_list[5].integer_reference;
9279           channel_mask=SetPixelChannelMask(image,channel);
9280           image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9281             geometry_info.xi,geometry_info.psi,exception);
9282           if (image != (Image *) NULL)
9283             (void) SetPixelChannelMask(image,channel_mask);
9284           break;
9285         }
9286         case 70:  /* MotionBlur */
9287         {
9288           if (attribute_flag[0] != 0)
9289             {
9290               flags=ParseGeometry(argument_list[0].string_reference,
9291                 &geometry_info);
9292               if ((flags & SigmaValue) == 0)
9293                 geometry_info.sigma=1.0;
9294               if ((flags & XiValue) == 0)
9295                 geometry_info.xi=1.0;
9296             }
9297           if (attribute_flag[1] != 0)
9298             geometry_info.rho=argument_list[1].real_reference;
9299           if (attribute_flag[2] != 0)
9300             geometry_info.sigma=argument_list[2].real_reference;
9301           if (attribute_flag[3] != 0)
9302             geometry_info.xi=argument_list[3].real_reference;
9303           if (attribute_flag[4] != 0)
9304             channel=(ChannelType) argument_list[4].integer_reference;
9305           channel_mask=SetPixelChannelMask(image,channel);
9306           image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9307             geometry_info.xi,exception);
9308           if (image != (Image *) NULL)
9309             (void) SetPixelChannelMask(image,channel_mask);
9310           break;
9311         }
9312         case 71:  /* OrderedDither */
9313         {
9314           if (attribute_flag[0] == 0)
9315             argument_list[0].string_reference="o8x8";
9316           if (attribute_flag[1] != 0)
9317             channel=(ChannelType) argument_list[1].integer_reference;
9318           channel_mask=SetPixelChannelMask(image,channel);
9319           (void) OrderedPosterizeImage(image,argument_list[0].string_reference,
9320             exception);
9321           (void) SetPixelChannelMask(image,channel_mask);
9322           break;
9323         }
9324         case 72:  /* Shave */
9325         {
9326           if (attribute_flag[0] != 0)
9327             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9328               &geometry,exception);
9329           if (attribute_flag[1] != 0)
9330             geometry.width=argument_list[1].integer_reference;
9331           if (attribute_flag[2] != 0)
9332             geometry.height=argument_list[2].integer_reference;
9333           image=ShaveImage(image,&geometry,exception);
9334           break;
9335         }
9336         case 73:  /* Level */
9337         {
9338           double
9339             black_point,
9340             gamma,
9341             white_point;
9342
9343           black_point=0.0;
9344           white_point=(MagickRealType) image->columns*image->rows;
9345           gamma=1.0;
9346           if (attribute_flag[0] != 0)
9347             {
9348               flags=ParseGeometry(argument_list[0].string_reference,
9349                 &geometry_info);
9350               black_point=geometry_info.rho;
9351               if ((flags & SigmaValue) != 0)
9352                 white_point=geometry_info.sigma;
9353               if ((flags & XiValue) != 0)
9354                 gamma=geometry_info.xi;
9355               if ((flags & PercentValue) != 0)
9356                 {
9357                   black_point*=(double) (QuantumRange/100.0);
9358                   white_point*=(double) (QuantumRange/100.0);
9359                 }
9360               if ((flags & SigmaValue) == 0)
9361                 white_point=(double) QuantumRange-black_point;
9362             }
9363           if (attribute_flag[1] != 0)
9364             black_point=argument_list[1].real_reference;
9365           if (attribute_flag[2] != 0)
9366             white_point=argument_list[2].real_reference;
9367           if (attribute_flag[3] != 0)
9368             gamma=argument_list[3].real_reference;
9369           if (attribute_flag[4] != 0)
9370             channel=(ChannelType) argument_list[4].integer_reference;
9371           if (attribute_flag[5] != 0)
9372             {
9373               argument_list[0].real_reference=argument_list[5].real_reference;
9374               attribute_flag[0]=attribute_flag[5];
9375             }
9376           channel_mask=SetPixelChannelMask(image,channel);
9377           (void) LevelImage(image,black_point,white_point,gamma,exception);
9378           (void) SetPixelChannelMask(image,channel_mask);
9379           break;
9380         }
9381         case 74:  /* Clip */
9382         {
9383           if (attribute_flag[0] == 0)
9384             argument_list[0].string_reference="#1";
9385           if (attribute_flag[1] == 0)
9386             argument_list[1].integer_reference=MagickTrue;
9387           (void) ClipImagePath(image,argument_list[0].string_reference,
9388             argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse);
9389           break;
9390         }
9391         case 75:  /* AffineTransform */
9392         {
9393           DrawInfo
9394             *draw_info;
9395
9396           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9397             (DrawInfo *) NULL);
9398           if (attribute_flag[0] != 0)
9399             {
9400               AV
9401                 *av;
9402
9403               av=(AV *) argument_list[0].array_reference;
9404               if ((av_len(av) != 3) && (av_len(av) != 5))
9405                 {
9406                   ThrowPerlException(exception,OptionError,
9407                     "affine matrix must have 4 or 6 elements",PackageName);
9408                   goto PerlException;
9409                 }
9410               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9411               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9412               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9413               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9414               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9415                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9416                 {
9417                   ThrowPerlException(exception,OptionError,
9418                     "affine matrix is singular",PackageName);
9419                    goto PerlException;
9420                 }
9421               if (av_len(av) == 5)
9422                 {
9423                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9424                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9425                 }
9426             }
9427           for (j=1; j < 6; j++)
9428           {
9429             if (attribute_flag[j] == 0)
9430               continue;
9431             value=argument_list[j].string_reference;
9432             angle=argument_list[j].real_reference;
9433             current=draw_info->affine;
9434             GetAffineMatrix(&affine);
9435             switch (j)
9436             {
9437               case 1:
9438               {
9439                 /*
9440                   Translate.
9441                 */
9442                 flags=ParseGeometry(value,&geometry_info);
9443                 affine.tx=geometry_info.xi;
9444                 affine.ty=geometry_info.psi;
9445                 if ((flags & PsiValue) == 0)
9446                   affine.ty=affine.tx;
9447                 break;
9448               }
9449               case 2:
9450               {
9451                 /*
9452                   Scale.
9453                 */
9454                 flags=ParseGeometry(value,&geometry_info);
9455                 affine.sx=geometry_info.rho;
9456                 affine.sy=geometry_info.sigma;
9457                 if ((flags & SigmaValue) == 0)
9458                   affine.sy=affine.sx;
9459                 break;
9460               }
9461               case 3:
9462               {
9463                 /*
9464                   Rotate.
9465                 */
9466                 if (angle == 0.0)
9467                   break;
9468                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9469                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9470                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9471                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9472                 break;
9473               }
9474               case 4:
9475               {
9476                 /*
9477                   SkewX.
9478                 */
9479                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9480                 break;
9481               }
9482               case 5:
9483               {
9484                 /*
9485                   SkewY.
9486                 */
9487                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9488                 break;
9489               }
9490             }
9491             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9492             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9493             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9494             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9495             draw_info->affine.tx=
9496               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9497             draw_info->affine.ty=
9498               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9499           }
9500           if (attribute_flag[6] != 0)
9501             image->interpolate=(InterpolatePixelMethod)
9502               argument_list[6].integer_reference;
9503           if (attribute_flag[7] != 0)
9504             QueryColorDatabase(argument_list[7].string_reference,
9505               &image->background_color,exception);
9506           image=AffineTransformImage(image,&draw_info->affine,exception);
9507           draw_info=DestroyDrawInfo(draw_info);
9508           break;
9509         }
9510         case 76:  /* Difference */
9511         {
9512           if (attribute_flag[0] == 0)
9513             {
9514               ThrowPerlException(exception,OptionError,
9515                 "ReferenceImageRequired",PackageName);
9516               goto PerlException;
9517             }
9518           if (attribute_flag[1] != 0)
9519             image->fuzz=SiPrefixToDouble(argument_list[1].string_reference,
9520               QuantumRange);
9521           (void) IsImagesEqual(image,argument_list[0].image_reference);
9522           break;
9523         }
9524         case 77:  /* AdaptiveThreshold */
9525         {
9526           if (attribute_flag[0] != 0)
9527             {
9528               flags=ParseGeometry(argument_list[0].string_reference,
9529                 &geometry_info);
9530               if ((flags & PercentValue) != 0)
9531                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9532             }
9533           if (attribute_flag[1] != 0)
9534             geometry_info.rho=argument_list[1].integer_reference;
9535           if (attribute_flag[2] != 0)
9536             geometry_info.sigma=argument_list[2].integer_reference;
9537           if (attribute_flag[3] != 0)
9538             geometry_info.xi=argument_list[3].integer_reference;;
9539           image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
9540             (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
9541           break;
9542         }
9543         case 78:  /* Resample */
9544         {
9545           size_t
9546             height,
9547             width;
9548
9549           if (attribute_flag[0] != 0)
9550             {
9551               flags=ParseGeometry(argument_list[0].string_reference,
9552                 &geometry_info);
9553               if ((flags & SigmaValue) == 0)
9554                 geometry_info.sigma=geometry_info.rho;
9555             }
9556           if (attribute_flag[1] != 0)
9557             geometry_info.rho=argument_list[1].real_reference;
9558           if (attribute_flag[2] != 0)
9559             geometry_info.sigma=argument_list[2].real_reference;
9560           if (attribute_flag[3] == 0)
9561             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
9562           if (attribute_flag[4] == 0)
9563             SetImageArtifact(image,"filter:support",
9564               argument_list[4].string_reference);
9565           if (attribute_flag[5] != 0)
9566             argument_list[5].real_reference=1.0;
9567           width=(size_t) (geometry_info.rho*image->columns/
9568             (image->x_resolution == 0.0 ? 72.0 : image->x_resolution)+0.5);
9569           height=(size_t) (geometry_info.sigma*image->rows/
9570             (image->y_resolution == 0.0 ? 72.0 : image->y_resolution)+0.5);
9571           image=ResizeImage(image,width,height,(FilterTypes)
9572             argument_list[3].integer_reference,argument_list[5].real_reference,
9573             exception);
9574           if (image != (Image *) NULL)
9575             {
9576               image->x_resolution=geometry_info.rho;
9577               image->y_resolution=geometry_info.sigma;
9578             }
9579           break;
9580         }
9581         case 79:  /* Describe */
9582         {
9583           if (attribute_flag[0] == 0)
9584             argument_list[0].file_reference=(FILE *) NULL;
9585           if (attribute_flag[1] != 0)
9586             (void) SetImageArtifact(image,"identify:features",
9587               argument_list[1].string_reference);
9588           (void) IdentifyImage(image,argument_list[0].file_reference,
9589             MagickTrue);
9590           break;
9591         }
9592         case 80:  /* BlackThreshold */
9593         {
9594           if (attribute_flag[0] == 0)
9595             argument_list[0].string_reference="50%";
9596           if (attribute_flag[2] != 0)
9597             channel=(ChannelType) argument_list[2].integer_reference;
9598           channel_mask=SetPixelChannelMask(image,channel);
9599           BlackThresholdImage(image,argument_list[0].string_reference,
9600             exception);
9601           (void) SetPixelChannelMask(image,channel_mask);
9602           break;
9603         }
9604         case 81:  /* WhiteThreshold */
9605         {
9606           if (attribute_flag[0] == 0)
9607             argument_list[0].string_reference="50%";
9608           if (attribute_flag[2] != 0)
9609             channel=(ChannelType) argument_list[2].integer_reference;
9610           channel_mask=SetPixelChannelMask(image,channel);
9611           WhiteThresholdImage(image,argument_list[0].string_reference,
9612             exception);
9613           (void) SetPixelChannelMask(image,channel_mask);
9614           break;
9615         }
9616         case 82:  /* RadialBlur */
9617         {
9618           if (attribute_flag[0] != 0)
9619             {
9620               flags=ParseGeometry(argument_list[0].string_reference,
9621                 &geometry_info);
9622               if ((flags & SigmaValue) == 0)
9623                 geometry_info.sigma=1.0;
9624             }
9625           if (attribute_flag[1] != 0)
9626             geometry_info.rho=argument_list[1].real_reference;
9627           if (attribute_flag[2] != 0)
9628             channel=(ChannelType) argument_list[2].integer_reference;
9629           channel_mask=SetPixelChannelMask(image,channel);
9630           image=RadialBlurImage(image,geometry_info.rho,exception);
9631           if (image != (Image *) NULL)
9632             (void) SetPixelChannelMask(image,channel_mask);
9633           break;
9634         }
9635         case 83:  /* Thumbnail */
9636         {
9637           if (attribute_flag[0] != 0)
9638             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
9639               &geometry,exception);
9640           if (attribute_flag[1] != 0)
9641             geometry.width=argument_list[1].integer_reference;
9642           if (attribute_flag[2] != 0)
9643             geometry.height=argument_list[2].integer_reference;
9644           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
9645           break;
9646         }
9647         case 84:  /* Strip */
9648         {
9649           (void) StripImage(image);
9650           break;
9651         }
9652         case 85:  /* Tint */
9653         {
9654           PixelPacket
9655             target;
9656
9657           (void) GetOneVirtualPixel(image,0,0,&target,exception);
9658           if (attribute_flag[0] != 0)
9659             (void) QueryColorDatabase(argument_list[0].string_reference,&target,
9660               exception);
9661           if (attribute_flag[1] == 0)
9662             argument_list[1].string_reference="100";
9663           image=TintImage(image,argument_list[1].string_reference,target,
9664             exception);
9665           break;
9666         }
9667         case 86:  /* Channel */
9668         {
9669           if (attribute_flag[0] != 0)
9670             channel=(ChannelType) argument_list[0].integer_reference;
9671           channel_mask=SetPixelChannelMask(image,channel);
9672           (void) SeparateImage(image);
9673           (void) SetPixelChannelMask(image,channel_mask);
9674           break;
9675         }
9676         case 87:  /* Splice */
9677         {
9678           if (attribute_flag[0] != 0)
9679             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
9680               &geometry,exception);
9681           if (attribute_flag[1] != 0)
9682             geometry.width=argument_list[1].integer_reference;
9683           if (attribute_flag[2] != 0)
9684             geometry.height=argument_list[2].integer_reference;
9685           if (attribute_flag[3] != 0)
9686             geometry.x=argument_list[3].integer_reference;
9687           if (attribute_flag[4] != 0)
9688             geometry.y=argument_list[4].integer_reference;
9689           if (attribute_flag[5] != 0)
9690             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
9691               QuantumRange);
9692           if (attribute_flag[6] != 0)
9693             (void) QueryColorDatabase(argument_list[6].string_reference,
9694               &image->background_color,exception);
9695           if (attribute_flag[7] != 0)
9696             image->gravity=(GravityType) argument_list[7].integer_reference;
9697           image=SpliceImage(image,&geometry,exception);
9698           break;
9699         }
9700         case 88:  /* Posterize */
9701         {
9702           if (attribute_flag[0] == 0)
9703             argument_list[0].integer_reference=3;
9704           if (attribute_flag[1] == 0)
9705             argument_list[1].integer_reference=0;
9706           (void) PosterizeImage(image,argument_list[0].integer_reference,
9707             argument_list[1].integer_reference ? MagickTrue : MagickFalse);
9708           break;
9709         }
9710         case 89:  /* Shadow */
9711         {
9712           if (attribute_flag[0] != 0)
9713             {
9714               flags=ParseGeometry(argument_list[0].string_reference,
9715                 &geometry_info);
9716               if ((flags & SigmaValue) == 0)
9717                 geometry_info.sigma=1.0;
9718               if ((flags & XiValue) == 0)
9719                 geometry_info.xi=4.0;
9720               if ((flags & PsiValue) == 0)
9721                 geometry_info.psi=4.0;
9722             }
9723           if (attribute_flag[1] != 0)
9724             geometry_info.rho=argument_list[1].real_reference;
9725           if (attribute_flag[2] != 0)
9726             geometry_info.sigma=argument_list[2].real_reference;
9727           if (attribute_flag[3] != 0)
9728             geometry_info.xi=argument_list[3].integer_reference;
9729           if (attribute_flag[4] != 0)
9730             geometry_info.psi=argument_list[4].integer_reference;
9731           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
9732             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-
9733             0.5),exception);
9734           break;
9735         }
9736         case 90:  /* Identify */
9737         {
9738           if (attribute_flag[0] == 0)
9739             argument_list[0].file_reference=(FILE *) NULL;
9740           if (attribute_flag[1] != 0)
9741             (void) SetImageArtifact(image,"identify:features",
9742               argument_list[1].string_reference);
9743           if ((attribute_flag[2] != 0) &&
9744               (argument_list[2].integer_reference != 0))
9745             (void) SetImageArtifact(image,"identify:unique","true");
9746           (void) IdentifyImage(image,argument_list[0].file_reference,
9747             MagickTrue);
9748           break;
9749         }
9750         case 91:  /* SepiaTone */
9751         {
9752           if (attribute_flag[0] == 0)
9753             argument_list[0].real_reference=80.0*QuantumRange/100.0;
9754           image=SepiaToneImage(image,argument_list[0].real_reference,
9755             exception);
9756           break;
9757         }
9758         case 92:  /* SigmoidalContrast */
9759         {
9760           MagickBooleanType
9761             sharpen;
9762
9763           if (attribute_flag[0] != 0)
9764             {
9765               flags=ParseGeometry(argument_list[0].string_reference,
9766                 &geometry_info);
9767               if ((flags & SigmaValue) == 0)
9768                 geometry_info.sigma=QuantumRange/2.0;
9769               if ((flags & PercentValue) != 0)
9770                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
9771             }
9772           if (attribute_flag[1] != 0)
9773             geometry_info.rho=argument_list[1].real_reference;
9774           if (attribute_flag[2] != 0)
9775             geometry_info.sigma=argument_list[2].real_reference;
9776           if (attribute_flag[3] != 0)
9777             channel=(ChannelType) argument_list[3].integer_reference;
9778           sharpen=MagickTrue;
9779           if (attribute_flag[4] != 0)
9780             sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
9781               MagickFalse;
9782           channel_mask=SetPixelChannelMask(image,channel);
9783           (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
9784             geometry_info.sigma);
9785           (void) SetPixelChannelMask(image,channel_mask);
9786           break;
9787         }
9788         case 93:  /* Extent */
9789         {
9790           if (attribute_flag[7] != 0)
9791             image->gravity=(GravityType) argument_list[7].integer_reference;
9792           if (attribute_flag[0] != 0)
9793             {
9794               int
9795                 flags;
9796
9797               flags=ParseGravityGeometry(image,
9798                 argument_list[0].string_reference,&geometry,exception);
9799               (void) flags;
9800               if (geometry.width == 0)
9801                 geometry.width=image->columns;
9802               if (geometry.height == 0)
9803                 geometry.height=image->rows;
9804             }
9805           if (attribute_flag[1] != 0)
9806             geometry.width=argument_list[1].integer_reference;
9807           if (attribute_flag[2] != 0)
9808             geometry.height=argument_list[2].integer_reference;
9809           if (attribute_flag[3] != 0)
9810             geometry.x=argument_list[3].integer_reference;
9811           if (attribute_flag[4] != 0)
9812             geometry.y=argument_list[4].integer_reference;
9813           if (attribute_flag[5] != 0)
9814             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
9815               QuantumRange);
9816           if (attribute_flag[6] != 0)
9817             (void) QueryColorDatabase(argument_list[6].string_reference,
9818               &image->background_color,exception);
9819           image=ExtentImage(image,&geometry,exception);
9820           break;
9821         }
9822         case 94:  /* Vignette */
9823         {
9824           if (attribute_flag[0] != 0)
9825             {
9826               flags=ParseGeometry(argument_list[0].string_reference,
9827                 &geometry_info);
9828               if ((flags & SigmaValue) == 0)
9829                 geometry_info.sigma=1.0;
9830               if ((flags & XiValue) == 0)
9831                 geometry_info.xi=0.1*image->columns;
9832               if ((flags & PsiValue) == 0)
9833                 geometry_info.psi=0.1*image->rows;
9834             }
9835           if (attribute_flag[1] != 0)
9836             geometry_info.rho=argument_list[1].real_reference;
9837           if (attribute_flag[2] != 0)
9838             geometry_info.sigma=argument_list[2].real_reference;
9839           if (attribute_flag[3] != 0)
9840             geometry_info.xi=argument_list[3].integer_reference;
9841           if (attribute_flag[4] != 0)
9842             geometry_info.psi=argument_list[4].integer_reference;
9843           if (attribute_flag[5] != 0)
9844             (void) QueryColorDatabase(argument_list[5].string_reference,
9845               &image->background_color,exception);
9846           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
9847             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-
9848             0.5),exception);
9849           break;
9850         }
9851         case 95:  /* ContrastStretch */
9852         {
9853           double
9854             black_point,
9855             white_point;
9856
9857           black_point=0.0;
9858           white_point=(MagickRealType) image->columns*image->rows;
9859           if (attribute_flag[0] != 0)
9860             {
9861               flags=ParseGeometry(argument_list[0].string_reference,
9862                 &geometry_info);
9863               black_point=geometry_info.rho;
9864               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
9865                 black_point;
9866               if ((flags & PercentValue) != 0)
9867                 {
9868                   black_point*=(double) image->columns*image->rows/100.0;
9869                   white_point*=(double) image->columns*image->rows/100.0;
9870                 }
9871               white_point=(MagickRealType) image->columns*image->rows-
9872                 white_point;
9873             }
9874           if (attribute_flag[1] != 0)
9875             black_point=argument_list[1].real_reference;
9876           if (attribute_flag[2] != 0)
9877             white_point=argument_list[2].real_reference;
9878           if (attribute_flag[4] != 0)
9879             channel=(ChannelType) argument_list[4].integer_reference;
9880           channel_mask=SetPixelChannelMask(image,channel);
9881           (void) ContrastStretchImage(image,black_point,white_point,exception);
9882           (void) SetPixelChannelMask(image,channel_mask);
9883           break;
9884         }
9885         case 96:  /* Sans0 */
9886         {
9887           break;
9888         }
9889         case 97:  /* Sans1 */
9890         {
9891           break;
9892         }
9893         case 98:  /* AdaptiveSharpen */
9894         {
9895           if (attribute_flag[0] != 0)
9896             {
9897               flags=ParseGeometry(argument_list[0].string_reference,
9898                 &geometry_info);
9899               if ((flags & SigmaValue) == 0)
9900                 geometry_info.sigma=1.0;
9901             }
9902           if (attribute_flag[1] != 0)
9903             geometry_info.rho=argument_list[1].real_reference;
9904           if (attribute_flag[2] != 0)
9905             geometry_info.sigma=argument_list[2].real_reference;
9906           if (attribute_flag[3] != 0)
9907             channel=(ChannelType) argument_list[3].integer_reference;
9908           channel_mask=SetPixelChannelMask(image,channel);
9909           image=AdaptiveSharpenImage(image,geometry_info.rho,
9910             geometry_info.sigma,exception);
9911           if (image != (Image *) NULL)
9912             (void) SetPixelChannelMask(image,channel_mask);
9913           break;
9914         }
9915         case 99:  /* Transpose */
9916         {
9917           image=TransposeImage(image,exception);
9918           break;
9919         }
9920         case 100:  /* Tranverse */
9921         {
9922           image=TransverseImage(image,exception);
9923           break;
9924         }
9925         case 101:  /* AutoOrient */
9926         {
9927           switch (image->orientation)
9928           {
9929             case TopRightOrientation:
9930             {
9931               image=FlopImage(image,exception);
9932               break;
9933             }
9934             case BottomRightOrientation:
9935             {
9936               image=RotateImage(image,180.0,exception);
9937               break;
9938             }
9939             case BottomLeftOrientation:
9940             {
9941               image=FlipImage(image,exception);
9942               break;
9943             }
9944             case LeftTopOrientation:
9945             {
9946               image=TransposeImage(image,exception);
9947               break;
9948             }
9949             case RightTopOrientation:
9950             {
9951               image=RotateImage(image,90.0,exception);
9952               break;
9953             }
9954             case RightBottomOrientation:
9955             {
9956               image=TransverseImage(image,exception);
9957               break;
9958             }
9959             case LeftBottomOrientation:
9960             {
9961               image=RotateImage(image,270.0,exception);
9962               break;
9963             }
9964             default:
9965               break;
9966           }
9967           break;
9968         }
9969         case 102:  /* AdaptiveBlur */
9970         {
9971           if (attribute_flag[0] != 0)
9972             {
9973               flags=ParseGeometry(argument_list[0].string_reference,
9974                 &geometry_info);
9975               if ((flags & SigmaValue) == 0)
9976                 geometry_info.sigma=1.0;
9977             }
9978           if (attribute_flag[1] != 0)
9979             geometry_info.rho=argument_list[1].real_reference;
9980           if (attribute_flag[2] != 0)
9981             geometry_info.sigma=argument_list[2].real_reference;
9982           if (attribute_flag[3] != 0)
9983             channel=(ChannelType) argument_list[3].integer_reference;
9984           channel_mask=SetPixelChannelMask(image,channel);
9985           image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
9986             exception);
9987           if (image != (Image *) NULL)
9988             (void) SetPixelChannelMask(image,channel_mask);
9989           break;
9990         }
9991         case 103:  /* Sketch */
9992         {
9993           if (attribute_flag[0] != 0)
9994             {
9995               flags=ParseGeometry(argument_list[0].string_reference,
9996                 &geometry_info);
9997               if ((flags & SigmaValue) == 0)
9998                 geometry_info.sigma=1.0;
9999               if ((flags & XiValue) == 0)
10000                 geometry_info.xi=1.0;
10001             }
10002           if (attribute_flag[1] != 0)
10003             geometry_info.rho=argument_list[1].real_reference;
10004           if (attribute_flag[2] != 0)
10005             geometry_info.sigma=argument_list[2].real_reference;
10006           if (attribute_flag[3] != 0)
10007             geometry_info.xi=argument_list[3].real_reference;
10008           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10009             geometry_info.xi,exception);
10010           break;
10011         }
10012         case 104:  /* UniqueColors */
10013         {
10014           image=UniqueImageColors(image,exception);
10015           break;
10016         }
10017         case 105:  /* AdaptiveResize */
10018         {
10019           if (attribute_flag[0] != 0)
10020             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10021               &geometry,exception);
10022           if (attribute_flag[1] != 0)
10023             geometry.width=argument_list[1].integer_reference;
10024           if (attribute_flag[2] != 0)
10025             geometry.height=argument_list[2].integer_reference;
10026           if (attribute_flag[3] != 0)
10027             image->filter=(FilterTypes) argument_list[4].integer_reference;
10028           if (attribute_flag[4] != 0)
10029             SetImageArtifact(image,"filter:support",
10030               argument_list[4].string_reference);
10031           if (attribute_flag[5] != 0)
10032             image->blur=argument_list[5].real_reference;
10033           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10034             exception);
10035           break;
10036         }
10037         case 106:  /* ClipMask */
10038         {
10039           if (attribute_flag[0] == 0)
10040             {
10041               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10042                 PackageName);
10043               goto PerlException;
10044             }
10045           image->clip_mask=CloneImage(argument_list[0].image_reference,0,0,
10046             MagickTrue,exception);
10047           (void) NegateImage(image->clip_mask,MagickFalse,exception);
10048           break;
10049         }
10050         case 107:  /* LinearStretch */
10051         {
10052            double
10053              black_point,
10054              white_point;
10055
10056            black_point=0.0;
10057            white_point=(MagickRealType) image->columns*image->rows;
10058            if (attribute_flag[0] != 0)
10059              {
10060                flags=ParseGeometry(argument_list[0].string_reference,
10061                  &geometry_info);
10062                if ((flags & SigmaValue) != 0)
10063                   white_point=geometry_info.sigma;
10064                if ((flags & PercentValue) != 0)
10065                  {
10066                    black_point*=(double) image->columns*image->rows/100.0;
10067                    white_point*=(double) image->columns*image->rows/100.0;
10068                  }
10069                if ((flags & SigmaValue) == 0)
10070                  white_point=(double) image->columns*image->rows-black_point;
10071              }
10072           if (attribute_flag[1] != 0)
10073             black_point=argument_list[1].real_reference;
10074           if (attribute_flag[2] != 0)
10075             white_point=argument_list[2].real_reference;
10076           (void) LinearStretchImage(image,black_point,white_point);
10077           break;
10078         }
10079         case 109:  /* Mask */
10080         {
10081           if (attribute_flag[0] == 0)
10082             {
10083               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10084                 PackageName);
10085               goto PerlException;
10086             }
10087           image->mask=CloneImage(argument_list[0].image_reference,0,0,
10088             MagickTrue,exception);
10089           (void) NegateImage(image->mask,MagickFalse,exception);
10090           break;
10091         }
10092         case 110:  /* Polaroid */
10093         {
10094           DrawInfo
10095             *draw_info;
10096
10097           double
10098             angle;
10099
10100           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10101             (DrawInfo *) NULL);
10102           if (attribute_flag[0] != 0)
10103             (void) SetImageProperty(image,"caption",InterpretImageProperties(
10104               info ? info->image_info : (ImageInfo *) NULL,image,
10105               argument_list[0].string_reference));
10106           angle=0.0;
10107           if (attribute_flag[1] != 0)
10108             angle=argument_list[1].real_reference;
10109           if (attribute_flag[2] != 0)
10110             (void) CloneString(&draw_info->font,
10111               argument_list[2].string_reference);
10112           if (attribute_flag[3] != 0)
10113             (void) QueryColorDatabase(argument_list[3].string_reference,
10114               &draw_info->stroke,exception);
10115           if (attribute_flag[4] != 0)
10116             (void) QueryColorDatabase(argument_list[4].string_reference,
10117               &draw_info->fill,exception);
10118           if (attribute_flag[5] != 0)
10119             draw_info->stroke_width=argument_list[5].real_reference;
10120           if (attribute_flag[6] != 0)
10121             draw_info->pointsize=argument_list[6].real_reference;
10122           if (attribute_flag[7] != 0)
10123             draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10124           if (attribute_flag[8] != 0)
10125             (void) QueryColorDatabase(argument_list[8].string_reference,
10126               &image->background_color,exception);
10127           image=PolaroidImage(image,draw_info,angle,exception);
10128           draw_info=DestroyDrawInfo(draw_info);
10129           break;
10130         }
10131         case 111:  /* FloodfillPaint */
10132         {
10133           DrawInfo
10134             *draw_info;
10135
10136           MagickBooleanType
10137             invert;
10138
10139           PixelInfo
10140             target;
10141
10142           draw_info=CloneDrawInfo(info ? info->image_info :
10143             (ImageInfo *) NULL,(DrawInfo *) NULL);
10144           if (attribute_flag[0] != 0)
10145             flags=ParsePageGeometry(image,argument_list[0].string_reference,
10146               &geometry,exception);
10147           if (attribute_flag[1] != 0)
10148             geometry.x=argument_list[1].integer_reference;
10149           if (attribute_flag[2] != 0)
10150             geometry.y=argument_list[2].integer_reference;
10151           if (attribute_flag[3] != 0)
10152             (void) QueryColorDatabase(argument_list[3].string_reference,
10153               &draw_info->fill,exception);
10154           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
10155             exception);
10156           if (attribute_flag[4] != 0)
10157             QueryMagickColor(argument_list[4].string_reference,&target,
10158               exception);
10159           if (attribute_flag[5] != 0)
10160             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
10161               QuantumRange);
10162           if (attribute_flag[6] != 0)
10163             channel=(ChannelType) argument_list[6].integer_reference;
10164           invert=MagickFalse;
10165           if (attribute_flag[7] != 0)
10166             invert=(MagickBooleanType) argument_list[7].integer_reference;
10167           channel_mask=SetPixelChannelMask(image,channel);
10168           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10169             geometry.y,invert);
10170           (void) SetPixelChannelMask(image,channel_mask);
10171           draw_info=DestroyDrawInfo(draw_info);
10172           break;
10173         }
10174         case 112:  /* Distort */
10175         {
10176           AV
10177             *av;
10178
10179           double
10180             *coordinates;
10181
10182           DistortImageMethod
10183             method;
10184
10185           size_t
10186             number_coordinates;
10187
10188           VirtualPixelMethod
10189             virtual_pixel;
10190
10191           if (attribute_flag[0] == 0)
10192             break;
10193           method=UndefinedDistortion;
10194           if (attribute_flag[1] != 0)
10195             method=(DistortImageMethod) argument_list[1].integer_reference;
10196           av=(AV *) argument_list[0].array_reference;
10197           number_coordinates=(size_t) av_len(av)+1;
10198           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10199             sizeof(*coordinates));
10200           if (coordinates == (double *) NULL)
10201             {
10202               ThrowPerlException(exception,ResourceLimitFatalError,
10203                 "MemoryAllocationFailed",PackageName);
10204               goto PerlException;
10205             }
10206           for (j=0; j < (ssize_t) number_coordinates; j++)
10207             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10208           virtual_pixel=UndefinedVirtualPixelMethod;
10209           if (attribute_flag[2] != 0)
10210             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10211               argument_list[2].integer_reference);
10212           image=DistortImage(image,method,number_coordinates,coordinates,
10213             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10214             exception);
10215           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10216             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10217           coordinates=(double *) RelinquishMagickMemory(coordinates);
10218           break;
10219         }
10220         case 113:  /* Clut */
10221         {
10222           if (attribute_flag[0] == 0)
10223             {
10224               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10225                 PackageName);
10226               goto PerlException;
10227             }
10228           if (attribute_flag[1] != 0)
10229             channel=(ChannelType) argument_list[1].integer_reference;
10230           channel_mask=SetPixelChannelMask(image,channel);
10231           (void) ClutImage(image,argument_list[0].image_reference,exception);
10232           (void) SetPixelChannelMask(image,channel_mask);
10233           break;
10234         }
10235         case 114:  /* LiquidRescale */
10236         {
10237           if (attribute_flag[0] != 0)
10238             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10239               &geometry,exception);
10240           if (attribute_flag[1] != 0)
10241             geometry.width=argument_list[1].integer_reference;
10242           if (attribute_flag[2] != 0)
10243             geometry.height=argument_list[2].integer_reference;
10244           if (attribute_flag[3] == 0)
10245             argument_list[3].real_reference=1.0;
10246           if (attribute_flag[4] == 0)
10247             argument_list[4].real_reference=0.0;
10248           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10249             argument_list[3].real_reference,argument_list[4].real_reference,
10250             exception);
10251           break;
10252         }
10253         case 115:  /* EncipherImage */
10254         {
10255           (void) EncipherImage(image,argument_list[0].string_reference,
10256             exception);
10257           break;
10258         }
10259         case 116:  /* DecipherImage */
10260         {
10261           (void) DecipherImage(image,argument_list[0].string_reference,
10262             exception);
10263           break;
10264         }
10265         case 117:  /* Deskew */
10266         {
10267           geometry_info.rho=QuantumRange/2.0;
10268           if (attribute_flag[0] != 0)
10269             flags=ParseGeometry(argument_list[0].string_reference,
10270               &geometry_info);
10271           if (attribute_flag[1] != 0)
10272             geometry_info.rho=SiPrefixToDouble(
10273               argument_list[1].string_reference,QuantumRange);
10274           image=DeskewImage(image,geometry_info.rho,exception);
10275           break;
10276         }
10277         case 118:  /* Remap */
10278         {
10279           QuantizeInfo
10280             *quantize_info;
10281
10282           if (attribute_flag[0] == 0)
10283             {
10284               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10285                 PackageName);
10286               goto PerlException;
10287             }
10288           quantize_info=AcquireQuantizeInfo(info->image_info);
10289           if (attribute_flag[1] != 0)
10290             quantize_info->dither=(MagickBooleanType)
10291               argument_list[1].integer_reference;
10292           if (attribute_flag[2] != 0)
10293             quantize_info->dither_method=(DitherMethod)
10294               argument_list[2].integer_reference;
10295           (void) RemapImages(quantize_info,image,
10296             argument_list[0].image_reference);
10297           quantize_info=DestroyQuantizeInfo(quantize_info);
10298           break;
10299         }
10300         case 119:  /* SparseColor */
10301         {
10302           AV
10303             *av;
10304
10305           double
10306             *coordinates;
10307
10308           SparseColorMethod
10309             method;
10310
10311           size_t
10312             number_coordinates;
10313
10314           VirtualPixelMethod
10315             virtual_pixel;
10316
10317           if (attribute_flag[0] == 0)
10318             break;
10319           method=UndefinedColorInterpolate;
10320           if (attribute_flag[1] != 0)
10321             method=(SparseColorMethod) argument_list[1].integer_reference;
10322           av=(AV *) argument_list[0].array_reference;
10323           number_coordinates=(size_t) av_len(av)+1;
10324           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10325             sizeof(*coordinates));
10326           if (coordinates == (double *) NULL)
10327             {
10328               ThrowPerlException(exception,ResourceLimitFatalError,
10329                 "MemoryAllocationFailed",PackageName);
10330               goto PerlException;
10331             }
10332           for (j=0; j < (ssize_t) number_coordinates; j++)
10333             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10334           virtual_pixel=UndefinedVirtualPixelMethod;
10335           if (attribute_flag[2] != 0)
10336             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10337               argument_list[2].integer_reference);
10338           if (attribute_flag[3] != 0)
10339             channel=(ChannelType) argument_list[3].integer_reference;
10340           channel_mask=SetPixelChannelMask(image,channel);
10341           image=SparseColorImage(image,method,number_coordinates,coordinates,
10342             exception);
10343           if (image != (Image *) NULL)
10344             (void) SetPixelChannelMask(image,channel_mask);
10345           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10346             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10347           coordinates=(double *) RelinquishMagickMemory(coordinates);
10348           break;
10349         }
10350         case 120:  /* Function */
10351         {
10352           AV
10353             *av;
10354
10355           double
10356             *parameters;
10357
10358           MagickFunction
10359             function;
10360
10361           size_t
10362             number_parameters;
10363
10364           VirtualPixelMethod
10365             virtual_pixel;
10366
10367           if (attribute_flag[0] == 0)
10368             break;
10369           function=UndefinedFunction;
10370           if (attribute_flag[1] != 0)
10371             function=(MagickFunction) argument_list[1].integer_reference;
10372           av=(AV *) argument_list[0].array_reference;
10373           number_parameters=(size_t) av_len(av)+1;
10374           parameters=(double *) AcquireQuantumMemory(number_parameters,
10375             sizeof(*parameters));
10376           if (parameters == (double *) NULL)
10377             {
10378               ThrowPerlException(exception,ResourceLimitFatalError,
10379                 "MemoryAllocationFailed",PackageName);
10380               goto PerlException;
10381             }
10382           for (j=0; j < (ssize_t) number_parameters; j++)
10383             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10384           virtual_pixel=UndefinedVirtualPixelMethod;
10385           if (attribute_flag[2] != 0)
10386             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10387               argument_list[2].integer_reference);
10388           (void) FunctionImage(image,function,number_parameters,parameters,
10389             exception);
10390           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10391             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10392           parameters=(double *) RelinquishMagickMemory(parameters);
10393           break;
10394         }
10395         case 121:  /* SelectiveBlur */
10396         {
10397           if (attribute_flag[0] != 0)
10398             {
10399               flags=ParseGeometry(argument_list[0].string_reference,
10400                 &geometry_info);
10401               if ((flags & SigmaValue) == 0)
10402                 geometry_info.sigma=1.0;
10403               if ((flags & PercentValue) != 0)
10404                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10405             }
10406           if (attribute_flag[1] != 0)
10407             geometry_info.rho=argument_list[1].real_reference;
10408           if (attribute_flag[2] != 0)
10409             geometry_info.sigma=argument_list[2].real_reference;
10410           if (attribute_flag[3] != 0)
10411             geometry_info.xi=argument_list[3].integer_reference;;
10412           if (attribute_flag[4] != 0)
10413             channel=(ChannelType) argument_list[4].integer_reference;
10414           channel_mask=SetPixelChannelMask(image,channel);
10415           image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10416             geometry_info.xi,exception);
10417           if (image != (Image *) NULL)
10418             (void) SetPixelChannelMask(image,channel_mask);
10419           break;
10420         }
10421         case 122:  /* HaldClut */
10422         {
10423           if (attribute_flag[0] == 0)
10424             {
10425               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10426                 PackageName);
10427               goto PerlException;
10428             }
10429           if (attribute_flag[1] != 0)
10430             channel=(ChannelType) argument_list[1].integer_reference;
10431           channel_mask=SetPixelChannelMask(image,channel);
10432           (void) HaldClutImage(image,argument_list[0].image_reference,
10433             exception);
10434           (void) SetPixelChannelMask(image,channel_mask);
10435           break;
10436         }
10437         case 123:  /* BlueShift */
10438         {
10439           if (attribute_flag[0] != 0)
10440             (void) ParseGeometry(argument_list[0].string_reference,
10441               &geometry_info);
10442           image=BlueShiftImage(image,geometry_info.rho,exception);
10443           break;
10444         }
10445         case 124:  /* ForwardFourierTransformImage */
10446         {
10447           image=ForwardFourierTransformImage(image,
10448             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10449             exception);
10450           break;
10451         }
10452         case 125:  /* InverseFourierTransformImage */
10453         {
10454           image=InverseFourierTransformImage(image,image->next,
10455             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10456             exception);
10457           break;
10458         }
10459         case 126:  /* ColorDecisionList */
10460         {
10461           if (attribute_flag[0] == 0)
10462             argument_list[0].string_reference=(char *) NULL;
10463           (void) ColorDecisionListImage(image,
10464             argument_list[0].string_reference,exception);
10465           break;
10466         }
10467         case 127:  /* AutoGamma */
10468         {
10469           if (attribute_flag[0] != 0)
10470             channel=(ChannelType) argument_list[0].integer_reference;
10471           channel_mask=SetPixelChannelMask(image,channel);
10472           (void) AutoGammaImage(image,exception);
10473           (void) SetPixelChannelMask(image,channel_mask);
10474           break;
10475         }
10476         case 128:  /* AutoLevel */
10477         {
10478           if (attribute_flag[0] != 0)
10479             channel=(ChannelType) argument_list[0].integer_reference;
10480           channel_mask=SetPixelChannelMask(image,channel);
10481           (void) AutoLevelImage(image,exception);
10482           (void) SetPixelChannelMask(image,channel_mask);
10483           break;
10484         }
10485         case 129:  /* LevelColors */
10486         {
10487           PixelInfo
10488             black_point,
10489             white_point;
10490
10491           (void) QueryMagickColor("#000000",&black_point,exception);
10492           (void) QueryMagickColor("#ffffff",&white_point,exception);
10493           if (attribute_flag[1] != 0)
10494              (void) QueryMagickColor(argument_list[1].string_reference,
10495                &black_point,exception);
10496           if (attribute_flag[2] != 0)
10497              (void) QueryMagickColor(argument_list[2].string_reference,
10498                &white_point,exception);
10499           if (attribute_flag[3] != 0)
10500             channel=(ChannelType) argument_list[3].integer_reference;
10501           channel_mask=SetPixelChannelMask(image,channel);
10502           (void) LevelImageColors(image,&black_point,&white_point,
10503             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10504             exception);
10505           (void) SetPixelChannelMask(image,channel_mask);
10506           break;
10507         }
10508         case 130:  /* Clamp */
10509         {
10510           if (attribute_flag[0] != 0)
10511             channel=(ChannelType) argument_list[0].integer_reference;
10512           channel_mask=SetPixelChannelMask(image,channel);
10513           (void) ClampImage(image);
10514           (void) SetPixelChannelMask(image,channel_mask);
10515           break;
10516         }
10517         case 132:  /* BrightnessContrast */
10518         {
10519           double
10520             brightness,
10521             contrast;
10522
10523           brightness=0.0;
10524           contrast=0.0;
10525           if (attribute_flag[0] != 0)
10526             {
10527               flags=ParseGeometry(argument_list[0].string_reference,
10528                 &geometry_info);
10529               brightness=geometry_info.rho;
10530               if ((flags & SigmaValue) == 0)
10531                 contrast=geometry_info.sigma;
10532             }
10533           if (attribute_flag[1] != 0)
10534             brightness=argument_list[1].real_reference;
10535           if (attribute_flag[2] != 0)
10536             contrast=argument_list[2].real_reference;
10537           if (attribute_flag[4] != 0)
10538             channel=(ChannelType) argument_list[4].integer_reference;
10539           channel_mask=SetPixelChannelMask(image,channel);
10540           (void) BrightnessContrastImage(image,brightness,contrast,exception);
10541           (void) SetPixelChannelMask(image,channel_mask);
10542           break;
10543         }
10544         case 133:  /* Morphology */
10545         {
10546           KernelInfo
10547             *kernel;
10548
10549           MorphologyMethod
10550             method;
10551
10552           ssize_t
10553             iterations;
10554
10555           if (attribute_flag[0] == 0)
10556             break;
10557           kernel=AcquireKernelInfo(argument_list[0].string_reference);
10558           if (kernel == (KernelInfo *) NULL)
10559             break;
10560           if (attribute_flag[1] != 0)
10561             channel=(ChannelType) argument_list[1].integer_reference;
10562           method=UndefinedMorphology;
10563           if (attribute_flag[2] != 0)
10564             method=argument_list[2].integer_reference;
10565           iterations=1;
10566           if (attribute_flag[3] != 0)
10567             iterations=argument_list[4].integer_reference;
10568           channel_mask=SetPixelChannelMask(image,channel);
10569           image=MorphologyImage(image,method,iterations,kernel,exception);
10570           if (image != (Image *) NULL)
10571             (void) SetPixelChannelMask(image,channel_mask);
10572           kernel=DestroyKernelInfo(kernel);
10573           break;
10574         }
10575         case 108:  /* Recolor */
10576         case 134:  /* ColorMatrix */
10577         {
10578           AV
10579             *av;
10580
10581           double
10582             *color_matrix;
10583
10584           KernelInfo
10585             *kernel_info;
10586
10587           size_t
10588             order;
10589
10590           if (attribute_flag[0] == 0)
10591             break;
10592           av=(AV *) argument_list[0].array_reference;
10593           if (av == (AV *) NULL)
10594             break;
10595           order=(size_t) sqrt(av_len(av)+1);
10596           color_matrix=(double *) AcquireQuantumMemory(order,order*
10597             sizeof(*color_matrix));
10598           if (color_matrix == (double *) NULL)
10599             {
10600               ThrowPerlException(exception,ResourceLimitFatalError,
10601                 "MemoryAllocationFailed",PackageName);
10602               goto PerlException;
10603            }
10604           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10605             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10606           for ( ; j < (ssize_t) (order*order); j++)
10607             color_matrix[j]=0.0;
10608           kernel_info=AcquireKernelInfo((const char *) NULL);
10609           if (kernel_info == (KernelInfo *) NULL)
10610             break;
10611           kernel_info->width=order;
10612           kernel_info->height=order;
10613           kernel_info->values=color_matrix;
10614           image=ColorMatrixImage(image,kernel_info,exception);
10615           kernel_info->values=(double *) NULL;
10616           kernel_info=DestroyKernelInfo(kernel_info);
10617           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10618           break;
10619         }
10620         case 135:  /* Color */
10621         {
10622           PixelInfo
10623             color;
10624
10625           (void) QueryMagickColor("none",&color,exception);
10626           if (attribute_flag[0] != 0)
10627             (void) QueryMagickColor(argument_list[0].string_reference,
10628               &color,exception);
10629           (void) SetImageColor(image,&color);
10630           break;
10631         }
10632         case 136:  /* Mode */
10633         {
10634           if (attribute_flag[0] != 0)
10635             {
10636               flags=ParseGeometry(argument_list[0].string_reference,
10637                 &geometry_info);
10638               if ((flags & SigmaValue) == 0)
10639                 geometry_info.sigma=1.0;
10640             }
10641           if (attribute_flag[1] != 0)
10642             geometry_info.rho=argument_list[1].real_reference;
10643           if (attribute_flag[2] != 0)
10644             geometry_info.sigma=argument_list[2].real_reference;
10645           if (attribute_flag[3] != 0)
10646             channel=(ChannelType) argument_list[3].integer_reference;
10647           channel_mask=SetPixelChannelMask(image,channel);
10648           image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
10649             (size_t) geometry_info.sigma,exception);
10650           if (image != (Image *) NULL)
10651             (void) SetPixelChannelMask(image,channel_mask);
10652           break;
10653         }
10654         case 137:  /* Statistic */
10655         {
10656           StatisticType
10657             statistic;
10658
10659           statistic=UndefinedStatistic;
10660           if (attribute_flag[0] != 0)
10661             {
10662               flags=ParseGeometry(argument_list[0].string_reference,
10663                 &geometry_info);
10664               if ((flags & SigmaValue) == 0)
10665                 geometry_info.sigma=1.0;
10666             }
10667           if (attribute_flag[1] != 0)
10668             geometry_info.rho=argument_list[1].real_reference;
10669           if (attribute_flag[2] != 0)
10670             geometry_info.sigma=argument_list[2].real_reference;
10671           if (attribute_flag[3] != 0)
10672             channel=(ChannelType) argument_list[3].integer_reference;
10673           if (attribute_flag[4] != 0)
10674             statistic=(StatisticType) argument_list[4].integer_reference;
10675           channel_mask=SetPixelChannelMask(image,channel);
10676           image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
10677             (size_t) geometry_info.sigma,exception);
10678           if (image != (Image *) NULL)
10679             (void) SetPixelChannelMask(image,channel_mask);
10680           break;
10681         }
10682       }
10683       if (next != (Image *) NULL)
10684         (void) CatchImageException(next);
10685       if (region_image != (Image *) NULL)
10686         {
10687           /*
10688             Composite region.
10689           */ 
10690           status=CompositeImage(region_image,CopyCompositeOp,image,
10691             region_info.x,region_info.y);
10692           (void) status;
10693           (void) CatchImageException(region_image);
10694           image=DestroyImage(image);
10695           image=region_image;
10696         }
10697       if (image != (Image *) NULL)
10698         {
10699           number_images++;
10700           if (next && (next != image))
10701             {
10702               image->next=next->next;
10703               DeleteImageFromRegistry(*pv,next);
10704             }
10705           sv_setiv(*pv,(IV) image);
10706           next=image;
10707         }
10708       if (*pv)
10709         pv++;
10710     }
10711
10712   PerlException:
10713     if (reference_vector)
10714       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
10715     InheritPerlException(exception,perl_exception);
10716     exception=DestroyExceptionInfo(exception);
10717     sv_setiv(perl_exception,(IV) number_images);
10718     SvPOK_on(perl_exception);
10719     ST(0)=sv_2mortal(perl_exception);
10720     XSRETURN(1);
10721   }
10722 \f
10723 #
10724 ###############################################################################
10725 #                                                                             #
10726 #                                                                             #
10727 #                                                                             #
10728 #   M o n t a g e                                                             #
10729 #                                                                             #
10730 #                                                                             #
10731 #                                                                             #
10732 ###############################################################################
10733 #
10734 #
10735 void
10736 Montage(ref,...)
10737   Image::Magick ref=NO_INIT
10738   ALIAS:
10739     MontageImage  = 1
10740     montage       = 2
10741     montageimage  = 3
10742   PPCODE:
10743   {
10744     AV
10745       *av;
10746
10747     char
10748       *attribute;
10749
10750     ExceptionInfo
10751       *exception;
10752
10753     HV
10754       *hv;
10755
10756     Image
10757       *image,
10758       *next;
10759
10760     PixelInfo
10761       transparent_color;
10762
10763     MontageInfo
10764       *montage_info;
10765
10766     register ssize_t
10767       i;
10768
10769     ssize_t
10770       sp;
10771
10772     struct PackageInfo
10773       *info;
10774
10775     SV
10776       *av_reference,
10777       *perl_exception,
10778       *reference,
10779       *rv,
10780       *sv;
10781
10782     PERL_UNUSED_VAR(ref);
10783     PERL_UNUSED_VAR(ix);
10784     exception=AcquireExceptionInfo();
10785     perl_exception=newSVpv("",0);
10786     sv=NULL;
10787     attribute=NULL;
10788     if (sv_isobject(ST(0)) == 0)
10789       {
10790         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
10791           PackageName);
10792         goto PerlException;
10793       }
10794     reference=SvRV(ST(0));
10795     hv=SvSTASH(reference);
10796     av=newAV();
10797     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
10798     SvREFCNT_dec(av);
10799     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
10800     if (image == (Image *) NULL)
10801       {
10802         ThrowPerlException(exception,OptionError,"NoImagesDefined",
10803           PackageName);
10804         goto PerlException;
10805       }
10806     /*
10807       Get options.
10808     */
10809     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
10810     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
10811     (void) QueryMagickColor("none",&transparent_color,exception);
10812     for (i=2; i < items; i+=2)
10813     {
10814       attribute=(char *) SvPV(ST(i-1),na);
10815       switch (*attribute)
10816       {
10817         case 'B':
10818         case 'b':
10819         {
10820           if (LocaleCompare(attribute,"background") == 0)
10821             {
10822               (void) QueryColorDatabase(SvPV(ST(i),na),
10823                 &montage_info->background_color,exception);
10824               for (next=image; next; next=next->next)
10825                 next->background_color=montage_info->background_color;
10826               break;
10827             }
10828           if (LocaleCompare(attribute,"border") == 0)
10829             {
10830               montage_info->border_width=SvIV(ST(i));
10831               break;
10832             }
10833           if (LocaleCompare(attribute,"bordercolor") == 0)
10834             {
10835               (void) QueryColorDatabase(SvPV(ST(i),na),
10836                 &montage_info->border_color,exception);
10837               for (next=image; next; next=next->next)
10838                 next->border_color=montage_info->border_color;
10839               break;
10840             }
10841           if (LocaleCompare(attribute,"borderwidth") == 0)
10842             {
10843               montage_info->border_width=SvIV(ST(i));
10844               break;
10845             }
10846           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10847             attribute);
10848           break;
10849         }
10850         case 'C':
10851         case 'c':
10852         {
10853           if (LocaleCompare(attribute,"compose") == 0)
10854             {
10855               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
10856                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
10857               if (sp < 0)
10858                 {
10859                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
10860                     SvPV(ST(i),na));
10861                   break;
10862                 }
10863               for (next=image; next; next=next->next)
10864                 next->compose=(CompositeOperator) sp;
10865               break;
10866             }
10867           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10868             attribute);
10869           break;
10870         }
10871         case 'F':
10872         case 'f':
10873         {
10874           if (LocaleCompare(attribute,"fill") == 0)
10875             {
10876               (void) QueryColorDatabase(SvPV(ST(i),na),&montage_info->fill,
10877                 exception);
10878               break;
10879             }
10880           if (LocaleCompare(attribute,"font") == 0)
10881             {
10882               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
10883               break;
10884             }
10885           if (LocaleCompare(attribute,"frame") == 0)
10886             {
10887               char
10888                 *p;
10889
10890               p=SvPV(ST(i),na);
10891               if (IsGeometry(p) == MagickFalse)
10892                 {
10893                   ThrowPerlException(exception,OptionError,"MissingGeometry",
10894                     p);
10895                   break;
10896                 }
10897               (void) CloneString(&montage_info->frame,p);
10898               if (*p == '\0')
10899                 montage_info->frame=(char *) NULL;
10900               break;
10901             }
10902           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10903             attribute);
10904           break;
10905         }
10906         case 'G':
10907         case 'g':
10908         {
10909           if (LocaleCompare(attribute,"geometry") == 0)
10910             {
10911               char
10912                 *p;
10913
10914               p=SvPV(ST(i),na);
10915               if (IsGeometry(p) == MagickFalse)
10916                 {
10917                   ThrowPerlException(exception,OptionError,"MissingGeometry",
10918                     p);
10919                   break;
10920                 }
10921              (void) CloneString(&montage_info->geometry,p);
10922              if (*p == '\0')
10923                montage_info->geometry=(char *) NULL;
10924              break;
10925            }
10926          if (LocaleCompare(attribute,"gravity") == 0)
10927            {
10928              ssize_t
10929                in;
10930
10931              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
10932                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
10933              if (in < 0)
10934                {
10935                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
10936                    SvPV(ST(i),na));
10937                  return;
10938                }
10939              montage_info->gravity=(GravityType) in;
10940              for (next=image; next; next=next->next)
10941                next->gravity=(GravityType) in;
10942              break;
10943            }
10944           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10945             attribute);
10946           break;
10947         }
10948         case 'L':
10949         case 'l':
10950         {
10951           if (LocaleCompare(attribute,"label") == 0)
10952             {
10953               for (next=image; next; next=next->next)
10954                 (void) SetImageProperty(next,"label",InterpretImageProperties(
10955                   info ? info->image_info : (ImageInfo *) NULL,next,
10956                   SvPV(ST(i),na)));
10957               break;
10958             }
10959           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10960             attribute);
10961           break;
10962         }
10963         case 'M':
10964         case 'm':
10965         {
10966           if (LocaleCompare(attribute,"mattecolor") == 0)
10967             {
10968               (void) QueryColorDatabase(SvPV(ST(i),na),
10969                 &montage_info->matte_color,exception);
10970               for (next=image; next; next=next->next)
10971                 next->matte_color=montage_info->matte_color;
10972               break;
10973             }
10974           if (LocaleCompare(attribute,"mode") == 0)
10975             {
10976               ssize_t
10977                 in;
10978
10979               in=!SvPOK(ST(i)) ? SvIV(ST(i)) :
10980                 ParseCommandOption(MagickModeOptions,MagickFalse,SvPV(ST(i),na));
10981               switch (in)
10982               {
10983                 default:
10984                 {
10985                   ThrowPerlException(exception,OptionError,
10986                     "UnrecognizedModeType",SvPV(ST(i),na));
10987                   break;
10988                 }
10989                 case FrameMode:
10990                 {
10991                   (void) CloneString(&montage_info->frame,"15x15+3+3");
10992                   montage_info->shadow=MagickTrue;
10993                   break;
10994                 }
10995                 case UnframeMode:
10996                 {
10997                   montage_info->frame=(char *) NULL;
10998                   montage_info->shadow=MagickFalse;
10999                   montage_info->border_width=0;
11000                   break;
11001                 }
11002                 case ConcatenateMode:
11003                 {
11004                   montage_info->frame=(char *) NULL;
11005                   montage_info->shadow=MagickFalse;
11006                   (void) CloneString(&montage_info->geometry,"+0+0");
11007                   montage_info->border_width=0;
11008                 }
11009               }
11010               break;
11011             }
11012           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11013             attribute);
11014           break;
11015         }
11016         case 'P':
11017         case 'p':
11018         {
11019           if (LocaleCompare(attribute,"pointsize") == 0)
11020             {
11021               montage_info->pointsize=SvIV(ST(i));
11022               break;
11023             }
11024           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11025             attribute);
11026           break;
11027         }
11028         case 'S':
11029         case 's':
11030         {
11031           if (LocaleCompare(attribute,"shadow") == 0)
11032             {
11033               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11034                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11035               if (sp < 0)
11036                 {
11037                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11038                     SvPV(ST(i),na));
11039                   break;
11040                 }
11041              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11042              break;
11043             }
11044           if (LocaleCompare(attribute,"stroke") == 0)
11045             {
11046               (void) QueryColorDatabase(SvPV(ST(i),na),&montage_info->stroke,
11047                 exception);
11048               break;
11049             }
11050           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11051             attribute);
11052           break;
11053         }
11054         case 'T':
11055         case 't':
11056         {
11057           if (LocaleCompare(attribute,"texture") == 0)
11058             {
11059               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11060               break;
11061             }
11062           if (LocaleCompare(attribute,"tile") == 0)
11063             {
11064               char *p=SvPV(ST(i),na);
11065               if (IsGeometry(p) == MagickFalse)
11066                 {
11067                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11068                     p);
11069                   break;
11070                 }
11071               (void) CloneString(&montage_info->tile,p);
11072               if (*p == '\0')
11073                 montage_info->tile=(char *) NULL;
11074               break;
11075             }
11076           if (LocaleCompare(attribute,"title") == 0)
11077             {
11078               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11079               break;
11080             }
11081           if (LocaleCompare(attribute,"transparent") == 0)
11082             {
11083               PixelInfo
11084                 transparent_color;
11085
11086               QueryMagickColor(SvPV(ST(i),na),&transparent_color,exception);
11087               for (next=image; next; next=next->next)
11088                 (void) TransparentPaintImage(next,&transparent_color,
11089                   TransparentAlpha,MagickFalse);
11090               break;
11091             }
11092           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11093             attribute);
11094           break;
11095         }
11096         default:
11097         {
11098           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11099             attribute);
11100           break;
11101         }
11102       }
11103     }
11104     image=MontageImageList(info->image_info,montage_info,image,exception);
11105     montage_info=DestroyMontageInfo(montage_info);
11106     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11107       goto PerlException;
11108     if (transparent_color.alpha != TransparentAlpha)
11109       for (next=image; next; next=next->next)
11110         (void) TransparentPaintImage(next,&transparent_color,
11111           TransparentAlpha,MagickFalse);
11112     for (  ; image; image=image->next)
11113     {
11114       AddImageToRegistry(sv,image);
11115       rv=newRV(sv);
11116       av_push(av,sv_bless(rv,hv));
11117       SvREFCNT_dec(sv);
11118     }
11119     exception=DestroyExceptionInfo(exception);
11120     ST(0)=av_reference;
11121     SvREFCNT_dec(perl_exception);
11122     XSRETURN(1);
11123
11124   PerlException:
11125     InheritPerlException(exception,perl_exception);
11126     exception=DestroyExceptionInfo(exception);
11127     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11128     SvPOK_on(perl_exception);
11129     ST(0)=sv_2mortal(perl_exception);
11130     XSRETURN(1);
11131   }
11132 \f
11133 #
11134 ###############################################################################
11135 #                                                                             #
11136 #                                                                             #
11137 #                                                                             #
11138 #   M o r p h                                                                 #
11139 #                                                                             #
11140 #                                                                             #
11141 #                                                                             #
11142 ###############################################################################
11143 #
11144 #
11145 void
11146 Morph(ref,...)
11147   Image::Magick ref=NO_INIT
11148   ALIAS:
11149     MorphImage  = 1
11150     morph       = 2
11151     morphimage  = 3
11152   PPCODE:
11153   {
11154     AV
11155       *av;
11156
11157     char
11158       *attribute;
11159
11160     ExceptionInfo
11161       *exception;
11162
11163     HV
11164       *hv;
11165
11166     Image
11167       *image;
11168
11169     register ssize_t
11170       i;
11171
11172     ssize_t
11173       number_frames;
11174
11175     struct PackageInfo
11176       *info;
11177
11178     SV
11179       *av_reference,
11180       *perl_exception,
11181       *reference,
11182       *rv,
11183       *sv;
11184
11185     PERL_UNUSED_VAR(ref);
11186     PERL_UNUSED_VAR(ix);
11187     exception=AcquireExceptionInfo();
11188     perl_exception=newSVpv("",0);
11189     sv=NULL;
11190     av=NULL;
11191     attribute=NULL;
11192     if (sv_isobject(ST(0)) == 0)
11193       {
11194         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11195           PackageName);
11196         goto PerlException;
11197       }
11198     reference=SvRV(ST(0));
11199     hv=SvSTASH(reference);
11200     av=newAV();
11201     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11202     SvREFCNT_dec(av);
11203     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11204     if (image == (Image *) NULL)
11205       {
11206         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11207           PackageName);
11208         goto PerlException;
11209       }
11210     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11211     /*
11212       Get attribute.
11213     */
11214     number_frames=30;
11215     for (i=2; i < items; i+=2)
11216     {
11217       attribute=(char *) SvPV(ST(i-1),na);
11218       switch (*attribute)
11219       {
11220         case 'F':
11221         case 'f':
11222         {
11223           if (LocaleCompare(attribute,"frames") == 0)
11224             {
11225               number_frames=SvIV(ST(i));
11226               break;
11227             }
11228           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11229             attribute);
11230           break;
11231         }
11232         default:
11233         {
11234           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11235             attribute);
11236           break;
11237         }
11238       }
11239     }
11240     image=MorphImages(image,number_frames,exception);
11241     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11242       goto PerlException;
11243     for ( ; image; image=image->next)
11244     {
11245       AddImageToRegistry(sv,image);
11246       rv=newRV(sv);
11247       av_push(av,sv_bless(rv,hv));
11248       SvREFCNT_dec(sv);
11249     }
11250     exception=DestroyExceptionInfo(exception);
11251     ST(0)=av_reference;
11252     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11253     XSRETURN(1);
11254
11255   PerlException:
11256     InheritPerlException(exception,perl_exception);
11257     exception=DestroyExceptionInfo(exception);
11258     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11259     SvPOK_on(perl_exception);
11260     ST(0)=sv_2mortal(perl_exception);
11261     XSRETURN(1);
11262   }
11263 \f
11264 #
11265 ###############################################################################
11266 #                                                                             #
11267 #                                                                             #
11268 #                                                                             #
11269 #   M o s a i c                                                               #
11270 #                                                                             #
11271 #                                                                             #
11272 #                                                                             #
11273 ###############################################################################
11274 #
11275 #
11276 void
11277 Mosaic(ref)
11278   Image::Magick ref=NO_INIT
11279   ALIAS:
11280     MosaicImage   = 1
11281     mosaic        = 2
11282     mosaicimage   = 3
11283   PPCODE:
11284   {
11285     AV
11286       *av;
11287
11288     ExceptionInfo
11289       *exception;
11290
11291     HV
11292       *hv;
11293
11294     Image
11295       *image;
11296
11297     struct PackageInfo
11298       *info;
11299
11300     SV
11301       *perl_exception,
11302       *reference,
11303       *rv,
11304       *sv;
11305
11306     PERL_UNUSED_VAR(ref);
11307     PERL_UNUSED_VAR(ix);
11308     exception=AcquireExceptionInfo();
11309     perl_exception=newSVpv("",0);
11310     sv=NULL;
11311     if (sv_isobject(ST(0)) == 0)
11312       {
11313         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11314           PackageName);
11315         goto PerlException;
11316       }
11317     reference=SvRV(ST(0));
11318     hv=SvSTASH(reference);
11319     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11320     if (image == (Image *) NULL)
11321       {
11322         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11323           PackageName);
11324         goto PerlException;
11325       }
11326     image=MergeImageLayers(image,MosaicLayer,exception);
11327     /*
11328       Create blessed Perl array for the returned image.
11329     */
11330     av=newAV();
11331     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11332     SvREFCNT_dec(av);
11333     AddImageToRegistry(sv,image);
11334     rv=newRV(sv);
11335     av_push(av,sv_bless(rv,hv));
11336     SvREFCNT_dec(sv);
11337     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11338     (void) CopyMagickString(image->filename,info->image_info->filename,
11339       MaxTextExtent);
11340     SetImageInfo(info->image_info,0,&image->exception);
11341     exception=DestroyExceptionInfo(exception);
11342     SvREFCNT_dec(perl_exception);
11343     XSRETURN(1);
11344
11345   PerlException:
11346     InheritPerlException(exception,perl_exception);
11347     exception=DestroyExceptionInfo(exception);
11348     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11349     SvPOK_on(perl_exception);  /* return messages in string context */
11350     ST(0)=sv_2mortal(perl_exception);
11351     XSRETURN(1);
11352   }
11353 \f
11354 #
11355 ###############################################################################
11356 #                                                                             #
11357 #                                                                             #
11358 #                                                                             #
11359 #   P i n g                                                                   #
11360 #                                                                             #
11361 #                                                                             #
11362 #                                                                             #
11363 ###############################################################################
11364 #
11365 #
11366 void
11367 Ping(ref,...)
11368   Image::Magick ref=NO_INIT
11369   ALIAS:
11370     PingImage  = 1
11371     ping       = 2
11372     pingimage  = 3
11373   PPCODE:
11374   {
11375     AV
11376       *av;
11377
11378     char
11379       **keep,
11380       **list;
11381
11382     ExceptionInfo
11383       *exception;
11384
11385     Image
11386       *image,
11387       *next;
11388
11389     int
11390       n;
11391
11392     MagickBooleanType
11393       status;
11394
11395     register char
11396       **p;
11397
11398     register ssize_t
11399       i;
11400
11401     ssize_t
11402       ac;
11403
11404     STRLEN
11405       *length;
11406
11407     struct PackageInfo
11408       *info,
11409       *package_info;
11410
11411     SV
11412       *perl_exception,
11413       *reference;
11414
11415     size_t
11416       count;
11417
11418     PERL_UNUSED_VAR(ref);
11419     PERL_UNUSED_VAR(ix);
11420     exception=AcquireExceptionInfo();
11421     perl_exception=newSVpv("",0);
11422     package_info=(struct PackageInfo *) NULL;
11423     ac=(items < 2) ? 1 : items-1;
11424     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
11425     keep=list;
11426     length=(STRLEN *) NULL;
11427     if (list == (char **) NULL)
11428       {
11429         ThrowPerlException(exception,ResourceLimitError,
11430           "MemoryAllocationFailed",PackageName);
11431         goto PerlException;
11432       }
11433     keep=list;
11434     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
11435     if (length == (STRLEN *) NULL)
11436       {
11437         ThrowPerlException(exception,ResourceLimitError,
11438           "MemoryAllocationFailed",PackageName);
11439         goto PerlException;
11440       }
11441     if (sv_isobject(ST(0)) == 0)
11442       {
11443         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11444           PackageName);
11445         goto PerlException;
11446       }
11447     reference=SvRV(ST(0));
11448     if (SvTYPE(reference) != SVt_PVAV)
11449       {
11450         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11451           PackageName);
11452         goto PerlException;
11453       }
11454     av=(AV *) reference;
11455     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11456       exception);
11457     package_info=ClonePackageInfo(info,exception);
11458     n=1;
11459     if (items <= 1)
11460       *list=(char *) (*package_info->image_info->filename ?
11461         package_info->image_info->filename : "XC:black");
11462     else
11463       for (n=0, i=0; i < ac; i++)
11464       {
11465         list[n]=(char *) SvPV(ST(i+1),length[n]);
11466         if ((items >= 3) && strEQcase(list[n],"blob"))
11467           {
11468             void
11469               *blob;
11470
11471             i++;
11472             blob=(void *) (SvPV(ST(i+1),length[n]));
11473             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
11474           }
11475         if ((items >= 3) && strEQcase(list[n],"filename"))
11476           continue;
11477         if ((items >= 3) && strEQcase(list[n],"file"))
11478           {
11479             FILE
11480               *file;
11481
11482             PerlIO
11483               *io_info;
11484
11485             i++;
11486             io_info=IoIFP(sv_2io(ST(i+1)));
11487             if (io_info == (PerlIO *) NULL)
11488               {
11489                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11490                   PackageName);
11491                 continue;
11492               }
11493             file=PerlIO_findFILE(io_info);
11494             if (file == (FILE *) NULL)
11495               {
11496                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11497                   PackageName);
11498                 continue;
11499               }
11500             SetImageInfoFile(package_info->image_info,file);
11501           }
11502         if ((items >= 3) && strEQcase(list[n],"magick"))
11503           continue;
11504         n++;
11505       }
11506     list[n]=(char *) NULL;
11507     keep=list;
11508     status=ExpandFilenames(&n,&list);
11509     if (status == MagickFalse)
11510       {
11511         ThrowPerlException(exception,ResourceLimitError,
11512           "MemoryAllocationFailed",PackageName);
11513         goto PerlException;
11514       }
11515     count=0;
11516     for (i=0; i < n; i++)
11517     {
11518       (void) CopyMagickString(package_info->image_info->filename,list[i],
11519         MaxTextExtent);
11520       image=PingImage(package_info->image_info,exception);
11521       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11522         break;
11523       if ((package_info->image_info->file != (FILE *) NULL) ||
11524           (package_info->image_info->blob != (void *) NULL))
11525         DisassociateImageStream(image);
11526       count+=GetImageListLength(image);
11527       EXTEND(sp,4*count);
11528       for (next=image; next; next=next->next)
11529       {
11530         PUSHs(sv_2mortal(newSViv(next->columns)));
11531         PUSHs(sv_2mortal(newSViv(next->rows)));
11532         PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
11533         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
11534       }
11535       image=DestroyImageList(image);
11536     }
11537     /*
11538       Free resources.
11539     */
11540     for (i=0; i < n; i++)
11541       if (list[i] != (char *) NULL)
11542         for (p=keep; list[i] != *p++; )
11543           if (*p == NULL)
11544             {
11545               list[i]=(char *) RelinquishMagickMemory(list[i]);
11546               break;
11547             }
11548
11549   PerlException:
11550     if (package_info != (struct PackageInfo *) NULL)
11551       DestroyPackageInfo(package_info);
11552     if (list && (list != keep))
11553       list=(char **) RelinquishMagickMemory(list);
11554     if (keep)
11555       keep=(char **) RelinquishMagickMemory(keep);
11556     if (length)
11557       length=(STRLEN *) RelinquishMagickMemory(length);
11558     InheritPerlException(exception,perl_exception);
11559     exception=DestroyExceptionInfo(exception);
11560     SvREFCNT_dec(perl_exception);  /* throw away all errors */
11561   }
11562 \f
11563 #
11564 ###############################################################################
11565 #                                                                             #
11566 #                                                                             #
11567 #                                                                             #
11568 #   P r e v i e w                                                             #
11569 #                                                                             #
11570 #                                                                             #
11571 #                                                                             #
11572 ###############################################################################
11573 #
11574 #
11575 void
11576 Preview(ref,...)
11577   Image::Magick ref=NO_INIT
11578   ALIAS:
11579     PreviewImage = 1
11580     preview      = 2
11581     previewimage = 3
11582   PPCODE:
11583   {
11584     AV
11585       *av;
11586
11587     ExceptionInfo
11588       *exception;
11589
11590     HV
11591       *hv;
11592
11593     Image
11594       *image,
11595       *preview_image;
11596
11597     PreviewType
11598       preview_type;
11599
11600     struct PackageInfo
11601       *info;
11602
11603     SV
11604       *av_reference,
11605       *perl_exception,
11606       *reference,
11607       *rv,
11608       *sv;
11609
11610     PERL_UNUSED_VAR(ref);
11611     PERL_UNUSED_VAR(ix);
11612     exception=AcquireExceptionInfo();
11613     perl_exception=newSVpv("",0);
11614     sv=NULL;
11615     av=NULL;
11616     if (sv_isobject(ST(0)) == 0)
11617       {
11618         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11619           PackageName);
11620         goto PerlException;
11621       }
11622     reference=SvRV(ST(0));
11623     hv=SvSTASH(reference);
11624     av=newAV();
11625     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11626     SvREFCNT_dec(av);
11627     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11628     if (image == (Image *) NULL)
11629       {
11630         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11631           PackageName);
11632         goto PerlException;
11633       }
11634     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11635     preview_type=GammaPreview;
11636     if (items > 1)
11637       preview_type=(PreviewType)
11638         ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
11639     for ( ; image; image=image->next)
11640     {
11641       preview_image=PreviewImage(image,preview_type,exception);
11642       if (preview_image == (Image *) NULL)
11643         goto PerlException;
11644       AddImageToRegistry(sv,preview_image);
11645       rv=newRV(sv);
11646       av_push(av,sv_bless(rv,hv));
11647       SvREFCNT_dec(sv);
11648     }
11649     exception=DestroyExceptionInfo(exception);
11650     ST(0)=av_reference;
11651     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11652     XSRETURN(1);
11653
11654   PerlException:
11655     InheritPerlException(exception,perl_exception);
11656     exception=DestroyExceptionInfo(exception);
11657     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11658     SvPOK_on(perl_exception);
11659     ST(0)=sv_2mortal(perl_exception);
11660     XSRETURN(1);
11661   }
11662 \f
11663 #
11664 ###############################################################################
11665 #                                                                             #
11666 #                                                                             #
11667 #                                                                             #
11668 #   Q u e r y C o l o r                                                       #
11669 #                                                                             #
11670 #                                                                             #
11671 #                                                                             #
11672 ###############################################################################
11673 #
11674 #
11675 void
11676 QueryColor(ref,...)
11677   Image::Magick ref=NO_INIT
11678   ALIAS:
11679     querycolor = 1
11680   PPCODE:
11681   {
11682     char
11683       *name;
11684
11685     ExceptionInfo
11686       *exception;
11687
11688     PixelInfo
11689       color;
11690
11691     register ssize_t
11692       i;
11693
11694     SV
11695       *perl_exception;
11696
11697     PERL_UNUSED_VAR(ref);
11698     PERL_UNUSED_VAR(ix);
11699     exception=AcquireExceptionInfo();
11700     perl_exception=newSVpv("",0);
11701     if (items == 1)
11702       {
11703         const ColorInfo
11704           **colorlist;
11705
11706         size_t
11707           colors;
11708
11709         colorlist=GetColorInfoList("*",&colors,exception);
11710         EXTEND(sp,colors);
11711         for (i=0; i < (ssize_t) colors; i++)
11712         {
11713           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
11714         }
11715         colorlist=(const ColorInfo **)
11716           RelinquishMagickMemory((ColorInfo **) colorlist);
11717         goto PerlException;
11718       }
11719     EXTEND(sp,5*items);
11720     for (i=1; i < items; i++)
11721     {
11722       name=(char *) SvPV(ST(i),na);
11723       if (QueryMagickColor(name,&color,exception) == MagickFalse)
11724         {
11725           PUSHs(&sv_undef);
11726           continue;
11727         }
11728       PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
11729       PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
11730       PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
11731       if (color.colorspace == CMYKColorspace)
11732         PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
11733       if (color.matte != MagickFalse)
11734         PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
11735     }
11736
11737   PerlException:
11738     InheritPerlException(exception,perl_exception);
11739     exception=DestroyExceptionInfo(exception);
11740     SvREFCNT_dec(perl_exception);
11741   }
11742 \f
11743 #
11744 ###############################################################################
11745 #                                                                             #
11746 #                                                                             #
11747 #                                                                             #
11748 #   Q u e r y C o l o r N a m e                                               #
11749 #                                                                             #
11750 #                                                                             #
11751 #                                                                             #
11752 ###############################################################################
11753 #
11754 #
11755 void
11756 QueryColorname(ref,...)
11757   Image::Magick ref=NO_INIT
11758   ALIAS:
11759     querycolorname = 1
11760   PPCODE:
11761   {
11762     AV
11763       *av;
11764
11765     char
11766       message[MaxTextExtent];
11767
11768     ExceptionInfo
11769       *exception;
11770
11771     Image
11772       *image;
11773
11774     PixelPacket
11775       target_color;
11776
11777     register ssize_t
11778       i;
11779
11780     struct PackageInfo
11781       *info;
11782
11783     SV
11784       *perl_exception,
11785       *reference;  /* reference is the SV* of ref=SvIV(reference) */
11786
11787     PERL_UNUSED_VAR(ref);
11788     PERL_UNUSED_VAR(ix);
11789     exception=AcquireExceptionInfo();
11790     perl_exception=newSVpv("",0);
11791     reference=SvRV(ST(0));
11792     av=(AV *) reference;
11793     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11794       exception);
11795     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11796     if (image == (Image *) NULL)
11797       {
11798         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11799           PackageName);
11800         goto PerlException;
11801       }
11802     EXTEND(sp,items);
11803     for (i=1; i < items; i++)
11804     {
11805       (void) QueryColorDatabase(SvPV(ST(i),na),&target_color,exception);
11806       (void) QueryColorname(image,&target_color,SVGCompliance,message,
11807         exception);
11808       PUSHs(sv_2mortal(newSVpv(message,0)));
11809     }
11810
11811   PerlException:
11812     InheritPerlException(exception,perl_exception);
11813     exception=DestroyExceptionInfo(exception);
11814     SvREFCNT_dec(perl_exception);
11815   }
11816 \f
11817 #
11818 ###############################################################################
11819 #                                                                             #
11820 #                                                                             #
11821 #                                                                             #
11822 #   Q u e r y F o n t                                                         #
11823 #                                                                             #
11824 #                                                                             #
11825 #                                                                             #
11826 ###############################################################################
11827 #
11828 #
11829 void
11830 QueryFont(ref,...)
11831   Image::Magick ref=NO_INIT
11832   ALIAS:
11833     queryfont = 1
11834   PPCODE:
11835   {
11836     char
11837       *name,
11838       message[MaxTextExtent];
11839
11840     ExceptionInfo
11841       *exception;
11842
11843     register ssize_t
11844       i;
11845
11846     SV
11847       *perl_exception;
11848
11849     volatile const TypeInfo
11850       *type_info;
11851
11852     PERL_UNUSED_VAR(ref);
11853     PERL_UNUSED_VAR(ix);
11854     exception=AcquireExceptionInfo();
11855     perl_exception=newSVpv("",0);
11856     if (items == 1)
11857       {
11858         const TypeInfo
11859           **typelist;
11860
11861         size_t
11862           types;
11863
11864         typelist=GetTypeInfoList("*",&types,exception);
11865         EXTEND(sp,types);
11866         for (i=0; i < (ssize_t) types; i++)
11867         {
11868           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
11869         }
11870         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
11871           typelist);
11872         goto PerlException;
11873       }
11874     EXTEND(sp,10*items);
11875     for (i=1; i < items; i++)
11876     {
11877       name=(char *) SvPV(ST(i),na);
11878       type_info=GetTypeInfo(name,exception);
11879       if (type_info == (TypeInfo *) NULL)
11880         {
11881           PUSHs(&sv_undef);
11882           continue;
11883         }
11884       if (type_info->name == (char *) NULL)
11885         PUSHs(&sv_undef);
11886       else
11887         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
11888       if (type_info->description == (char *) NULL)
11889         PUSHs(&sv_undef);
11890       else
11891         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
11892       if (type_info->family == (char *) NULL)
11893         PUSHs(&sv_undef);
11894       else
11895         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
11896       if (type_info->style == UndefinedStyle)
11897         PUSHs(&sv_undef);
11898       else
11899         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
11900           type_info->style),0)));
11901       if (type_info->stretch == UndefinedStretch)
11902         PUSHs(&sv_undef);
11903       else
11904         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
11905           type_info->stretch),0)));
11906       (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
11907         type_info->weight);
11908       PUSHs(sv_2mortal(newSVpv(message,0)));
11909       if (type_info->encoding == (char *) NULL)
11910         PUSHs(&sv_undef);
11911       else
11912         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
11913       if (type_info->foundry == (char *) NULL)
11914         PUSHs(&sv_undef);
11915       else
11916         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
11917       if (type_info->format == (char *) NULL)
11918         PUSHs(&sv_undef);
11919       else
11920         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
11921       if (type_info->metrics == (char *) NULL)
11922         PUSHs(&sv_undef);
11923       else
11924         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
11925       if (type_info->glyphs == (char *) NULL)
11926         PUSHs(&sv_undef);
11927       else
11928         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
11929     }
11930
11931   PerlException:
11932     InheritPerlException(exception,perl_exception);
11933     exception=DestroyExceptionInfo(exception);
11934     SvREFCNT_dec(perl_exception);
11935   }
11936 \f
11937 #
11938 ###############################################################################
11939 #                                                                             #
11940 #                                                                             #
11941 #                                                                             #
11942 #   Q u e r y F o n t M e t r i c s                                           #
11943 #                                                                             #
11944 #                                                                             #
11945 #                                                                             #
11946 ###############################################################################
11947 #
11948 #
11949 void
11950 QueryFontMetrics(ref,...)
11951   Image::Magick ref=NO_INIT
11952   ALIAS:
11953     queryfontmetrics = 1
11954   PPCODE:
11955   {
11956     AffineMatrix
11957       affine,
11958       current;
11959
11960     AV
11961       *av;
11962
11963     char
11964       *attribute;
11965
11966     double
11967       x,
11968       y;
11969
11970     DrawInfo
11971       *draw_info;
11972
11973     ExceptionInfo
11974       *exception;
11975
11976     GeometryInfo
11977       geometry_info;
11978
11979     Image
11980       *image;
11981
11982     MagickBooleanType
11983       status;
11984
11985     MagickStatusType
11986       flags;
11987
11988     register ssize_t
11989       i;
11990
11991     ssize_t
11992       type;
11993
11994     struct PackageInfo
11995       *info,
11996       *package_info;
11997
11998     SV
11999       *perl_exception,
12000       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12001
12002     TypeMetric
12003       metrics;
12004
12005     PERL_UNUSED_VAR(ref);
12006     PERL_UNUSED_VAR(ix);
12007     exception=AcquireExceptionInfo();
12008     package_info=(struct PackageInfo *) NULL;
12009     perl_exception=newSVpv("",0);
12010     reference=SvRV(ST(0));
12011     av=(AV *) reference;
12012     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12013       exception);
12014     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12015     if (image == (Image *) NULL)
12016       {
12017         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12018           PackageName);
12019         goto PerlException;
12020       }
12021     package_info=ClonePackageInfo(info,exception);
12022     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12023     CloneString(&draw_info->text,"");
12024     current=draw_info->affine;
12025     GetAffineMatrix(&affine);
12026     x=0.0;
12027     y=0.0;
12028     EXTEND(sp,7*items);
12029     for (i=2; i < items; i+=2)
12030     {
12031       attribute=(char *) SvPV(ST(i-1),na);
12032       switch (*attribute)
12033       {
12034         case 'A':
12035         case 'a':
12036         {
12037           if (LocaleCompare(attribute,"antialias") == 0)
12038             {
12039               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12040                 SvPV(ST(i),na));
12041               if (type < 0)
12042                 {
12043                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12044                     SvPV(ST(i),na));
12045                   break;
12046                 }
12047               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12048               break;
12049             }
12050           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12051             attribute);
12052           break;
12053         }
12054         case 'd':
12055         case 'D':
12056         {
12057           if (LocaleCompare(attribute,"density") == 0)
12058             {
12059               CloneString(&draw_info->density,SvPV(ST(i),na));
12060               break;
12061             }
12062           if (LocaleCompare(attribute,"direction") == 0)
12063             {
12064               draw_info->direction=(DirectionType) ParseCommandOption(
12065                 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12066               break;
12067             }
12068           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12069             attribute);
12070           break;
12071         }
12072         case 'e':
12073         case 'E':
12074         {
12075           if (LocaleCompare(attribute,"encoding") == 0)
12076             {
12077               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12078               break;
12079             }
12080           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12081             attribute);
12082           break;
12083         }
12084         case 'f':
12085         case 'F':
12086         {
12087           if (LocaleCompare(attribute,"family") == 0)
12088             {
12089               CloneString(&draw_info->family,SvPV(ST(i),na));
12090               break;
12091             }
12092           if (LocaleCompare(attribute,"fill") == 0)
12093             {
12094               if (info)
12095                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->fill,
12096                   &image->exception);
12097               break;
12098             }
12099           if (LocaleCompare(attribute,"font") == 0)
12100             {
12101               CloneString(&draw_info->font,SvPV(ST(i),na));
12102               break;
12103             }
12104           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12105             attribute);
12106           break;
12107         }
12108         case 'g':
12109         case 'G':
12110         {
12111           if (LocaleCompare(attribute,"geometry") == 0)
12112             {
12113               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12114               break;
12115             }
12116           if (LocaleCompare(attribute,"gravity") == 0)
12117             {
12118               draw_info->gravity=(GravityType) ParseCommandOption(
12119                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12120               break;
12121             }
12122           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12123             attribute);
12124           break;
12125         }
12126         case 'i':
12127         case 'I':
12128         {
12129           if (LocaleCompare(attribute,"interline-spacing") == 0)
12130             {
12131               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12132               draw_info->interline_spacing=geometry_info.rho;
12133               break;
12134             }
12135           if (LocaleCompare(attribute,"interword-spacing") == 0)
12136             {
12137               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12138               draw_info->interword_spacing=geometry_info.rho;
12139               break;
12140             }
12141           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12142             attribute);
12143           break;
12144         }
12145         case 'k':
12146         case 'K':
12147         {
12148           if (LocaleCompare(attribute,"kerning") == 0)
12149             {
12150               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12151               draw_info->kerning=geometry_info.rho;
12152               break;
12153             }
12154           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12155             attribute);
12156           break;
12157         }
12158         case 'p':
12159         case 'P':
12160         {
12161           if (LocaleCompare(attribute,"pointsize") == 0)
12162             {
12163               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12164               draw_info->pointsize=geometry_info.rho;
12165               break;
12166             }
12167           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12168             attribute);
12169           break;
12170         }
12171         case 'r':
12172         case 'R':
12173         {
12174           if (LocaleCompare(attribute,"rotate") == 0)
12175             {
12176               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12177               affine.rx=geometry_info.rho;
12178               affine.ry=geometry_info.sigma;
12179               if ((flags & SigmaValue) == 0)
12180                 affine.ry=affine.rx;
12181               break;
12182             }
12183           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12184             attribute);
12185           break;
12186         }
12187         case 's':
12188         case 'S':
12189         {
12190           if (LocaleCompare(attribute,"scale") == 0)
12191             {
12192               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12193               affine.sx=geometry_info.rho;
12194               affine.sy=geometry_info.sigma;
12195               if ((flags & SigmaValue) == 0)
12196                 affine.sy=affine.sx;
12197               break;
12198             }
12199           if (LocaleCompare(attribute,"skew") == 0)
12200             {
12201               double
12202                 x_angle,
12203                 y_angle;
12204
12205               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12206               x_angle=geometry_info.rho;
12207               y_angle=geometry_info.sigma;
12208               if ((flags & SigmaValue) == 0)
12209                 y_angle=x_angle;
12210               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12211               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12212               break;
12213             }
12214           if (LocaleCompare(attribute,"stroke") == 0)
12215             {
12216               if (info)
12217                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->stroke,
12218                   &image->exception);
12219               break;
12220             }
12221           if (LocaleCompare(attribute,"style") == 0)
12222             {
12223               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12224                 SvPV(ST(i),na));
12225               if (type < 0)
12226                 {
12227                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12228                     SvPV(ST(i),na));
12229                   break;
12230                 }
12231               draw_info->style=(StyleType) type;
12232               break;
12233             }
12234           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12235             attribute);
12236           break;
12237         }
12238         case 't':
12239         case 'T':
12240         {
12241           if (LocaleCompare(attribute,"text") == 0)
12242             {
12243               CloneString(&draw_info->text,SvPV(ST(i),na));
12244               break;
12245             }
12246           if (LocaleCompare(attribute,"translate") == 0)
12247             {
12248               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12249               affine.tx=geometry_info.rho;
12250               affine.ty=geometry_info.sigma;
12251               if ((flags & SigmaValue) == 0)
12252                 affine.ty=affine.tx;
12253               break;
12254             }
12255           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12256             attribute);
12257           break;
12258         }
12259         case 'w':
12260         case 'W':
12261         {
12262           if (LocaleCompare(attribute,"weight") == 0)
12263             {
12264               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12265               draw_info->weight=(size_t) geometry_info.rho;
12266               break;
12267             }
12268           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12269             attribute);
12270           break;
12271         }
12272         case 'x':
12273         case 'X':
12274         {
12275           if (LocaleCompare(attribute,"x") == 0)
12276             {
12277               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12278               x=geometry_info.rho;
12279               break;
12280             }
12281           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12282             attribute);
12283           break;
12284         }
12285         case 'y':
12286         case 'Y':
12287         {
12288           if (LocaleCompare(attribute,"y") == 0)
12289             {
12290               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12291               y=geometry_info.rho;
12292               break;
12293             }
12294           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12295             attribute);
12296           break;
12297         }
12298         default:
12299         {
12300           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12301             attribute);
12302           break;
12303         }
12304       }
12305     }
12306     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12307     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12308     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12309     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12310     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12311     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12312     if (draw_info->geometry == (char *) NULL)
12313       {
12314         draw_info->geometry=AcquireString((char *) NULL);
12315         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12316           "%.15g,%.15g",x,y);
12317       }
12318     status=GetTypeMetrics(image,draw_info,&metrics);
12319     (void) CatchImageException(image);
12320     if (status == MagickFalse)
12321       PUSHs(&sv_undef);
12322     else
12323       {
12324         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12325         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12326         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12327         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12328         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12329         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12330         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12331         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12332         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12333         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12334         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12335         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12336         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12337       }
12338     draw_info=DestroyDrawInfo(draw_info);
12339
12340   PerlException:
12341     if (package_info != (struct PackageInfo *) NULL)
12342       DestroyPackageInfo(package_info);
12343     InheritPerlException(exception,perl_exception);
12344     exception=DestroyExceptionInfo(exception);
12345     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12346   }
12347 \f
12348 #
12349 ###############################################################################
12350 #                                                                             #
12351 #                                                                             #
12352 #                                                                             #
12353 #   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                         #
12354 #                                                                             #
12355 #                                                                             #
12356 #                                                                             #
12357 ###############################################################################
12358 #
12359 #
12360 void
12361 QueryMultilineFontMetrics(ref,...)
12362   Image::Magick ref=NO_INIT
12363   ALIAS:
12364     querymultilinefontmetrics = 1
12365   PPCODE:
12366   {
12367     AffineMatrix
12368       affine,
12369       current;
12370
12371     AV
12372       *av;
12373
12374     char
12375       *attribute;
12376
12377     double
12378       x,
12379       y;
12380
12381     DrawInfo
12382       *draw_info;
12383
12384     ExceptionInfo
12385       *exception;
12386
12387     GeometryInfo
12388       geometry_info;
12389
12390     Image
12391       *image;
12392
12393     MagickBooleanType
12394       status;
12395
12396     MagickStatusType
12397       flags;
12398
12399     register ssize_t
12400       i;
12401
12402     ssize_t
12403       type;
12404
12405     struct PackageInfo
12406       *info,
12407       *package_info;
12408
12409     SV
12410       *perl_exception,
12411       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12412
12413     TypeMetric
12414       metrics;
12415
12416     PERL_UNUSED_VAR(ref);
12417     PERL_UNUSED_VAR(ix);
12418     exception=AcquireExceptionInfo();
12419     package_info=(struct PackageInfo *) NULL;
12420     perl_exception=newSVpv("",0);
12421     reference=SvRV(ST(0));
12422     av=(AV *) reference;
12423     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12424       exception);
12425     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12426     if (image == (Image *) NULL)
12427       {
12428         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12429           PackageName);
12430         goto PerlException;
12431       }
12432     package_info=ClonePackageInfo(info,exception);
12433     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12434     CloneString(&draw_info->text,"");
12435     current=draw_info->affine;
12436     GetAffineMatrix(&affine);
12437     x=0.0;
12438     y=0.0;
12439     EXTEND(sp,7*items);
12440     for (i=2; i < items; i+=2)
12441     {
12442       attribute=(char *) SvPV(ST(i-1),na);
12443       switch (*attribute)
12444       {
12445         case 'A':
12446         case 'a':
12447         {
12448           if (LocaleCompare(attribute,"antialias") == 0)
12449             {
12450               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12451                 SvPV(ST(i),na));
12452               if (type < 0)
12453                 {
12454                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12455                     SvPV(ST(i),na));
12456                   break;
12457                 }
12458               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12459               break;
12460             }
12461           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12462             attribute);
12463           break;
12464         }
12465         case 'd':
12466         case 'D':
12467         {
12468           if (LocaleCompare(attribute,"density") == 0)
12469             {
12470               CloneString(&draw_info->density,SvPV(ST(i),na));
12471               break;
12472             }
12473           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12474             attribute);
12475           break;
12476         }
12477         case 'e':
12478         case 'E':
12479         {
12480           if (LocaleCompare(attribute,"encoding") == 0)
12481             {
12482               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12483               break;
12484             }
12485           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12486             attribute);
12487           break;
12488         }
12489         case 'f':
12490         case 'F':
12491         {
12492           if (LocaleCompare(attribute,"family") == 0)
12493             {
12494               CloneString(&draw_info->family,SvPV(ST(i),na));
12495               break;
12496             }
12497           if (LocaleCompare(attribute,"fill") == 0)
12498             {
12499               if (info)
12500                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->fill,
12501                   &image->exception);
12502               break;
12503             }
12504           if (LocaleCompare(attribute,"font") == 0)
12505             {
12506               CloneString(&draw_info->font,SvPV(ST(i),na));
12507               break;
12508             }
12509           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12510             attribute);
12511           break;
12512         }
12513         case 'g':
12514         case 'G':
12515         {
12516           if (LocaleCompare(attribute,"geometry") == 0)
12517             {
12518               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12519               break;
12520             }
12521           if (LocaleCompare(attribute,"gravity") == 0)
12522             {
12523               draw_info->gravity=(GravityType) ParseCommandOption(
12524                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12525               break;
12526             }
12527           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12528             attribute);
12529           break;
12530         }
12531         case 'p':
12532         case 'P':
12533         {
12534           if (LocaleCompare(attribute,"pointsize") == 0)
12535             {
12536               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12537               draw_info->pointsize=geometry_info.rho;
12538               break;
12539             }
12540           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12541             attribute);
12542           break;
12543         }
12544         case 'r':
12545         case 'R':
12546         {
12547           if (LocaleCompare(attribute,"rotate") == 0)
12548             {
12549               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12550               affine.rx=geometry_info.rho;
12551               affine.ry=geometry_info.sigma;
12552               if ((flags & SigmaValue) == 0)
12553                 affine.ry=affine.rx;
12554               break;
12555             }
12556           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12557             attribute);
12558           break;
12559         }
12560         case 's':
12561         case 'S':
12562         {
12563           if (LocaleCompare(attribute,"scale") == 0)
12564             {
12565               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12566               affine.sx=geometry_info.rho;
12567               affine.sy=geometry_info.sigma;
12568               if ((flags & SigmaValue) == 0)
12569                 affine.sy=affine.sx;
12570               break;
12571             }
12572           if (LocaleCompare(attribute,"skew") == 0)
12573             {
12574               double
12575                 x_angle,
12576                 y_angle;
12577
12578               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12579               x_angle=geometry_info.rho;
12580               y_angle=geometry_info.sigma;
12581               if ((flags & SigmaValue) == 0)
12582                 y_angle=x_angle;
12583               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12584               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12585               break;
12586             }
12587           if (LocaleCompare(attribute,"stroke") == 0)
12588             {
12589               if (info)
12590                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->stroke,
12591                   &image->exception);
12592               break;
12593             }
12594           if (LocaleCompare(attribute,"style") == 0)
12595             {
12596               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12597                 SvPV(ST(i),na));
12598               if (type < 0)
12599                 {
12600                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12601                     SvPV(ST(i),na));
12602                   break;
12603                 }
12604               draw_info->style=(StyleType) type;
12605               break;
12606             }
12607           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12608             attribute);
12609           break;
12610         }
12611         case 't':
12612         case 'T':
12613         {
12614           if (LocaleCompare(attribute,"text") == 0)
12615             {
12616               CloneString(&draw_info->text,SvPV(ST(i),na));
12617               break;
12618             }
12619           if (LocaleCompare(attribute,"translate") == 0)
12620             {
12621               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12622               affine.tx=geometry_info.rho;
12623               affine.ty=geometry_info.sigma;
12624               if ((flags & SigmaValue) == 0)
12625                 affine.ty=affine.tx;
12626               break;
12627             }
12628           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12629             attribute);
12630           break;
12631         }
12632         case 'w':
12633         case 'W':
12634         {
12635           if (LocaleCompare(attribute,"weight") == 0)
12636             {
12637               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12638               draw_info->weight=(size_t) geometry_info.rho;
12639               break;
12640             }
12641           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12642             attribute);
12643           break;
12644         }
12645         case 'x':
12646         case 'X':
12647         {
12648           if (LocaleCompare(attribute,"x") == 0)
12649             {
12650               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12651               x=geometry_info.rho;
12652               break;
12653             }
12654           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12655             attribute);
12656           break;
12657         }
12658         case 'y':
12659         case 'Y':
12660         {
12661           if (LocaleCompare(attribute,"y") == 0)
12662             {
12663               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12664               y=geometry_info.rho;
12665               break;
12666             }
12667           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12668             attribute);
12669           break;
12670         }
12671         default:
12672         {
12673           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12674             attribute);
12675           break;
12676         }
12677       }
12678     }
12679     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12680     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12681     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12682     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12683     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12684     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12685     if (draw_info->geometry == (char *) NULL)
12686       {
12687         draw_info->geometry=AcquireString((char *) NULL);
12688         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12689           "%.15g,%.15g",x,y);
12690       }
12691     status=GetMultilineTypeMetrics(image,draw_info,&metrics);
12692     (void) CatchImageException(image);
12693     if (status == MagickFalse)
12694       PUSHs(&sv_undef);
12695     else
12696       {
12697         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12698         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12699         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12700         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12701         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12702         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12703         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12704         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12705         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12706         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12707         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12708         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12709         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12710       }
12711     draw_info=DestroyDrawInfo(draw_info);
12712
12713   PerlException:
12714     if (package_info != (struct PackageInfo *) NULL)
12715       DestroyPackageInfo(package_info);
12716     InheritPerlException(exception,perl_exception);
12717     exception=DestroyExceptionInfo(exception);
12718     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12719   }
12720 \f
12721 #
12722 ###############################################################################
12723 #                                                                             #
12724 #                                                                             #
12725 #                                                                             #
12726 #   Q u e r y F o r m a t                                                     #
12727 #                                                                             #
12728 #                                                                             #
12729 #                                                                             #
12730 ###############################################################################
12731 #
12732 #
12733 void
12734 QueryFormat(ref,...)
12735   Image::Magick ref=NO_INIT
12736   ALIAS:
12737     queryformat = 1
12738   PPCODE:
12739   {
12740     char
12741       *name;
12742
12743     ExceptionInfo
12744       *exception;
12745
12746     register ssize_t
12747       i;
12748
12749     SV
12750       *perl_exception;
12751
12752     volatile const MagickInfo
12753       *magick_info;
12754
12755     PERL_UNUSED_VAR(ref);
12756     PERL_UNUSED_VAR(ix);
12757     exception=AcquireExceptionInfo();
12758     perl_exception=newSVpv("",0);
12759     if (items == 1)
12760       {
12761         char
12762           format[MaxTextExtent];
12763
12764         const MagickInfo
12765           **format_list;
12766
12767         size_t
12768           types;
12769
12770         format_list=GetMagickInfoList("*",&types,exception);
12771         EXTEND(sp,types);
12772         for (i=0; i < (ssize_t) types; i++)
12773         {
12774           (void) CopyMagickString(format,format_list[i]->name,MaxTextExtent);
12775           LocaleLower(format);
12776           PUSHs(sv_2mortal(newSVpv(format,0)));
12777         }
12778         format_list=(const MagickInfo **)
12779           RelinquishMagickMemory((MagickInfo *) format_list);
12780         goto PerlException;
12781       }
12782     EXTEND(sp,8*items);
12783     for (i=1; i < items; i++)
12784     {
12785       name=(char *) SvPV(ST(i),na);
12786       magick_info=GetMagickInfo(name,exception);
12787       if (magick_info == (const MagickInfo *) NULL)
12788         {
12789           PUSHs(&sv_undef);
12790           continue;
12791         }
12792       PUSHs(sv_2mortal(newSViv(magick_info->adjoin)));
12793       PUSHs(sv_2mortal(newSViv(magick_info->blob_support)));
12794       PUSHs(sv_2mortal(newSViv(magick_info->raw)));
12795       PUSHs(sv_2mortal(newSViv((long) magick_info->decoder)));
12796       PUSHs(sv_2mortal(newSViv((long) magick_info->encoder)));
12797       if (magick_info->description == (char *) NULL)
12798         PUSHs(&sv_undef);
12799       else
12800         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
12801       if (magick_info->module == (char *) NULL)
12802         PUSHs(&sv_undef);
12803       else
12804         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
12805     }
12806
12807   PerlException:
12808     InheritPerlException(exception,perl_exception);
12809     exception=DestroyExceptionInfo(exception);
12810     SvREFCNT_dec(perl_exception);
12811   }
12812 \f
12813 #
12814 ###############################################################################
12815 #                                                                             #
12816 #                                                                             #
12817 #                                                                             #
12818 #   Q u e r y O p t i o n                                                     #
12819 #                                                                             #
12820 #                                                                             #
12821 #                                                                             #
12822 ###############################################################################
12823 #
12824 #
12825 void
12826 QueryOption(ref,...)
12827   Image::Magick ref=NO_INIT
12828   ALIAS:
12829     queryoption = 1
12830   PPCODE:
12831   {
12832     char
12833       **options;
12834
12835     ExceptionInfo
12836       *exception;
12837
12838     register ssize_t
12839       i;
12840
12841     ssize_t
12842       j,
12843       option;
12844
12845     SV
12846       *perl_exception;
12847
12848     PERL_UNUSED_VAR(ref);
12849     PERL_UNUSED_VAR(ix);
12850     exception=AcquireExceptionInfo();
12851     perl_exception=newSVpv("",0);
12852     EXTEND(sp,8*items);
12853     for (i=1; i < items; i++)
12854     {
12855       option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
12856         SvPV(ST(i),na));
12857       options=GetCommandOptions((CommandOption) option);
12858       if (options == (char **) NULL)
12859         PUSHs(&sv_undef);
12860       else
12861         {
12862           for (j=0; options[j] != (char *) NULL; j++)
12863             PUSHs(sv_2mortal(newSVpv(options[j],0)));
12864           options=DestroyStringList(options);
12865         }
12866     }
12867
12868     InheritPerlException(exception,perl_exception);
12869     exception=DestroyExceptionInfo(exception);
12870     SvREFCNT_dec(perl_exception);
12871   }
12872 \f
12873 #
12874 ###############################################################################
12875 #                                                                             #
12876 #                                                                             #
12877 #                                                                             #
12878 #   R e a d                                                                   #
12879 #                                                                             #
12880 #                                                                             #
12881 #                                                                             #
12882 ###############################################################################
12883 #
12884 #
12885 void
12886 Read(ref,...)
12887   Image::Magick ref=NO_INIT
12888   ALIAS:
12889     ReadImage  = 1
12890     read       = 2
12891     readimage  = 3
12892   PPCODE:
12893   {
12894     AV
12895       *av;
12896
12897     char
12898       **keep,
12899       **list;
12900
12901     ExceptionInfo
12902       *exception;
12903
12904     HV
12905       *hv;
12906
12907     Image
12908       *image;
12909
12910     int
12911       n;
12912
12913     MagickBooleanType
12914       status;
12915
12916     register char
12917       **p;
12918
12919     register ssize_t
12920       i;
12921
12922     ssize_t
12923       ac,
12924       number_images;
12925
12926     STRLEN
12927       *length;
12928
12929     struct PackageInfo
12930       *info,
12931       *package_info;
12932
12933     SV
12934       *perl_exception,  /* Perl variable for storing messages */
12935       *reference,
12936       *rv,
12937       *sv;
12938
12939     PERL_UNUSED_VAR(ref);
12940     PERL_UNUSED_VAR(ix);
12941     exception=AcquireExceptionInfo();
12942     perl_exception=newSVpv("",0);
12943     sv=NULL;
12944     package_info=(struct PackageInfo *) NULL;
12945     number_images=0;
12946     ac=(items < 2) ? 1 : items-1;
12947     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
12948     keep=list;
12949     length=(STRLEN *) NULL;
12950     if (list == (char **) NULL)
12951       {
12952         ThrowPerlException(exception,ResourceLimitError,
12953           "MemoryAllocationFailed",PackageName);
12954         goto PerlException;
12955       }
12956     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
12957     if (length == (STRLEN *) NULL)
12958       {
12959         ThrowPerlException(exception,ResourceLimitError,
12960           "MemoryAllocationFailed",PackageName);
12961         goto PerlException;
12962       }
12963     if (sv_isobject(ST(0)) == 0)
12964       {
12965         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12966           PackageName);
12967         goto PerlException;
12968       }
12969     reference=SvRV(ST(0));
12970     hv=SvSTASH(reference);
12971     if (SvTYPE(reference) != SVt_PVAV)
12972       {
12973         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12974           PackageName);
12975         goto PerlException;
12976       }
12977     av=(AV *) reference;
12978     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12979       exception);
12980     package_info=ClonePackageInfo(info,exception);
12981     n=1;
12982     if (items <= 1)
12983       *list=(char *) (*package_info->image_info->filename ?
12984         package_info->image_info->filename : "XC:black");
12985     else
12986       for (n=0, i=0; i < ac; i++)
12987       {
12988         list[n]=(char *) SvPV(ST(i+1),length[n]);
12989         if ((items >= 3) && strEQcase(list[n],"blob"))
12990           {
12991             void
12992               *blob;
12993
12994             i++;
12995             blob=(void *) (SvPV(ST(i+1),length[n]));
12996             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
12997           }
12998         if ((items >= 3) && strEQcase(list[n],"filename"))
12999           continue;
13000         if ((items >= 3) && strEQcase(list[n],"file"))
13001           {
13002             FILE
13003               *file;
13004
13005             PerlIO
13006               *io_info;
13007
13008             i++;
13009             io_info=IoIFP(sv_2io(ST(i+1)));
13010             if (io_info == (PerlIO *) NULL)
13011               {
13012                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13013                   PackageName);
13014                 continue;
13015               }
13016             file=PerlIO_findFILE(io_info);
13017             if (file == (FILE *) NULL)
13018               {
13019                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13020                   PackageName);
13021                 continue;
13022               }
13023             SetImageInfoFile(package_info->image_info,file);
13024           }
13025         if ((items >= 3) && strEQcase(list[n],"magick"))
13026           continue;
13027         n++;
13028       }
13029     list[n]=(char *) NULL;
13030     keep=list;
13031     status=ExpandFilenames(&n,&list);
13032     if (status == MagickFalse)
13033       {
13034         ThrowPerlException(exception,ResourceLimitError,
13035           "MemoryAllocationFailed",PackageName);
13036         goto PerlException;
13037       }
13038     number_images=0;
13039     for (i=0; i < n; i++)
13040     {
13041       if ((package_info->image_info->file != (FILE *) NULL) ||
13042           (package_info->image_info->blob != (void *) NULL))
13043         {
13044           image=ReadImages(package_info->image_info,exception);
13045           if (image != (Image *) NULL)
13046             DisassociateImageStream(image);
13047         }
13048       else
13049         {
13050           (void) CopyMagickString(package_info->image_info->filename,list[i],
13051             MaxTextExtent);
13052           image=ReadImages(package_info->image_info,exception);
13053         }
13054       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
13055         break;
13056       for ( ; image; image=image->next)
13057       {
13058         AddImageToRegistry(sv,image);
13059         rv=newRV(sv);
13060         av_push(av,sv_bless(rv,hv));
13061         SvREFCNT_dec(sv);
13062         number_images++;
13063       }
13064     }
13065     /*
13066       Free resources.
13067     */
13068     for (i=0; i < n; i++)
13069       if (list[i] != (char *) NULL)
13070         for (p=keep; list[i] != *p++; )
13071           if (*p == (char *) NULL)
13072             {
13073               list[i]=(char *) RelinquishMagickMemory(list[i]);
13074               break;
13075             }
13076
13077   PerlException:
13078     if (package_info != (struct PackageInfo *) NULL)
13079       DestroyPackageInfo(package_info);
13080     if (list && (list != keep))
13081       list=(char **) RelinquishMagickMemory(list);
13082     if (keep)
13083       keep=(char **) RelinquishMagickMemory(keep);
13084     if (length)
13085       length=(STRLEN *) RelinquishMagickMemory(length);
13086     InheritPerlException(exception,perl_exception);
13087     exception=DestroyExceptionInfo(exception);
13088     sv_setiv(perl_exception,(IV) number_images);
13089     SvPOK_on(perl_exception);
13090     ST(0)=sv_2mortal(perl_exception);
13091     XSRETURN(1);
13092   }
13093 \f
13094 #
13095 ###############################################################################
13096 #                                                                             #
13097 #                                                                             #
13098 #                                                                             #
13099 #   R e m o t e                                                               #
13100 #                                                                             #
13101 #                                                                             #
13102 #                                                                             #
13103 ###############################################################################
13104 #
13105 #
13106 void
13107 Remote(ref,...)
13108   Image::Magick ref=NO_INIT
13109   ALIAS:
13110     RemoteCommand  = 1
13111     remote         = 2
13112     remoteCommand  = 3
13113   PPCODE:
13114   {
13115     AV
13116       *av;
13117
13118     ExceptionInfo
13119       *exception;
13120
13121     register ssize_t
13122       i;
13123
13124     SV
13125       *perl_exception,
13126       *reference;
13127
13128     struct PackageInfo
13129       *info;
13130
13131     PERL_UNUSED_VAR(ref);
13132     PERL_UNUSED_VAR(ix);
13133     exception=AcquireExceptionInfo();
13134     perl_exception=newSVpv("",0);
13135     reference=SvRV(ST(0));
13136     av=(AV *) reference;
13137     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13138       exception);
13139     for (i=1; i < items; i++)
13140       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13141         SvPV(ST(i),na),exception);
13142     InheritPerlException(exception,perl_exception);
13143     exception=DestroyExceptionInfo(exception);
13144     SvREFCNT_dec(perl_exception);    /* throw away all errors */
13145   }
13146 \f
13147 #
13148 ###############################################################################
13149 #                                                                             #
13150 #                                                                             #
13151 #                                                                             #
13152 #   S e t                                                                     #
13153 #                                                                             #
13154 #                                                                             #
13155 #                                                                             #
13156 ###############################################################################
13157 #
13158 #
13159 void
13160 Set(ref,...)
13161   Image::Magick ref=NO_INIT
13162   ALIAS:
13163     SetAttributes  = 1
13164     SetAttribute   = 2
13165     set            = 3
13166     setattributes  = 4
13167     setattribute   = 5
13168   PPCODE:
13169   {
13170     ExceptionInfo
13171       *exception;
13172
13173     Image
13174       *image;
13175
13176     register ssize_t
13177       i;
13178
13179     struct PackageInfo
13180       *info;
13181
13182     SV
13183       *perl_exception,
13184       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13185
13186     PERL_UNUSED_VAR(ref);
13187     PERL_UNUSED_VAR(ix);
13188     exception=AcquireExceptionInfo();
13189     perl_exception=newSVpv("",0);
13190     if (sv_isobject(ST(0)) == 0)
13191       {
13192         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13193           PackageName);
13194         goto PerlException;
13195       }
13196     reference=SvRV(ST(0));
13197     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13198     if (items == 2)
13199       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13200     else
13201       for (i=2; i < items; i+=2)
13202         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13203
13204   PerlException:
13205     InheritPerlException(exception,perl_exception);
13206     exception=DestroyExceptionInfo(exception);
13207     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13208     SvPOK_on(perl_exception);
13209     ST(0)=sv_2mortal(perl_exception);
13210     XSRETURN(1);
13211   }
13212 \f
13213 #
13214 ###############################################################################
13215 #                                                                             #
13216 #                                                                             #
13217 #                                                                             #
13218 #   S e t P i x e l                                                           #
13219 #                                                                             #
13220 #                                                                             #
13221 #                                                                             #
13222 ###############################################################################
13223 #
13224 #
13225 void
13226 SetPixel(ref,...)
13227   Image::Magick ref=NO_INIT
13228   ALIAS:
13229     setpixel = 1
13230     setPixel = 2
13231   PPCODE:
13232   {
13233     AV
13234       *av;
13235
13236     char
13237       *attribute;
13238
13239     ChannelType
13240       channel,
13241       channel_mask;
13242
13243     ExceptionInfo
13244       *exception;
13245
13246     Image
13247       *image;
13248
13249     MagickBooleanType
13250       normalize;
13251
13252     RectangleInfo
13253       region;
13254
13255     register ssize_t
13256       i;
13257
13258     register Quantum
13259       *q;
13260
13261     ssize_t
13262       option;
13263
13264     struct PackageInfo
13265       *info;
13266
13267     SV
13268       *perl_exception,
13269       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13270
13271     PERL_UNUSED_VAR(ref);
13272     PERL_UNUSED_VAR(ix);
13273     exception=AcquireExceptionInfo();
13274     perl_exception=newSVpv("",0);
13275     reference=SvRV(ST(0));
13276     av=(AV *) reference;
13277     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13278       exception);
13279     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13280     if (image == (Image *) NULL)
13281       {
13282         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13283           PackageName);
13284         goto PerlException;
13285       }
13286     av=(AV *) NULL;
13287     normalize=MagickTrue;
13288     region.x=0;
13289     region.y=0;
13290     region.width=image->columns;
13291     region.height=1;
13292     if (items == 1)
13293       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13294     channel=DefaultChannels;
13295     for (i=2; i < items; i+=2)
13296     {
13297       attribute=(char *) SvPV(ST(i-1),na);
13298       switch (*attribute)
13299       {
13300         case 'C':
13301         case 'c':
13302         {
13303           if (LocaleCompare(attribute,"channel") == 0)
13304             {
13305               ssize_t
13306                 option;
13307
13308               option=ParseChannelOption(SvPV(ST(i),na));
13309               if (option < 0)
13310                 {
13311                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13312                     SvPV(ST(i),na));
13313                   return;
13314                 }
13315               channel=(ChannelType) option;
13316               break;
13317             }
13318           if (LocaleCompare(attribute,"color") == 0)
13319             {
13320               if (SvTYPE(ST(i)) != SVt_RV)
13321                 {
13322                   char
13323                     message[MaxTextExtent];
13324
13325                   (void) FormatLocaleString(message,MaxTextExtent,
13326                     "invalid %.60s value",attribute);
13327                   ThrowPerlException(exception,OptionError,message,
13328                     SvPV(ST(i),na));
13329                 }
13330               av=(AV *) SvRV(ST(i));
13331               break;
13332             }
13333           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13334             attribute);
13335           break;
13336         }
13337         case 'g':
13338         case 'G':
13339         {
13340           if (LocaleCompare(attribute,"geometry") == 0)
13341             {
13342               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
13343               break;
13344             }
13345           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13346             attribute);
13347           break;
13348         }
13349         case 'N':
13350         case 'n':
13351         {
13352           if (LocaleCompare(attribute,"normalize") == 0)
13353             {
13354               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13355                 SvPV(ST(i),na));
13356               if (option < 0)
13357                 {
13358                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13359                     SvPV(ST(i),na));
13360                   break;
13361                 }
13362              normalize=option != 0 ? MagickTrue : MagickFalse;
13363              break;
13364             }
13365           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13366             attribute);
13367           break;
13368         }
13369         case 'x':
13370         case 'X':
13371         {
13372           if (LocaleCompare(attribute,"x") == 0)
13373             {
13374               region.x=SvIV(ST(i));
13375               break;
13376             }
13377           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13378             attribute);
13379           break;
13380         }
13381         case 'y':
13382         case 'Y':
13383         {
13384           if (LocaleCompare(attribute,"y") == 0)
13385             {
13386               region.y=SvIV(ST(i));
13387               break;
13388             }
13389           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13390             attribute);
13391           break;
13392         }
13393         default:
13394         {
13395           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13396             attribute);
13397           break;
13398         }
13399       }
13400     }
13401     (void) SetImageStorageClass(image,DirectClass,exception);
13402     channel_mask=SetPixelChannelMask(image,channel);
13403     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
13404     if ((q == (const Quantum *) NULL) || (av == (AV *) NULL) ||
13405         (SvTYPE(av) != SVt_PVAV))
13406       PUSHs(&sv_undef);
13407     else
13408       {
13409         double
13410           scale;
13411
13412         register ssize_t
13413           i;
13414
13415         i=0;
13416         scale=1.0;
13417         if (normalize != MagickFalse)
13418           scale=QuantumRange;
13419         if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
13420             (i <= av_len(av)))
13421           {
13422             SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
13423               av_fetch(av,i,0)))),q);
13424             i++;
13425           }
13426         if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
13427             (i <= av_len(av)))
13428           {
13429             SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
13430               av_fetch(av,i,0)))),q);
13431             i++;
13432           }
13433         if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
13434             (i <= av_len(av)))
13435           {
13436             SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
13437               av_fetch(av,i,0)))),q);
13438             i++;
13439           }
13440         if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
13441             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
13442           {
13443             SetPixelBlack(image,ClampToQuantum(scale*
13444               SvNV(*(av_fetch(av,i,0)))),q);
13445             i++;
13446           }
13447         if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
13448             (i <= av_len(av)))
13449           {
13450             SetPixelAlpha(image,ClampToQuantum(scale*
13451               SvNV(*(av_fetch(av,i,0)))),q);
13452             i++;
13453           }
13454         (void) SyncAuthenticPixels(image,exception);
13455       }
13456     (void) SetPixelChannelMask(image,channel_mask);
13457
13458   PerlException:
13459     InheritPerlException(exception,perl_exception);
13460     exception=DestroyExceptionInfo(exception);
13461     SvREFCNT_dec(perl_exception);
13462   }
13463 \f
13464 #
13465 ###############################################################################
13466 #                                                                             #
13467 #                                                                             #
13468 #                                                                             #
13469 #   S m u s h                                                                 #
13470 #                                                                             #
13471 #                                                                             #
13472 #                                                                             #
13473 ###############################################################################
13474 #
13475 #
13476 void
13477 Smush(ref,...)
13478   Image::Magick ref=NO_INIT
13479   ALIAS:
13480     SmushImage  = 1
13481     smush       = 2
13482     smushimage  = 3
13483   PPCODE:
13484   {
13485     AV
13486       *av;
13487
13488     char
13489       *attribute;
13490
13491     ExceptionInfo
13492       *exception;
13493
13494     HV
13495       *hv;
13496
13497     Image
13498       *image;
13499
13500     register ssize_t
13501       i;
13502
13503     ssize_t
13504       offset,
13505       stack;
13506
13507     struct PackageInfo
13508       *info;
13509
13510     SV
13511       *av_reference,
13512       *perl_exception,
13513       *reference,
13514       *rv,
13515       *sv;
13516
13517     PERL_UNUSED_VAR(ref);
13518     PERL_UNUSED_VAR(ix);
13519     exception=AcquireExceptionInfo();
13520     perl_exception=newSVpv("",0);
13521     sv=NULL;
13522     attribute=NULL;
13523     av=NULL;
13524     if (sv_isobject(ST(0)) == 0)
13525       {
13526         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13527           PackageName);
13528         goto PerlException;
13529       }
13530     reference=SvRV(ST(0));
13531     hv=SvSTASH(reference);
13532     av=newAV();
13533     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13534     SvREFCNT_dec(av);
13535     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13536     if (image == (Image *) NULL)
13537       {
13538         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13539           PackageName);
13540         goto PerlException;
13541       }
13542     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13543     /*
13544       Get options.
13545     */
13546     offset=0;
13547     stack=MagickTrue;
13548     for (i=2; i < items; i+=2)
13549     {
13550       attribute=(char *) SvPV(ST(i-1),na);
13551       switch (*attribute)
13552       {
13553         case 'O':
13554         case 'o':
13555         {
13556           if (LocaleCompare(attribute,"offset") == 0)
13557             {
13558               offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
13559               break;
13560             }
13561           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13562             attribute);
13563           break;
13564         }
13565         case 'S':
13566         case 's':
13567         {
13568           if (LocaleCompare(attribute,"stack") == 0)
13569             {
13570               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13571                 SvPV(ST(i),na));
13572               if (stack < 0)
13573                 {
13574                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13575                     SvPV(ST(i),na));
13576                   return;
13577                 }
13578               break;
13579             }
13580           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13581             attribute);
13582           break;
13583         }
13584         default:
13585         {
13586           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13587             attribute);
13588           break;
13589         }
13590       }
13591     }
13592     image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
13593       exception);
13594     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
13595       goto PerlException;
13596     for ( ; image; image=image->next)
13597     {
13598       AddImageToRegistry(sv,image);
13599       rv=newRV(sv);
13600       av_push(av,sv_bless(rv,hv));
13601       SvREFCNT_dec(sv);
13602     }
13603     exception=DestroyExceptionInfo(exception);
13604     ST(0)=av_reference;
13605     SvREFCNT_dec(perl_exception);
13606     XSRETURN(1);
13607
13608   PerlException:
13609     InheritPerlException(exception,perl_exception);
13610     exception=DestroyExceptionInfo(exception);
13611     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
13612     SvPOK_on(perl_exception);
13613     ST(0)=sv_2mortal(perl_exception);
13614     XSRETURN(1);
13615   }
13616 \f
13617 #
13618 ###############################################################################
13619 #                                                                             #
13620 #                                                                             #
13621 #                                                                             #
13622 #   S t a t i s t i c s                                                       #
13623 #                                                                             #
13624 #                                                                             #
13625 #                                                                             #
13626 ###############################################################################
13627 #
13628 #
13629 void
13630 Statistics(ref,...)
13631   Image::Magick ref=NO_INIT
13632   ALIAS:
13633     StatisticsImage = 1
13634     statistics      = 2
13635     statisticsimage = 3
13636   PPCODE:
13637   {
13638 #define ChannelStatistics(channel) \
13639 { \
13640   (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
13641     (double) channel_statistics[channel].depth); \
13642   PUSHs(sv_2mortal(newSVpv(message,0))); \
13643   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13644     channel_statistics[channel].minima/scale); \
13645   PUSHs(sv_2mortal(newSVpv(message,0))); \
13646   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13647     channel_statistics[channel].maxima/scale); \
13648   PUSHs(sv_2mortal(newSVpv(message,0))); \
13649   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13650     channel_statistics[channel].mean/scale); \
13651   PUSHs(sv_2mortal(newSVpv(message,0))); \
13652   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13653     channel_statistics[channel].standard_deviation/scale); \
13654   PUSHs(sv_2mortal(newSVpv(message,0))); \
13655   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13656     channel_statistics[channel].kurtosis); \
13657   PUSHs(sv_2mortal(newSVpv(message,0))); \
13658   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13659     channel_statistics[channel].skewness); \
13660   PUSHs(sv_2mortal(newSVpv(message,0))); \
13661 }
13662
13663     AV
13664       *av;
13665
13666     char
13667       message[MaxTextExtent];
13668
13669     ChannelStatistics
13670       *channel_statistics;
13671
13672     double
13673       scale;
13674
13675     ExceptionInfo
13676       *exception;
13677
13678     Image
13679       *image;
13680
13681     ssize_t
13682       count;
13683
13684     struct PackageInfo
13685       *info;
13686
13687     SV
13688       *perl_exception,
13689       *reference;
13690
13691     PERL_UNUSED_VAR(ref);
13692     PERL_UNUSED_VAR(ix);
13693     exception=AcquireExceptionInfo();
13694     perl_exception=newSVpv("",0);
13695     av=NULL;
13696     if (sv_isobject(ST(0)) == 0)
13697       {
13698         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13699           PackageName);
13700         goto PerlException;
13701       }
13702     reference=SvRV(ST(0));
13703     av=newAV();
13704     SvREFCNT_dec(av);
13705     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13706     if (image == (Image *) NULL)
13707       {
13708         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13709           PackageName);
13710         goto PerlException;
13711       }
13712     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13713     count=0;
13714     for ( ; image; image=image->next)
13715     {
13716       channel_statistics=GetImageStatistics(image,&image->exception);
13717       if (channel_statistics == (ChannelStatistics *) NULL)
13718         continue;
13719       count++;
13720       EXTEND(sp,35*count);
13721       scale=(double) QuantumRange;
13722       ChannelStatistics(RedChannel);
13723       ChannelStatistics(GreenChannel);
13724       ChannelStatistics(BlueChannel);
13725       if (image->colorspace == CMYKColorspace)
13726         ChannelStatistics(BlackChannel);
13727       if (image->matte != MagickFalse)
13728         ChannelStatistics(AlphaChannel);
13729       channel_statistics=(ChannelStatistics *)
13730         RelinquishMagickMemory(channel_statistics);
13731     }
13732
13733   PerlException:
13734     InheritPerlException(exception,perl_exception);
13735     exception=DestroyExceptionInfo(exception);
13736     SvREFCNT_dec(perl_exception);
13737   }
13738 \f
13739 #
13740 ###############################################################################
13741 #                                                                             #
13742 #                                                                             #
13743 #                                                                             #
13744 #   S y n c A u t h e n t i c P i x e l s                                     #
13745 #                                                                             #
13746 #                                                                             #
13747 #                                                                             #
13748 ###############################################################################
13749 #
13750 #
13751 void
13752 SyncAuthenticPixels(ref,...)
13753   Image::Magick ref = NO_INIT
13754   ALIAS:
13755     Syncauthenticpixels = 1
13756     SyncImagePixels = 2
13757     syncimagepixels = 3
13758   CODE:
13759   {
13760     ExceptionInfo
13761       *exception;
13762
13763     Image
13764       *image;
13765
13766     MagickBooleanType
13767       status;
13768
13769     struct PackageInfo
13770       *info;
13771
13772     SV
13773       *perl_exception,
13774       *reference;
13775
13776     PERL_UNUSED_VAR(ref);
13777     PERL_UNUSED_VAR(ix);
13778     exception=AcquireExceptionInfo();
13779     perl_exception=newSVpv("",0);
13780     if (sv_isobject(ST(0)) == 0)
13781       {
13782         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13783           PackageName);
13784         goto PerlException;
13785       }
13786
13787     reference=SvRV(ST(0));
13788     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13789     if (image == (Image *) NULL)
13790       {
13791         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13792           PackageName);
13793         goto PerlException;
13794       }
13795
13796     status=SyncAuthenticPixels(image,exception);
13797     if (status != MagickFalse)
13798       return;
13799     InheritException(exception,&image->exception);
13800
13801   PerlException:
13802     InheritPerlException(exception,perl_exception);
13803     exception=DestroyExceptionInfo(exception);
13804     SvREFCNT_dec(perl_exception);  /* throw away all errors */
13805   }
13806 \f
13807 #
13808 ###############################################################################
13809 #                                                                             #
13810 #                                                                             #
13811 #                                                                             #
13812 #   T r a n s f o r m                                                         #
13813 #                                                                             #
13814 #                                                                             #
13815 #                                                                             #
13816 ###############################################################################
13817 #
13818 #
13819 void
13820 Transform(ref,...)
13821   Image::Magick ref=NO_INIT
13822   ALIAS:
13823     TransformImage = 1
13824     transform      = 2
13825     transformimage = 3
13826   PPCODE:
13827   {
13828     AV
13829       *av;
13830
13831     char
13832       *attribute,
13833       *crop_geometry,
13834       *geometry;
13835
13836     ExceptionInfo
13837       *exception;
13838
13839     HV
13840       *hv;
13841
13842     Image
13843       *clone,
13844       *image;
13845
13846     register ssize_t
13847       i;
13848
13849     struct PackageInfo
13850       *info;
13851
13852     SV
13853       *av_reference,
13854       *perl_exception,
13855       *reference,
13856       *rv,
13857       *sv;
13858
13859     PERL_UNUSED_VAR(ref);
13860     PERL_UNUSED_VAR(ix);
13861     exception=AcquireExceptionInfo();
13862     perl_exception=newSVpv("",0);
13863     sv=NULL;
13864     av=NULL;
13865     attribute=NULL;
13866     if (sv_isobject(ST(0)) == 0)
13867       {
13868         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13869           PackageName);
13870         goto PerlException;
13871       }
13872     reference=SvRV(ST(0));
13873     hv=SvSTASH(reference);
13874     av=newAV();
13875     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13876     SvREFCNT_dec(av);
13877     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13878     if (image == (Image *) NULL)
13879       {
13880         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13881           PackageName);
13882         goto PerlException;
13883       }
13884     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13885     /*
13886       Get attribute.
13887     */
13888     crop_geometry=(char *) NULL;
13889     geometry=(char *) NULL;
13890     for (i=2; i < items; i+=2)
13891     {
13892       attribute=(char *) SvPV(ST(i-1),na);
13893       switch (*attribute)
13894       {
13895         case 'c':
13896         case 'C':
13897         {
13898           if (LocaleCompare(attribute,"crop") == 0)
13899             {
13900               crop_geometry=SvPV(ST(i),na);
13901               break;
13902             }
13903           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13904             attribute);
13905           break;
13906         }
13907         case 'g':
13908         case 'G':
13909         {
13910           if (LocaleCompare(attribute,"geometry") == 0)
13911             {
13912               geometry=SvPV(ST(i),na);
13913               break;
13914             }
13915          if (LocaleCompare(attribute,"gravity") == 0)
13916            {
13917              Image
13918                *next;
13919
13920              ssize_t
13921                in;
13922
13923              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
13924                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13925              if (in < 0)
13926                {
13927                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
13928                    SvPV(ST(i),na));
13929                  return;
13930                }
13931              for (next=image; next; next=next->next)
13932                next->gravity=(GravityType) in;
13933              break;
13934            }
13935           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13936             attribute);
13937           break;
13938         }
13939         default:
13940         {
13941           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13942             attribute);
13943           break;
13944         }
13945       }
13946     }
13947     for ( ; image; image=image->next)
13948     {
13949       clone=CloneImage(image,0,0,MagickTrue,exception);
13950       if ((clone == (Image *) NULL) || (exception->severity >= ErrorException))
13951         goto PerlException;
13952       TransformImage(&clone,crop_geometry,geometry);
13953       for ( ; clone; clone=clone->next)
13954       {
13955         AddImageToRegistry(sv,clone);
13956         rv=newRV(sv);
13957         av_push(av,sv_bless(rv,hv));
13958         SvREFCNT_dec(sv);
13959       }
13960     }
13961     exception=DestroyExceptionInfo(exception);
13962     ST(0)=av_reference;
13963     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13964     XSRETURN(1);
13965
13966   PerlException:
13967     InheritPerlException(exception,perl_exception);
13968     exception=DestroyExceptionInfo(exception);
13969     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
13970     SvPOK_on(perl_exception);
13971     ST(0)=sv_2mortal(perl_exception);
13972     XSRETURN(1);
13973   }
13974 \f
13975 #
13976 ###############################################################################
13977 #                                                                             #
13978 #                                                                             #
13979 #                                                                             #
13980 #   W r i t e                                                                 #
13981 #                                                                             #
13982 #                                                                             #
13983 #                                                                             #
13984 ###############################################################################
13985 #
13986 #
13987 void
13988 Write(ref,...)
13989   Image::Magick ref=NO_INIT
13990   ALIAS:
13991     WriteImage    = 1
13992     write         = 2
13993     writeimage    = 3
13994   PPCODE:
13995   {
13996     char
13997       filename[MaxTextExtent];
13998
13999     ExceptionInfo
14000       *exception;
14001
14002     Image
14003       *image,
14004       *next;
14005
14006     register ssize_t
14007       i;
14008
14009     ssize_t
14010       number_images,
14011       scene;
14012
14013     struct PackageInfo
14014       *info,
14015       *package_info;
14016
14017     SV
14018       *perl_exception,
14019       *reference;
14020
14021     PERL_UNUSED_VAR(ref);
14022     PERL_UNUSED_VAR(ix);
14023     exception=AcquireExceptionInfo();
14024     perl_exception=newSVpv("",0);
14025     number_images=0;
14026     package_info=(struct PackageInfo *) NULL;
14027     if (sv_isobject(ST(0)) == 0)
14028       {
14029         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14030           PackageName);
14031         goto PerlException;
14032       }
14033     reference=SvRV(ST(0));
14034     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14035     if (image == (Image *) NULL)
14036       {
14037         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14038           PackageName);
14039         goto PerlException;
14040       }
14041     package_info=ClonePackageInfo(info,exception);
14042     if (items == 2)
14043       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14044     else
14045       if (items > 2)
14046         for (i=2; i < items; i+=2)
14047           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14048             exception);
14049     (void) CopyMagickString(filename,package_info->image_info->filename,
14050       MaxTextExtent);
14051     scene=0;
14052     for (next=image; next; next=next->next)
14053     {
14054       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
14055       next->scene=scene++;
14056     }
14057     SetImageInfo(package_info->image_info,(unsigned int)
14058       GetImageListLength(image),&image->exception);
14059     for (next=image; next; next=next->next)
14060     {
14061       (void) WriteImage(package_info->image_info,next);
14062       if (next->exception.severity >= ErrorException)
14063         InheritException(exception,&next->exception);
14064       GetImageException(next,exception);
14065       number_images++;
14066       if (package_info->image_info->adjoin)
14067         break;
14068     }
14069
14070   PerlException:
14071     if (package_info != (struct PackageInfo *) NULL)
14072       DestroyPackageInfo(package_info);
14073     InheritPerlException(exception,perl_exception);
14074     exception=DestroyExceptionInfo(exception);
14075     sv_setiv(perl_exception,(IV) number_images);
14076     SvPOK_on(perl_exception);
14077     ST(0)=sv_2mortal(perl_exception);
14078     XSRETURN(1);
14079   }