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