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