]> granicus.if.org Git - imagemagick/blob - PerlMagick/Magick.xs
(no commit message)
[imagemagick] / PerlMagick / Magick.xs
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                         PPPP   EEEEE  RRRR   L                              %
6 %                         P   P  E      R   R  L                              %
7 %                         PPPP   EEE    RRRR   L                              %
8 %                         P      E      R  R   L                              %
9 %                         P      EEEEE  R   R  LLLLL                          %
10 %                                                                             %
11 %                  M   M   AAA    GGGG  IIIII   CCCC  K   K                   %
12 %                  MM MM  A   A  G        I    C      K  K                    %
13 %                  M M M  AAAAA  G GGG    I    C      KKK                     %
14 %                  M   M  A   A  G   G    I    C      K  K                    %
15 %                  M   M  A   A   GGGG  IIIII   CCCC  K   K                   %
16 %                                                                             %
17 %                                                                             %
18 %                Object-oriented Perl interface to ImageMagick                %
19 %                                                                             %
20 %                            Software Design                                  %
21 %                              Kyle Shorter                                   %
22 %                              John Cristy                                    %
23 %                             February 1997                                   %
24 %                                                                             %
25 %                                                                             %
26 %  Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization      %
27 %  dedicated to making software imaging solutions freely available.           %
28 %                                                                             %
29 %  You may not use this file except in compliance with the License.  You may  %
30 %  obtain a copy of the License at                                            %
31 %                                                                             %
32 %    http://www.imagemagick.org/script/license.php                            %
33 %                                                                             %
34 %  Unless required by applicable law or agreed to in writing, software        %
35 %  distributed under the License is distributed on an "AS IS" BASIS,          %
36 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
37 %  See the License for the specific language governing permissions and        %
38 %  limitations under the License.                                             %
39 %                                                                             %
40 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
41 %
42 %  PerlMagick is an objected-oriented Perl interface to ImageMagick.  Use
43 %  the module to read, manipulate, or write an image or image sequence from
44 %  within a Perl script.  This makes PerlMagick suitable for Web CGI scripts.
45 %
46 */
47 \f
48 /*
49   Include declarations.
50 */
51 #if !defined(WIN32)
52 #define MagickExport
53 #endif
54
55 #if defined(__cplusplus) || defined(c_plusplus)
56 extern "C" {
57 #endif
58
59 #define PERL_NO_GET_CONTEXT
60 #include "EXTERN.h"
61 #include "perl.h"
62 #include "XSUB.h"
63 #include <math.h>
64 #include <MagickCore/MagickCore.h>
65 #undef tainted
66
67 #if defined(__cplusplus) || defined(c_plusplus)
68 }
69 #endif
70 \f
71 /*
72   Define declarations.
73 */
74 #ifndef aTHX_
75 #define aTHX_
76 #define pTHX_
77 #define dTHX
78 #endif
79 #define DegreesToRadians(x)  (MagickPI*(x)/180.0)
80 #define EndOf(array)  (&array[NumberOf(array)])
81 #define MaxArguments  33
82 #ifndef na
83 #define na  PL_na
84 #endif
85 #define NumberOf(array)  (sizeof(array)/sizeof(*array))
86 #define PackageName   "Image::Magick"
87 #if PERL_VERSION <= 6
88 #define PerlIO  FILE
89 #define PerlIO_importFILE(f, fl)  (f)
90 #define PerlIO_findFILE(f)  NULL
91 #endif
92 #ifndef sv_undef
93 #define sv_undef  PL_sv_undef
94 #endif
95
96 #define AddImageToRegistry(sv,image) \
97 { \
98   if (magick_registry != (SplayTreeInfo *) NULL) \
99     { \
100       (void) AddValueToSplayTree(magick_registry,image,image); \
101       (sv)=newSViv((IV) image); \
102     } \
103 }
104
105 #define DeleteImageFromRegistry(reference,image) \
106 { \
107   if (magick_registry != (SplayTreeInfo *) NULL) \
108     { \
109       if (GetImageReferenceCount(image) == 1) \
110        (void) DeleteNodeByValueFromSplayTree(magick_registry,image); \
111       image=DestroyImage(image); \
112       sv_setiv(reference,0); \
113     } \
114 }
115
116 #define InheritPerlException(exception,perl_exception) \
117 { \
118   char \
119     message[MaxTextExtent]; \
120  \
121   if ((exception)->severity != UndefinedException) \
122     { \
123       (void) FormatLocaleString(message,MaxTextExtent,"Exception %d: %s%s%s%s",\
124         (exception)->severity, (exception)->reason ? \
125         GetLocaleExceptionMessage((exception)->severity,(exception)->reason) : \
126         "Unknown", (exception)->description ? " (" : "", \
127         (exception)->description ? GetLocaleExceptionMessage( \
128         (exception)->severity,(exception)->description) : "", \
129         (exception)->description ? ")" : ""); \
130       if ((perl_exception) != (SV *) NULL) \
131         { \
132           if (SvCUR(perl_exception)) \
133             sv_catpv(perl_exception,"\n"); \
134           sv_catpv(perl_exception,message); \
135         } \
136     } \
137 }
138
139 #define ThrowPerlException(exception,severity,tag,reason) \
140   (void) ThrowMagickException(exception,GetMagickModule(),severity, \
141     tag,"`%s'",reason); \
142 \f
143 /*
144   Typedef and structure declarations.
145 */
146 typedef enum
147 {
148   ArrayReference = (~0),
149   RealReference = (~0)-1,
150   FileReference = (~0)-2,
151   ImageReference = (~0)-3,
152   IntegerReference = (~0)-4,
153   StringReference = (~0)-5
154 } MagickReference;
155
156 typedef struct _Arguments
157 {
158   const char
159     *method;
160
161   ssize_t
162     type;
163 } Arguments;
164
165 struct ArgumentList
166 {
167   ssize_t
168     integer_reference;
169
170   MagickRealType
171     real_reference;
172
173   const char
174     *string_reference;
175
176   Image
177     *image_reference;
178
179   SV
180     *array_reference;
181
182   FILE
183     *file_reference;
184
185   size_t
186     length;
187 };
188
189 struct PackageInfo
190 {
191   ImageInfo
192     *image_info;
193 };
194
195 typedef void
196   *Image__Magick;  /* data type for the Image::Magick package */
197 \f
198 /*
199   Static declarations.
200 */
201 static struct
202   Methods
203   {
204     const char
205       *name;
206
207     Arguments
208       arguments[MaxArguments];
209   } Methods[] =
210   {
211     { "Comment", { {"comment", StringReference} } },
212     { "Label", { {"label", StringReference} } },
213     { "AddNoise", { {"noise", MagickNoiseOptions},
214       {"channel", MagickChannelOptions} } },
215     { "Colorize", { {"fill", StringReference}, {"opacity", StringReference} } },
216     { "Border", { {"geometry", StringReference}, {"width", IntegerReference},
217       {"height", IntegerReference}, {"fill", StringReference},
218       {"bordercolor", StringReference}, {"color", StringReference},
219       {"compose", MagickComposeOptions} } },
220     { "Blur", { {"geometry", StringReference}, {"radius", RealReference},
221       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
222     { "Chop", { {"geometry", StringReference}, {"width", IntegerReference},
223       {"height", IntegerReference}, {"x", IntegerReference},
224       {"y", IntegerReference} } },
225     { "Crop", { {"geometry", StringReference}, {"width", IntegerReference},
226       {"height", IntegerReference}, {"x", IntegerReference},
227       {"y", IntegerReference}, {"fuzz", StringReference},
228       {"gravity", MagickGravityOptions} } },
229     { "Despeckle", },
230     { "Edge", { {"radius", RealReference} } },
231     { "Emboss", { {"geometry", StringReference}, {"radius", RealReference},
232       {"sigma", RealReference} } },
233     { "Enhance", },
234     { "Flip", },
235     { "Flop", },
236     { "Frame", { {"geometry", StringReference}, {"width", IntegerReference},
237       {"height", IntegerReference}, {"inner", IntegerReference},
238       {"outer", IntegerReference}, {"fill", StringReference},
239       {"color", StringReference}, {"compose", MagickComposeOptions} } },
240     { "Implode", { {"amount", RealReference},
241       {"interpolate", MagickInterpolateOptions} } },
242     { "Magnify", },
243     { "MedianFilter", { {"geometry", StringReference},
244       {"width", IntegerReference},{"height", IntegerReference},
245       {"channel", MagickChannelOptions} } },
246     { "Minify", },
247     { "OilPaint", { {"radius", RealReference} } },
248     { "ReduceNoise", { {"geometry", StringReference},
249       {"width", IntegerReference},{"height", IntegerReference},
250       {"channel", MagickChannelOptions} } },
251     { "Roll", { {"geometry", StringReference}, {"x", IntegerReference},
252       {"y", IntegerReference} } },
253     { "Rotate", { {"degrees", RealReference}, {"fill", StringReference},
254       {"color", StringReference}, {"background", StringReference} } },
255     { "Sample", { {"geometry", StringReference}, {"width", IntegerReference},
256       {"height", IntegerReference} } },
257     { "Scale", { {"geometry", StringReference}, {"width", IntegerReference},
258       {"height", IntegerReference} } },
259     { "Shade", { {"geometry", StringReference}, {"azimuth", RealReference},
260       {"elevation", RealReference}, {"gray", MagickBooleanOptions} } },
261     { "Sharpen", { {"geometry", StringReference}, {"radius", RealReference},
262       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
263     { "Shear", { {"geometry", StringReference}, {"x", RealReference},
264       {"y", RealReference}, { "fill", StringReference},
265       {"color", StringReference} } },
266     { "Spread", { {"radius", RealReference} } },
267     { "Swirl", { {"degrees", RealReference},
268       {"interpolate", MagickInterpolateOptions} } },
269     { "Resize", { {"geometry", StringReference}, {"width", IntegerReference},
270       {"height", IntegerReference}, {"filter", MagickFilterOptions},
271       {"support", StringReference }, {"blur", RealReference } } },
272     { "Zoom", { {"geometry", StringReference}, {"width", IntegerReference},
273       {"height", IntegerReference}, {"filter", MagickFilterOptions},
274       {"support", RealReference }, {"blur", RealReference } } },
275     { "Annotate", { {"text", StringReference}, {"font", StringReference},
276       {"pointsize", RealReference}, {"density", StringReference},
277       {"undercolor", StringReference}, {"stroke", StringReference},
278       {"fill", StringReference}, {"geometry", StringReference},
279       {"pen", StringReference}, {"x", RealReference},
280       {"y", RealReference}, {"gravity", MagickGravityOptions},
281       {"translate", StringReference}, {"scale", StringReference},
282       {"rotate", RealReference}, {"skewX", RealReference},
283       {"skewY", RealReference}, {"strokewidth", RealReference},
284       {"antialias", MagickBooleanOptions}, {"family", StringReference},
285       {"style", MagickStyleOptions}, {"stretch", MagickStretchOptions},
286       {"weight", IntegerReference}, {"align", MagickAlignOptions},
287       {"encoding", StringReference}, {"affine", ArrayReference},
288       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
289       {"tile", ImageReference}, {"kerning", RealReference},
290       {"interline-spacing", RealReference},
291       {"interword-spacing", RealReference},
292       {"direction", MagickDirectionOptions} } },
293     { "ColorFloodfill", { {"geometry", StringReference},
294       {"x", IntegerReference}, {"y", IntegerReference},
295       {"fill", StringReference}, {"bordercolor", StringReference},
296       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
297     { "Composite", { {"image", ImageReference},
298       {"compose", MagickComposeOptions}, {"geometry", StringReference},
299       {"x", IntegerReference}, {"y", IntegerReference},
300       {"gravity", MagickGravityOptions}, {"opacity", StringReference},
301       {"tile", MagickBooleanOptions}, {"rotate", RealReference},
302       {"color", StringReference}, {"mask", ImageReference},
303       {"channel", MagickChannelOptions},
304       {"interpolate", MagickInterpolateOptions}, {"args", StringReference},
305       {"blend", StringReference} } },
306     { "Contrast", { {"sharpen", MagickBooleanOptions} } },
307     { "CycleColormap", { {"display", IntegerReference} } },
308     { "Draw", { {"primitive", MagickPrimitiveOptions},
309       {"points", StringReference}, {"method", MagickMethodOptions},
310       {"stroke", StringReference}, {"fill", StringReference},
311       {"strokewidth", RealReference}, {"font", StringReference},
312       {"bordercolor", StringReference}, {"x", RealReference},
313       {"y", RealReference}, {"translate", StringReference},
314       {"scale", StringReference}, {"rotate", RealReference},
315       {"skewX", RealReference}, {"skewY", RealReference},
316       {"tile", ImageReference}, {"pointsize", RealReference},
317       {"antialias", MagickBooleanOptions}, {"density", StringReference},
318       {"linewidth", RealReference}, {"affine", ArrayReference},
319       {"stroke-dashoffset", RealReference},
320       {"stroke-dasharray", ArrayReference},
321       {"interpolate", MagickInterpolateOptions},
322       {"origin", StringReference}, {"text", StringReference},
323       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
324       {"vector-graphics", StringReference}, {"kerning", RealReference},
325       {"interline-spacing", RealReference},
326       {"interword-spacing", RealReference},
327       {"direction", MagickDirectionOptions} } },
328     { "Equalize", { {"channel", MagickChannelOptions} } },
329     { "Gamma", { {"gamma", StringReference}, {"channel", MagickChannelOptions},
330       {"red", RealReference}, {"green", RealReference},
331       {"blue", RealReference} } },
332     { "Map", { {"image", ImageReference}, {"dither", MagickBooleanOptions},
333       {"dither-method", MagickDitherOptions} } },
334     { "MatteFloodfill", { {"geometry", StringReference},
335       {"x", IntegerReference}, {"y", IntegerReference},
336       {"opacity", StringReference}, {"bordercolor", StringReference},
337       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
338     { "Modulate", { {"factor", StringReference}, {"hue", RealReference},
339       {"saturation", RealReference}, {"whiteness", RealReference},
340       {"brightness", RealReference}, {"lightness", RealReference},
341       {"blackness", RealReference} } },
342     { "Negate", { {"gray", MagickBooleanOptions},
343       {"channel", MagickChannelOptions} } },
344     { "Normalize", { {"channel", MagickChannelOptions} } },
345     { "NumberColors", },
346     { "Opaque", { {"color", StringReference}, {"fill", StringReference},
347       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
348       {"invert", MagickBooleanOptions} } },
349     { "Quantize", { {"colors", IntegerReference},
350       {"treedepth", IntegerReference}, {"colorspace", MagickColorspaceOptions},
351       {"dither", MagickBooleanOptions}, {"measure", MagickBooleanOptions},
352       {"global", MagickBooleanOptions}, {"transparent-color", StringReference},
353       {"dither-method", MagickDitherOptions} } },
354     { "Raise", { {"geometry", StringReference}, {"width", IntegerReference},
355       {"height", IntegerReference}, {"raise", MagickBooleanOptions} } },
356     { "Segment", { {"geometry", StringReference},
357       {"cluster-threshold", RealReference},
358       {"smoothing-threshold", RealReference},
359       {"colorspace", MagickColorspaceOptions},
360       {"verbose", MagickBooleanOptions} } },
361     { "Signature", },
362     { "Solarize", { {"geometry", StringReference},
363       {"threshold", StringReference} } },
364     { "Sync", },
365     { "Texture", { {"texture", ImageReference} } },
366     { "Evaluate", { {"value", RealReference},
367       {"operator", MagickEvaluateOptions},
368       {"channel", MagickChannelOptions} } },
369     { "Transparent", { {"color", StringReference}, {"opacity", StringReference},
370       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
371     { "Threshold", { {"threshold", StringReference},
372       {"channel", MagickChannelOptions} } },
373     { "Charcoal", { {"geometry", StringReference}, {"radius", RealReference},
374       {"sigma", RealReference} } },
375     { "Trim", { {"fuzz", StringReference} } },
376     { "Wave", { {"geometry", StringReference}, {"amplitude", RealReference},
377       {"wavelength", RealReference},
378       {"interpolate", MagickInterpolateOptions} } },
379     { "Separate", { {"channel", MagickChannelOptions} } },
380     { "Condense", },
381     { "Stereo", { {"image", ImageReference}, {"x", IntegerReference},
382       {"y", IntegerReference} } },
383     { "Stegano", { {"image", ImageReference}, {"offset", IntegerReference} } },
384     { "Deconstruct", },
385     { "GaussianBlur", { {"geometry", StringReference},
386       {"radius", RealReference}, {"sigma", RealReference},
387       {"channel", MagickChannelOptions} } },
388     { "Convolve", { {"coefficients", ArrayReference},
389       {"channel", MagickChannelOptions}, {"bias", StringReference} } },
390     { "Profile", { {"name", StringReference}, {"profile", StringReference},
391       { "rendering-intent", MagickIntentOptions},
392       { "black-point-compensation", MagickBooleanOptions} } },
393     { "UnsharpMask", { {"geometry", StringReference},
394       {"radius", RealReference}, {"sigma", RealReference},
395       {"amount", RealReference}, {"threshold", RealReference},
396       {"channel", MagickChannelOptions} } },
397     { "MotionBlur", { {"geometry", StringReference},
398       {"radius", RealReference}, {"sigma", RealReference},
399       {"angle", RealReference}, {"channel", MagickChannelOptions} } },
400     { "OrderedDither", { {"threshold", StringReference},
401       {"channel", MagickChannelOptions} } },
402     { "Shave", { {"geometry", StringReference}, {"width", IntegerReference},
403       {"height", IntegerReference} } },
404     { "Level", { {"levels", StringReference}, {"black-point", RealReference},
405       {"white-point", RealReference}, {"gamma", RealReference},
406       {"channel", MagickChannelOptions}, {"level", StringReference} } },
407     { "Clip", { {"id", StringReference}, {"inside", MagickBooleanOptions} } },
408     { "AffineTransform", { {"affine", ArrayReference},
409       {"translate", StringReference}, {"scale", StringReference},
410       {"rotate", RealReference}, {"skewX", RealReference},
411       {"skewY", RealReference}, {"interpolate", MagickInterpolateOptions},
412       {"background", StringReference} } },
413     { "Difference", { {"image", ImageReference}, {"fuzz", StringReference} } },
414     { "AdaptiveThreshold", { {"geometry", StringReference},
415       {"width", IntegerReference}, {"height", IntegerReference},
416       {"offset", IntegerReference} } },
417     { "Resample", { {"density", StringReference}, {"x", RealReference},
418       {"y", RealReference}, {"filter", MagickFilterOptions},
419       {"support", RealReference }, {"blur", RealReference } } },
420     { "Describe", { {"file", FileReference} } },
421     { "BlackThreshold", { {"threshold", StringReference},
422       {"channel", MagickChannelOptions} } },
423     { "WhiteThreshold", { {"threshold", StringReference},
424       {"channel", MagickChannelOptions} } },
425     { "RadialBlur", { {"geometry", StringReference}, {"angle", RealReference},
426       {"channel", MagickChannelOptions} } },
427     { "Thumbnail", { {"geometry", StringReference}, {"width", IntegerReference},
428       {"height", IntegerReference} } },
429     { "Strip", },
430     { "Tint", { {"fill", StringReference}, {"opacity", StringReference} } },
431     { "Channel", { {"channel", MagickChannelOptions} } },
432     { "Splice", { {"geometry", StringReference}, {"width", IntegerReference},
433       {"height", IntegerReference}, {"x", IntegerReference},
434       {"y", IntegerReference}, {"fuzz", StringReference},
435       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
436     { "Posterize", { {"levels", IntegerReference},
437       {"dither", MagickBooleanOptions} } },
438     { "Shadow", { {"geometry", StringReference}, {"opacity", RealReference},
439       {"sigma", RealReference}, {"x", IntegerReference},
440       {"y", IntegerReference} } },
441     { "Identify", { {"file", FileReference}, {"features", StringReference},
442       {"unique", MagickBooleanOptions} } },
443     { "SepiaTone", { {"threshold", RealReference} } },
444     { "SigmoidalContrast", { {"geometry", StringReference},
445       {"contrast", RealReference}, {"mid-point", RealReference},
446       {"channel", MagickChannelOptions}, {"sharpen", MagickBooleanOptions} } },
447     { "Extent", { {"geometry", StringReference}, {"width", IntegerReference},
448       {"height", IntegerReference}, {"x", IntegerReference},
449       {"y", IntegerReference}, {"fuzz", StringReference},
450       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
451     { "Vignette", { {"geometry", StringReference}, {"radius", RealReference},
452       {"sigma", RealReference}, {"x", IntegerReference},
453       {"y", IntegerReference}, {"background", StringReference} } },
454     { "ContrastStretch", { {"levels", StringReference},
455       {"black-point", RealReference},{"white-point", RealReference},
456       {"channel", MagickChannelOptions} } },
457     { "Sans0", },
458     { "Sans1", },
459     { "AdaptiveSharpen", { {"geometry", StringReference},
460       {"radius", RealReference}, {"sigma", RealReference},
461       {"channel", MagickChannelOptions} } },
462     { "Transpose", },
463     { "Transverse", },
464     { "AutoOrient", },
465     { "AdaptiveBlur", { {"geometry", StringReference},
466       {"radius", RealReference}, {"sigma", RealReference},
467       {"channel", MagickChannelOptions} } },
468     { "Sketch", { {"geometry", StringReference},
469       {"radius", RealReference}, {"sigma", RealReference},
470       {"angle", RealReference} } },
471     { "UniqueColors", },
472     { "AdaptiveResize", { {"geometry", StringReference},
473       {"width", IntegerReference}, {"height", IntegerReference},
474       {"filter", MagickFilterOptions}, {"support", StringReference },
475       {"blur", RealReference } } },
476     { "ClipMask", { {"mask", ImageReference} } },
477     { "LinearStretch", { {"levels", StringReference},
478       {"black-point", RealReference},{"white-point", RealReference} } },
479     { "Recolor", { {"matrix", ArrayReference} } },
480     { "Mask", { {"mask", ImageReference} } },
481     { "Polaroid", { {"caption", StringReference}, {"angle", RealReference},
482       {"font", StringReference}, {"stroke", StringReference},
483       {"fill", StringReference}, {"strokewidth", RealReference},
484       {"pointsize", RealReference}, {"gravity", MagickGravityOptions},
485       {"background", StringReference} } },
486     { "FloodfillPaint", { {"geometry", StringReference},
487       {"x", IntegerReference}, {"y", IntegerReference},
488       {"fill", StringReference}, {"bordercolor", StringReference},
489       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
490       {"invert", MagickBooleanOptions} } },
491     { "Distort", { {"points", ArrayReference}, {"method", MagickDistortOptions},
492       {"virtual-pixel", MagickVirtualPixelOptions},
493       {"best-fit", MagickBooleanOptions} } },
494     { "Clut", { {"image", ImageReference},
495       {"channel", MagickChannelOptions} } },
496     { "LiquidRescale", { {"geometry", StringReference},
497       {"width", IntegerReference}, {"height", IntegerReference},
498       {"delta-x", RealReference}, {"rigidity", RealReference } } },
499     { "Encipher", { {"passphrase", StringReference} } },
500     { "Decipher", { {"passphrase", StringReference} } },
501     { "Deskew", { {"geometry", StringReference},
502       {"threshold", StringReference} } },
503     { "Remap", { {"image", ImageReference}, {"dither", MagickBooleanOptions},
504       {"dither-method", MagickDitherOptions} } },
505     { "SparseColor", { {"points", ArrayReference},
506       {"method", MagickSparseColorOptions},
507       {"virtual-pixel", MagickVirtualPixelOptions},
508       {"channel", MagickChannelOptions} } },
509     { "Function", { {"parameters", ArrayReference},
510       {"function", MagickFunctionOptions},
511       {"virtual-pixel", MagickVirtualPixelOptions} } },
512     { "SelectiveBlur", { {"geometry", StringReference},
513       {"radius", RealReference}, {"sigma", RealReference},
514       {"threshold", RealReference}, {"channel", MagickChannelOptions} } },
515     { "HaldClut", { {"image", ImageReference},
516       {"channel", MagickChannelOptions} } },
517     { "BlueShift", { {"factor", StringReference} } },
518     { "ForwardFourierTransform", { {"magnitude", MagickBooleanOptions} } },
519     { "InverseFourierTransform", { {"magnitude", MagickBooleanOptions} } },
520     { "ColorDecisionList", {
521       {"color-correction-collection", StringReference} } },
522     { "AutoGamma", { {"channel", MagickChannelOptions} } },
523     { "AutoLevel", { {"channel", MagickChannelOptions} } },
524     { "LevelColors", { {"invert", MagickBooleanOptions},
525       {"black-point", StringReference}, {"white-point", StringReference},
526       {"channel", MagickChannelOptions}, {"invert", MagickBooleanOptions} } },
527     { "Clamp", { {"channel", MagickChannelOptions} } },
528     { "Filter", { {"kernel", StringReference},
529       {"channel", MagickChannelOptions}, {"bias", StringReference} } },
530     { "BrightnessContrast", { {"levels", StringReference},
531       {"brightness", RealReference},{"contrast", RealReference},
532       {"channel", MagickChannelOptions} } },
533     { "Morphology", { {"kernel", StringReference},
534       {"channel", MagickChannelOptions}, {"method", MagickMorphologyOptions},
535       {"iterations", IntegerReference} } },
536     { "ColorMatrix", { {"matrix", ArrayReference} } },
537     { "Color", { {"color", StringReference} } },
538     { "Mode", { {"geometry", StringReference},
539       {"width", IntegerReference},{"height", IntegerReference},
540       {"channel", MagickChannelOptions} } },
541     { "Statistic", { {"geometry", StringReference},
542       {"width", IntegerReference},{"height", IntegerReference},
543       {"channel", MagickChannelOptions}, {"type", MagickStatisticOptions} } }
544   };
545
546 static SplayTreeInfo
547   *magick_registry = (SplayTreeInfo *) NULL;
548 \f
549 /*
550   Forward declarations.
551 */
552 static Image
553   *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
554
555 static ssize_t
556   strEQcase(const char *,const char *);
557 \f
558 /*
559 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
560 %                                                                             %
561 %                                                                             %
562 %                                                                             %
563 %   C l o n e P a c k a g e I n f o                                           %
564 %                                                                             %
565 %                                                                             %
566 %                                                                             %
567 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
568 %
569 %  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
570 %  a new one.
571 %
572 %  The format of the ClonePackageInfo routine is:
573 %
574 %      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
575 %        exception)
576 %
577 %  A description of each parameter follows:
578 %
579 %    o info: a structure of type info.
580 %
581 %    o exception: Return any errors or warnings in this structure.
582 %
583 */
584 static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
585   ExceptionInfo *exception)
586 {
587   struct PackageInfo
588     *clone_info;
589
590   clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
591   if (clone_info == (struct PackageInfo *) NULL)
592     {
593       ThrowPerlException(exception,ResourceLimitError,
594         "UnableToClonePackageInfo",PackageName);
595       return((struct PackageInfo *) NULL);
596     }
597   if (info == (struct PackageInfo *) NULL)
598     {
599       clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
600       return(clone_info);
601     }
602   *clone_info=(*info);
603   clone_info->image_info=CloneImageInfo(info->image_info);
604   return(clone_info);
605 }
606 \f
607 /*
608 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
609 %                                                                             %
610 %                                                                             %
611 %                                                                             %
612 %   c o n s t a n t                                                           %
613 %                                                                             %
614 %                                                                             %
615 %                                                                             %
616 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
617 %
618 %  constant() returns a double value for the specified name.
619 %
620 %  The format of the constant routine is:
621 %
622 %      double constant(char *name,ssize_t sans)
623 %
624 %  A description of each parameter follows:
625 %
626 %    o value: Method constant returns a double value for the specified name.
627 %
628 %    o name: The name of the constant.
629 %
630 %    o sans: This integer value is not used.
631 %
632 */
633 static double constant(char *name,ssize_t sans)
634 {
635   (void) sans;
636   errno=0;
637   switch (*name)
638   {
639     case 'B':
640     {
641       if (strEQ(name,"BlobError"))
642         return(BlobError);
643       if (strEQ(name,"BlobWarning"))
644         return(BlobWarning);
645       break;
646     }
647     case 'C':
648     {
649       if (strEQ(name,"CacheError"))
650         return(CacheError);
651       if (strEQ(name,"CacheWarning"))
652         return(CacheWarning);
653       if (strEQ(name,"CoderError"))
654         return(CoderError);
655       if (strEQ(name,"CoderWarning"))
656         return(CoderWarning);
657       if (strEQ(name,"ConfigureError"))
658         return(ConfigureError);
659       if (strEQ(name,"ConfigureWarning"))
660         return(ConfigureWarning);
661       if (strEQ(name,"CorruptImageError"))
662         return(CorruptImageError);
663       if (strEQ(name,"CorruptImageWarning"))
664         return(CorruptImageWarning);
665       break;
666     }
667     case 'D':
668     {
669       if (strEQ(name,"DelegateError"))
670         return(DelegateError);
671       if (strEQ(name,"DelegateWarning"))
672         return(DelegateWarning);
673       if (strEQ(name,"DrawError"))
674         return(DrawError);
675       if (strEQ(name,"DrawWarning"))
676         return(DrawWarning);
677       break;
678     }
679     case 'E':
680     {
681       if (strEQ(name,"ErrorException"))
682         return(ErrorException);
683       if (strEQ(name,"ExceptionError"))
684         return(CoderError);
685       if (strEQ(name,"ExceptionWarning"))
686         return(CoderWarning);
687       break;
688     }
689     case 'F':
690     {
691       if (strEQ(name,"FatalErrorException"))
692         return(FatalErrorException);
693       if (strEQ(name,"FileOpenError"))
694         return(FileOpenError);
695       if (strEQ(name,"FileOpenWarning"))
696         return(FileOpenWarning);
697       break;
698     }
699     case 'I':
700     {
701       if (strEQ(name,"ImageError"))
702         return(ImageError);
703       if (strEQ(name,"ImageWarning"))
704         return(ImageWarning);
705       break;
706     }
707     case 'M':
708     {
709       if (strEQ(name,"MaxRGB"))
710         return(QuantumRange);
711       if (strEQ(name,"MissingDelegateError"))
712         return(MissingDelegateError);
713       if (strEQ(name,"MissingDelegateWarning"))
714         return(MissingDelegateWarning);
715       if (strEQ(name,"ModuleError"))
716         return(ModuleError);
717       if (strEQ(name,"ModuleWarning"))
718         return(ModuleWarning);
719       break;
720     }
721     case 'O':
722     {
723       if (strEQ(name,"Opaque"))
724         return(OpaqueAlpha);
725       if (strEQ(name,"OptionError"))
726         return(OptionError);
727       if (strEQ(name,"OptionWarning"))
728         return(OptionWarning);
729       break;
730     }
731     case 'Q':
732     {
733       if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
734         return(MAGICKCORE_QUANTUM_DEPTH);
735       if (strEQ(name,"QuantumDepth"))
736         return(MAGICKCORE_QUANTUM_DEPTH);
737       if (strEQ(name,"QuantumRange"))
738         return(QuantumRange);
739       break;
740     }
741     case 'R':
742     {
743       if (strEQ(name,"ResourceLimitError"))
744         return(ResourceLimitError);
745       if (strEQ(name,"ResourceLimitWarning"))
746         return(ResourceLimitWarning);
747       if (strEQ(name,"RegistryError"))
748         return(RegistryError);
749       if (strEQ(name,"RegistryWarning"))
750         return(RegistryWarning);
751       break;
752     }
753     case 'S':
754     {
755       if (strEQ(name,"StreamError"))
756         return(StreamError);
757       if (strEQ(name,"StreamWarning"))
758         return(StreamWarning);
759       if (strEQ(name,"Success"))
760         return(0);
761       break;
762     }
763     case 'T':
764     {
765       if (strEQ(name,"Transparent"))
766         return(TransparentAlpha);
767       if (strEQ(name,"TypeError"))
768         return(TypeError);
769       if (strEQ(name,"TypeWarning"))
770         return(TypeWarning);
771       break;
772     }
773     case 'W':
774     {
775       if (strEQ(name,"WarningException"))
776         return(WarningException);
777       break;
778     }
779     case 'X':
780     {
781       if (strEQ(name,"XServerError"))
782         return(XServerError);
783       if (strEQ(name,"XServerWarning"))
784         return(XServerWarning);
785       break;
786     }
787   }
788   errno=EINVAL;
789   return(0);
790 }
791 \f
792 /*
793 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
794 %                                                                             %
795 %                                                                             %
796 %                                                                             %
797 %   D e s t r o y P a c k a g e I n f o                                       %
798 %                                                                             %
799 %                                                                             %
800 %                                                                             %
801 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
802 %
803 %  Method DestroyPackageInfo frees a previously created info structure.
804 %
805 %  The format of the DestroyPackageInfo routine is:
806 %
807 %      DestroyPackageInfo(struct PackageInfo *info)
808 %
809 %  A description of each parameter follows:
810 %
811 %    o info: a structure of type info.
812 %
813 */
814 static void DestroyPackageInfo(struct PackageInfo *info)
815 {
816   info->image_info=DestroyImageInfo(info->image_info);
817   info=(struct PackageInfo *) RelinquishMagickMemory(info);
818 }
819 \f
820 /*
821 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
822 %                                                                             %
823 %                                                                             %
824 %                                                                             %
825 %   G e t L i s t                                                             %
826 %                                                                             %
827 %                                                                             %
828 %                                                                             %
829 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
830 %
831 %  Method GetList is recursively called by SetupList to traverse the
832 %  Image__Magick reference.  If building an reference_vector (see SetupList),
833 %  *current is the current position in *reference_vector and *last is the final
834 %  entry in *reference_vector.
835 %
836 %  The format of the GetList routine is:
837 %
838 %      GetList(info)
839 %
840 %  A description of each parameter follows:
841 %
842 %    o info: a structure of type info.
843 %
844 */
845 static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
846   ssize_t *current,ssize_t *last,ExceptionInfo *exception)
847 {
848   Image
849     *image;
850
851   if (reference == (SV *) NULL)
852     return(NULL);
853   switch (SvTYPE(reference))
854   {
855     case SVt_PVAV:
856     {
857       AV
858         *av;
859
860       Image
861         *head,
862         *previous;
863
864       register ssize_t
865         i;
866
867       ssize_t
868         n;
869
870       /*
871         Array of images.
872       */
873       previous=(Image *) NULL;
874       head=(Image *) NULL;
875       av=(AV *) reference;
876       n=av_len(av);
877       for (i=0; i <= n; i++)
878       {
879         SV
880           **rv;
881
882         rv=av_fetch(av,i,0);
883         if (rv && *rv && sv_isobject(*rv))
884           {
885             image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
886               exception);
887             if (image == (Image *) NULL)
888               continue;
889             if (image == previous)
890               {
891                 image=CloneImage(image,0,0,MagickTrue,exception);
892                 if (image == (Image *) NULL)
893                   return(NULL);
894               }
895             image->previous=previous;
896             *(previous ? &previous->next : &head)=image;
897             for (previous=image; previous->next; previous=previous->next) ;
898           }
899       }
900       return(head);
901     }
902     case SVt_PVMG:
903     {
904       /*
905         Blessed scalar, one image.
906       */
907       image=(Image *) SvIV(reference);
908       if (image == (Image *) NULL)
909         return(NULL);
910       image->previous=(Image *) NULL;
911       image->next=(Image *) NULL;
912       if (reference_vector)
913         {
914           if (*current == *last)
915             {
916               *last+=256;
917               if (*reference_vector == (SV **) NULL)
918                 *reference_vector=(SV **) AcquireQuantumMemory(*last,
919                   sizeof(*reference_vector));
920               else
921                 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
922                   *last,sizeof(*reference_vector));
923             }
924           if (*reference_vector == (SV **) NULL)
925             {
926               ThrowPerlException(exception,ResourceLimitError,
927                 "MemoryAllocationFailed",PackageName);
928               return((Image *) NULL);
929             }
930           (*reference_vector)[*current]=reference;
931           (*reference_vector)[++(*current)]=NULL;
932         }
933       return(image);
934     }
935     default:
936       break;
937   }
938   (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
939     (double) SvTYPE(reference));
940   return((Image *) NULL);
941 }
942 \f
943 /*
944 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
945 %                                                                             %
946 %                                                                             %
947 %                                                                             %
948 %   G e t P a c k a g e I n f o                                               %
949 %                                                                             %
950 %                                                                             %
951 %                                                                             %
952 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
953 %
954 %  Method GetPackageInfo looks up or creates an info structure for the given
955 %  Image__Magick reference.  If it does create a new one, the information in
956 %  package_info is used to initialize it.
957 %
958 %  The format of the GetPackageInfo routine is:
959 %
960 %      struct PackageInfo *GetPackageInfo(void *reference,
961 %        struct PackageInfo *package_info,ExceptionInfo *exception)
962 %
963 %  A description of each parameter follows:
964 %
965 %    o info: a structure of type info.
966 %
967 %    o exception: Return any errors or warnings in this structure.
968 %
969 */
970 static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
971   struct PackageInfo *package_info,ExceptionInfo *exception)
972 {
973   char
974     message[MaxTextExtent];
975
976   struct PackageInfo
977     *clone_info;
978
979   SV
980     *sv;
981
982   (void) FormatLocaleString(message,MaxTextExtent,"%s::package%s%p",
983     PackageName,XS_VERSION,reference);
984   sv=perl_get_sv(message,(TRUE | 0x02));
985   if (sv == (SV *) NULL)
986     {
987       ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
988         message);
989       return(package_info);
990     }
991   if (SvREFCNT(sv) == 0)
992     (void) SvREFCNT_inc(sv);
993   if (SvIOKp(sv) && (clone_info=(struct PackageInfo *) SvIV(sv)))
994     return(clone_info);
995   clone_info=ClonePackageInfo(package_info,exception);
996   sv_setiv(sv,(IV) clone_info);
997   return(clone_info);
998 }
999 \f
1000 /*
1001 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1002 %                                                                             %
1003 %                                                                             %
1004 %                                                                             %
1005 %   S e t A t t r i b u t e                                                   %
1006 %                                                                             %
1007 %                                                                             %
1008 %                                                                             %
1009 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1010 %
1011 %  SetAttribute() sets the attribute to the value in sval.  This can change
1012 %  either or both of image or info.
1013 %
1014 %  The format of the SetAttribute routine is:
1015 %
1016 %      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1017 %        SV *sval,ExceptionInfo *exception)
1018 %
1019 %  A description of each parameter follows:
1020 %
1021 %    o list: a list of strings.
1022 %
1023 %    o string: a character string.
1024 %
1025 */
1026
1027 static double SiPrefixToDouble(const char *string,const double interval)
1028 {
1029   char
1030     *q;
1031
1032   double
1033     scale,
1034     value;
1035
1036   value=InterpretLocaleValue(string,&q);
1037   scale=1000.0;
1038   if ((*q != '\0') && (tolower((int) ((unsigned char) *(q+1))) == 'i'))
1039     scale=1024.0;
1040   switch (tolower((int) ((unsigned char) *q)))
1041   {
1042     case '%': value*=pow(scale,0)*interval/100.0; break;
1043     case 'k': value*=pow(scale,1); break;
1044     case 'm': value*=pow(scale,2); break;
1045     case 'g': value*=pow(scale,3); break;
1046     case 't': value*=pow(scale,4); break;
1047     case 'p': value*=pow(scale,5); break;
1048     case 'e': value*=pow(scale,6); break;
1049     case 'z': value*=pow(scale,7); break;
1050     case 'y': value*=pow(scale,8); break;
1051     default:  break;
1052   }
1053   return(value);
1054 }
1055
1056 static inline ssize_t StringToLong(const char *value)
1057 {
1058   return(strtol(value,(char **) NULL,10));
1059 }
1060
1061 static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1062   const char *attribute,SV *sval,ExceptionInfo *exception)
1063 {
1064   GeometryInfo
1065     geometry_info;
1066
1067   long
1068     x,
1069     y;
1070
1071   PixelInfo
1072     pixel;
1073
1074   MagickStatusType
1075     flags;
1076
1077   PixelPacket
1078     *color,
1079     target_color;
1080
1081   ssize_t
1082     sp;
1083
1084   switch (*attribute)
1085   {
1086     case 'A':
1087     case 'a':
1088     {
1089       if (LocaleCompare(attribute,"adjoin") == 0)
1090         {
1091           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1092             SvPV(sval,na)) : SvIV(sval);
1093           if (sp < 0)
1094             {
1095               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1096                 SvPV(sval,na));
1097               break;
1098             }
1099           if (info)
1100             info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1101           break;
1102         }
1103       if (LocaleCompare(attribute,"alpha") == 0)
1104         {
1105           sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaOptions,MagickFalse,
1106             SvPV(sval,na)) : SvIV(sval);
1107           if (sp < 0)
1108             {
1109               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1110                 SvPV(sval,na));
1111               break;
1112             }
1113           for ( ; image; image=image->next)
1114             (void) SetImageAlphaChannel(image,(AlphaChannelType) sp);
1115           break;
1116         }
1117       if (LocaleCompare(attribute,"antialias") == 0)
1118         {
1119           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1120             SvPV(sval,na)) : SvIV(sval);
1121           if (sp < 0)
1122             {
1123               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1124                 SvPV(sval,na));
1125               break;
1126             }
1127           if (info)
1128             info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1129           break;
1130         }
1131       if (LocaleCompare(attribute,"area-limit") == 0)
1132         {
1133           MagickSizeType
1134             limit;
1135
1136           limit=MagickResourceInfinity;
1137           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1138             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1139           (void) SetMagickResourceLimit(AreaResource,limit);
1140           break;
1141         }
1142       if (LocaleCompare(attribute,"attenuate") == 0)
1143         {
1144           if (info)
1145             (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1146           break;
1147         }
1148       if (LocaleCompare(attribute,"authenticate") == 0)
1149         {
1150           if (info)
1151             (void) CloneString(&info->image_info->authenticate,SvPV(sval,na));
1152           break;
1153         }
1154       if (info)
1155         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1156       for ( ; image; image=image->next)
1157         SetImageProperty(image,attribute,SvPV(sval,na));
1158       break;
1159     }
1160     case 'B':
1161     case 'b':
1162     {
1163       if (LocaleCompare(attribute,"background") == 0)
1164         {
1165           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1166           if (info)
1167             info->image_info->background_color=target_color;
1168           for ( ; image; image=image->next)
1169             image->background_color=target_color;
1170           break;
1171         }
1172       if (LocaleCompare(attribute,"bias") == 0)
1173         {
1174           for ( ; image; image=image->next)
1175             image->bias=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1176           break;
1177         }
1178       if (LocaleCompare(attribute,"blue-primary") == 0)
1179         {
1180           for ( ; image; image=image->next)
1181           {
1182             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1183             image->chromaticity.blue_primary.x=geometry_info.rho;
1184             image->chromaticity.blue_primary.y=geometry_info.sigma;
1185             if ((flags & SigmaValue) == 0)
1186               image->chromaticity.blue_primary.y=
1187                 image->chromaticity.blue_primary.x;
1188           }
1189           break;
1190         }
1191       if (LocaleCompare(attribute,"bordercolor") == 0)
1192         {
1193           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1194           if (info)
1195             info->image_info->border_color=target_color;
1196           for ( ; image; image=image->next)
1197             image->border_color=target_color;
1198           break;
1199         }
1200       if (info)
1201         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1202       for ( ; image; image=image->next)
1203         SetImageProperty(image,attribute,SvPV(sval,na));
1204       break;
1205     }
1206     case 'C':
1207     case 'c':
1208     {
1209       if (LocaleCompare(attribute,"cache-threshold") == 0)
1210         {
1211           (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1212             SiPrefixToDouble(SvPV(sval,na),100.0));
1213           (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1214             (2*SiPrefixToDouble(SvPV(sval,na),100.0)));
1215           break;
1216         }
1217       if (LocaleCompare(attribute,"clip-mask") == 0)
1218         {
1219           Image
1220             *clip_mask;
1221
1222           clip_mask=(Image *) NULL;
1223           if (SvPOK(sval))
1224             clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1225           for ( ; image; image=image->next)
1226             SetImageClipMask(image,clip_mask);
1227           break;
1228         }
1229       if (LocaleNCompare(attribute,"colormap",8) == 0)
1230         {
1231           for ( ; image; image=image->next)
1232           {
1233             int
1234               items;
1235
1236             long
1237               i;
1238
1239             if (image->storage_class == DirectClass)
1240               continue;
1241             i=0;
1242             items=sscanf(attribute,"%*[^[][%ld",&i);
1243             (void) items;
1244             if (i > (ssize_t) image->colors)
1245               i%=image->colors;
1246             if ((strchr(SvPV(sval,na),',') == 0) ||
1247                 (strchr(SvPV(sval,na),')') != 0))
1248               QueryColorDatabase(SvPV(sval,na),image->colormap+i,exception);
1249             else
1250               {
1251                 color=image->colormap+i;
1252                 pixel.red=color->red;
1253                 pixel.green=color->green;
1254                 pixel.blue=color->blue;
1255                 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1256                 pixel.red=geometry_info.rho;
1257                 pixel.green=geometry_info.sigma;
1258                 pixel.blue=geometry_info.xi;
1259                 color->red=ClampToQuantum(pixel.red);
1260                 color->green=ClampToQuantum(pixel.green);
1261                 color->blue=ClampToQuantum(pixel.blue);
1262               }
1263           }
1264           break;
1265         }
1266       if (LocaleCompare(attribute,"colorspace") == 0)
1267         {
1268           sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1269             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1270           if (sp < 0)
1271             {
1272               ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1273                 SvPV(sval,na));
1274               break;
1275             }
1276           for ( ; image; image=image->next)
1277             (void) TransformImageColorspace(image,(ColorspaceType) sp);
1278           break;
1279         }
1280       if (LocaleCompare(attribute,"comment") == 0)
1281         {
1282           for ( ; image; image=image->next)
1283             (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1284               info ? info->image_info : (ImageInfo *) NULL,image,
1285               SvPV(sval,na)));
1286           break;
1287         }
1288       if (LocaleCompare(attribute,"compression") == 0)
1289         {
1290           sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1291             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1292           if (sp < 0)
1293             {
1294               ThrowPerlException(exception,OptionError,
1295                 "UnrecognizedImageCompression",SvPV(sval,na));
1296               break;
1297             }
1298           if (info)
1299             info->image_info->compression=(CompressionType) sp;
1300           for ( ; image; image=image->next)
1301             image->compression=(CompressionType) sp;
1302           break;
1303         }
1304       if (info)
1305         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1306       for ( ; image; image=image->next)
1307         SetImageProperty(image,attribute,SvPV(sval,na));
1308       break;
1309     }
1310     case 'D':
1311     case 'd':
1312     {
1313       if (LocaleCompare(attribute,"debug") == 0)
1314         {
1315           SetLogEventMask(SvPV(sval,na));
1316           break;
1317         }
1318       if (LocaleCompare(attribute,"delay") == 0)
1319         {
1320           flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1321           for ( ; image; image=image->next)
1322           {
1323             image->delay=(size_t) floor(geometry_info.rho+0.5);
1324             if ((flags & SigmaValue) != 0)
1325               image->ticks_per_second=(ssize_t)
1326                 floor(geometry_info.sigma+0.5);
1327           }
1328           break;
1329         }
1330       if (LocaleCompare(attribute,"disk-limit") == 0)
1331         {
1332           MagickSizeType
1333             limit;
1334
1335           limit=MagickResourceInfinity;
1336           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1337             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1338           (void) SetMagickResourceLimit(DiskResource,limit);
1339           break;
1340         }
1341       if (LocaleCompare(attribute,"density") == 0)
1342         {
1343           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1344             {
1345               ThrowPerlException(exception,OptionError,"MissingGeometry",
1346                 SvPV(sval,na));
1347               break;
1348             }
1349           if (info)
1350             (void) CloneString(&info->image_info->density,SvPV(sval,na));
1351           for ( ; image; image=image->next)
1352           {
1353             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1354             image->x_resolution=geometry_info.rho;
1355             image->y_resolution=geometry_info.sigma;
1356             if ((flags & SigmaValue) == 0)
1357               image->y_resolution=image->x_resolution;
1358           }
1359           break;
1360         }
1361       if (LocaleCompare(attribute,"depth") == 0)
1362         {
1363           if (info)
1364             info->image_info->depth=SvIV(sval);
1365           for ( ; image; image=image->next)
1366             (void) SetImageDepth(image,SvIV(sval));
1367           break;
1368         }
1369       if (LocaleCompare(attribute,"dispose") == 0)
1370         {
1371           sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1372             SvPV(sval,na)) : SvIV(sval);
1373           if (sp < 0)
1374             {
1375               ThrowPerlException(exception,OptionError,
1376                 "UnrecognizedDisposeMethod",SvPV(sval,na));
1377               break;
1378             }
1379           for ( ; image; image=image->next)
1380             image->dispose=(DisposeType) sp;
1381           break;
1382         }
1383       if (LocaleCompare(attribute,"dither") == 0)
1384         {
1385           if (info)
1386             {
1387               sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1388                 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1389               if (sp < 0)
1390                 {
1391                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
1392                     SvPV(sval,na));
1393                   break;
1394                 }
1395               info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1396             }
1397           break;
1398         }
1399       if (LocaleCompare(attribute,"display") == 0)
1400         {
1401           display:
1402           if (info)
1403             (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1404           break;
1405         }
1406       if (info)
1407         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1408       for ( ; image; image=image->next)
1409         SetImageProperty(image,attribute,SvPV(sval,na));
1410       break;
1411     }
1412     case 'E':
1413     case 'e':
1414     {
1415       if (LocaleCompare(attribute,"endian") == 0)
1416         {
1417           sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1418             SvPV(sval,na)) : SvIV(sval);
1419           if (sp < 0)
1420             {
1421               ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1422                 SvPV(sval,na));
1423               break;
1424             }
1425           if (info)
1426             info->image_info->endian=(EndianType) sp;
1427           for ( ; image; image=image->next)
1428             image->endian=(EndianType) sp;
1429           break;
1430         }
1431       if (LocaleCompare(attribute,"extract") == 0)
1432         {
1433           /*
1434             Set image extract geometry.
1435           */
1436           (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1437           break;
1438         }
1439       if (info)
1440         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1441       for ( ; image; image=image->next)
1442         SetImageProperty(image,attribute,SvPV(sval,na));
1443       break;
1444     }
1445     case 'F':
1446     case 'f':
1447     {
1448       if (LocaleCompare(attribute,"filename") == 0)
1449         {
1450           if (info)
1451             (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1452               MaxTextExtent);
1453           for ( ; image; image=image->next)
1454             (void) CopyMagickString(image->filename,SvPV(sval,na),
1455               MaxTextExtent);
1456           break;
1457         }
1458       if (LocaleCompare(attribute,"file") == 0)
1459         {
1460           FILE
1461             *file;
1462
1463           PerlIO
1464             *io_info;
1465
1466           if (info == (struct PackageInfo *) NULL)
1467             break;
1468           io_info=IoIFP(sv_2io(sval));
1469           if (io_info == (PerlIO *) NULL)
1470             {
1471               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1472                 PackageName);
1473               break;
1474             }
1475           file=PerlIO_findFILE(io_info);
1476           if (file == (FILE *) NULL)
1477             {
1478               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1479                 PackageName);
1480               break;
1481             }
1482           SetImageInfoFile(info->image_info,file);
1483           break;
1484         }
1485       if (LocaleCompare(attribute,"fill") == 0)
1486         {
1487           if (info)
1488             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1489           break;
1490         }
1491       if (LocaleCompare(attribute,"font") == 0)
1492         {
1493           if (info)
1494             (void) CloneString(&info->image_info->font,SvPV(sval,na));
1495           break;
1496         }
1497       if (LocaleCompare(attribute,"foreground") == 0)
1498         break;
1499       if (LocaleCompare(attribute,"fuzz") == 0)
1500         {
1501           if (info)
1502             info->image_info->fuzz=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1503           for ( ; image; image=image->next)
1504             image->fuzz=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1505           break;
1506         }
1507       if (info)
1508         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1509       for ( ; image; image=image->next)
1510         SetImageProperty(image,attribute,SvPV(sval,na));
1511       break;
1512     }
1513     case 'G':
1514     case 'g':
1515     {
1516       if (LocaleCompare(attribute,"gamma") == 0)
1517         {
1518           for ( ; image; image=image->next)
1519             image->gamma=SvNV(sval);
1520           break;
1521         }
1522       if (LocaleCompare(attribute,"gravity") == 0)
1523         {
1524           sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1525             SvPV(sval,na)) : SvIV(sval);
1526           if (sp < 0)
1527             {
1528               ThrowPerlException(exception,OptionError,
1529                 "UnrecognizedGravityType",SvPV(sval,na));
1530               break;
1531             }
1532           if (info)
1533             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1534           for ( ; image; image=image->next)
1535             image->gravity=(GravityType) sp;
1536           break;
1537         }
1538       if (LocaleCompare(attribute,"green-primary") == 0)
1539         {
1540           for ( ; image; image=image->next)
1541           {
1542             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1543             image->chromaticity.green_primary.x=geometry_info.rho;
1544             image->chromaticity.green_primary.y=geometry_info.sigma;
1545             if ((flags & SigmaValue) == 0)
1546               image->chromaticity.green_primary.y=
1547                 image->chromaticity.green_primary.x;
1548           }
1549           break;
1550         }
1551       if (info)
1552         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1553       for ( ; image; image=image->next)
1554         SetImageProperty(image,attribute,SvPV(sval,na));
1555       break;
1556     }
1557     case 'I':
1558     case 'i':
1559     {
1560       if (LocaleNCompare(attribute,"index",5) == 0)
1561         {
1562           int
1563             items;
1564
1565           long
1566             index;
1567
1568           register Quantum
1569             *q;
1570
1571           CacheView
1572             *image_view;
1573
1574           for ( ; image; image=image->next)
1575           {
1576             if (image->storage_class != PseudoClass)
1577               continue;
1578             x=0;
1579             y=0;
1580             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1581             (void) items;
1582             image_view=AcquireCacheView(image);
1583             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1584             if (q != (Quantum *) NULL)
1585               {
1586                 items=sscanf(SvPV(sval,na),"%ld",&index);
1587                 if ((index >= 0) && (index < (ssize_t) image->colors))
1588                   SetPixelIndex(image,index,q);
1589                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1590               }
1591             image_view=DestroyCacheView(image_view);
1592           }
1593           break;
1594         }
1595       if (LocaleCompare(attribute,"iterations") == 0)
1596         {
1597   iterations:
1598           for ( ; image; image=image->next)
1599             image->iterations=SvIV(sval);
1600           break;
1601         }
1602       if (LocaleCompare(attribute,"interlace") == 0)
1603         {
1604           sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1605             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1606           if (sp < 0)
1607             {
1608               ThrowPerlException(exception,OptionError,
1609                 "UnrecognizedInterlaceType",SvPV(sval,na));
1610               break;
1611             }
1612           if (info)
1613             info->image_info->interlace=(InterlaceType) sp;
1614           for ( ; image; image=image->next)
1615             image->interlace=(InterlaceType) sp;
1616           break;
1617         }
1618       if (info)
1619         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1620       for ( ; image; image=image->next)
1621         SetImageProperty(image,attribute,SvPV(sval,na));
1622       break;
1623     }
1624     case 'L':
1625     case 'l':
1626     {
1627       if (LocaleCompare(attribute,"label") == 0)
1628         {
1629           for ( ; image; image=image->next)
1630             (void) SetImageProperty(image,"label",InterpretImageProperties(
1631               info ? info->image_info : (ImageInfo *) NULL,image,
1632               SvPV(sval,na)));
1633           break;
1634         }
1635       if (LocaleCompare(attribute,"loop") == 0)
1636         goto iterations;
1637       if (info)
1638         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1639       for ( ; image; image=image->next)
1640         SetImageProperty(image,attribute,SvPV(sval,na));
1641       break;
1642     }
1643     case 'M':
1644     case 'm':
1645     {
1646       if (LocaleCompare(attribute,"magick") == 0)
1647         {
1648           if (info)
1649             (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
1650               "%s:",SvPV(sval,na));
1651           for ( ; image; image=image->next)
1652             (void) CopyMagickString(image->magick,SvPV(sval,na),MaxTextExtent);
1653           break;
1654         }
1655       if (LocaleCompare(attribute,"map-limit") == 0)
1656         {
1657           MagickSizeType
1658             limit;
1659
1660           limit=MagickResourceInfinity;
1661           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1662             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1663           (void) SetMagickResourceLimit(MapResource,limit);
1664           break;
1665         }
1666       if (LocaleCompare(attribute,"mask") == 0)
1667         {
1668           Image
1669             *mask;
1670
1671           mask=(Image *) NULL;
1672           if (SvPOK(sval))
1673             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1674           for ( ; image; image=image->next)
1675             SetImageMask(image,mask);
1676           break;
1677         }
1678       if (LocaleCompare(attribute,"mattecolor") == 0)
1679         {
1680           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1681           if (info)
1682             info->image_info->matte_color=target_color;
1683           for ( ; image; image=image->next)
1684             image->matte_color=target_color;
1685           break;
1686         }
1687       if (LocaleCompare(attribute,"matte") == 0)
1688         {
1689           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1690             SvPV(sval,na)) : SvIV(sval);
1691           if (sp < 0)
1692             {
1693               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1694                 SvPV(sval,na));
1695               break;
1696             }
1697           for ( ; image; image=image->next)
1698             image->matte=sp != 0 ? MagickTrue : MagickFalse;
1699           break;
1700         }
1701       if (LocaleCompare(attribute,"memory-limit") == 0)
1702         {
1703           MagickSizeType
1704             limit;
1705
1706           limit=MagickResourceInfinity;
1707           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1708             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1709           (void) SetMagickResourceLimit(MemoryResource,limit);
1710           break;
1711         }
1712       if (LocaleCompare(attribute,"monochrome") == 0)
1713         {
1714           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1715             SvPV(sval,na)) : SvIV(sval);
1716           if (sp < 0)
1717             {
1718               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1719                 SvPV(sval,na));
1720               break;
1721             }
1722           if (info)
1723             info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1724           for ( ; image; image=image->next)
1725             (void) SetImageType(image,BilevelType);
1726           break;
1727         }
1728       if (info)
1729         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1730       for ( ; image; image=image->next)
1731         SetImageProperty(image,attribute,SvPV(sval,na));
1732       break;
1733     }
1734     case 'O':
1735     case 'o':
1736     {
1737       if (LocaleCompare(attribute,"option") == 0)
1738         {
1739           if (info)
1740             DefineImageOption(info->image_info,SvPV(sval,na));
1741           break;
1742         }
1743       if (LocaleCompare(attribute,"orientation") == 0)
1744         {
1745           sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1746             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1747           if (sp < 0)
1748             {
1749               ThrowPerlException(exception,OptionError,
1750                 "UnrecognizedOrientationType",SvPV(sval,na));
1751               break;
1752             }
1753           if (info)
1754             info->image_info->orientation=(OrientationType) sp;
1755           for ( ; image; image=image->next)
1756             image->orientation=(OrientationType) sp;
1757           break;
1758         }
1759       if (info)
1760         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1761       for ( ; image; image=image->next)
1762         SetImageProperty(image,attribute,SvPV(sval,na));
1763       break;
1764     }
1765     case 'P':
1766     case 'p':
1767     {
1768       if (LocaleCompare(attribute,"page") == 0)
1769         {
1770           char
1771             *geometry;
1772
1773           geometry=GetPageGeometry(SvPV(sval,na));
1774           if (info)
1775             (void) CloneString(&info->image_info->page,geometry);
1776           for ( ; image; image=image->next)
1777             (void) ParsePageGeometry(image,geometry,&image->page,exception);
1778           geometry=(char *) RelinquishMagickMemory(geometry);
1779           break;
1780         }
1781       if (LocaleCompare(attribute,"pen") == 0)
1782         {
1783           if (info)
1784             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1785           break;
1786         }
1787       if (LocaleNCompare(attribute,"pixel",5) == 0)
1788         {
1789           int
1790             items;
1791
1792           PixelInfo
1793             pixel;
1794
1795           register Quantum
1796             *q;
1797
1798           CacheView
1799             *image_view;
1800
1801           for ( ; image; image=image->next)
1802           {
1803             if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1804               break;
1805             x=0;
1806             y=0;
1807             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1808             (void) items;
1809             image_view=AcquireCacheView(image);
1810             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1811             if (q != (Quantum *) NULL)
1812               {
1813                 if ((strchr(SvPV(sval,na),',') == 0) ||
1814                     (strchr(SvPV(sval,na),')') != 0))
1815                   QueryMagickColor(SvPV(sval,na),&pixel,exception);
1816                 else
1817                   {
1818                     GetPixelInfo(image,&pixel);
1819                     flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1820                     pixel.red=geometry_info.rho;
1821                     if ((flags & SigmaValue) != 0)
1822                       pixel.green=geometry_info.sigma;
1823                     if ((flags & XiValue) != 0)
1824                       pixel.blue=geometry_info.xi;
1825                     if ((flags & PsiValue) != 0)
1826                       pixel.alpha=geometry_info.psi;
1827                     if ((flags & ChiValue) != 0)
1828                       pixel.black=geometry_info.chi;
1829                   }
1830                 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1831                 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1832                 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1833                 if (image->colorspace == CMYKColorspace)
1834                   SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1835                 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1836                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1837               }
1838             image_view=DestroyCacheView(image_view);
1839           }
1840           break;
1841         }
1842       if (LocaleCompare(attribute,"pointsize") == 0)
1843         {
1844           if (info)
1845             {
1846               (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1847               info->image_info->pointsize=geometry_info.rho;
1848             }
1849           break;
1850         }
1851       if (LocaleCompare(attribute,"preview") == 0)
1852         {
1853           sp=SvPOK(sval) ? ParseCommandOption(MagickPreviewOptions,MagickFalse,
1854             SvPV(sval,na)) : SvIV(sval);
1855           if (sp < 0)
1856             {
1857               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1858                 SvPV(sval,na));
1859               break;
1860             }
1861           if (info)
1862             info->image_info->preview_type=(PreviewType) sp;
1863           break;
1864         }
1865       if (info)
1866         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1867       for ( ; image; image=image->next)
1868         SetImageProperty(image,attribute,SvPV(sval,na));
1869       break;
1870     }
1871     case 'Q':
1872     case 'q':
1873     {
1874       if (LocaleCompare(attribute,"quality") == 0)
1875         {
1876           if (info)
1877             info->image_info->quality=SvIV(sval);
1878           for ( ; image; image=image->next)
1879             image->quality=SvIV(sval);
1880           break;
1881         }
1882       if (info)
1883         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1884       for ( ; image; image=image->next)
1885         SetImageProperty(image,attribute,SvPV(sval,na));
1886       break;
1887     }
1888     case 'R':
1889     case 'r':
1890     {
1891       if (LocaleCompare(attribute,"red-primary") == 0)
1892         {
1893           for ( ; image; image=image->next)
1894           {
1895             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1896             image->chromaticity.red_primary.x=geometry_info.rho;
1897             image->chromaticity.red_primary.y=geometry_info.sigma;
1898             if ((flags & SigmaValue) == 0)
1899               image->chromaticity.red_primary.y=
1900                 image->chromaticity.red_primary.x;
1901           }
1902           break;
1903         }
1904       if (LocaleCompare(attribute,"render") == 0)
1905         {
1906           sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1907             SvPV(sval,na)) : SvIV(sval);
1908           if (sp < 0)
1909             {
1910               ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1911                 SvPV(sval,na));
1912               break;
1913             }
1914          for ( ; image; image=image->next)
1915            image->rendering_intent=(RenderingIntent) sp;
1916          break;
1917        }
1918       if (LocaleCompare(attribute,"repage") == 0)
1919         {
1920           RectangleInfo
1921             geometry;
1922
1923           for ( ; image; image=image->next)
1924           {
1925             flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
1926             if ((flags & WidthValue) != 0)
1927               {
1928                 if ((flags & HeightValue) == 0)
1929                   geometry.height=geometry.width;
1930                 image->page.width=geometry.width;
1931                 image->page.height=geometry.height;
1932               }
1933             if ((flags & AspectValue) != 0)
1934               {
1935                 if ((flags & XValue) != 0)
1936                   image->page.x+=geometry.x;
1937                 if ((flags & YValue) != 0)
1938                   image->page.y+=geometry.y;
1939               }
1940             else
1941               {
1942                 if ((flags & XValue) != 0)
1943                   {
1944                     image->page.x=geometry.x;
1945                     if (((flags & WidthValue) != 0) && (geometry.x > 0))
1946                       image->page.width=image->columns+geometry.x;
1947                   }
1948                 if ((flags & YValue) != 0)
1949                   {
1950                     image->page.y=geometry.y;
1951                     if (((flags & HeightValue) != 0) && (geometry.y > 0))
1952                       image->page.height=image->rows+geometry.y;
1953                   }
1954               }
1955           }
1956           break;
1957         }
1958       if (info)
1959         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1960       for ( ; image; image=image->next)
1961         SetImageProperty(image,attribute,SvPV(sval,na));
1962       break;
1963     }
1964     case 'S':
1965     case 's':
1966     {
1967       if (LocaleCompare(attribute,"sampling-factor") == 0)
1968         {
1969           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1970             {
1971               ThrowPerlException(exception,OptionError,"MissingGeometry",
1972                 SvPV(sval,na));
1973               break;
1974             }
1975           if (info)
1976             (void) CloneString(&info->image_info->sampling_factor,
1977               SvPV(sval,na));
1978           break;
1979         }
1980       if (LocaleCompare(attribute,"scene") == 0)
1981         {
1982           for ( ; image; image=image->next)
1983             image->scene=SvIV(sval);
1984           break;
1985         }
1986       if (LocaleCompare(attribute,"server") == 0)
1987         goto display;
1988       if (LocaleCompare(attribute,"size") == 0)
1989         {
1990           if (info)
1991             {
1992               if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1993                 {
1994                   ThrowPerlException(exception,OptionError,"MissingGeometry",
1995                     SvPV(sval,na));
1996                   break;
1997                 }
1998               (void) CloneString(&info->image_info->size,SvPV(sval,na));
1999             }
2000           break;
2001         }
2002       if (LocaleCompare(attribute,"stroke") == 0)
2003         {
2004           if (info)
2005             (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2006           break;
2007         }
2008       if (info)
2009         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2010       for ( ; image; image=image->next)
2011         SetImageProperty(image,attribute,SvPV(sval,na));
2012       break;
2013     }
2014     case 'T':
2015     case 't':
2016     {
2017       if (LocaleCompare(attribute,"texture") == 0)
2018         {
2019           if (info)
2020             (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2021           break;
2022         }
2023       if (LocaleCompare(attribute,"thread-limit") == 0)
2024         {
2025           MagickSizeType
2026             limit;
2027
2028           limit=MagickResourceInfinity;
2029           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2030             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
2031           (void) SetMagickResourceLimit(ThreadResource,limit);
2032           break;
2033         }
2034       if (LocaleCompare(attribute,"tile-offset") == 0)
2035         {
2036           char
2037             *geometry;
2038
2039           geometry=GetPageGeometry(SvPV(sval,na));
2040           if (info)
2041             (void) CloneString(&info->image_info->page,geometry);
2042           for ( ; image; image=image->next)
2043             (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2044               exception);
2045           geometry=(char *) RelinquishMagickMemory(geometry);
2046           break;
2047         }
2048       if (LocaleCompare(attribute,"time-limit") == 0)
2049         {
2050           MagickSizeType
2051             limit;
2052
2053           limit=MagickResourceInfinity;
2054           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2055             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
2056           (void) SetMagickResourceLimit(TimeResource,limit);
2057           break;
2058         }
2059       if (LocaleCompare(attribute,"transparent-color") == 0)
2060         {
2061           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
2062           if (info)
2063             info->image_info->transparent_color=target_color;
2064           for ( ; image; image=image->next)
2065             image->transparent_color=target_color;
2066           break;
2067         }
2068       if (LocaleCompare(attribute,"type") == 0)
2069         {
2070           sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2071             SvPV(sval,na)) : SvIV(sval);
2072           if (sp < 0)
2073             {
2074               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2075                 SvPV(sval,na));
2076               break;
2077             }
2078           if (info)
2079             info->image_info->type=(ImageType) sp;
2080           for ( ; image; image=image->next)
2081             SetImageType(image,(ImageType) sp);
2082           break;
2083         }
2084       if (info)
2085         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2086       for ( ; image; image=image->next)
2087         SetImageProperty(image,attribute,SvPV(sval,na));
2088       break;
2089     }
2090     case 'U':
2091     case 'u':
2092     {
2093       if (LocaleCompare(attribute,"units") == 0)
2094         {
2095           sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2096             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2097           if (sp < 0)
2098             {
2099               ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2100                 SvPV(sval,na));
2101               break;
2102             }
2103           if (info)
2104             info->image_info->units=(ResolutionType) sp;
2105           for ( ; image; image=image->next)
2106           {
2107             ResolutionType
2108               units;
2109
2110             units=(ResolutionType) sp;
2111             if (image->units != units)
2112               switch (image->units)
2113               {
2114                 case UndefinedResolution:
2115                 case PixelsPerInchResolution:
2116                 {
2117                   if (units == PixelsPerCentimeterResolution)
2118                     {
2119                       image->x_resolution*=2.54;
2120                       image->y_resolution*=2.54;
2121                     }
2122                   break;
2123                 }
2124                 case PixelsPerCentimeterResolution:
2125                 {
2126                   if (units == PixelsPerInchResolution)
2127                     {
2128                       image->x_resolution/=2.54;
2129                       image->y_resolution/=2.54;
2130                     }
2131                   break;
2132                 }
2133               }
2134             image->units=units;
2135           }
2136           break;
2137         }
2138       if (info)
2139         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2140       for ( ; image; image=image->next)
2141         SetImageProperty(image,attribute,SvPV(sval,na));
2142       break;
2143     }
2144     case 'V':
2145     case 'v':
2146     {
2147       if (LocaleCompare(attribute,"verbose") == 0)
2148         {
2149           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2150             SvPV(sval,na)) : SvIV(sval);
2151           if (sp < 0)
2152             {
2153               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2154                 SvPV(sval,na));
2155               break;
2156             }
2157           if (info)
2158             info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2159           break;
2160         }
2161       if (LocaleCompare(attribute,"view") == 0)
2162         {
2163           if (info)
2164             (void) CloneString(&info->image_info->view,SvPV(sval,na));
2165           break;
2166         }
2167       if (LocaleCompare(attribute,"virtual-pixel") == 0)
2168         {
2169           sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2170             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2171           if (sp < 0)
2172             {
2173               ThrowPerlException(exception,OptionError,
2174                 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2175               break;
2176             }
2177           if (info)
2178             info->image_info->virtual_pixel_method=(VirtualPixelMethod) sp;
2179           for ( ; image; image=image->next)
2180             SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp);
2181           break;
2182         }
2183       if (info)
2184         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2185       for ( ; image; image=image->next)
2186         SetImageProperty(image,attribute,SvPV(sval,na));
2187       break;
2188     }
2189     case 'W':
2190     case 'w':
2191     {
2192       if (LocaleCompare(attribute,"white-point") == 0)
2193         {
2194           for ( ; image; image=image->next)
2195           {
2196             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2197             image->chromaticity.white_point.x=geometry_info.rho;
2198             image->chromaticity.white_point.y=geometry_info.sigma;
2199             if ((flags & SigmaValue) == 0)
2200               image->chromaticity.white_point.y=
2201                 image->chromaticity.white_point.x;
2202           }
2203           break;
2204         }
2205       if (info)
2206         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2207       for ( ; image; image=image->next)
2208         SetImageProperty(image,attribute,SvPV(sval,na));
2209       break;
2210     }
2211     default:
2212     {
2213       if (info)
2214         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2215       for ( ; image; image=image->next)
2216         SetImageProperty(image,attribute,SvPV(sval,na));
2217       break;
2218     }
2219   }
2220 }
2221 \f
2222 /*
2223 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2224 %                                                                             %
2225 %                                                                             %
2226 %                                                                             %
2227 %   S e t u p L i s t                                                         %
2228 %                                                                             %
2229 %                                                                             %
2230 %                                                                             %
2231 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2232 %
2233 %  Method SetupList returns the list of all the images linked by their
2234 %  image->next and image->previous link lists for use with ImageMagick.  If
2235 %  info is non-NULL, an info structure is returned in *info.  If
2236 %  reference_vector is non-NULL,an array of SV* are returned in
2237 %  *reference_vector.  Reference_vector is used when the images are going to be
2238 %  replaced with new Image*'s.
2239 %
2240 %  The format of the SetupList routine is:
2241 %
2242 %      Image *SetupList(SV *reference,struct PackageInfo **info,
2243 %        SV ***reference_vector,ExceptionInfo *exception)
2244 %
2245 %  A description of each parameter follows:
2246 %
2247 %    o list: a list of strings.
2248 %
2249 %    o string: a character string.
2250 %
2251 %    o exception: Return any errors or warnings in this structure.
2252 %
2253 */
2254 static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2255   SV ***reference_vector,ExceptionInfo *exception)
2256 {
2257   Image
2258     *image;
2259
2260   ssize_t
2261     current,
2262     last;
2263
2264   if (reference_vector)
2265     *reference_vector=NULL;
2266   if (info)
2267     *info=NULL;
2268   current=0;
2269   last=0;
2270   image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2271   if (info && (SvTYPE(reference) == SVt_PVAV))
2272     *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2273       exception);
2274   return(image);
2275 }
2276 \f
2277 /*
2278 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2279 %                                                                             %
2280 %                                                                             %
2281 %                                                                             %
2282 %   s t r E Q c a s e                                                         %
2283 %                                                                             %
2284 %                                                                             %
2285 %                                                                             %
2286 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2287 %
2288 %  strEQcase() compares two strings and returns 0 if they are the
2289 %  same or if the second string runs out first.  The comparison is case
2290 %  insensitive.
2291 %
2292 %  The format of the strEQcase routine is:
2293 %
2294 %      ssize_t strEQcase(const char *p,const char *q)
2295 %
2296 %  A description of each parameter follows:
2297 %
2298 %    o p: a character string.
2299 %
2300 %    o q: a character string.
2301 %
2302 %
2303 */
2304 static ssize_t strEQcase(const char *p,const char *q)
2305 {
2306   char
2307     c;
2308
2309   register ssize_t
2310     i;
2311
2312   for (i=0 ; (c=(*q)) != 0; i++)
2313   {
2314     if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2315         (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2316       return(0);
2317     p++;
2318     q++;
2319   }
2320   return(((*q == 0) && (*p == 0)) ? i : 0);
2321 }
2322 \f
2323 /*
2324 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2325 %                                                                             %
2326 %                                                                             %
2327 %                                                                             %
2328 %   I m a g e : : M a g i c k                                                 %
2329 %                                                                             %
2330 %                                                                             %
2331 %                                                                             %
2332 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2333 %
2334 %
2335 */
2336 MODULE = Image::Magick PACKAGE = Image::Magick
2337
2338 PROTOTYPES: ENABLE
2339
2340 BOOT:
2341   MagickCoreGenesis("PerlMagick",MagickFalse);
2342   SetWarningHandler(NULL);
2343   SetErrorHandler(NULL);
2344   magick_registry=NewSplayTree((int (*)(const void *,const void *))
2345     NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2346
2347 void
2348 UNLOAD()
2349   PPCODE:
2350   {
2351     if (magick_registry != (SplayTreeInfo *) NULL)
2352       magick_registry=DestroySplayTree(magick_registry);
2353     MagickCoreTerminus();
2354   }
2355
2356 double
2357 constant(name,argument)
2358   char *name
2359   ssize_t argument
2360 \f
2361 #
2362 ###############################################################################
2363 #                                                                             #
2364 #                                                                             #
2365 #                                                                             #
2366 #   A n i m a t e                                                             #
2367 #                                                                             #
2368 #                                                                             #
2369 #                                                                             #
2370 ###############################################################################
2371 #
2372 #
2373 void
2374 Animate(ref,...)
2375   Image::Magick ref=NO_INIT
2376   ALIAS:
2377     AnimateImage  = 1
2378     animate       = 2
2379     animateimage  = 3
2380   PPCODE:
2381   {
2382     ExceptionInfo
2383       *exception;
2384
2385     Image
2386       *image;
2387
2388     register ssize_t
2389       i;
2390
2391     struct PackageInfo
2392       *info,
2393       *package_info;
2394
2395     SV
2396       *perl_exception,
2397       *reference;
2398
2399     PERL_UNUSED_VAR(ref);
2400     PERL_UNUSED_VAR(ix);
2401     exception=AcquireExceptionInfo();
2402     perl_exception=newSVpv("",0);
2403     package_info=(struct PackageInfo *) NULL;
2404     if (sv_isobject(ST(0)) == 0)
2405       {
2406         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2407           PackageName);
2408         goto PerlException;
2409       }
2410     reference=SvRV(ST(0));
2411     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2412     if (image == (Image *) NULL)
2413       {
2414         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2415           PackageName);
2416         goto PerlException;
2417       }
2418     package_info=ClonePackageInfo(info,exception);
2419     if (items == 2)
2420       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2421     else
2422       if (items > 2)
2423         for (i=2; i < items; i+=2)
2424           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2425             exception);
2426     (void) AnimateImages(package_info->image_info,image);
2427     (void) CatchImageException(image);
2428     InheritException(exception,&image->exception);
2429
2430   PerlException:
2431     if (package_info != (struct PackageInfo *) NULL)
2432       DestroyPackageInfo(package_info);
2433     InheritPerlException(exception,perl_exception);
2434     exception=DestroyExceptionInfo(exception);
2435     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2436     SvPOK_on(perl_exception);
2437     ST(0)=sv_2mortal(perl_exception);
2438     XSRETURN(1);
2439   }
2440 \f
2441 #
2442 ###############################################################################
2443 #                                                                             #
2444 #                                                                             #
2445 #                                                                             #
2446 #   A p p e n d                                                               #
2447 #                                                                             #
2448 #                                                                             #
2449 #                                                                             #
2450 ###############################################################################
2451 #
2452 #
2453 void
2454 Append(ref,...)
2455   Image::Magick ref=NO_INIT
2456   ALIAS:
2457     AppendImage  = 1
2458     append       = 2
2459     appendimage  = 3
2460   PPCODE:
2461   {
2462     AV
2463       *av;
2464
2465     char
2466       *attribute;
2467
2468     ExceptionInfo
2469       *exception;
2470
2471     HV
2472       *hv;
2473
2474     Image
2475       *image;
2476
2477     register ssize_t
2478       i;
2479
2480     ssize_t
2481       stack;
2482
2483     struct PackageInfo
2484       *info;
2485
2486     SV
2487       *av_reference,
2488       *perl_exception,
2489       *reference,
2490       *rv,
2491       *sv;
2492
2493     PERL_UNUSED_VAR(ref);
2494     PERL_UNUSED_VAR(ix);
2495     exception=AcquireExceptionInfo();
2496     perl_exception=newSVpv("",0);
2497     sv=NULL;
2498     attribute=NULL;
2499     av=NULL;
2500     if (sv_isobject(ST(0)) == 0)
2501       {
2502         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2503           PackageName);
2504         goto PerlException;
2505       }
2506     reference=SvRV(ST(0));
2507     hv=SvSTASH(reference);
2508     av=newAV();
2509     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2510     SvREFCNT_dec(av);
2511     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2512     if (image == (Image *) NULL)
2513       {
2514         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2515           PackageName);
2516         goto PerlException;
2517       }
2518     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2519     /*
2520       Get options.
2521     */
2522     stack=MagickTrue;
2523     for (i=2; i < items; i+=2)
2524     {
2525       attribute=(char *) SvPV(ST(i-1),na);
2526       switch (*attribute)
2527       {
2528         case 'S':
2529         case 's':
2530         {
2531           if (LocaleCompare(attribute,"stack") == 0)
2532             {
2533               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2534                 SvPV(ST(i),na));
2535               if (stack < 0)
2536                 {
2537                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
2538                     SvPV(ST(i),na));
2539                   return;
2540                 }
2541               break;
2542             }
2543           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2544             attribute);
2545           break;
2546         }
2547         default:
2548         {
2549           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2550             attribute);
2551           break;
2552         }
2553       }
2554     }
2555     image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2556     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2557       goto PerlException;
2558     for ( ; image; image=image->next)
2559     {
2560       AddImageToRegistry(sv,image);
2561       rv=newRV(sv);
2562       av_push(av,sv_bless(rv,hv));
2563       SvREFCNT_dec(sv);
2564     }
2565     exception=DestroyExceptionInfo(exception);
2566     ST(0)=av_reference;
2567     SvREFCNT_dec(perl_exception);
2568     XSRETURN(1);
2569
2570   PerlException:
2571     InheritPerlException(exception,perl_exception);
2572     exception=DestroyExceptionInfo(exception);
2573     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2574     SvPOK_on(perl_exception);
2575     ST(0)=sv_2mortal(perl_exception);
2576     XSRETURN(1);
2577   }
2578 \f
2579 #
2580 ###############################################################################
2581 #                                                                             #
2582 #                                                                             #
2583 #                                                                             #
2584 #   A v e r a g e                                                             #
2585 #                                                                             #
2586 #                                                                             #
2587 #                                                                             #
2588 ###############################################################################
2589 #
2590 #
2591 void
2592 Average(ref)
2593   Image::Magick ref=NO_INIT
2594   ALIAS:
2595     AverageImage   = 1
2596     average        = 2
2597     averageimage   = 3
2598   PPCODE:
2599   {
2600     AV
2601       *av;
2602
2603     char
2604       *p;
2605
2606     ExceptionInfo
2607       *exception;
2608
2609     HV
2610       *hv;
2611
2612     Image
2613       *image;
2614
2615     struct PackageInfo
2616       *info;
2617
2618     SV
2619       *perl_exception,
2620       *reference,
2621       *rv,
2622       *sv;
2623
2624     PERL_UNUSED_VAR(ref);
2625     PERL_UNUSED_VAR(ix);
2626     exception=AcquireExceptionInfo();
2627     perl_exception=newSVpv("",0);
2628     sv=NULL;
2629     if (sv_isobject(ST(0)) == 0)
2630       {
2631         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2632           PackageName);
2633         goto PerlException;
2634       }
2635     reference=SvRV(ST(0));
2636     hv=SvSTASH(reference);
2637     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2638     if (image == (Image *) NULL)
2639       {
2640         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2641           PackageName);
2642         goto PerlException;
2643       }
2644     image=EvaluateImages(image,MeanEvaluateOperator,exception);
2645     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2646       goto PerlException;
2647     /*
2648       Create blessed Perl array for the returned image.
2649     */
2650     av=newAV();
2651     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2652     SvREFCNT_dec(av);
2653     AddImageToRegistry(sv,image);
2654     rv=newRV(sv);
2655     av_push(av,sv_bless(rv,hv));
2656     SvREFCNT_dec(sv);
2657     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2658     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
2659       "average-%.*s",(int) (MaxTextExtent-9),
2660       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2661     (void) CopyMagickString(image->filename,info->image_info->filename,
2662       MaxTextExtent);
2663     SetImageInfo(info->image_info,0,exception);
2664     exception=DestroyExceptionInfo(exception);
2665     SvREFCNT_dec(perl_exception);
2666     XSRETURN(1);
2667
2668   PerlException:
2669     InheritPerlException(exception,perl_exception);
2670     exception=DestroyExceptionInfo(exception);
2671     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2672     SvPOK_on(perl_exception);
2673     ST(0)=sv_2mortal(perl_exception);
2674     XSRETURN(1);
2675   }
2676 \f
2677 #
2678 ###############################################################################
2679 #                                                                             #
2680 #                                                                             #
2681 #                                                                             #
2682 #   B l o b T o I m a g e                                                     #
2683 #                                                                             #
2684 #                                                                             #
2685 #                                                                             #
2686 ###############################################################################
2687 #
2688 #
2689 void
2690 BlobToImage(ref,...)
2691   Image::Magick ref=NO_INIT
2692   ALIAS:
2693     BlobToImage  = 1
2694     blobtoimage  = 2
2695     blobto       = 3
2696   PPCODE:
2697   {
2698     AV
2699       *av;
2700
2701     char
2702       **keep,
2703       **list;
2704
2705     ExceptionInfo
2706       *exception;
2707
2708     HV
2709       *hv;
2710
2711     Image
2712       *image;
2713
2714     register char
2715       **p;
2716
2717     register ssize_t
2718       i;
2719
2720     ssize_t
2721       ac,
2722       n,
2723       number_images;
2724
2725     STRLEN
2726       *length;
2727
2728     struct PackageInfo
2729       *info;
2730
2731     SV
2732       *perl_exception,
2733       *reference,
2734       *rv,
2735       *sv;
2736
2737     PERL_UNUSED_VAR(ref);
2738     PERL_UNUSED_VAR(ix);
2739     exception=AcquireExceptionInfo();
2740     perl_exception=newSVpv("",0);
2741     sv=NULL;
2742     number_images=0;
2743     ac=(items < 2) ? 1 : items-1;
2744     length=(STRLEN *) NULL;
2745     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2746     if (list == (char **) NULL)
2747       {
2748         ThrowPerlException(exception,ResourceLimitError,
2749           "MemoryAllocationFailed",PackageName);
2750         goto PerlException;
2751       }
2752     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2753     if (length == (STRLEN *) NULL)
2754       {
2755         ThrowPerlException(exception,ResourceLimitError,
2756           "MemoryAllocationFailed",PackageName);
2757         goto PerlException;
2758       }
2759     if (sv_isobject(ST(0)) == 0)
2760       {
2761         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2762           PackageName);
2763         goto PerlException;
2764       }
2765     reference=SvRV(ST(0));
2766     hv=SvSTASH(reference);
2767     if (SvTYPE(reference) != SVt_PVAV)
2768       {
2769         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2770           PackageName);
2771         goto PerlException;
2772       }
2773     av=(AV *) reference;
2774     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2775       exception);
2776     n=1;
2777     if (items <= 1)
2778       {
2779         ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2780         goto PerlException;
2781       }
2782     for (n=0, i=0; i < ac; i++)
2783     {
2784       list[n]=(char *) (SvPV(ST(i+1),length[n]));
2785       if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2786         {
2787           list[n]=(char *) (SvPV(ST(i+2),length[n]));
2788           continue;
2789         }
2790       n++;
2791     }
2792     list[n]=(char *) NULL;
2793     keep=list;
2794     for (i=number_images=0; i < n; i++)
2795     {
2796       image=BlobToImage(info->image_info,list[i],length[i],exception);
2797       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2798         break;
2799       for ( ; image; image=image->next)
2800       {
2801         AddImageToRegistry(sv,image);
2802         rv=newRV(sv);
2803         av_push(av,sv_bless(rv,hv));
2804         SvREFCNT_dec(sv);
2805         number_images++;
2806       }
2807     }
2808     /*
2809       Free resources.
2810     */
2811     for (i=0; i < n; i++)
2812       if (list[i] != (char *) NULL)
2813         for (p=keep; list[i] != *p++; )
2814           if (*p == (char *) NULL)
2815             {
2816               list[i]=(char *) RelinquishMagickMemory(list[i]);
2817               break;
2818             }
2819
2820   PerlException:
2821     if (list)
2822       list=(char **) RelinquishMagickMemory(list);
2823     if (length)
2824       length=(STRLEN *) RelinquishMagickMemory(length);
2825     InheritPerlException(exception,perl_exception);
2826     exception=DestroyExceptionInfo(exception);
2827     sv_setiv(perl_exception,(IV) number_images);
2828     SvPOK_on(perl_exception);
2829     ST(0)=sv_2mortal(perl_exception);
2830     XSRETURN(1);
2831   }
2832 \f
2833 #
2834 ###############################################################################
2835 #                                                                             #
2836 #                                                                             #
2837 #                                                                             #
2838 #   C l o n e                                                                 #
2839 #                                                                             #
2840 #                                                                             #
2841 #                                                                             #
2842 ###############################################################################
2843 #
2844 #
2845 void
2846 Clone(ref)
2847   Image::Magick ref=NO_INIT
2848   ALIAS:
2849     CopyImage   = 1
2850     copy        = 2
2851     copyimage   = 3
2852     CloneImage  = 4
2853     clone       = 5
2854     cloneimage  = 6
2855     Clone       = 7
2856   PPCODE:
2857   {
2858     AV
2859       *av;
2860
2861     ExceptionInfo
2862       *exception;
2863
2864     HV
2865       *hv;
2866
2867     Image
2868       *clone,
2869       *image;
2870
2871     struct PackageInfo
2872       *info;
2873
2874     SV
2875       *perl_exception,
2876       *reference,
2877       *rv,
2878       *sv;
2879
2880     PERL_UNUSED_VAR(ref);
2881     PERL_UNUSED_VAR(ix);
2882     exception=AcquireExceptionInfo();
2883     perl_exception=newSVpv("",0);
2884     sv=NULL;
2885     if (sv_isobject(ST(0)) == 0)
2886       {
2887         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2888           PackageName);
2889         goto PerlException;
2890       }
2891     reference=SvRV(ST(0));
2892     hv=SvSTASH(reference);
2893     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2894     if (image == (Image *) NULL)
2895       {
2896         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2897           PackageName);
2898         goto PerlException;
2899       }
2900     /*
2901       Create blessed Perl array for the returned image.
2902     */
2903     av=newAV();
2904     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2905     SvREFCNT_dec(av);
2906     for ( ; image; image=image->next)
2907     {
2908       clone=CloneImage(image,0,0,MagickTrue,exception);
2909       if ((clone == (Image *) NULL) || (exception->severity >= ErrorException))
2910         break;
2911       AddImageToRegistry(sv,clone);
2912       rv=newRV(sv);
2913       av_push(av,sv_bless(rv,hv));
2914       SvREFCNT_dec(sv);
2915     }
2916     exception=DestroyExceptionInfo(exception);
2917     SvREFCNT_dec(perl_exception);
2918     XSRETURN(1);
2919
2920   PerlException:
2921     InheritPerlException(exception,perl_exception);
2922     exception=DestroyExceptionInfo(exception);
2923     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2924     SvPOK_on(perl_exception);
2925     ST(0)=sv_2mortal(perl_exception);
2926     XSRETURN(1);
2927   }
2928 \f
2929 #
2930 ###############################################################################
2931 #                                                                             #
2932 #                                                                             #
2933 #                                                                             #
2934 #   C L O N E                                                                 #
2935 #                                                                             #
2936 #                                                                             #
2937 #                                                                             #
2938 ###############################################################################
2939 #
2940 #
2941 void
2942 CLONE(ref,...)
2943   SV *ref;
2944   CODE:
2945   {
2946     PERL_UNUSED_VAR(ref);
2947     if (magick_registry != (SplayTreeInfo *) NULL)
2948       {
2949         register Image
2950           *p;
2951
2952         ResetSplayTreeIterator(magick_registry);
2953         p=(Image *) GetNextKeyInSplayTree(magick_registry);
2954         while (p != (Image *) NULL)
2955         {
2956           ReferenceImage(p);
2957           p=(Image *) GetNextKeyInSplayTree(magick_registry);
2958         }
2959       }
2960   }
2961 \f
2962 #
2963 ###############################################################################
2964 #                                                                             #
2965 #                                                                             #
2966 #                                                                             #
2967 #   C o a l e s c e                                                           #
2968 #                                                                             #
2969 #                                                                             #
2970 #                                                                             #
2971 ###############################################################################
2972 #
2973 #
2974 void
2975 Coalesce(ref)
2976   Image::Magick ref=NO_INIT
2977   ALIAS:
2978     CoalesceImage   = 1
2979     coalesce        = 2
2980     coalesceimage   = 3
2981   PPCODE:
2982   {
2983     AV
2984       *av;
2985
2986     ExceptionInfo
2987       *exception;
2988
2989     HV
2990       *hv;
2991
2992     Image
2993       *image;
2994
2995     struct PackageInfo
2996       *info;
2997
2998     SV
2999       *av_reference,
3000       *perl_exception,
3001       *reference,
3002       *rv,
3003       *sv;
3004
3005     PERL_UNUSED_VAR(ref);
3006     PERL_UNUSED_VAR(ix);
3007     exception=AcquireExceptionInfo();
3008     perl_exception=newSVpv("",0);
3009     sv=NULL;
3010     if (sv_isobject(ST(0)) == 0)
3011       {
3012         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3013           PackageName);
3014         goto PerlException;
3015       }
3016     reference=SvRV(ST(0));
3017     hv=SvSTASH(reference);
3018     av=newAV();
3019     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3020     SvREFCNT_dec(av);
3021     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3022     if (image == (Image *) NULL)
3023       {
3024         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3025           PackageName);
3026         goto PerlException;
3027       }
3028     image=CoalesceImages(image,exception);
3029     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3030       goto PerlException;
3031     for ( ; image; image=image->next)
3032     {
3033       AddImageToRegistry(sv,image);
3034       rv=newRV(sv);
3035       av_push(av,sv_bless(rv,hv));
3036       SvREFCNT_dec(sv);
3037     }
3038     exception=DestroyExceptionInfo(exception);
3039     ST(0)=av_reference;
3040     SvREFCNT_dec(perl_exception);
3041     XSRETURN(1);
3042
3043   PerlException:
3044     InheritPerlException(exception,perl_exception);
3045     exception=DestroyExceptionInfo(exception);
3046     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3047     SvPOK_on(perl_exception);
3048     ST(0)=sv_2mortal(perl_exception);
3049     XSRETURN(1);
3050   }
3051 \f
3052 #
3053 ###############################################################################
3054 #                                                                             #
3055 #                                                                             #
3056 #                                                                             #
3057 #   C o m p a r e                                                             #
3058 #                                                                             #
3059 #                                                                             #
3060 #                                                                             #
3061 ###############################################################################
3062 #
3063 #
3064 void
3065 Compare(ref,...)
3066   Image::Magick ref=NO_INIT
3067   ALIAS:
3068     CompareImages = 1
3069     compare      = 2
3070     compareimage = 3
3071   PPCODE:
3072   {
3073     AV
3074       *av;
3075
3076     char
3077       *attribute;
3078
3079     double
3080       distortion;
3081
3082     ExceptionInfo
3083       *exception;
3084
3085     HV
3086       *hv;
3087
3088     Image
3089       *difference_image,
3090       *image,
3091       *reconstruct_image;
3092
3093     MetricType
3094       metric;
3095
3096     register ssize_t
3097       i;
3098
3099     ssize_t
3100       option;
3101
3102     struct PackageInfo
3103       *info;
3104
3105     SV
3106       *av_reference,
3107       *perl_exception,
3108       *reference,
3109       *rv,
3110       *sv;
3111
3112     PERL_UNUSED_VAR(ref);
3113     PERL_UNUSED_VAR(ix);
3114     exception=AcquireExceptionInfo();
3115     perl_exception=newSVpv("",0);
3116     sv=NULL;
3117     av=NULL;
3118     attribute=NULL;
3119     if (sv_isobject(ST(0)) == 0)
3120       {
3121         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3122           PackageName);
3123         goto PerlException;
3124       }
3125     reference=SvRV(ST(0));
3126     hv=SvSTASH(reference);
3127     av=newAV();
3128     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3129     SvREFCNT_dec(av);
3130     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3131     if (image == (Image *) NULL)
3132       {
3133         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3134           PackageName);
3135         goto PerlException;
3136       }
3137     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3138     /*
3139       Get attribute.
3140     */
3141     reconstruct_image=image;
3142     metric=RootMeanSquaredErrorMetric;
3143     for (i=2; i < items; i+=2)
3144     {
3145       attribute=(char *) SvPV(ST(i-1),na);
3146       switch (*attribute)
3147       {
3148         case 'C':
3149         case 'c':
3150         {
3151           if (LocaleCompare(attribute,"channel") == 0)
3152             {
3153               ssize_t
3154                 option;
3155
3156               option=ParseChannelOption(SvPV(ST(i),na));
3157               if (option < 0)
3158                 {
3159                   ThrowPerlException(exception,OptionError,
3160                     "UnrecognizedType",SvPV(ST(i),na));
3161                   return;
3162                 }
3163               SetPixelComponentMap(image,(ChannelType) option);
3164               break;
3165             }
3166           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3167             attribute);
3168           break;
3169         }
3170         case 'F':
3171         case 'f':
3172         {
3173           if (LocaleCompare(attribute,"fuzz") == 0)
3174             {
3175               image->fuzz=SiPrefixToDouble(SvPV(ST(i),na),100.0);
3176               break;
3177             }
3178           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3179             attribute);
3180           break;
3181         }
3182         case 'I':
3183         case 'i':
3184         {
3185           if (LocaleCompare(attribute,"image") == 0)
3186             {
3187               reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3188                 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3189               break;
3190             }
3191           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3192             attribute);
3193           break;
3194         }
3195         case 'M':
3196         case 'm':
3197         {
3198           if (LocaleCompare(attribute,"metric") == 0)
3199             {
3200               option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3201                 SvPV(ST(i),na));
3202               if (option < 0)
3203                 {
3204                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3205                     SvPV(ST(i),na));
3206                   break;
3207                 }
3208               metric=(MetricType) option;
3209               break;
3210             }
3211           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3212             attribute);
3213           break;
3214         }
3215         default:
3216         {
3217           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3218             attribute);
3219           break;
3220         }
3221       }
3222     }
3223     difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3224       exception);
3225     if (difference_image != (Image *) NULL)
3226       {
3227         difference_image->error.mean_error_per_pixel=distortion;
3228         AddImageToRegistry(sv,difference_image);
3229         rv=newRV(sv);
3230         av_push(av,sv_bless(rv,hv));
3231         SvREFCNT_dec(sv);
3232       }
3233     exception=DestroyExceptionInfo(exception);
3234     ST(0)=av_reference;
3235     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3236     XSRETURN(1);
3237
3238   PerlException:
3239     InheritPerlException(exception,perl_exception);
3240     exception=DestroyExceptionInfo(exception);
3241     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3242     SvPOK_on(perl_exception);
3243     ST(0)=sv_2mortal(perl_exception);
3244     XSRETURN(1);
3245   }
3246 \f
3247 #
3248 ###############################################################################
3249 #                                                                             #
3250 #                                                                             #
3251 #                                                                             #
3252 #   C o m p a r e L a y e r s                                                 #
3253 #                                                                             #
3254 #                                                                             #
3255 #                                                                             #
3256 ###############################################################################
3257 #
3258 #
3259 void
3260 CompareLayers(ref)
3261   Image::Magick ref=NO_INIT
3262   ALIAS:
3263     CompareImagesLayers   = 1
3264     comparelayers        = 2
3265     compareimagelayers   = 3
3266   PPCODE:
3267   {
3268     AV
3269       *av;
3270
3271     char
3272       *attribute;
3273
3274     ExceptionInfo
3275       *exception;
3276
3277     HV
3278       *hv;
3279
3280     Image
3281       *image;
3282
3283     ImageLayerMethod
3284       method;
3285
3286     register ssize_t
3287       i;
3288
3289     ssize_t
3290       option;
3291
3292     struct PackageInfo
3293       *info;
3294
3295     SV
3296       *av_reference,
3297       *perl_exception,
3298       *reference,
3299       *rv,
3300       *sv;
3301
3302     PERL_UNUSED_VAR(ref);
3303     PERL_UNUSED_VAR(ix);
3304     exception=AcquireExceptionInfo();
3305     perl_exception=newSVpv("",0);
3306     sv=NULL;
3307     if (sv_isobject(ST(0)) == 0)
3308       {
3309         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3310           PackageName);
3311         goto PerlException;
3312       }
3313     reference=SvRV(ST(0));
3314     hv=SvSTASH(reference);
3315     av=newAV();
3316     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3317     SvREFCNT_dec(av);
3318     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3319     if (image == (Image *) NULL)
3320       {
3321         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3322           PackageName);
3323         goto PerlException;
3324       }
3325     method=CompareAnyLayer;
3326     for (i=2; i < items; i+=2)
3327     {
3328       attribute=(char *) SvPV(ST(i-1),na);
3329       switch (*attribute)
3330       {
3331         case 'M':
3332         case 'm':
3333         {
3334           if (LocaleCompare(attribute,"method") == 0)
3335             {
3336               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3337                 SvPV(ST(i),na));
3338               if (option < 0)
3339                 {
3340                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3341                     SvPV(ST(i),na));
3342                   break;
3343                 }
3344                method=(ImageLayerMethod) option;
3345               break;
3346             }
3347           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3348             attribute);
3349           break;
3350         }
3351         default:
3352         {
3353           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3354             attribute);
3355           break;
3356         }
3357       }
3358     }
3359     image=CompareImagesLayers(image,method,exception);
3360     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3361       goto PerlException;
3362     for ( ; image; image=image->next)
3363     {
3364       AddImageToRegistry(sv,image);
3365       rv=newRV(sv);
3366       av_push(av,sv_bless(rv,hv));
3367       SvREFCNT_dec(sv);
3368     }
3369     exception=DestroyExceptionInfo(exception);
3370     ST(0)=av_reference;
3371     SvREFCNT_dec(perl_exception);
3372     XSRETURN(1);
3373
3374   PerlException:
3375     InheritPerlException(exception,perl_exception);
3376     exception=DestroyExceptionInfo(exception);
3377     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3378     SvPOK_on(perl_exception);
3379     ST(0)=sv_2mortal(perl_exception);
3380     XSRETURN(1);
3381   }
3382 \f
3383 #
3384 ###############################################################################
3385 #                                                                             #
3386 #                                                                             #
3387 #                                                                             #
3388 #   D e s t r o y                                                             #
3389 #                                                                             #
3390 #                                                                             #
3391 #                                                                             #
3392 ###############################################################################
3393 #
3394 #
3395 void
3396 DESTROY(ref)
3397   Image::Magick ref=NO_INIT
3398   PPCODE:
3399   {
3400     SV
3401       *reference;
3402
3403     PERL_UNUSED_VAR(ref);
3404     if (sv_isobject(ST(0)) == 0)
3405       croak("ReferenceIsNotMyType");
3406     reference=SvRV(ST(0));
3407     switch (SvTYPE(reference))
3408     {
3409       case SVt_PVAV:
3410       {
3411         char
3412           message[MaxTextExtent];
3413
3414         const SV
3415           *key;
3416
3417         HV
3418           *hv;
3419
3420         GV
3421           **gvp;
3422
3423         struct PackageInfo
3424           *info;
3425
3426         SV
3427           *sv;
3428
3429         /*
3430           Array (AV *) reference
3431         */
3432         (void) FormatLocaleString(message,MaxTextExtent,"package%s%p",
3433           XS_VERSION,reference);
3434         hv=gv_stashpv(PackageName, FALSE);
3435         if (!hv)
3436           break;
3437         gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3438         if (!gvp)
3439           break;
3440         sv=GvSV(*gvp);
3441         if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3442           {
3443             info=(struct PackageInfo *) SvIV(sv);
3444             DestroyPackageInfo(info);
3445           }
3446         key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3447         (void) key;
3448         break;
3449       }
3450       case SVt_PVMG:
3451       {
3452         Image
3453           *image;
3454
3455         /*
3456           Blessed scalar = (Image *) SvIV(reference)
3457         */
3458         image=(Image *) SvIV(reference);
3459         if (image != (Image *) NULL)
3460           DeleteImageFromRegistry(reference,image);
3461         break;
3462       }
3463       default:
3464         break;
3465     }
3466   }
3467 \f
3468 #
3469 ###############################################################################
3470 #                                                                             #
3471 #                                                                             #
3472 #                                                                             #
3473 #   D i s p l a y                                                             #
3474 #                                                                             #
3475 #                                                                             #
3476 #                                                                             #
3477 ###############################################################################
3478 #
3479 #
3480 void
3481 Display(ref,...)
3482   Image::Magick ref=NO_INIT
3483   ALIAS:
3484     DisplayImage  = 1
3485     display       = 2
3486     displayimage  = 3
3487   PPCODE:
3488   {
3489     ExceptionInfo
3490       *exception;
3491
3492     Image
3493       *image;
3494
3495     register ssize_t
3496       i;
3497
3498     struct PackageInfo
3499       *info,
3500       *package_info;
3501
3502     SV
3503       *perl_exception,
3504       *reference;
3505
3506     PERL_UNUSED_VAR(ref);
3507     PERL_UNUSED_VAR(ix);
3508     exception=AcquireExceptionInfo();
3509     perl_exception=newSVpv("",0);
3510     package_info=(struct PackageInfo *) NULL;
3511     if (sv_isobject(ST(0)) == 0)
3512       {
3513         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3514           PackageName);
3515         goto PerlException;
3516       }
3517     reference=SvRV(ST(0));
3518     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3519     if (image == (Image *) NULL)
3520       {
3521         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3522           PackageName);
3523         goto PerlException;
3524       }
3525     package_info=ClonePackageInfo(info,exception);
3526     if (items == 2)
3527       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3528     else
3529       if (items > 2)
3530         for (i=2; i < items; i+=2)
3531           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3532             exception);
3533     (void) DisplayImages(package_info->image_info,image);
3534     (void) CatchImageException(image);
3535     InheritException(exception,&image->exception);
3536
3537   PerlException:
3538     if (package_info != (struct PackageInfo *) NULL)
3539       DestroyPackageInfo(package_info);
3540     InheritPerlException(exception,perl_exception);
3541     exception=DestroyExceptionInfo(exception);
3542     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3543     SvPOK_on(perl_exception);
3544     ST(0)=sv_2mortal(perl_exception);
3545     XSRETURN(1);
3546   }
3547 \f
3548 #
3549 ###############################################################################
3550 #                                                                             #
3551 #                                                                             #
3552 #                                                                             #
3553 #   E v a l u a t e I m a g e s                                               #
3554 #                                                                             #
3555 #                                                                             #
3556 #                                                                             #
3557 ###############################################################################
3558 #
3559 #
3560 void
3561 EvaluateImages(ref)
3562   Image::Magick ref=NO_INIT
3563   ALIAS:
3564     EvaluateImages   = 1
3565     evaluateimages   = 2
3566   PPCODE:
3567   {
3568     AV
3569       *av;
3570
3571     char
3572       *attribute,
3573       *p;
3574
3575     ExceptionInfo
3576       *exception;
3577
3578     HV
3579       *hv;
3580
3581     Image
3582       *image;
3583
3584     MagickEvaluateOperator
3585       op;
3586
3587     register ssize_t
3588       i;
3589
3590     struct PackageInfo
3591       *info;
3592
3593     SV
3594       *perl_exception,
3595       *reference,
3596       *rv,
3597       *sv;
3598
3599     PERL_UNUSED_VAR(ref);
3600     PERL_UNUSED_VAR(ix);
3601     exception=AcquireExceptionInfo();
3602     perl_exception=newSVpv("",0);
3603     sv=NULL;
3604     if (sv_isobject(ST(0)) == 0)
3605       {
3606         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3607           PackageName);
3608         goto PerlException;
3609       }
3610     reference=SvRV(ST(0));
3611     hv=SvSTASH(reference);
3612     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3613     if (image == (Image *) NULL)
3614       {
3615         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3616           PackageName);
3617         goto PerlException;
3618       }
3619     op=MeanEvaluateOperator;
3620     if (items == 2)
3621       {
3622         ssize_t
3623           in;
3624
3625         in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
3626           SvPV(ST(1),na));
3627         if (in < 0)
3628           {
3629             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3630               SvPV(ST(1),na));
3631             return;
3632           }
3633         op=(MagickEvaluateOperator) in;
3634       }
3635     else
3636       for (i=2; i < items; i+=2)
3637       {
3638         attribute=(char *) SvPV(ST(i-1),na);
3639         switch (*attribute)
3640         {
3641           case 'O':
3642           case 'o':
3643           {
3644             if (LocaleCompare(attribute,"operator") == 0)
3645               {
3646                 ssize_t
3647                   in;
3648
3649                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3650                   MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
3651                 if (in < 0)
3652                   {
3653                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3654                       SvPV(ST(i),na));
3655                     return;
3656                   }
3657                 op=(MagickEvaluateOperator) in;
3658                 break;
3659               }
3660             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3661               attribute);
3662             break;
3663           }
3664           default:
3665           {
3666             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3667               attribute);
3668             break;
3669           }
3670         }
3671       }
3672     image=EvaluateImages(image,op,exception);
3673     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3674       goto PerlException;
3675     /*
3676       Create blessed Perl array for the returned image.
3677     */
3678     av=newAV();
3679     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3680     SvREFCNT_dec(av);
3681     AddImageToRegistry(sv,image);
3682     rv=newRV(sv);
3683     av_push(av,sv_bless(rv,hv));
3684     SvREFCNT_dec(sv);
3685     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3686     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
3687       "evaluate-%.*s",(int) (MaxTextExtent-9),
3688       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3689     (void) CopyMagickString(image->filename,info->image_info->filename,
3690       MaxTextExtent);
3691     SetImageInfo(info->image_info,0,exception);
3692     exception=DestroyExceptionInfo(exception);
3693     SvREFCNT_dec(perl_exception);
3694     XSRETURN(1);
3695
3696   PerlException:
3697     InheritPerlException(exception,perl_exception);
3698     exception=DestroyExceptionInfo(exception);
3699     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3700     SvPOK_on(perl_exception);
3701     ST(0)=sv_2mortal(perl_exception);
3702     XSRETURN(1);
3703   }
3704 \f
3705 #
3706 ###############################################################################
3707 #                                                                             #
3708 #                                                                             #
3709 #                                                                             #
3710 #   F e a t u r e s                                                           #
3711 #                                                                             #
3712 #                                                                             #
3713 #                                                                             #
3714 ###############################################################################
3715 #
3716 #
3717 void
3718 Features(ref,...)
3719   Image::Magick ref=NO_INIT
3720   ALIAS:
3721     FeaturesImage = 1
3722     features      = 2
3723     featuresimage = 3
3724   PPCODE:
3725   {
3726 #define ChannelFeatures(channel,direction) \
3727 { \
3728   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3729     channel_features[channel].angular_second_moment[direction]); \
3730   PUSHs(sv_2mortal(newSVpv(message,0))); \
3731   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3732     channel_features[channel].contrast[direction]); \
3733   PUSHs(sv_2mortal(newSVpv(message,0))); \
3734   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3735     channel_features[channel].contrast[direction]); \
3736   PUSHs(sv_2mortal(newSVpv(message,0))); \
3737   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3738     channel_features[channel].variance_sum_of_squares[direction]); \
3739   PUSHs(sv_2mortal(newSVpv(message,0))); \
3740   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3741     channel_features[channel].inverse_difference_moment[direction]); \
3742   PUSHs(sv_2mortal(newSVpv(message,0))); \
3743   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3744     channel_features[channel].sum_average[direction]); \
3745   PUSHs(sv_2mortal(newSVpv(message,0))); \
3746   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3747     channel_features[channel].sum_variance[direction]); \
3748   PUSHs(sv_2mortal(newSVpv(message,0))); \
3749   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3750     channel_features[channel].sum_entropy[direction]); \
3751   PUSHs(sv_2mortal(newSVpv(message,0))); \
3752   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3753     channel_features[channel].entropy[direction]); \
3754   PUSHs(sv_2mortal(newSVpv(message,0))); \
3755   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3756     channel_features[channel].difference_variance[direction]); \
3757   PUSHs(sv_2mortal(newSVpv(message,0))); \
3758   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3759     channel_features[channel].difference_entropy[direction]); \
3760   PUSHs(sv_2mortal(newSVpv(message,0))); \
3761   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3762     channel_features[channel].measure_of_correlation_1[direction]); \
3763   PUSHs(sv_2mortal(newSVpv(message,0))); \
3764   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3765     channel_features[channel].measure_of_correlation_2[direction]); \
3766   PUSHs(sv_2mortal(newSVpv(message,0))); \
3767   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3768     channel_features[channel].maximum_correlation_coefficient[direction]); \
3769   PUSHs(sv_2mortal(newSVpv(message,0))); \
3770 }
3771
3772     AV
3773       *av;
3774
3775     char
3776       *attribute,
3777       message[MaxTextExtent];
3778
3779     ChannelFeatures
3780       *channel_features;
3781
3782     double
3783       distance;
3784
3785     ExceptionInfo
3786       *exception;
3787
3788     Image
3789       *image;
3790
3791     register ssize_t
3792       i;
3793
3794     ssize_t
3795       count;
3796
3797     struct PackageInfo
3798       *info;
3799
3800     SV
3801       *perl_exception,
3802       *reference;
3803
3804     PERL_UNUSED_VAR(ref);
3805     PERL_UNUSED_VAR(ix);
3806     exception=AcquireExceptionInfo();
3807     perl_exception=newSVpv("",0);
3808     av=NULL;
3809     if (sv_isobject(ST(0)) == 0)
3810       {
3811         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3812           PackageName);
3813         goto PerlException;
3814       }
3815     reference=SvRV(ST(0));
3816     av=newAV();
3817     SvREFCNT_dec(av);
3818     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3819     if (image == (Image *) NULL)
3820       {
3821         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3822           PackageName);
3823         goto PerlException;
3824       }
3825     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3826     distance=1;
3827     for (i=2; i < items; i+=2)
3828     {
3829       attribute=(char *) SvPV(ST(i-1),na);
3830       switch (*attribute)
3831       {
3832         case 'D':
3833         case 'd':
3834         {
3835           if (LocaleCompare(attribute,"distance") == 0)
3836             {
3837               distance=StringToLong((char *) SvPV(ST(1),na));
3838               break;
3839             }
3840           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3841             attribute);
3842           break;
3843         }
3844         default:
3845         {
3846           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3847             attribute);
3848           break;
3849         }
3850       }
3851     }
3852     count=0;
3853     for ( ; image; image=image->next)
3854     {
3855       channel_features=GetImageFeatures(image,distance,
3856         &image->exception);
3857       if (channel_features == (ChannelFeatures *) NULL)
3858         continue;
3859       count++;
3860       EXTEND(sp,75*count);
3861       for (i=0; i < 4; i++)
3862       {
3863         ChannelFeatures(RedChannel,i);
3864         ChannelFeatures(GreenChannel,i);
3865         ChannelFeatures(BlueChannel,i);
3866         if (image->colorspace == CMYKColorspace)
3867           ChannelFeatures(BlackChannel,i);
3868         if (image->matte != MagickFalse)
3869           ChannelFeatures(AlphaChannel,i);
3870       }
3871       channel_features=(ChannelFeatures *)
3872         RelinquishMagickMemory(channel_features);
3873     }
3874
3875   PerlException:
3876     InheritPerlException(exception,perl_exception);
3877     exception=DestroyExceptionInfo(exception);
3878     SvREFCNT_dec(perl_exception);
3879   }
3880 \f
3881 #
3882 ###############################################################################
3883 #                                                                             #
3884 #                                                                             #
3885 #                                                                             #
3886 #   F l a t t e n                                                             #
3887 #                                                                             #
3888 #                                                                             #
3889 #                                                                             #
3890 ###############################################################################
3891 #
3892 #
3893 void
3894 Flatten(ref)
3895   Image::Magick ref=NO_INIT
3896   ALIAS:
3897     FlattenImage   = 1
3898     flatten        = 2
3899     flattenimage   = 3
3900   PPCODE:
3901   {
3902     AV
3903       *av;
3904
3905     char
3906       *attribute,
3907       *p;
3908
3909     ExceptionInfo
3910       *exception;
3911
3912     HV
3913       *hv;
3914
3915     Image
3916       *image;
3917
3918     PixelPacket
3919       background_color;
3920
3921     register ssize_t
3922       i;
3923
3924     struct PackageInfo
3925       *info;
3926
3927     SV
3928       *perl_exception,
3929       *reference,
3930       *rv,
3931       *sv;
3932
3933     PERL_UNUSED_VAR(ref);
3934     PERL_UNUSED_VAR(ix);
3935     exception=AcquireExceptionInfo();
3936     perl_exception=newSVpv("",0);
3937     sv=NULL;
3938     if (sv_isobject(ST(0)) == 0)
3939       {
3940         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3941           PackageName);
3942         goto PerlException;
3943       }
3944     reference=SvRV(ST(0));
3945     hv=SvSTASH(reference);
3946     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3947     if (image == (Image *) NULL)
3948       {
3949         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3950           PackageName);
3951         goto PerlException;
3952       }
3953     background_color=image->background_color;
3954     if (items == 2)
3955       (void) QueryColorDatabase((char *) SvPV(ST(1),na),&background_color,
3956         exception);
3957     else
3958       for (i=2; i < items; i+=2)
3959       {
3960         attribute=(char *) SvPV(ST(i-1),na);
3961         switch (*attribute)
3962         {
3963           case 'B':
3964           case 'b':
3965           {
3966             if (LocaleCompare(attribute,"background") == 0)
3967               {
3968                 (void) QueryColorDatabase((char *) SvPV(ST(1),na),
3969                   &background_color,exception);
3970                 break;
3971               }
3972             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3973               attribute);
3974             break;
3975           }
3976           default:
3977           {
3978             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3979               attribute);
3980             break;
3981           }
3982         }
3983       }
3984     image->background_color=background_color;
3985     image=MergeImageLayers(image,FlattenLayer,exception);
3986     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3987       goto PerlException;
3988     /*
3989       Create blessed Perl array for the returned image.
3990     */
3991     av=newAV();
3992     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3993     SvREFCNT_dec(av);
3994     AddImageToRegistry(sv,image);
3995     rv=newRV(sv);
3996     av_push(av,sv_bless(rv,hv));
3997     SvREFCNT_dec(sv);
3998     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3999     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
4000       "flatten-%.*s",(int) (MaxTextExtent-9),
4001       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4002     (void) CopyMagickString(image->filename,info->image_info->filename,
4003       MaxTextExtent);
4004     SetImageInfo(info->image_info,0,exception);
4005     exception=DestroyExceptionInfo(exception);
4006     SvREFCNT_dec(perl_exception);
4007     XSRETURN(1);
4008
4009   PerlException:
4010     InheritPerlException(exception,perl_exception);
4011     exception=DestroyExceptionInfo(exception);
4012     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4013     SvPOK_on(perl_exception);  /* return messages in string context */
4014     ST(0)=sv_2mortal(perl_exception);
4015     XSRETURN(1);
4016   }
4017 \f
4018 #
4019 ###############################################################################
4020 #                                                                             #
4021 #                                                                             #
4022 #                                                                             #
4023 #   F x                                                                       #
4024 #                                                                             #
4025 #                                                                             #
4026 #                                                                             #
4027 ###############################################################################
4028 #
4029 #
4030 void
4031 Fx(ref,...)
4032   Image::Magick ref=NO_INIT
4033   ALIAS:
4034     FxImage  = 1
4035     fx       = 2
4036     fximage  = 3
4037   PPCODE:
4038   {
4039     AV
4040       *av;
4041
4042     char
4043       *attribute,
4044       expression[MaxTextExtent];
4045
4046     ChannelType
4047       channel;
4048
4049     ExceptionInfo
4050       *exception;
4051
4052     HV
4053       *hv;
4054
4055     Image
4056       *image;
4057
4058     register ssize_t
4059       i;
4060
4061     struct PackageInfo
4062       *info;
4063
4064     SV
4065       *av_reference,
4066       *perl_exception,
4067       *reference,
4068       *rv,
4069       *sv;
4070
4071     PERL_UNUSED_VAR(ref);
4072     PERL_UNUSED_VAR(ix);
4073     exception=AcquireExceptionInfo();
4074     perl_exception=newSVpv("",0);
4075     sv=NULL;
4076     attribute=NULL;
4077     av=NULL;
4078     if (sv_isobject(ST(0)) == 0)
4079       {
4080         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4081           PackageName);
4082         goto PerlException;
4083       }
4084     reference=SvRV(ST(0));
4085     hv=SvSTASH(reference);
4086     av=newAV();
4087     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4088     SvREFCNT_dec(av);
4089     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4090     if (image == (Image *) NULL)
4091       {
4092         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4093           PackageName);
4094         goto PerlException;
4095       }
4096     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4097     /*
4098       Get options.
4099     */
4100     channel=DefaultChannels;
4101     (void) CopyMagickString(expression,"u",MaxTextExtent);
4102     if (items == 2)
4103       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MaxTextExtent);
4104     else
4105       for (i=2; i < items; i+=2)
4106       {
4107         attribute=(char *) SvPV(ST(i-1),na);
4108         switch (*attribute)
4109         {
4110           case 'C':
4111           case 'c':
4112           {
4113             if (LocaleCompare(attribute,"channel") == 0)
4114               {
4115                 ssize_t
4116                   option;
4117
4118                 option=ParseChannelOption(SvPV(ST(i),na));
4119                 if (option < 0)
4120                   {
4121                     ThrowPerlException(exception,OptionError,
4122                       "UnrecognizedType",SvPV(ST(i),na));
4123                     return;
4124                   }
4125                 channel=(ChannelType) option;
4126                 break;
4127               }
4128             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4129               attribute);
4130             break;
4131           }
4132           case 'E':
4133           case 'e':
4134           {
4135             if (LocaleCompare(attribute,"expression") == 0)
4136               {
4137                 (void) CopyMagickString(expression,SvPV(ST(i),na),
4138                   MaxTextExtent);
4139                 break;
4140               }
4141             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4142               attribute);
4143             break;
4144           }
4145           default:
4146           {
4147             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4148               attribute);
4149             break;
4150           }
4151         }
4152       }
4153     PushPixelComponentMap(image,channel);
4154     image=FxImage(image,expression,exception);
4155     PopPixelComponentMap(image);
4156     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
4157       goto PerlException;
4158     for ( ; image; image=image->next)
4159     {
4160       AddImageToRegistry(sv,image);
4161       rv=newRV(sv);
4162       av_push(av,sv_bless(rv,hv));
4163       SvREFCNT_dec(sv);
4164     }
4165     exception=DestroyExceptionInfo(exception);
4166     ST(0)=av_reference;
4167     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4168     XSRETURN(1);
4169
4170   PerlException:
4171     InheritPerlException(exception,perl_exception);
4172     exception=DestroyExceptionInfo(exception);
4173     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4174     SvPOK_on(perl_exception);
4175     ST(0)=sv_2mortal(perl_exception);
4176     XSRETURN(1);
4177   }
4178 \f
4179 #
4180 ###############################################################################
4181 #                                                                             #
4182 #                                                                             #
4183 #                                                                             #
4184 #   G e t                                                                     #
4185 #                                                                             #
4186 #                                                                             #
4187 #                                                                             #
4188 ###############################################################################
4189 #
4190 #
4191 void
4192 Get(ref,...)
4193   Image::Magick ref=NO_INIT
4194   ALIAS:
4195     GetAttributes = 1
4196     GetAttribute  = 2
4197     get           = 3
4198     getattributes = 4
4199     getattribute  = 5
4200   PPCODE:
4201   {
4202     char
4203       *attribute,
4204       color[MaxTextExtent];
4205
4206     const char
4207       *value;
4208
4209     ExceptionInfo
4210       *exception;
4211
4212     Image
4213       *image;
4214
4215     long
4216       j;
4217
4218     register ssize_t
4219       i;
4220
4221     struct PackageInfo
4222       *info;
4223
4224     SV
4225       *perl_exception,
4226       *reference,
4227       *s;
4228
4229     PERL_UNUSED_VAR(ref);
4230     PERL_UNUSED_VAR(ix);
4231     exception=AcquireExceptionInfo();
4232     perl_exception=newSVpv("",0);
4233     if (sv_isobject(ST(0)) == 0)
4234       {
4235         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4236           PackageName);
4237         XSRETURN_EMPTY;
4238       }
4239     reference=SvRV(ST(0));
4240     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4241     if (image == (Image *) NULL && !info)
4242       XSRETURN_EMPTY;
4243     EXTEND(sp,items);
4244     for (i=1; i < items; i++)
4245     {
4246       attribute=(char *) SvPV(ST(i),na);
4247       s=NULL;
4248       switch (*attribute)
4249       {
4250         case 'A':
4251         case 'a':
4252         {
4253           if (LocaleCompare(attribute,"adjoin") == 0)
4254             {
4255               if (info)
4256                 s=newSViv((ssize_t) info->image_info->adjoin);
4257               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4258               continue;
4259             }
4260           if (LocaleCompare(attribute,"antialias") == 0)
4261             {
4262               if (info)
4263                 s=newSViv((ssize_t) info->image_info->antialias);
4264               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4265               continue;
4266             }
4267           if (LocaleCompare(attribute,"area") == 0)
4268             {
4269               s=newSViv(GetMagickResource(AreaResource));
4270               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4271               continue;
4272             }
4273           if (LocaleCompare(attribute,"attenuate") == 0)
4274             {
4275               const char
4276                 *value;
4277
4278               value=GetImageProperty(image,attribute);
4279               if (value != (const char *) NULL)
4280                 s=newSVpv(value,0);
4281               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4282               continue;
4283             }
4284           if (LocaleCompare(attribute,"authenticate") == 0)
4285             {
4286               if (info)
4287                 s=newSVpv(info->image_info->authenticate,0);
4288               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4289               continue;
4290             }
4291           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4292             attribute);
4293           break;
4294         }
4295         case 'B':
4296         case 'b':
4297         {
4298           if (LocaleCompare(attribute,"background") == 0)
4299             {
4300               if (image == (Image *) NULL)
4301                 break;
4302               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4303                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4304                 image->background_color.red,image->background_color.green,
4305                 image->background_color.blue,image->background_color.alpha);
4306               s=newSVpv(color,0);
4307               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4308               continue;
4309             }
4310           if (LocaleCompare(attribute,"base-columns") == 0)
4311             {
4312               if (image != (Image *) NULL)
4313                 s=newSViv((ssize_t) image->magick_columns);
4314               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4315               continue;
4316             }
4317           if (LocaleCompare(attribute,"base-filename") == 0)
4318             {
4319               if (image != (Image *) NULL)
4320                 s=newSVpv(image->magick_filename,0);
4321               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4322               continue;
4323             }
4324           if (LocaleCompare(attribute,"base-height") == 0)
4325             {
4326               if (image != (Image *) NULL)
4327                 s=newSViv((ssize_t) image->magick_rows);
4328               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4329               continue;
4330             }
4331           if (LocaleCompare(attribute,"base-rows") == 0)
4332             {
4333               if (image != (Image *) NULL)
4334                 s=newSViv((ssize_t) image->magick_rows);
4335               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4336               continue;
4337             }
4338           if (LocaleCompare(attribute,"base-width") == 0)
4339             {
4340               if (image != (Image *) NULL)
4341                 s=newSViv((ssize_t) image->magick_columns);
4342               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4343               continue;
4344             }
4345           if (LocaleCompare(attribute,"bias") == 0)
4346             {
4347               if (image != (Image *) NULL)
4348                 s=newSVnv(image->bias);
4349               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4350               continue;
4351             }
4352           if (LocaleCompare(attribute,"blue-primary") == 0)
4353             {
4354               if (image == (Image *) NULL)
4355                 break;
4356               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4357                 image->chromaticity.blue_primary.x,
4358                 image->chromaticity.blue_primary.y);
4359               s=newSVpv(color,0);
4360               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4361               continue;
4362             }
4363           if (LocaleCompare(attribute,"bordercolor") == 0)
4364             {
4365               if (image == (Image *) NULL)
4366                 break;
4367               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4368                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4369                 image->border_color.red,image->border_color.green,
4370                 image->border_color.blue,image->border_color.alpha);
4371               s=newSVpv(color,0);
4372               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4373               continue;
4374             }
4375           if (LocaleCompare(attribute,"bounding-box") == 0)
4376             {
4377               char
4378                 geometry[MaxTextExtent];
4379
4380               RectangleInfo
4381                 page;
4382
4383               if (image == (Image *) NULL)
4384                 break;
4385               page=GetImageBoundingBox(image,&image->exception);
4386               (void) FormatLocaleString(geometry,MaxTextExtent,
4387                 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4388                 page.height,(double) page.x,(double) page.y);
4389               s=newSVpv(geometry,0);
4390               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4391               continue;
4392             }
4393           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4394             attribute);
4395           break;
4396         }
4397         case 'C':
4398         case 'c':
4399         {
4400           if (LocaleCompare(attribute,"class") == 0)
4401             {
4402               if (image == (Image *) NULL)
4403                 break;
4404               s=newSViv(image->storage_class);
4405               (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4406                 image->storage_class));
4407               SvIOK_on(s);
4408               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4409               continue;
4410             }
4411           if (LocaleCompare(attribute,"clip-mask") == 0)
4412             {
4413               if (image != (Image *) NULL)
4414                 {
4415                   SV
4416                     *sv;
4417
4418                   sv=NULL;
4419                   if (image->mask == (Image *) NULL)
4420                     ClipImage(image);
4421                   if (image->mask != (Image *) NULL)
4422                     {
4423                       AddImageToRegistry(sv,image->mask);
4424                       s=sv_bless(newRV(sv),SvSTASH(reference));
4425                     }
4426                 }
4427               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4428               continue;
4429             }
4430           if (LocaleCompare(attribute,"clip-path") == 0)
4431             {
4432               if (image != (Image *) NULL)
4433                 {
4434                   SV
4435                     *sv;
4436
4437                   sv=NULL;
4438                   if (image->clip_mask == (Image *) NULL)
4439                     ClipImage(image);
4440                   if (image->clip_mask != (Image *) NULL)
4441                     {
4442                       AddImageToRegistry(sv,image->clip_mask);
4443                       s=sv_bless(newRV(sv),SvSTASH(reference));
4444                     }
4445                 }
4446               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4447               continue;
4448             }
4449           if (LocaleCompare(attribute,"compression") == 0)
4450             {
4451               j=info ? info->image_info->compression : image ?
4452                 image->compression : UndefinedCompression;
4453               if (info)
4454                 if (info->image_info->compression == UndefinedCompression)
4455                   j=image->compression;
4456               s=newSViv(j);
4457               (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4458                 j));
4459               SvIOK_on(s);
4460               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4461               continue;
4462             }
4463           if (LocaleCompare(attribute,"colorspace") == 0)
4464             {
4465               j=image ? image->colorspace : RGBColorspace;
4466               s=newSViv(j);
4467               (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4468                 j));
4469               SvIOK_on(s);
4470               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4471               continue;
4472             }
4473           if (LocaleCompare(attribute,"colors") == 0)
4474             {
4475               if (image != (Image *) NULL)
4476                 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4477                   &image->exception));
4478               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4479               continue;
4480             }
4481           if (LocaleNCompare(attribute,"colormap",8) == 0)
4482             {
4483               int
4484                 items;
4485
4486               if (image == (Image *) NULL || !image->colormap)
4487                 break;
4488               j=0;
4489               items=sscanf(attribute,"%*[^[][%ld",&j);
4490               (void) items;
4491               if (j > (ssize_t) image->colors)
4492                 j%=image->colors;
4493               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4494                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4495                 image->colormap[j].red,image->colormap[j].green,
4496                 image->colormap[j].blue,image->colormap[j].alpha);
4497               s=newSVpv(color,0);
4498               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4499               continue;
4500             }
4501           if (LocaleCompare(attribute,"columns") == 0)
4502             {
4503               if (image != (Image *) NULL)
4504                 s=newSViv((ssize_t) image->columns);
4505               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4506               continue;
4507             }
4508           if (LocaleCompare(attribute,"comment") == 0)
4509             {
4510               const char
4511                 *value;
4512
4513               value=GetImageProperty(image,attribute);
4514               if (value != (const char *) NULL)
4515                 s=newSVpv(value,0);
4516               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4517               continue;
4518             }
4519           if (LocaleCompare(attribute,"copyright") == 0)
4520             {
4521               s=newSVpv(GetMagickCopyright(),0);
4522               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4523               continue;
4524             }
4525           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4526             attribute);
4527           break;
4528         }
4529         case 'D':
4530         case 'd':
4531         {
4532           if (LocaleCompare(attribute,"density") == 0)
4533             {
4534               char
4535                 geometry[MaxTextExtent];
4536
4537               if (image == (Image *) NULL)
4538                 break;
4539               (void) FormatLocaleString(geometry,MaxTextExtent,"%.15gx%.15g",
4540                 image->x_resolution,image->y_resolution);
4541               s=newSVpv(geometry,0);
4542               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4543               continue;
4544             }
4545           if (LocaleCompare(attribute,"delay") == 0)
4546             {
4547               if (image != (Image *) NULL)
4548                 s=newSViv((ssize_t) image->delay);
4549               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4550               continue;
4551             }
4552           if (LocaleCompare(attribute,"depth") == 0)
4553             {
4554               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4555               if (image != (Image *) NULL)
4556                 s=newSViv((ssize_t) GetImageDepth(image,&image->exception));
4557               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4558               continue;
4559             }
4560           if (LocaleCompare(attribute,"directory") == 0)
4561             {
4562               if (image && image->directory)
4563                 s=newSVpv(image->directory,0);
4564               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4565               continue;
4566             }
4567           if (LocaleCompare(attribute,"dispose") == 0)
4568             {
4569               if (image == (Image *) NULL)
4570                 break;
4571
4572               s=newSViv(image->dispose);
4573               (void) sv_setpv(s,
4574                 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
4575               SvIOK_on(s);
4576               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4577               continue;
4578             }
4579           if (LocaleCompare(attribute,"disk") == 0)
4580             {
4581               s=newSViv(GetMagickResource(DiskResource));
4582               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4583               continue;
4584             }
4585           if (LocaleCompare(attribute,"dither") == 0)
4586             {
4587               if (info)
4588                 s=newSViv((ssize_t) info->image_info->dither);
4589               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4590               continue;
4591             }
4592           if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4593             {
4594               if (info && info->image_info->server_name)
4595                 s=newSVpv(info->image_info->server_name,0);
4596               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4597               continue;
4598             }
4599           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4600             attribute);
4601           break;
4602         }
4603         case 'E':
4604         case 'e':
4605         {
4606           if (LocaleCompare(attribute,"elapsed-time") == 0)
4607             {
4608               if (image != (Image *) NULL)
4609                 s=newSVnv(GetElapsedTime(&image->timer));
4610               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4611               continue;
4612             }
4613           if (LocaleCompare(attribute,"endian") == 0)
4614             {
4615               j=info ? info->image_info->endian : image ? image->endian :
4616                 UndefinedEndian;
4617               s=newSViv(j);
4618               (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
4619               SvIOK_on(s);
4620               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4621               continue;
4622             }
4623           if (LocaleCompare(attribute,"error") == 0)
4624             {
4625               if (image != (Image *) NULL)
4626                 s=newSVnv(image->error.mean_error_per_pixel);
4627               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4628               continue;
4629             }
4630           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4631             attribute);
4632           break;
4633         }
4634         case 'F':
4635         case 'f':
4636         {
4637           if (LocaleCompare(attribute,"filesize") == 0)
4638             {
4639               if (image != (Image *) NULL)
4640                 s=newSViv((ssize_t) GetBlobSize(image));
4641               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4642               continue;
4643             }
4644           if (LocaleCompare(attribute,"filename") == 0)
4645             {
4646               if (info && info->image_info->filename &&
4647                   *info->image_info->filename)
4648                 s=newSVpv(info->image_info->filename,0);
4649               if (image != (Image *) NULL)
4650                 s=newSVpv(image->filename,0);
4651               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4652               continue;
4653             }
4654           if (LocaleCompare(attribute,"filter") == 0)
4655             {
4656               s=image ? newSViv(image->filter) : newSViv(0);
4657               (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
4658                 image->filter));
4659               SvIOK_on(s);
4660               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4661               continue;
4662             }
4663           if (LocaleCompare(attribute,"font") == 0)
4664             {
4665               if (info && info->image_info->font)
4666                 s=newSVpv(info->image_info->font,0);
4667               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4668               continue;
4669             }
4670           if (LocaleCompare(attribute,"foreground") == 0)
4671             continue;
4672           if (LocaleCompare(attribute,"format") == 0)
4673             {
4674               const MagickInfo
4675                 *magick_info;
4676
4677               magick_info=(const MagickInfo *) NULL;
4678               if (info && (*info->image_info->magick != '\0'))
4679                 magick_info=GetMagickInfo(info->image_info->magick,exception);
4680               if (image != (Image *) NULL)
4681                 magick_info=GetMagickInfo(image->magick,&image->exception);
4682               if ((magick_info != (const MagickInfo *) NULL) &&
4683                   (*magick_info->description != '\0'))
4684                 s=newSVpv((char *) magick_info->description,0);
4685               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4686               continue;
4687             }
4688           if (LocaleCompare(attribute,"fuzz") == 0)
4689             {
4690               if (info)
4691                 s=newSVnv(info->image_info->fuzz);
4692               if (image != (Image *) NULL)
4693                 s=newSVnv(image->fuzz);
4694               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4695               continue;
4696             }
4697           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4698             attribute);
4699           break;
4700         }
4701         case 'G':
4702         case 'g':
4703         {
4704           if (LocaleCompare(attribute,"gamma") == 0)
4705             {
4706               if (image != (Image *) NULL)
4707                 s=newSVnv(image->gamma);
4708               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4709               continue;
4710             }
4711           if (LocaleCompare(attribute,"geometry") == 0)
4712             {
4713               if (image && image->geometry)
4714                 s=newSVpv(image->geometry,0);
4715               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4716               continue;
4717             }
4718           if (LocaleCompare(attribute,"gravity") == 0)
4719             {
4720               s=image ? newSViv(image->gravity) : newSViv(0);
4721               (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
4722                 image->gravity));
4723               SvIOK_on(s);
4724               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4725               continue;
4726             }
4727           if (LocaleCompare(attribute,"green-primary") == 0)
4728             {
4729               if (image == (Image *) NULL)
4730                 break;
4731               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4732                 image->chromaticity.green_primary.x,
4733                 image->chromaticity.green_primary.y);
4734               s=newSVpv(color,0);
4735               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4736               continue;
4737             }
4738           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4739             attribute);
4740           break;
4741         }
4742         case 'H':
4743         case 'h':
4744         {
4745           if (LocaleCompare(attribute,"height") == 0)
4746             {
4747               if (image != (Image *) NULL)
4748                 s=newSViv((ssize_t) image->rows);
4749               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4750               continue;
4751             }
4752           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4753             attribute);
4754           break;
4755         }
4756         case 'I':
4757         case 'i':
4758         {
4759           if (LocaleCompare(attribute,"icc") == 0)
4760             {
4761               if (image != (Image *) NULL)
4762                 {
4763                   const StringInfo
4764                     *profile;
4765
4766                   profile=GetImageProfile(image,"icc");
4767                   if (profile != (StringInfo *) NULL)
4768                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4769                       GetStringInfoLength(profile));
4770                 }
4771               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4772               continue;
4773             }
4774           if (LocaleCompare(attribute,"icm") == 0)
4775             {
4776               if (image != (Image *) NULL)
4777                 {
4778                   const StringInfo
4779                     *profile;
4780
4781                   profile=GetImageProfile(image,"icm");
4782                   if (profile != (const StringInfo *) NULL)
4783                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4784                       GetStringInfoLength(profile));
4785                 }
4786               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4787               continue;
4788             }
4789           if (LocaleCompare(attribute,"id") == 0)
4790             {
4791               if (image != (Image *) NULL)
4792                 {
4793                   char
4794                     key[MaxTextExtent];
4795
4796                   MagickBooleanType
4797                     status;
4798
4799                   static ssize_t
4800                     id = 0;
4801
4802                   (void) FormatLocaleString(key,MaxTextExtent,"%.20g\n",(double)
4803                     id);
4804                   status=SetImageRegistry(ImageRegistryType,key,image,
4805                     &image->exception);
4806                   (void) status;
4807                   s=newSViv(id++);
4808                 }
4809               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4810               continue;
4811             }
4812           if (LocaleNCompare(attribute,"index",5) == 0)
4813             {
4814               char
4815                 name[MaxTextExtent];
4816
4817               int
4818                 items;
4819
4820               long
4821                 x,
4822                 y;
4823
4824               register const Quantum
4825                 *p;
4826
4827               CacheView
4828                 *image_view;
4829
4830               if (image == (Image *) NULL)
4831                 break;
4832               if (image->storage_class != PseudoClass)
4833                 break;
4834               x=0;
4835               y=0;
4836               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
4837               (void) items;
4838               image_view=AcquireCacheView(image);
4839               p=GetCacheViewVirtualPixels(image_view,x,y,1,1,&image->exception);
4840               if (p != (const Quantum *) NULL)
4841                 {
4842                   (void) FormatLocaleString(name,MaxTextExtent,QuantumFormat,
4843                     GetPixelIndex(image,p));
4844                   s=newSVpv(name,0);
4845                   PUSHs(s ? sv_2mortal(s) : &sv_undef);
4846                 }
4847               image_view=DestroyCacheView(image_view);
4848               continue;
4849             }
4850           if (LocaleCompare(attribute,"iptc") == 0)
4851             {
4852               if (image != (Image *) NULL)
4853                 {
4854                   const StringInfo
4855                     *profile;
4856
4857                   profile=GetImageProfile(image,"iptc");
4858                   if (profile != (const StringInfo *) NULL)
4859                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4860                       GetStringInfoLength(profile));
4861                 }
4862               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4863               continue;
4864             }
4865           if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
4866             {
4867               if (image != (Image *) NULL)
4868                 s=newSViv((ssize_t) image->iterations);
4869               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4870               continue;
4871             }
4872           if (LocaleCompare(attribute,"interlace") == 0)
4873             {
4874               j=info ? info->image_info->interlace : image ? image->interlace :
4875                 UndefinedInterlace;
4876               s=newSViv(j);
4877               (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
4878                 j));
4879               SvIOK_on(s);
4880               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4881               continue;
4882             }
4883           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4884             attribute);
4885           break;
4886         }
4887         case 'L':
4888         case 'l':
4889         {
4890           if (LocaleCompare(attribute,"label") == 0)
4891             {
4892               const char
4893                 *value;
4894
4895               if (image == (Image *) NULL)
4896                 break;
4897               value=GetImageProperty(image,"Label");
4898               if (value != (const char *) NULL)
4899                 s=newSVpv(value,0);
4900               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4901               continue;
4902             }
4903           if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
4904             {
4905               if (image != (Image *) NULL)
4906                 s=newSViv((ssize_t) image->iterations);
4907               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4908               continue;
4909             }
4910           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4911             attribute);
4912           break;
4913         }
4914         case 'M':
4915         case 'm':
4916         {
4917           if (LocaleCompare(attribute,"magick") == 0)
4918             {
4919               if (info && *info->image_info->magick)
4920                 s=newSVpv(info->image_info->magick,0);
4921               if (image != (Image *) NULL)
4922                 s=newSVpv(image->magick,0);
4923               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4924               continue;
4925             }
4926           if (LocaleCompare(attribute,"map") == 0)
4927             {
4928               s=newSViv(GetMagickResource(MapResource));
4929               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4930               continue;
4931             }
4932           if (LocaleCompare(attribute,"maximum-error") == 0)
4933             {
4934               if (image != (Image *) NULL)
4935                 s=newSVnv(image->error.normalized_maximum_error);
4936               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4937               continue;
4938             }
4939           if (LocaleCompare(attribute,"memory") == 0)
4940             {
4941               s=newSViv(GetMagickResource(MemoryResource));
4942               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4943               continue;
4944             }
4945           if (LocaleCompare(attribute,"mean-error") == 0)
4946             {
4947               if (image != (Image *) NULL)
4948                 s=newSVnv(image->error.normalized_mean_error);
4949               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4950               continue;
4951             }
4952           if (LocaleCompare(attribute,"mime") == 0)
4953             {
4954               if (info && *info->image_info->magick)
4955                 s=newSVpv(MagickToMime(info->image_info->magick),0);
4956               if (image != (Image *) NULL)
4957                 s=newSVpv(MagickToMime(image->magick),0);
4958               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4959               continue;
4960             }
4961           if (LocaleCompare(attribute,"mattecolor") == 0)
4962             {
4963               if (image == (Image *) NULL)
4964                 break;
4965               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4966                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4967                 image->matte_color.red,image->matte_color.green,
4968                 image->matte_color.blue,image->matte_color.alpha);
4969               s=newSVpv(color,0);
4970               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4971               continue;
4972             }
4973           if (LocaleCompare(attribute,"matte") == 0)
4974             {
4975               if (image != (Image *) NULL)
4976                 s=newSViv((ssize_t) image->matte);
4977               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4978               continue;
4979             }
4980           if (LocaleCompare(attribute,"mime") == 0)
4981             {
4982               const char
4983                 *magick;
4984
4985               magick=NULL;
4986               if (info && *info->image_info->magick)
4987                 magick=info->image_info->magick;
4988               if (image != (Image *) NULL)
4989                 magick=image->magick;
4990               if (magick)
4991                 {
4992                   char
4993                     *mime;
4994
4995                   mime=MagickToMime(magick);
4996                   s=newSVpv(mime,0);
4997                   mime=(char *) RelinquishMagickMemory(mime);
4998                 }
4999               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5000               continue;
5001             }
5002           if (LocaleCompare(attribute,"monochrome") == 0)
5003             {
5004               if (image == (Image *) NULL)
5005                 continue;
5006               j=info ? info->image_info->monochrome :
5007                 IsImageMonochrome(image,&image->exception);
5008               s=newSViv(j);
5009               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5010               continue;
5011             }
5012           if (LocaleCompare(attribute,"montage") == 0)
5013             {
5014               if (image && image->montage)
5015                 s=newSVpv(image->montage,0);
5016               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5017               continue;
5018             }
5019           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5020             attribute);
5021           break;
5022         }
5023         case 'O':
5024         case 'o':
5025         {
5026           if (LocaleCompare(attribute,"orientation") == 0)
5027             {
5028               j=info ? info->image_info->orientation : image ?
5029                 image->orientation : UndefinedOrientation;
5030               s=newSViv(j);
5031               (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5032                 j));
5033               SvIOK_on(s);
5034               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5035               continue;
5036             }
5037           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5038             attribute);
5039           break;
5040         }
5041         case 'P':
5042         case 'p':
5043         {
5044           if (LocaleCompare(attribute,"page") == 0)
5045             {
5046               if (info && info->image_info->page)
5047                 s=newSVpv(info->image_info->page,0);
5048               if (image != (Image *) NULL)
5049                 {
5050                   char
5051                     geometry[MaxTextExtent];
5052
5053                   (void) FormatLocaleString(geometry,MaxTextExtent,
5054                     "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5055                     (double) image->page.height,(double) image->page.x,(double)
5056                     image->page.y);
5057                   s=newSVpv(geometry,0);
5058                 }
5059               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5060               continue;
5061             }
5062           if (LocaleCompare(attribute,"page.x") == 0)
5063             {
5064               if (image != (Image *) NULL)
5065                 s=newSViv((ssize_t) image->page.x);
5066               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5067               continue;
5068             }
5069           if (LocaleCompare(attribute,"page.y") == 0)
5070             {
5071               if (image != (Image *) NULL)
5072                 s=newSViv((ssize_t) image->page.y);
5073               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5074               continue;
5075             }
5076           if (LocaleNCompare(attribute,"pixel",5) == 0)
5077             {
5078               char
5079                 tuple[MaxTextExtent];
5080
5081               int
5082                 items;
5083
5084               long
5085                 x,
5086                 y;
5087
5088               register const Quantum
5089                 *p;
5090
5091               if (image == (Image *) NULL)
5092                 break;
5093               x=0;
5094               y=0;
5095               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5096               (void) items;
5097               p=GetVirtualPixels(image,x,y,1,1,exception);
5098               if (image->colorspace != CMYKColorspace)
5099                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5100                   QuantumFormat "," QuantumFormat "," QuantumFormat,
5101                   GetPixelRed(image,p),GetPixelGreen(image,p),
5102                   GetPixelBlue(image,p),GetPixelAlpha(image,p));
5103               else
5104                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5105                   QuantumFormat "," QuantumFormat "," QuantumFormat ","
5106                   QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5107                   GetPixelBlue(image,p),GetPixelBlack(image,p),
5108                   GetPixelAlpha(image,p));
5109               s=newSVpv(tuple,0);
5110               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5111               continue;
5112             }
5113           if (LocaleCompare(attribute,"pointsize") == 0)
5114             {
5115               if (info)
5116                 s=newSViv((ssize_t) info->image_info->pointsize);
5117               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5118               continue;
5119             }
5120           if (LocaleCompare(attribute,"preview") == 0)
5121             {
5122               s=newSViv(info->image_info->preview_type);
5123               (void) sv_setpv(s,CommandOptionToMnemonic(MagickPreviewOptions,
5124                 info->image_info->preview_type));
5125               SvIOK_on(s);
5126               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5127               continue;
5128             }
5129           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5130             attribute);
5131           break;
5132         }
5133         case 'Q':
5134         case 'q':
5135         {
5136           if (LocaleCompare(attribute,"quality") == 0)
5137             {
5138               if (info)
5139                 s=newSViv((ssize_t) info->image_info->quality);
5140               if (image != (Image *) NULL)
5141                 s=newSViv((ssize_t) image->quality);
5142               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5143               continue;
5144             }
5145           if (LocaleCompare(attribute,"quantum") == 0)
5146             {
5147               if (info)
5148                 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5149               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5150               continue;
5151             }
5152           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5153             attribute);
5154           break;
5155         }
5156         case 'R':
5157         case 'r':
5158         {
5159           if (LocaleCompare(attribute,"rendering-intent") == 0)
5160             {
5161               s=newSViv(image->rendering_intent);
5162               (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5163                 image->rendering_intent));
5164               SvIOK_on(s);
5165               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5166               continue;
5167             }
5168           if (LocaleCompare(attribute,"red-primary") == 0)
5169             {
5170               if (image == (Image *) NULL)
5171                 break;
5172               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5173                 image->chromaticity.red_primary.x,
5174                 image->chromaticity.red_primary.y);
5175               s=newSVpv(color,0);
5176               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5177               continue;
5178             }
5179           if (LocaleCompare(attribute,"rows") == 0)
5180             {
5181               if (image != (Image *) NULL)
5182                 s=newSViv((ssize_t) image->rows);
5183               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5184               continue;
5185             }
5186           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5187             attribute);
5188           break;
5189         }
5190         case 'S':
5191         case 's':
5192         {
5193           if (LocaleCompare(attribute,"sampling-factor") == 0)
5194             {
5195               if (info && info->image_info->sampling_factor)
5196                 s=newSVpv(info->image_info->sampling_factor,0);
5197               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5198               continue;
5199             }
5200           if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5201             {
5202               if (info && info->image_info->server_name)
5203                 s=newSVpv(info->image_info->server_name,0);
5204               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5205               continue;
5206             }
5207           if (LocaleCompare(attribute,"size") == 0)
5208             {
5209               if (info && info->image_info->size)
5210                 s=newSVpv(info->image_info->size,0);
5211               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5212               continue;
5213             }
5214           if (LocaleCompare(attribute,"scene") == 0)
5215             {
5216               if (image != (Image *) NULL)
5217                 s=newSViv((ssize_t) image->scene);
5218               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5219               continue;
5220             }
5221           if (LocaleCompare(attribute,"scenes") == 0)
5222             {
5223               if (image != (Image *) NULL)
5224                 s=newSViv((ssize_t) info->image_info->number_scenes);
5225               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5226               continue;
5227             }
5228           if (LocaleCompare(attribute,"signature") == 0)
5229             {
5230               const char
5231                 *value;
5232
5233               if (image == (Image *) NULL)
5234                 break;
5235               (void) SignatureImage(image);
5236               value=GetImageProperty(image,"Signature");
5237               if (value != (const char *) NULL)
5238                 s=newSVpv(value,0);
5239               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5240               continue;
5241             }
5242           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5243             attribute);
5244           break;
5245         }
5246         case 'T':
5247         case 't':
5248         {
5249           if (LocaleCompare(attribute,"taint") == 0)
5250             {
5251               if (image != (Image *) NULL)
5252                 s=newSViv((ssize_t) IsTaintImage(image));
5253               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5254               continue;
5255             }
5256           if (LocaleCompare(attribute,"texture") == 0)
5257             {
5258               if (info && info->image_info->texture)
5259                 s=newSVpv(info->image_info->texture,0);
5260               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5261               continue;
5262             }
5263           if (LocaleCompare(attribute,"total-ink-density") == 0)
5264             {
5265               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5266               if (image != (Image *) NULL)
5267                 s=newSVnv(GetImageTotalInkDensity(image));
5268               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5269               continue;
5270             }
5271           if (LocaleCompare(attribute,"transparent-color") == 0)
5272             {
5273               if (image == (Image *) NULL)
5274                 break;
5275               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
5276                 QuantumFormat "," QuantumFormat "," QuantumFormat,
5277                 image->transparent_color.red,image->transparent_color.green,
5278                 image->transparent_color.blue,image->transparent_color.alpha);
5279               s=newSVpv(color,0);
5280               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5281               continue;
5282             }
5283           if (LocaleCompare(attribute,"type") == 0)
5284             {
5285               if (image == (Image *) NULL)
5286                 break;
5287               j=(ssize_t) GetImageType(image,&image->exception);
5288               s=newSViv(j);
5289               (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5290               SvIOK_on(s);
5291               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5292               continue;
5293             }
5294           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5295             attribute);
5296           break;
5297         }
5298         case 'U':
5299         case 'u':
5300         {
5301           if (LocaleCompare(attribute,"units") == 0)
5302             {
5303               j=info ? info->image_info->units : image ? image->units :
5304                 UndefinedResolution;
5305               if (info && (info->image_info->units == UndefinedResolution))
5306                 if (image)
5307                   j=image->units;
5308               if (j == UndefinedResolution)
5309                 s=newSVpv("undefined units",0);
5310               else
5311                 if (j == PixelsPerInchResolution)
5312                   s=newSVpv("pixels / inch",0);
5313                 else
5314                   s=newSVpv("pixels / centimeter",0);
5315               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5316               continue;
5317             }
5318           if (LocaleCompare(attribute,"user-time") == 0)
5319             {
5320               if (image != (Image *) NULL)
5321                 s=newSVnv(GetUserTime(&image->timer));
5322               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5323               continue;
5324             }
5325           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5326             attribute);
5327           break;
5328         }
5329         case 'V':
5330         case 'v':
5331         {
5332           if (LocaleCompare(attribute,"verbose") == 0)
5333             {
5334               if (info)
5335                 s=newSViv((ssize_t) info->image_info->verbose);
5336               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5337               continue;
5338             }
5339           if (LocaleCompare(attribute,"version") == 0)
5340             {
5341               s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5342               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5343               continue;
5344             }
5345           if (LocaleCompare(attribute,"view") == 0)
5346             {
5347               if (info && info->image_info->view)
5348                 s=newSVpv(info->image_info->view,0);
5349               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5350               continue;
5351             }
5352           if (LocaleCompare(attribute,"virtual-pixel") == 0)
5353             {
5354               if (image == (Image *) NULL)
5355                 break;
5356               j=(ssize_t) GetImageVirtualPixelMethod(image);
5357               s=newSViv(j);
5358               (void) sv_setpv(s,CommandOptionToMnemonic(
5359                 MagickVirtualPixelOptions,j));
5360               SvIOK_on(s);
5361               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5362               continue;
5363             }
5364           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5365             attribute);
5366           break;
5367         }
5368         case 'W':
5369         case 'w':
5370         {
5371           if (LocaleCompare(attribute,"white-point") == 0)
5372             {
5373               if (image == (Image *) NULL)
5374                 break;
5375               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5376                 image->chromaticity.white_point.x,
5377                 image->chromaticity.white_point.y);
5378               s=newSVpv(color,0);
5379               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5380               continue;
5381             }
5382           if (LocaleCompare(attribute,"width") == 0)
5383             {
5384               if (image != (Image *) NULL)
5385                 s=newSViv((ssize_t) image->columns);
5386               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5387               continue;
5388             }
5389           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5390              attribute);
5391           break;
5392         }
5393         case 'X':
5394         case 'x':
5395         {
5396           if (LocaleCompare(attribute,"x-resolution") == 0)
5397             {
5398               if (image != (Image *) NULL)
5399                 s=newSVnv(image->x_resolution);
5400               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5401               continue;
5402             }
5403           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5404             attribute);
5405           break;
5406         }
5407         case 'Y':
5408         case 'y':
5409         {
5410           if (LocaleCompare(attribute,"y-resolution") == 0)
5411             {
5412               if (image != (Image *) NULL)
5413                 s=newSVnv(image->y_resolution);
5414               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5415               continue;
5416             }
5417           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5418             attribute);
5419           break;
5420         }
5421         default:
5422           break;
5423       }
5424       if (image == (Image *) NULL)
5425         ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5426           attribute)
5427       else
5428         {
5429           value=GetImageProperty(image,attribute);
5430           if (value != (const char *) NULL)
5431             {
5432               s=newSVpv(value,0);
5433               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5434             }
5435           else
5436             if (*attribute != '%')
5437               ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5438                 attribute)
5439             else
5440               {
5441                  char
5442                    *meta;
5443
5444                  meta=InterpretImageProperties(info ? info->image_info :
5445                    (ImageInfo *) NULL,image,attribute);
5446                  s=newSVpv(meta,0);
5447                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5448                  meta=(char *) RelinquishMagickMemory(meta);
5449               }
5450         }
5451     }
5452     exception=DestroyExceptionInfo(exception);
5453     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5454   }
5455 \f
5456 #
5457 ###############################################################################
5458 #                                                                             #
5459 #                                                                             #
5460 #                                                                             #
5461 #   G e t A u t h e n t i c P i x e l s                                       #
5462 #                                                                             #
5463 #                                                                             #
5464 #                                                                             #
5465 ###############################################################################
5466 #
5467 #
5468 void *
5469 GetAuthenticPixels(ref,...)
5470   Image::Magick ref = NO_INIT
5471   ALIAS:
5472     getauthenticpixels = 1
5473     GetImagePixels = 2
5474     getimagepixels = 3
5475   CODE:
5476   {
5477     char
5478       *attribute;
5479
5480     ExceptionInfo
5481       *exception;
5482
5483     Image
5484       *image;
5485
5486     RectangleInfo
5487       region;
5488
5489     ssize_t
5490       i;
5491
5492     struct PackageInfo
5493       *info;
5494
5495     SV
5496       *perl_exception,
5497       *reference;
5498
5499     void
5500       *blob = NULL;
5501
5502     PERL_UNUSED_VAR(ref);
5503     PERL_UNUSED_VAR(ix);
5504     exception=AcquireExceptionInfo();
5505     perl_exception=newSVpv("",0);
5506     if (sv_isobject(ST(0)) == 0)
5507       {
5508         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5509           PackageName);
5510         goto PerlException;
5511       }
5512     reference=SvRV(ST(0));
5513
5514     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5515     if (image == (Image *) NULL)
5516       {
5517         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5518           PackageName);
5519         goto PerlException;
5520       }
5521
5522     region.x=0;
5523     region.y=0;
5524     region.width=image->columns;
5525     region.height=1;
5526     if (items == 1)
5527       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5528     for (i=2; i < items; i+=2)
5529     {
5530       attribute=(char *) SvPV(ST(i-1),na);
5531       switch (*attribute)
5532       {
5533         case 'g':
5534         case 'G':
5535         {
5536           if (LocaleCompare(attribute,"geometry") == 0)
5537             {
5538               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5539               break;
5540             }
5541           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5542             attribute);
5543           break;
5544         }
5545         case 'H':
5546         case 'h':
5547         {
5548           if (LocaleCompare(attribute,"height") == 0)
5549             {
5550               region.height=SvIV(ST(i));
5551               continue;
5552             }
5553           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5554             attribute);
5555           break;
5556         }
5557         case 'X':
5558         case 'x':
5559         {
5560           if (LocaleCompare(attribute,"x") == 0)
5561             {
5562               region.x=SvIV(ST(i));
5563               continue;
5564             }
5565           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5566             attribute);
5567           break;
5568         }
5569         case 'Y':
5570         case 'y':
5571         {
5572           if (LocaleCompare(attribute,"y") == 0)
5573             {
5574               region.y=SvIV(ST(i));
5575               continue;
5576             }
5577           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5578             attribute);
5579           break;
5580         }
5581         case 'W':
5582         case 'w':
5583         {
5584           if (LocaleCompare(attribute,"width") == 0)
5585             {
5586               region.width=SvIV(ST(i));
5587               continue;
5588             }
5589           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5590             attribute);
5591           break;
5592         }
5593       }
5594     }
5595     blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5596       region.height,exception);
5597     if (blob != (void *) NULL)
5598       goto PerlEnd;
5599
5600   PerlException:
5601     InheritPerlException(exception,perl_exception);
5602     exception=DestroyExceptionInfo(exception);
5603     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5604
5605   PerlEnd:
5606     RETVAL = blob;
5607   }
5608   OUTPUT:
5609     RETVAL
5610 \f
5611 #
5612 ###############################################################################
5613 #                                                                             #
5614 #                                                                             #
5615 #                                                                             #
5616 #   G e t V i r t u a l P i x e l s                                           #
5617 #                                                                             #
5618 #                                                                             #
5619 #                                                                             #
5620 ###############################################################################
5621 #
5622 #
5623 void *
5624 GetVirtualPixels(ref,...)
5625   Image::Magick ref = NO_INIT
5626   ALIAS:
5627     getvirtualpixels = 1
5628     AcquireImagePixels = 2
5629     acquireimagepixels = 3
5630   CODE:
5631   {
5632     char
5633       *attribute;
5634
5635     const void
5636       *blob = NULL;
5637
5638     ExceptionInfo
5639       *exception;
5640
5641     Image
5642       *image;
5643
5644     RectangleInfo
5645       region;
5646
5647     ssize_t
5648       i;
5649
5650     struct PackageInfo
5651       *info;
5652
5653     SV
5654       *perl_exception,
5655       *reference;
5656
5657     PERL_UNUSED_VAR(ref);
5658     PERL_UNUSED_VAR(ix);
5659     exception=AcquireExceptionInfo();
5660     perl_exception=newSVpv("",0);
5661     if (sv_isobject(ST(0)) == 0)
5662       {
5663         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5664           PackageName);
5665         goto PerlException;
5666       }
5667     reference=SvRV(ST(0));
5668
5669     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5670     if (image == (Image *) NULL)
5671       {
5672         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5673           PackageName);
5674         goto PerlException;
5675       }
5676
5677     region.x=0;
5678     region.y=0;
5679     region.width=image->columns;
5680     region.height=1;
5681     if (items == 1)
5682       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5683     for (i=2; i < items; i+=2)
5684     {
5685       attribute=(char *) SvPV(ST(i-1),na);
5686       switch (*attribute)
5687       {
5688         case 'g':
5689         case 'G':
5690         {
5691           if (LocaleCompare(attribute,"geometry") == 0)
5692             {
5693               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5694               break;
5695             }
5696           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5697             attribute);
5698           break;
5699         }
5700         case 'H':
5701         case 'h':
5702         {
5703           if (LocaleCompare(attribute,"height") == 0)
5704             {
5705               region.height=SvIV(ST(i));
5706               continue;
5707             }
5708           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5709             attribute);
5710           break;
5711         }
5712         case 'X':
5713         case 'x':
5714         {
5715           if (LocaleCompare(attribute,"x") == 0)
5716             {
5717               region.x=SvIV(ST(i));
5718               continue;
5719             }
5720           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5721             attribute);
5722           break;
5723         }
5724         case 'Y':
5725         case 'y':
5726         {
5727           if (LocaleCompare(attribute,"y") == 0)
5728             {
5729               region.y=SvIV(ST(i));
5730               continue;
5731             }
5732           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5733             attribute);
5734           break;
5735         }
5736         case 'W':
5737         case 'w':
5738         {
5739           if (LocaleCompare(attribute,"width") == 0)
5740             {
5741               region.width=SvIV(ST(i));
5742               continue;
5743             }
5744           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5745             attribute);
5746           break;
5747         }
5748       }
5749     }
5750     blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
5751       region.height,exception);
5752     if (blob != (void *) NULL)
5753       goto PerlEnd;
5754
5755   PerlException:
5756     InheritPerlException(exception,perl_exception);
5757     exception=DestroyExceptionInfo(exception);
5758     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5759
5760   PerlEnd:
5761     RETVAL = (void *) blob;
5762   }
5763   OUTPUT:
5764     RETVAL
5765 \f
5766 #
5767 ###############################################################################
5768 #                                                                             #
5769 #                                                                             #
5770 #                                                                             #
5771 #   G e t A u t h e n t i c M e t a c o n t e n t                             #
5772 #                                                                             #
5773 #                                                                             #
5774 #                                                                             #
5775 ###############################################################################
5776 #
5777 #
5778 void *
5779 GetAuthenticMetacontent(ref,...)
5780   Image::Magick ref = NO_INIT
5781   ALIAS:
5782     getauthenticmetacontent = 1
5783     GetMetacontent = 2
5784     getmetacontent = 3
5785   CODE:
5786   {
5787     ExceptionInfo
5788       *exception;
5789
5790     Image
5791       *image;
5792
5793     struct PackageInfo
5794       *info;
5795
5796     SV
5797       *perl_exception,
5798       *reference;
5799
5800     void
5801       *blob = NULL;
5802
5803     PERL_UNUSED_VAR(ref);
5804     PERL_UNUSED_VAR(ix);
5805     exception=AcquireExceptionInfo();
5806     perl_exception=newSVpv("",0);
5807     if (sv_isobject(ST(0)) == 0)
5808       {
5809         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5810           PackageName);
5811         goto PerlException;
5812       }
5813     reference=SvRV(ST(0));
5814
5815     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5816     if (image == (Image *) NULL)
5817       {
5818         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5819           PackageName);
5820         goto PerlException;
5821       }
5822
5823     blob=(void *) GetAuthenticMetacontent(image);
5824     if (blob != (void *) NULL)
5825       goto PerlEnd;
5826
5827   PerlException:
5828     InheritPerlException(exception,perl_exception);
5829     exception=DestroyExceptionInfo(exception);
5830     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5831
5832   PerlEnd:
5833     RETVAL = blob;
5834   }
5835   OUTPUT:
5836     RETVAL
5837 \f
5838 #
5839 ###############################################################################
5840 #                                                                             #
5841 #                                                                             #
5842 #                                                                             #
5843 #   G e t V i r t u a l M e t a c o n t e n t                                 #
5844 #                                                                             #
5845 #                                                                             #
5846 #                                                                             #
5847 ###############################################################################
5848 #
5849 #
5850 void *
5851 GetVirtualMetacontent(ref,...)
5852   Image::Magick ref = NO_INIT
5853   ALIAS:
5854     getvirtualmetacontent = 1
5855   CODE:
5856   {
5857     ExceptionInfo
5858       *exception;
5859
5860     Image
5861       *image;
5862
5863     struct PackageInfo
5864       *info;
5865
5866     SV
5867       *perl_exception,
5868       *reference;
5869
5870     void
5871       *blob = NULL;
5872
5873     PERL_UNUSED_VAR(ref);
5874     PERL_UNUSED_VAR(ix);
5875     exception=AcquireExceptionInfo();
5876     perl_exception=newSVpv("",0);
5877     if (sv_isobject(ST(0)) == 0)
5878       {
5879         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5880           PackageName);
5881         goto PerlException;
5882       }
5883     reference=SvRV(ST(0));
5884
5885     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5886     if (image == (Image *) NULL)
5887       {
5888         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5889           PackageName);
5890         goto PerlException;
5891       }
5892
5893     blob=(void *) GetVirtualMetacontent(image);
5894     if (blob != (void *) NULL)
5895       goto PerlEnd;
5896
5897   PerlException:
5898     InheritPerlException(exception,perl_exception);
5899     exception=DestroyExceptionInfo(exception);
5900     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5901
5902   PerlEnd:
5903     RETVAL = blob;
5904   }
5905   OUTPUT:
5906     RETVAL
5907 \f
5908 #
5909 ###############################################################################
5910 #                                                                             #
5911 #                                                                             #
5912 #                                                                             #
5913 #   H i s t o g r a m                                                         #
5914 #                                                                             #
5915 #                                                                             #
5916 #                                                                             #
5917 ###############################################################################
5918 #
5919 #
5920 void
5921 Histogram(ref,...)
5922   Image::Magick ref=NO_INIT
5923   ALIAS:
5924     HistogramImage = 1
5925     histogram      = 2
5926     histogramimage = 3
5927   PPCODE:
5928   {
5929     AV
5930       *av;
5931
5932     char
5933       message[MaxTextExtent];
5934
5935     PixelPacket
5936       *histogram;
5937
5938     ExceptionInfo
5939       *exception;
5940
5941     Image
5942       *image;
5943
5944     register ssize_t
5945       i;
5946
5947     ssize_t
5948       count;
5949
5950     struct PackageInfo
5951       *info;
5952
5953     SV
5954       *perl_exception,
5955       *reference;
5956
5957     size_t
5958       number_colors;
5959
5960     PERL_UNUSED_VAR(ref);
5961     PERL_UNUSED_VAR(ix);
5962     exception=AcquireExceptionInfo();
5963     perl_exception=newSVpv("",0);
5964     av=NULL;
5965     if (sv_isobject(ST(0)) == 0)
5966       {
5967         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5968           PackageName);
5969         goto PerlException;
5970       }
5971     reference=SvRV(ST(0));
5972     av=newAV();
5973     SvREFCNT_dec(av);
5974     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5975     if (image == (Image *) NULL)
5976       {
5977         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5978           PackageName);
5979         goto PerlException;
5980       }
5981     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
5982     count=0;
5983     for ( ; image; image=image->next)
5984     {
5985       histogram=GetImageHistogram(image,&number_colors,&image->exception);
5986       if (histogram == (PixelPacket *) NULL)
5987         continue;
5988       count+=(ssize_t) number_colors;
5989       EXTEND(sp,6*count);
5990       for (i=0; i < (ssize_t) number_colors; i++)
5991       {
5992         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
5993           histogram[i].red);
5994         PUSHs(sv_2mortal(newSVpv(message,0)));
5995         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
5996           histogram[i].green);
5997         PUSHs(sv_2mortal(newSVpv(message,0)));
5998         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
5999           histogram[i].blue);
6000         PUSHs(sv_2mortal(newSVpv(message,0)));
6001         if (image->colorspace == CMYKColorspace)
6002           {
6003             (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
6004               histogram[i].black);
6005             PUSHs(sv_2mortal(newSVpv(message,0)));
6006           }
6007         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
6008           histogram[i].alpha);
6009         PUSHs(sv_2mortal(newSVpv(message,0)));
6010         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
6011           histogram[i].count);
6012         PUSHs(sv_2mortal(newSVpv(message,0)));
6013       }
6014       histogram=(PixelPacket *) RelinquishMagickMemory(histogram);
6015     }
6016
6017   PerlException:
6018     InheritPerlException(exception,perl_exception);
6019     exception=DestroyExceptionInfo(exception);
6020     SvREFCNT_dec(perl_exception);
6021   }
6022 \f
6023 #
6024 ###############################################################################
6025 #                                                                             #
6026 #                                                                             #
6027 #                                                                             #
6028 #   G e t P i x e l                                                           #
6029 #                                                                             #
6030 #                                                                             #
6031 #                                                                             #
6032 ###############################################################################
6033 #
6034 #
6035 void
6036 GetPixel(ref,...)
6037   Image::Magick ref=NO_INIT
6038   ALIAS:
6039     getpixel = 1
6040     getPixel = 2
6041   PPCODE:
6042   {
6043     AV
6044       *av;
6045
6046     char
6047       *attribute;
6048
6049     ExceptionInfo
6050       *exception;
6051
6052     Image
6053       *image;
6054
6055     MagickBooleanType
6056       normalize;
6057
6058     RectangleInfo
6059       region;
6060
6061     register const Quantum
6062       *p;
6063
6064     register ssize_t
6065       i;
6066
6067     ssize_t
6068       option;
6069
6070     struct PackageInfo
6071       *info;
6072
6073     SV
6074       *perl_exception,
6075       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6076
6077     PERL_UNUSED_VAR(ref);
6078     PERL_UNUSED_VAR(ix);
6079     exception=AcquireExceptionInfo();
6080     perl_exception=newSVpv("",0);
6081     reference=SvRV(ST(0));
6082     av=(AV *) reference;
6083     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6084       exception);
6085     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6086     if (image == (Image *) NULL)
6087       {
6088         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6089           PackageName);
6090         goto PerlException;
6091       }
6092     normalize=MagickTrue;
6093     region.x=0;
6094     region.y=0;
6095     region.width=image->columns;
6096     region.height=1;
6097     if (items == 1)
6098       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6099     for (i=2; i < items; i+=2)
6100     {
6101       attribute=(char *) SvPV(ST(i-1),na);
6102       switch (*attribute)
6103       {
6104         case 'C':
6105         case 'c':
6106         {
6107           if (LocaleCompare(attribute,"channel") == 0)
6108             {
6109               ssize_t
6110                 option;
6111
6112               option=ParseChannelOption(SvPV(ST(i),na));
6113               if (option < 0)
6114                 {
6115                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6116                     SvPV(ST(i),na));
6117                   return;
6118                 }
6119               SetPixelComponentMap(image,(ChannelType) option);
6120               break;
6121             }
6122           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6123             attribute);
6124           break;
6125         }
6126         case 'g':
6127         case 'G':
6128         {
6129           if (LocaleCompare(attribute,"geometry") == 0)
6130             {
6131               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6132               break;
6133             }
6134           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6135             attribute);
6136           break;
6137         }
6138         case 'N':
6139         case 'n':
6140         {
6141           if (LocaleCompare(attribute,"normalize") == 0)
6142             {
6143               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6144                 SvPV(ST(i),na));
6145               if (option < 0)
6146                 {
6147                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6148                     SvPV(ST(i),na));
6149                   break;
6150                 }
6151              normalize=option != 0 ? MagickTrue : MagickFalse;
6152              break;
6153             }
6154           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6155             attribute);
6156           break;
6157         }
6158         case 'x':
6159         case 'X':
6160         {
6161           if (LocaleCompare(attribute,"x") == 0)
6162             {
6163               region.x=SvIV(ST(i));
6164               break;
6165             }
6166           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6167             attribute);
6168           break;
6169         }
6170         case 'y':
6171         case 'Y':
6172         {
6173           if (LocaleCompare(attribute,"y") == 0)
6174             {
6175               region.y=SvIV(ST(i));
6176               break;
6177             }
6178           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6179             attribute);
6180           break;
6181         }
6182         default:
6183         {
6184           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6185             attribute);
6186           break;
6187         }
6188       }
6189     }
6190     p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6191     if (p == (const Quantum *) NULL)
6192       PUSHs(&sv_undef);
6193     else
6194       {
6195         double
6196           scale;
6197
6198         scale=1.0;
6199         if (normalize != MagickFalse)
6200           scale=1.0/QuantumRange;
6201         if ((GetPixelRedTraits(image) & ActivePixelTrait) != 0)
6202           PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6203         if ((GetPixelGreenTraits(image) & ActivePixelTrait) != 0)
6204           PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6205         if ((GetPixelBlueTraits(image) & ActivePixelTrait) != 0)
6206           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6207         if (((GetPixelBlackTraits(image) & ActivePixelTrait) != 0) &&
6208             (image->colorspace == CMYKColorspace))
6209           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6210         if ((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0)
6211           PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6212       }
6213
6214   PerlException:
6215     InheritPerlException(exception,perl_exception);
6216     exception=DestroyExceptionInfo(exception);
6217     SvREFCNT_dec(perl_exception);
6218   }
6219 \f
6220 #
6221 ###############################################################################
6222 #                                                                             #
6223 #                                                                             #
6224 #                                                                             #
6225 #   G e t P i x e l s                                                         #
6226 #                                                                             #
6227 #                                                                             #
6228 #                                                                             #
6229 ###############################################################################
6230 #
6231 #
6232 void
6233 GetPixels(ref,...)
6234   Image::Magick ref=NO_INIT
6235   ALIAS:
6236     getpixels = 1
6237     getPixels = 2
6238   PPCODE:
6239   {
6240     AV
6241       *av;
6242
6243     char
6244       *attribute;
6245
6246     const char
6247       *map;
6248
6249     ExceptionInfo
6250       *exception;
6251
6252     Image
6253       *image;
6254
6255     MagickBooleanType
6256       normalize,
6257       status;
6258
6259     RectangleInfo
6260       region;
6261
6262     register ssize_t
6263       i;
6264
6265     ssize_t
6266       option;
6267
6268     struct PackageInfo
6269       *info;
6270
6271     SV
6272       *perl_exception,
6273       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6274
6275     PERL_UNUSED_VAR(ref);
6276     PERL_UNUSED_VAR(ix);
6277     exception=AcquireExceptionInfo();
6278     perl_exception=newSVpv("",0);
6279     reference=SvRV(ST(0));
6280     av=(AV *) reference;
6281     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6282       exception);
6283     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6284     if (image == (Image *) NULL)
6285       {
6286         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6287           PackageName);
6288         goto PerlException;
6289       }
6290     map="RGB";
6291     if (image->matte != MagickFalse)
6292       map="RGBA";
6293     if (image->colorspace == CMYKColorspace)
6294       {
6295         map="CMYK";
6296         if (image->matte != MagickFalse)
6297           map="CMYKA";
6298       }
6299     normalize=MagickFalse;
6300     region.x=0;
6301     region.y=0;
6302     region.width=image->columns;
6303     region.height=1;
6304     if (items == 1)
6305       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6306     for (i=2; i < items; i+=2)
6307     {
6308       attribute=(char *) SvPV(ST(i-1),na);
6309       switch (*attribute)
6310       {
6311         case 'g':
6312         case 'G':
6313         {
6314           if (LocaleCompare(attribute,"geometry") == 0)
6315             {
6316               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6317               break;
6318             }
6319           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6320             attribute);
6321           break;
6322         }
6323         case 'H':
6324         case 'h':
6325         {
6326           if (LocaleCompare(attribute,"height") == 0)
6327             {
6328               region.height=SvIV(ST(i));
6329               break;
6330             }
6331           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6332             attribute);
6333           break;
6334         }
6335         case 'M':
6336         case 'm':
6337         {
6338           if (LocaleCompare(attribute,"map") == 0)
6339             {
6340               map=SvPV(ST(i),na);
6341               break;
6342             }
6343           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6344             attribute);
6345           break;
6346         }
6347         case 'N':
6348         case 'n':
6349         {
6350           if (LocaleCompare(attribute,"normalize") == 0)
6351             {
6352               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6353                 SvPV(ST(i),na));
6354               if (option < 0)
6355                 {
6356                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6357                     SvPV(ST(i),na));
6358                   break;
6359                 }
6360              normalize=option != 0 ? MagickTrue : MagickFalse;
6361              break;
6362             }
6363           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6364             attribute);
6365           break;
6366         }
6367         case 'W':
6368         case 'w':
6369         {
6370           if (LocaleCompare(attribute,"width") == 0)
6371             {
6372               region.width=SvIV(ST(i));
6373               break;
6374             }
6375           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6376             attribute);
6377           break;
6378         }
6379         case 'x':
6380         case 'X':
6381         {
6382           if (LocaleCompare(attribute,"x") == 0)
6383             {
6384               region.x=SvIV(ST(i));
6385               break;
6386             }
6387           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6388             attribute);
6389           break;
6390         }
6391         case 'y':
6392         case 'Y':
6393         {
6394           if (LocaleCompare(attribute,"y") == 0)
6395             {
6396               region.y=SvIV(ST(i));
6397               break;
6398             }
6399           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6400             attribute);
6401           break;
6402         }
6403         default:
6404         {
6405           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6406             attribute);
6407           break;
6408         }
6409       }
6410     }
6411     if (normalize != MagickFalse)
6412       {
6413         float
6414           *pixels;
6415
6416         pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6417           region.height*sizeof(*pixels));
6418         if (pixels == (float *) NULL)
6419           {
6420             ThrowPerlException(exception,ResourceLimitError,
6421               "MemoryAllocationFailed",PackageName);
6422             goto PerlException;
6423           }
6424         status=ExportImagePixels(image,region.x,region.y,region.width,
6425           region.height,map,FloatPixel,pixels,exception);
6426         if (status == MagickFalse)
6427           PUSHs(&sv_undef);
6428         else
6429           {
6430             EXTEND(sp,strlen(map)*region.width*region.height);
6431             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6432               PUSHs(sv_2mortal(newSVnv(pixels[i])));
6433           }
6434         pixels=(float *) RelinquishMagickMemory(pixels);
6435       }
6436     else
6437       {
6438         Quantum
6439           *pixels;
6440
6441         pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6442           region.height*sizeof(*pixels));
6443         if (pixels == (Quantum *) NULL)
6444           {
6445             ThrowPerlException(exception,ResourceLimitError,
6446               "MemoryAllocationFailed",PackageName);
6447             goto PerlException;
6448           }
6449         status=ExportImagePixels(image,region.x,region.y,region.width,
6450           region.height,map,QuantumPixel,pixels,exception);
6451         if (status == MagickFalse)
6452           PUSHs(&sv_undef);
6453         else
6454           {
6455             EXTEND(sp,strlen(map)*region.width*region.height);
6456             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6457               PUSHs(sv_2mortal(newSViv(pixels[i])));
6458           }
6459         pixels=(Quantum *) RelinquishMagickMemory(pixels);
6460       }
6461
6462   PerlException:
6463     InheritPerlException(exception,perl_exception);
6464     exception=DestroyExceptionInfo(exception);
6465     SvREFCNT_dec(perl_exception);
6466   }
6467 \f
6468 #
6469 ###############################################################################
6470 #                                                                             #
6471 #                                                                             #
6472 #                                                                             #
6473 #   I m a g e T o B l o b                                                     #
6474 #                                                                             #
6475 #                                                                             #
6476 #                                                                             #
6477 ###############################################################################
6478 #
6479 #
6480 void
6481 ImageToBlob(ref,...)
6482   Image::Magick ref=NO_INIT
6483   ALIAS:
6484     ImageToBlob  = 1
6485     imagetoblob  = 2
6486     toblob       = 3
6487     blob         = 4
6488   PPCODE:
6489   {
6490     char
6491       filename[MaxTextExtent];
6492
6493     ExceptionInfo
6494       *exception;
6495
6496     Image
6497       *image,
6498       *next;
6499
6500     register ssize_t
6501       i;
6502
6503     struct PackageInfo
6504       *info,
6505       *package_info;
6506
6507     size_t
6508       length;
6509
6510     ssize_t
6511       scene;
6512
6513     SV
6514       *perl_exception,
6515       *reference;
6516
6517     void
6518       *blob;
6519
6520     PERL_UNUSED_VAR(ref);
6521     PERL_UNUSED_VAR(ix);
6522     exception=AcquireExceptionInfo();
6523     perl_exception=newSVpv("",0);
6524     package_info=(struct PackageInfo *) NULL;
6525     if (sv_isobject(ST(0)) == 0)
6526       {
6527         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6528           PackageName);
6529         goto PerlException;
6530       }
6531     reference=SvRV(ST(0));
6532     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6533     if (image == (Image *) NULL)
6534       {
6535         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6536           PackageName);
6537         goto PerlException;
6538       }
6539     package_info=ClonePackageInfo(info,exception);
6540     for (i=2; i < items; i+=2)
6541       SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6542     (void) CopyMagickString(filename,package_info->image_info->filename,
6543       MaxTextExtent);
6544     scene=0;
6545     for (next=image; next; next=next->next)
6546     {
6547       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
6548       next->scene=scene++;
6549     }
6550     SetImageInfo(package_info->image_info,(unsigned int)
6551       GetImageListLength(image),&image->exception);
6552     EXTEND(sp,(ssize_t) GetImageListLength(image));
6553     for ( ; image; image=image->next)
6554     {
6555       length=0;
6556       blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6557       if (blob != (char *) NULL)
6558         {
6559           PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6560           blob=(unsigned char *) RelinquishMagickMemory(blob);
6561         }
6562       if (package_info->image_info->adjoin)
6563         break;
6564     }
6565
6566   PerlException:
6567     if (package_info != (struct PackageInfo *) NULL)
6568       DestroyPackageInfo(package_info);
6569     InheritPerlException(exception,perl_exception);
6570     exception=DestroyExceptionInfo(exception);
6571     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6572   }
6573 \f
6574 #
6575 ###############################################################################
6576 #                                                                             #
6577 #                                                                             #
6578 #                                                                             #
6579 #   L a y e r s                                                               #
6580 #                                                                             #
6581 #                                                                             #
6582 #                                                                             #
6583 ###############################################################################
6584 #
6585 #
6586 void
6587 Layers(ref,...)
6588   Image::Magick ref=NO_INIT
6589   ALIAS:
6590     Layers                = 1
6591     layers           = 2
6592     OptimizeImageLayers   = 3
6593     optimizelayers        = 4
6594     optimizeimagelayers   = 5
6595   PPCODE:
6596   {
6597     AV
6598       *av;
6599
6600     char
6601       *attribute;
6602
6603     CompositeOperator
6604       compose;
6605
6606     ExceptionInfo
6607       *exception;
6608
6609     HV
6610       *hv;
6611
6612     Image
6613       *image,
6614       *layers;
6615
6616     ImageLayerMethod
6617       method;
6618
6619     register ssize_t
6620       i;
6621
6622     ssize_t
6623       option,
6624       sp;
6625
6626     struct PackageInfo
6627       *info;
6628
6629     SV
6630       *av_reference,
6631       *perl_exception,
6632       *reference,
6633       *rv,
6634       *sv;
6635
6636     PERL_UNUSED_VAR(ref);
6637     PERL_UNUSED_VAR(ix);
6638     exception=AcquireExceptionInfo();
6639     perl_exception=newSVpv("",0);
6640     sv=NULL;
6641     if (sv_isobject(ST(0)) == 0)
6642       {
6643         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6644           PackageName);
6645         goto PerlException;
6646       }
6647     reference=SvRV(ST(0));
6648     hv=SvSTASH(reference);
6649     av=newAV();
6650     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
6651     SvREFCNT_dec(av);
6652     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6653     if (image == (Image *) NULL)
6654       {
6655         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6656           PackageName);
6657         goto PerlException;
6658       }
6659     compose=image->compose;
6660     method=OptimizeLayer;
6661     for (i=2; i < items; i+=2)
6662     {
6663       attribute=(char *) SvPV(ST(i-1),na);
6664       switch (*attribute)
6665       {
6666         case 'C':
6667         case 'c':
6668         {
6669           if (LocaleCompare(attribute,"compose") == 0)
6670             {
6671               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
6672                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
6673               if (sp < 0)
6674                 {
6675                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6676                     SvPV(ST(i),na));
6677                   break;
6678                 }
6679               compose=(CompositeOperator) sp;
6680               break;
6681             }
6682           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6683             attribute);
6684           break;
6685         }
6686         case 'M':
6687         case 'm':
6688         {
6689           if (LocaleCompare(attribute,"method") == 0)
6690             {
6691               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
6692                 SvPV(ST(i),na));
6693               if (option < 0)
6694                 {
6695                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6696                     SvPV(ST(i),na));
6697                   break;
6698                 }
6699               method=(ImageLayerMethod) option;
6700               break;
6701             }
6702           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6703             attribute);
6704           break;
6705         }
6706         default:
6707         {
6708           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6709             attribute);
6710           break;
6711         }
6712       }
6713     }
6714     layers=(Image *) NULL;
6715     switch (method)
6716     {
6717       case CompareAnyLayer:
6718       case CompareClearLayer:
6719       case CompareOverlayLayer:
6720       default:
6721       {
6722         layers=CompareImagesLayers(image,method,exception);
6723         break;
6724       }
6725       case MergeLayer:
6726       case FlattenLayer:
6727       case MosaicLayer:
6728       {
6729         layers=MergeImageLayers(image,method,exception);
6730         break;
6731       }
6732       case DisposeLayer:
6733       {
6734         layers=DisposeImages(image,exception);
6735         break;
6736       }
6737       case OptimizeImageLayer:
6738       {
6739         layers=OptimizeImageLayers(image,exception);
6740         break;
6741       }
6742       case OptimizePlusLayer:
6743       {
6744         layers=OptimizePlusImageLayers(image,exception);
6745         break;
6746       }
6747       case OptimizeTransLayer:
6748       {
6749         OptimizeImageTransparency(image,exception);
6750         InheritException(&(image->exception),exception);
6751         break;
6752       }
6753       case RemoveDupsLayer:
6754       {
6755         RemoveDuplicateLayers(&image,exception);
6756         InheritException(&(image->exception),exception);
6757         break;
6758       }
6759       case RemoveZeroLayer:
6760       {
6761         RemoveZeroDelayLayers(&image,exception);
6762         InheritException(&(image->exception),exception);
6763         break;
6764       }
6765       case OptimizeLayer:
6766       {
6767         QuantizeInfo
6768           *quantize_info;
6769
6770         /*
6771           General Purpose, GIF Animation Optimizer.
6772         */
6773         layers=CoalesceImages(image,exception);
6774         if (layers == (Image *) NULL)
6775           break;
6776         InheritException(&(layers->exception),exception);
6777         image=layers;
6778         layers=OptimizeImageLayers(image,exception);
6779         if (layers == (Image *) NULL)
6780           break;
6781         InheritException(&(layers->exception),exception);
6782         image=DestroyImageList(image);
6783         image=layers;
6784         layers=(Image *) NULL;
6785         OptimizeImageTransparency(image,exception);
6786         InheritException(&(image->exception),exception);
6787         quantize_info=AcquireQuantizeInfo(info->image_info);
6788         (void) RemapImages(quantize_info,image,(Image *) NULL);
6789         quantize_info=DestroyQuantizeInfo(quantize_info);
6790         break;
6791       }
6792       case CompositeLayer:
6793       {
6794         Image
6795           *source;
6796
6797         RectangleInfo
6798           geometry;
6799
6800         /*
6801           Split image sequence at the first 'NULL:' image.
6802         */
6803         source=image;
6804         while (source != (Image *) NULL)
6805         {
6806           source=GetNextImageInList(source);
6807           if ((source != (Image *) NULL) &&
6808               (LocaleCompare(source->magick,"NULL") == 0))
6809             break;
6810         }
6811         if (source != (Image *) NULL)
6812           {
6813             if ((GetPreviousImageInList(source) == (Image *) NULL) ||
6814                 (GetNextImageInList(source) == (Image *) NULL))
6815               source=(Image *) NULL;
6816             else
6817               {
6818                 /*
6819                   Separate the two lists, junk the null: image.
6820                 */
6821                 source=SplitImageList(source->previous);
6822                 DeleteImageFromList(&source);
6823               }
6824           }
6825         if (source == (Image *) NULL)
6826           {
6827             (void) ThrowMagickException(exception,GetMagickModule(),
6828               OptionError,"MissingNullSeparator","layers Composite");
6829             break;
6830           }
6831         /*
6832           Adjust offset with gravity and virtual canvas.
6833         */
6834         SetGeometry(image,&geometry);
6835         (void) ParseAbsoluteGeometry(image->geometry,&geometry);
6836         geometry.width=source->page.width != 0 ? source->page.width :
6837           source->columns;
6838         geometry.height=source->page.height != 0 ? source->page.height :
6839           source->rows;
6840         GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
6841           image->columns,image->page.height != 0 ? image->page.height :
6842           image->rows,image->gravity,&geometry);
6843         CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
6844         source=DestroyImageList(source);
6845         InheritException(&(image->exception),exception);
6846         break;
6847       }
6848     }
6849     if (layers != (Image *) NULL)
6850       {
6851         InheritException(&(layers->exception),exception);
6852         image=layers;
6853       }
6854     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
6855       goto PerlException;
6856     for ( ; image; image=image->next)
6857     {
6858       AddImageToRegistry(sv,image);
6859       rv=newRV(sv);
6860       av_push(av,sv_bless(rv,hv));
6861       SvREFCNT_dec(sv);
6862     }
6863     exception=DestroyExceptionInfo(exception);
6864     ST(0)=av_reference;
6865     SvREFCNT_dec(perl_exception);
6866     XSRETURN(1);
6867
6868   PerlException:
6869     InheritPerlException(exception,perl_exception);
6870     exception=DestroyExceptionInfo(exception);
6871     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
6872     SvPOK_on(perl_exception);
6873     ST(0)=sv_2mortal(perl_exception);
6874     XSRETURN(1);
6875   }
6876 \f
6877 #
6878 ###############################################################################
6879 #                                                                             #
6880 #                                                                             #
6881 #                                                                             #
6882 #   M a g i c k T o M i m e                                                   #
6883 #                                                                             #
6884 #                                                                             #
6885 #                                                                             #
6886 ###############################################################################
6887 #
6888 #
6889 SV *
6890 MagickToMime(ref,name)
6891   Image::Magick ref=NO_INIT
6892   char *name
6893   ALIAS:
6894     magicktomime = 1
6895   CODE:
6896   {
6897     char
6898       *mime;
6899
6900     PERL_UNUSED_VAR(ref);
6901     PERL_UNUSED_VAR(ix);
6902     mime=MagickToMime(name);
6903     RETVAL=newSVpv(mime,0);
6904     mime=(char *) RelinquishMagickMemory(mime);
6905   }
6906   OUTPUT:
6907     RETVAL
6908 \f
6909 #
6910 ###############################################################################
6911 #                                                                             #
6912 #                                                                             #
6913 #                                                                             #
6914 #   M o g r i f y                                                             #
6915 #                                                                             #
6916 #                                                                             #
6917 #                                                                             #
6918 ###############################################################################
6919 #
6920 #
6921 void
6922 Mogrify(ref,...)
6923   Image::Magick ref=NO_INIT
6924   ALIAS:
6925     Comment            =   1
6926     CommentImage       =   2
6927     Label              =   3
6928     LabelImage         =   4
6929     AddNoise           =   5
6930     AddNoiseImage      =   6
6931     Colorize           =   7
6932     ColorizeImage      =   8
6933     Border             =   9
6934     BorderImage        =  10
6935     Blur               =  11
6936     BlurImage          =  12
6937     Chop               =  13
6938     ChopImage          =  14
6939     Crop               =  15
6940     CropImage          =  16
6941     Despeckle          =  17
6942     DespeckleImage     =  18
6943     Edge               =  19
6944     EdgeImage          =  20
6945     Emboss             =  21
6946     EmbossImage        =  22
6947     Enhance            =  23
6948     EnhanceImage       =  24
6949     Flip               =  25
6950     FlipImage          =  26
6951     Flop               =  27
6952     FlopImage          =  28
6953     Frame              =  29
6954     FrameImage         =  30
6955     Implode            =  31
6956     ImplodeImage       =  32
6957     Magnify            =  33
6958     MagnifyImage       =  34
6959     MedianFilter       =  35
6960     MedianFilterImage  =  36
6961     Minify             =  37
6962     MinifyImage        =  38
6963     OilPaint           =  39
6964     OilPaintImage      =  40
6965     ReduceNoise        =  41
6966     ReduceNoiseImage   =  42
6967     Roll               =  43
6968     RollImage          =  44
6969     Rotate             =  45
6970     RotateImage        =  46
6971     Sample             =  47
6972     SampleImage        =  48
6973     Scale              =  49
6974     ScaleImage         =  50
6975     Shade              =  51
6976     ShadeImage         =  52
6977     Sharpen            =  53
6978     SharpenImage       =  54
6979     Shear              =  55
6980     ShearImage         =  56
6981     Spread             =  57
6982     SpreadImage        =  58
6983     Swirl              =  59
6984     SwirlImage         =  60
6985     Resize             =  61
6986     ResizeImage        =  62
6987     Zoom               =  63
6988     ZoomImage          =  64
6989     Annotate           =  65
6990     AnnotateImage      =  66
6991     ColorFloodfill     =  67
6992     ColorFloodfillImage=  68
6993     Composite          =  69
6994     CompositeImage     =  70
6995     Contrast           =  71
6996     ContrastImage      =  72
6997     CycleColormap      =  73
6998     CycleColormapImage =  74
6999     Draw               =  75
7000     DrawImage          =  76
7001     Equalize           =  77
7002     EqualizeImage      =  78
7003     Gamma              =  79
7004     GammaImage         =  80
7005     Map                =  81
7006     MapImage           =  82
7007     MatteFloodfill     =  83
7008     MatteFloodfillImage=  84
7009     Modulate           =  85
7010     ModulateImage      =  86
7011     Negate             =  87
7012     NegateImage        =  88
7013     Normalize          =  89
7014     NormalizeImage     =  90
7015     NumberColors       =  91
7016     NumberColorsImage  =  92
7017     Opaque             =  93
7018     OpaqueImage        =  94
7019     Quantize           =  95
7020     QuantizeImage      =  96
7021     Raise              =  97
7022     RaiseImage         =  98
7023     Segment            =  99
7024     SegmentImage       = 100
7025     Signature          = 101
7026     SignatureImage     = 102
7027     Solarize           = 103
7028     SolarizeImage      = 104
7029     Sync               = 105
7030     SyncImage          = 106
7031     Texture            = 107
7032     TextureImage       = 108
7033     Evaluate           = 109
7034     EvaluateImage      = 110
7035     Transparent        = 111
7036     TransparentImage   = 112
7037     Threshold          = 113
7038     ThresholdImage     = 114
7039     Charcoal           = 115
7040     CharcoalImage      = 116
7041     Trim               = 117
7042     TrimImage          = 118
7043     Wave               = 119
7044     WaveImage          = 120
7045     Separate           = 121
7046     SeparateImage      = 122
7047     Stereo             = 125
7048     StereoImage        = 126
7049     Stegano            = 127
7050     SteganoImage       = 128
7051     Deconstruct        = 129
7052     DeconstructImage   = 130
7053     GaussianBlur       = 131
7054     GaussianBlurImage  = 132
7055     Convolve           = 133
7056     ConvolveImage      = 134
7057     Profile            = 135
7058     ProfileImage       = 136
7059     UnsharpMask        = 137
7060     UnsharpMaskImage   = 138
7061     MotionBlur         = 139
7062     MotionBlurImage    = 140
7063     OrderedDither      = 141
7064     OrderedDitherImage = 142
7065     Shave              = 143
7066     ShaveImage         = 144
7067     Level              = 145
7068     LevelImage         = 146
7069     Clip               = 147
7070     ClipImage          = 148
7071     AffineTransform    = 149
7072     AffineTransformImage = 150
7073     Difference         = 151
7074     DifferenceImage    = 152
7075     AdaptiveThreshold  = 153
7076     AdaptiveThresholdImage = 154
7077     Resample           = 155
7078     ResampleImage      = 156
7079     Describe           = 157
7080     DescribeImage      = 158
7081     BlackThreshold     = 159
7082     BlackThresholdImage= 160
7083     WhiteThreshold     = 161
7084     WhiteThresholdImage= 162
7085     RadialBlur         = 163
7086     RadialBlurImage    = 164
7087     Thumbnail          = 165
7088     ThumbnailImage     = 166
7089     Strip              = 167
7090     StripImage         = 168
7091     Tint               = 169
7092     TintImage          = 170
7093     Channel            = 171
7094     ChannelImage       = 172
7095     Splice             = 173
7096     SpliceImage        = 174
7097     Posterize          = 175
7098     PosterizeImage     = 176
7099     Shadow             = 177
7100     ShadowImage        = 178
7101     Identify           = 179
7102     IdentifyImage      = 180
7103     SepiaTone          = 181
7104     SepiaToneImage     = 182
7105     SigmoidalContrast  = 183
7106     SigmoidalContrastImage = 184
7107     Extent             = 185
7108     ExtentImage        = 186
7109     Vignette           = 187
7110     VignetteImage      = 188
7111     ContrastStretch    = 189
7112     ContrastStretchImage = 190
7113     Sans0              = 191
7114     Sans0Image         = 192
7115     Sans1              = 193
7116     Sans1Image         = 194
7117     AdaptiveSharpen    = 195
7118     AdaptiveSharpenImage = 196
7119     Transpose          = 197
7120     TransposeImage     = 198
7121     Transverse         = 199
7122     TransverseImage    = 200
7123     AutoOrient         = 201
7124     AutoOrientImage    = 202
7125     AdaptiveBlur       = 203
7126     AdaptiveBlurImage  = 204
7127     Sketch             = 205
7128     SketchImage        = 206
7129     UniqueColors       = 207
7130     UniqueColorsImage  = 208
7131     AdaptiveResize     = 209
7132     AdaptiveResizeImage= 210
7133     ClipMask           = 211
7134     ClipMaskImage      = 212
7135     LinearStretch      = 213
7136     LinearStretchImage = 214
7137     RecolorImage       = 215
7138     Recolor            = 216
7139     Mask               = 217
7140     MaskImage          = 218
7141     Polaroid           = 219
7142     PolaroidImage      = 220
7143     FloodfillPaint     = 221
7144     FloodfillPaintImage= 222
7145     Distort            = 223
7146     DistortImage       = 224
7147     Clut               = 225
7148     ClutImage          = 226
7149     LiquidRescale      = 227
7150     LiquidRescaleImage = 228
7151     Encipher           = 229
7152     EncipherImage      = 230
7153     Decipher           = 231
7154     DecipherImage      = 232
7155     Deskew             = 233
7156     DeskewImage        = 234
7157     Remap              = 235
7158     RemapImage         = 236
7159     SparseColor        = 237
7160     SparseColorImage   = 238
7161     Function           = 239
7162     FunctionImage      = 240
7163     SelectiveBlur      = 241
7164     SelectiveBlurImage = 242
7165     HaldClut           = 243
7166     HaldClutImage      = 244
7167     BlueShift          = 245
7168     BlueShiftImage     = 246
7169     ForwardFourierTransform  = 247
7170     ForwardFourierTransformImage = 248
7171     InverseFourierTransform = 249
7172     InverseFourierTransformImage = 250
7173     ColorDecisionList  = 251
7174     ColorDecisionListImage = 252
7175     AutoGamma          = 253
7176     AutoGammaImage     = 254
7177     AutoLevel          = 255
7178     AutoLevelImage     = 256
7179     LevelColors        = 257
7180     LevelImageColors   = 258
7181     Clamp              = 259
7182     ClampImage         = 260
7183     Filter             = 261
7184     FilterImage        = 262
7185     BrightnessContrast = 263
7186     BrightnessContrastImage = 264
7187     Morphology         = 265
7188     MorphologyImage    = 266
7189     ColorMatrix        = 267
7190     ColorMatrixImage   = 268
7191     Color              = 269
7192     ColorImage         = 270
7193     Mode               = 271
7194     ModeImage          = 272
7195     Statistic          = 273
7196     StatisticImage     = 274
7197     MogrifyRegion      = 666
7198   PPCODE:
7199   {
7200     AffineMatrix
7201       affine,
7202       current;
7203
7204     char
7205       attribute_flag[MaxArguments],
7206       message[MaxTextExtent];
7207
7208     ChannelType
7209       channel;
7210
7211     CompositeOperator
7212       compose;
7213
7214     const char
7215       *attribute,
7216       *value;
7217
7218     double
7219       angle;
7220
7221     ExceptionInfo
7222       *exception;
7223
7224     GeometryInfo
7225       geometry_info;
7226
7227     Image
7228       *image,
7229       *next,
7230       *region_image;
7231
7232     MagickBooleanType
7233       status;
7234
7235     MagickStatusType
7236       flags;
7237
7238     PixelPacket
7239       fill_color;
7240
7241     RectangleInfo
7242       geometry,
7243       region_info;
7244
7245     register ssize_t
7246       i;
7247
7248     ssize_t
7249       base,
7250       j,
7251       number_images;
7252
7253     struct Methods
7254       *rp;
7255
7256     struct PackageInfo
7257       *info;
7258
7259     SV
7260       *perl_exception,
7261       **pv,
7262       *reference,
7263       **reference_vector;
7264
7265     struct ArgumentList
7266       argument_list[MaxArguments];
7267
7268     PERL_UNUSED_VAR(ref);
7269     PERL_UNUSED_VAR(ix);
7270     exception=AcquireExceptionInfo();
7271     perl_exception=newSVpv("",0);
7272     reference_vector=NULL;
7273     region_image=NULL;
7274     number_images=0;
7275     base=2;
7276     if (sv_isobject(ST(0)) == 0)
7277       {
7278         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7279           PackageName);
7280         goto PerlException;
7281       }
7282     reference=SvRV(ST(0));
7283     region_info.width=0;
7284     region_info.height=0;
7285     region_info.x=0;
7286     region_info.y=0;
7287     region_image=(Image *) NULL;
7288     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7289     if (ix && (ix != 666))
7290       {
7291         /*
7292           Called as Method(...)
7293         */
7294         ix=(ix+1)/2;
7295         rp=(&Methods[ix-1]);
7296         attribute=rp->name;
7297       }
7298     else
7299       {
7300         /*
7301           Called as Mogrify("Method",...)
7302         */
7303         attribute=(char *) SvPV(ST(1),na);
7304         if (ix)
7305           {
7306             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7307             attribute=(char *) SvPV(ST(2),na);
7308             base++;
7309           }
7310         for (rp=Methods; ; rp++)
7311         {
7312           if (rp >= EndOf(Methods))
7313             {
7314               ThrowPerlException(exception,OptionError,
7315                 "UnrecognizedPerlMagickMethod",attribute);
7316               goto PerlException;
7317             }
7318           if (strEQcase(attribute,rp->name))
7319             break;
7320         }
7321         ix=rp-Methods+1;
7322         base++;
7323       }
7324     if (image == (Image *) NULL)
7325       {
7326         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7327         goto PerlException;
7328       }
7329     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7330     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7331     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7332     {
7333       Arguments
7334         *pp,
7335         *qq;
7336
7337       ssize_t
7338         ssize_test;
7339
7340       struct ArgumentList
7341         *al;
7342
7343       SV
7344         *sv;
7345
7346       sv=NULL;
7347       ssize_test=0;
7348       pp=(Arguments *) NULL;
7349       qq=rp->arguments;
7350       if (i == items)
7351         {
7352           pp=rp->arguments,
7353           sv=ST(i-1);
7354         }
7355       else
7356         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7357         {
7358           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7359             break;
7360           if (strEQcase(attribute,qq->method) > ssize_test)
7361             {
7362               pp=qq;
7363               ssize_test=strEQcase(attribute,qq->method);
7364             }
7365         }
7366       if (pp == (Arguments *) NULL)
7367         {
7368           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7369             attribute);
7370           goto continue_outer_loop;
7371         }
7372       al=(&argument_list[pp-rp->arguments]);
7373       switch (pp->type)
7374       {
7375         case ArrayReference:
7376         {
7377           if (SvTYPE(sv) != SVt_RV)
7378             {
7379               (void) FormatLocaleString(message,MaxTextExtent,
7380                 "invalid %.60s value",pp->method);
7381               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7382               goto continue_outer_loop;
7383             }
7384           al->array_reference=SvRV(sv);
7385           break;
7386         }
7387         case RealReference:
7388         {
7389           al->real_reference=SvNV(sv);
7390           break;
7391         }
7392         case FileReference:
7393         {
7394           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7395           break;
7396         }
7397         case ImageReference:
7398         {
7399           if (!sv_isobject(sv) ||
7400               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7401                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7402             {
7403               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7404                 PackageName);
7405               goto PerlException;
7406             }
7407           break;
7408         }
7409         case IntegerReference:
7410         {
7411           al->integer_reference=SvIV(sv);
7412           break;
7413         }
7414         case StringReference:
7415         {
7416           al->string_reference=(char *) SvPV(sv,al->length);
7417           if (sv_isobject(sv))
7418             al->image_reference=SetupList(aTHX_ SvRV(sv),
7419               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7420           break;
7421         }
7422         default:
7423         {
7424           /*
7425             Is a string; look up name.
7426           */
7427           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7428             {
7429               al->string_reference=(char *) SvPV(sv,al->length);
7430               al->integer_reference=(-1);
7431               break;
7432             }
7433           al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7434             MagickFalse,SvPV(sv,na));
7435           if (pp->type == MagickChannelOptions)
7436             al->integer_reference=ParseChannelOption(SvPV(sv,na));
7437           if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7438             {
7439               (void) FormatLocaleString(message,MaxTextExtent,
7440                 "invalid %.60s value",pp->method);
7441               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7442               goto continue_outer_loop;
7443             }
7444           break;
7445         }
7446       }
7447       attribute_flag[pp-rp->arguments]++;
7448       continue_outer_loop: ;
7449     }
7450     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7451     pv=reference_vector;
7452     SetGeometryInfo(&geometry_info);
7453     channel=DefaultChannels;
7454     for (next=image; next; next=next->next)
7455     {
7456       image=next;
7457       SetGeometry(image,&geometry);
7458       if ((region_info.width*region_info.height) != 0)
7459         {
7460           region_image=image;
7461           image=CropImage(image,&region_info,exception);
7462         }
7463       switch (ix)
7464       {
7465         default:
7466         {
7467           (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double) ix);
7468           ThrowPerlException(exception,OptionError,
7469             "UnrecognizedPerlMagickMethod",message);
7470           goto PerlException;
7471         }
7472         case 1:  /* Comment */
7473         {
7474           if (attribute_flag[0] == 0)
7475             argument_list[0].string_reference=(char *) NULL;
7476           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7477             info ? info->image_info : (ImageInfo *) NULL,image,
7478             argument_list[0].string_reference));
7479           break;
7480         }
7481         case 2:  /* Label */
7482         {
7483           if (attribute_flag[0] == 0)
7484             argument_list[0].string_reference=(char *) NULL;
7485           (void) SetImageProperty(image,"label",InterpretImageProperties(
7486             info ? info->image_info : (ImageInfo *) NULL,image,
7487             argument_list[0].string_reference));
7488           break;
7489         }
7490         case 3:  /* AddNoise */
7491         {
7492           if (attribute_flag[0] == 0)
7493             argument_list[0].integer_reference=UniformNoise;
7494           if (attribute_flag[1] != 0)
7495             channel=(ChannelType) argument_list[1].integer_reference;
7496           PushPixelComponentMap(image,channel);
7497           image=AddNoiseImage(image,(NoiseType)
7498             argument_list[0].integer_reference,exception);
7499           PopPixelComponentMap(image);
7500           break;
7501         }
7502         case 4:  /* Colorize */
7503         {
7504           PixelPacket
7505             target;
7506
7507           (void) GetOneVirtualPixel(image,0,0,&target,exception);
7508           if (attribute_flag[0] != 0)
7509             (void) QueryColorDatabase(argument_list[0].string_reference,&target,
7510               exception);
7511           if (attribute_flag[1] == 0)
7512             argument_list[1].string_reference="100%";
7513           image=ColorizeImage(image,argument_list[1].string_reference,target,
7514             exception);
7515           break;
7516         }
7517         case 5:  /* Border */
7518         {
7519           geometry.width=0;
7520           geometry.height=0;
7521           if (attribute_flag[0] != 0)
7522             {
7523               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7524                 &geometry,exception);
7525               if ((flags & HeightValue) == 0)
7526                 geometry.height=geometry.width;
7527             }
7528           if (attribute_flag[1] != 0)
7529             geometry.width=argument_list[1].integer_reference;
7530           if (attribute_flag[2] != 0)
7531             geometry.height=argument_list[2].integer_reference;
7532           if (attribute_flag[3] != 0)
7533             QueryColorDatabase(argument_list[3].string_reference,
7534               &image->border_color,exception);
7535           if (attribute_flag[4] != 0)
7536             QueryColorDatabase(argument_list[4].string_reference,
7537               &image->border_color,exception);
7538           if (attribute_flag[5] != 0)
7539             QueryColorDatabase(argument_list[5].string_reference,
7540               &image->border_color,exception);
7541           if (attribute_flag[6] != 0)
7542             image->compose=(CompositeOperator) argument_list[6].integer_reference;
7543           image=BorderImage(image,&geometry,exception);
7544           break;
7545         }
7546         case 6:  /* Blur */
7547         {
7548           if (attribute_flag[0] != 0)
7549             {
7550               flags=ParseGeometry(argument_list[0].string_reference,
7551                 &geometry_info);
7552               if ((flags & SigmaValue) == 0)
7553                 geometry_info.sigma=1.0;
7554             }
7555           if (attribute_flag[1] != 0)
7556             geometry_info.rho=argument_list[1].real_reference;
7557           if (attribute_flag[2] != 0)
7558             geometry_info.sigma=argument_list[2].real_reference;
7559           if (attribute_flag[3] != 0)
7560             channel=(ChannelType) argument_list[3].integer_reference;
7561           PushPixelComponentMap(image,channel);
7562           image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
7563             exception);
7564           PopPixelComponentMap(image);
7565           break;
7566         }
7567         case 7:  /* Chop */
7568         {
7569           if (attribute_flag[0] != 0)
7570             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7571               &geometry,exception);
7572           if (attribute_flag[1] != 0)
7573             geometry.width=argument_list[1].integer_reference;
7574           if (attribute_flag[2] != 0)
7575             geometry.height=argument_list[2].integer_reference;
7576           if (attribute_flag[3] != 0)
7577             geometry.x=argument_list[3].integer_reference;
7578           if (attribute_flag[4] != 0)
7579             geometry.y=argument_list[4].integer_reference;
7580           image=ChopImage(image,&geometry,exception);
7581           break;
7582         }
7583         case 8:  /* Crop */
7584         {
7585           if (attribute_flag[6] != 0)
7586             image->gravity=(GravityType) argument_list[6].integer_reference;
7587           if (attribute_flag[0] != 0)
7588             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7589               &geometry,exception);
7590           if (attribute_flag[1] != 0)
7591             geometry.width=argument_list[1].integer_reference;
7592           if (attribute_flag[2] != 0)
7593             geometry.height=argument_list[2].integer_reference;
7594           if (attribute_flag[3] != 0)
7595             geometry.x=argument_list[3].integer_reference;
7596           if (attribute_flag[4] != 0)
7597             geometry.y=argument_list[4].integer_reference;
7598           if (attribute_flag[5] != 0)
7599             image->fuzz=
7600               SiPrefixToDouble(argument_list[5].string_reference,QuantumRange);
7601           image=CropImage(image,&geometry,exception);
7602           break;
7603         }
7604         case 9:  /* Despeckle */
7605         {
7606           image=DespeckleImage(image,exception);
7607           break;
7608         }
7609         case 10:  /* Edge */
7610         {
7611           if (attribute_flag[0] != 0)
7612             geometry_info.rho=argument_list[0].real_reference;
7613           image=EdgeImage(image,geometry_info.rho,exception);
7614           break;
7615         }
7616         case 11:  /* Emboss */
7617         {
7618           if (attribute_flag[0] != 0)
7619             {
7620               flags=ParseGeometry(argument_list[0].string_reference,
7621                 &geometry_info);
7622               if ((flags & SigmaValue) == 0)
7623                 geometry_info.sigma=1.0;
7624             }
7625           if (attribute_flag[1] != 0)
7626             geometry_info.rho=argument_list[1].real_reference;
7627           if (attribute_flag[2] != 0)
7628             geometry_info.sigma=argument_list[2].real_reference;
7629           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
7630             exception);
7631           break;
7632         }
7633         case 12:  /* Enhance */
7634         {
7635           image=EnhanceImage(image,exception);
7636           break;
7637         }
7638         case 13:  /* Flip */
7639         {
7640           image=FlipImage(image,exception);
7641           break;
7642         }
7643         case 14:  /* Flop */
7644         {
7645           image=FlopImage(image,exception);
7646           break;
7647         }
7648         case 15:  /* Frame */
7649         {
7650           FrameInfo
7651             frame_info;
7652
7653           if (attribute_flag[0] != 0)
7654             {
7655               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7656                 &geometry,exception);
7657               if ((flags & HeightValue) == 0)
7658                 geometry.height=geometry.width;
7659               frame_info.width=geometry.width;
7660               frame_info.height=geometry.height;
7661               frame_info.outer_bevel=geometry.x;
7662               frame_info.inner_bevel=geometry.y;
7663             }
7664           if (attribute_flag[1] != 0)
7665             frame_info.width=argument_list[1].integer_reference;
7666           if (attribute_flag[2] != 0)
7667             frame_info.height=argument_list[2].integer_reference;
7668           if (attribute_flag[3] != 0)
7669             frame_info.inner_bevel=argument_list[3].integer_reference;
7670           if (attribute_flag[4] != 0)
7671             frame_info.outer_bevel=argument_list[4].integer_reference;
7672           if (attribute_flag[5] != 0)
7673             QueryColorDatabase(argument_list[5].string_reference,&fill_color,
7674               exception);
7675           if (attribute_flag[6] != 0)
7676             QueryColorDatabase(argument_list[6].string_reference,&fill_color,
7677               exception);
7678           frame_info.x=(ssize_t) frame_info.width;
7679           frame_info.y=(ssize_t) frame_info.height;
7680           frame_info.width=image->columns+2*frame_info.x;
7681           frame_info.height=image->rows+2*frame_info.y;
7682           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
7683             image->matte_color=fill_color;
7684           if (attribute_flag[7] != 0)
7685             image->compose=(CompositeOperator) argument_list[7].integer_reference;
7686           image=FrameImage(image,&frame_info,exception);
7687           break;
7688         }
7689         case 16:  /* Implode */
7690         {
7691           if (attribute_flag[0] == 0)
7692             argument_list[0].real_reference=0.5;
7693           if (attribute_flag[1] != 0)
7694             image->interpolate=(InterpolatePixelMethod)
7695               argument_list[1].integer_reference;
7696           image=ImplodeImage(image,argument_list[0].real_reference,
7697             exception);
7698           break;
7699         }
7700         case 17:  /* Magnify */
7701         {
7702           image=MagnifyImage(image,exception);
7703           break;
7704         }
7705         case 18:  /* MedianFilter */
7706         {
7707           if (attribute_flag[0] != 0)
7708             {
7709               flags=ParseGeometry(argument_list[0].string_reference,
7710                 &geometry_info);
7711               if ((flags & SigmaValue) == 0)
7712                 geometry_info.sigma=1.0;
7713             }
7714           if (attribute_flag[1] != 0)
7715             geometry_info.rho=argument_list[1].real_reference;
7716           if (attribute_flag[2] != 0)
7717             geometry_info.sigma=argument_list[2].real_reference;
7718           if (attribute_flag[3] != 0)
7719             channel=(ChannelType) argument_list[3].integer_reference;
7720           PushPixelComponentMap(image,channel);
7721           image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
7722             (size_t) geometry_info.sigma,exception);
7723           PopPixelComponentMap(image);
7724           break;
7725         }
7726         case 19:  /* Minify */
7727         {
7728           image=MinifyImage(image,exception);
7729           break;
7730         }
7731         case 20:  /* OilPaint */
7732         {
7733           if (attribute_flag[0] == 0)
7734             argument_list[0].real_reference=0.0;
7735           image=OilPaintImage(image,argument_list[0].real_reference,
7736             exception);
7737           break;
7738         }
7739         case 21:  /* ReduceNoise */
7740         {
7741           if (attribute_flag[0] != 0)
7742             {
7743               flags=ParseGeometry(argument_list[0].string_reference,
7744                 &geometry_info);
7745               if ((flags & SigmaValue) == 0)
7746                 geometry_info.sigma=1.0;
7747             }
7748           if (attribute_flag[1] != 0)
7749             geometry_info.rho=argument_list[1].real_reference;
7750           if (attribute_flag[2] != 0)
7751             geometry_info.sigma=argument_list[2].real_reference;
7752           if (attribute_flag[3] != 0)
7753             channel=(ChannelType) argument_list[3].integer_reference;
7754           PushPixelComponentMap(image,channel);
7755           image=StatisticImage(image,NonpeakStatistic,(size_t)
7756             geometry_info.rho,(size_t) geometry_info.sigma,exception);
7757           PopPixelComponentMap(image);
7758           break;
7759         }
7760         case 22:  /* Roll */
7761         {
7762           if (attribute_flag[0] != 0)
7763             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7764               &geometry,exception);
7765           if (attribute_flag[1] != 0)
7766             geometry.x=argument_list[1].integer_reference;
7767           if (attribute_flag[2] != 0)
7768             geometry.y=argument_list[2].integer_reference;
7769           image=RollImage(image,geometry.x,geometry.y,exception);
7770           break;
7771         }
7772         case 23:  /* Rotate */
7773         {
7774           if (attribute_flag[0] == 0)
7775             argument_list[0].real_reference=90.0;
7776           if (attribute_flag[1] != 0)
7777             QueryColorDatabase(argument_list[1].string_reference,
7778               &image->background_color,exception);
7779           if (attribute_flag[2] != 0)
7780             QueryColorDatabase(argument_list[2].string_reference,
7781               &image->background_color,exception);
7782           if (attribute_flag[3] != 0)
7783             QueryColorDatabase(argument_list[3].string_reference,
7784               &image->background_color,exception);
7785           image=RotateImage(image,argument_list[0].real_reference,exception);
7786           break;
7787         }
7788         case 24:  /* Sample */
7789         {
7790           if (attribute_flag[0] != 0)
7791             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7792               &geometry,exception);
7793           if (attribute_flag[1] != 0)
7794             geometry.width=argument_list[1].integer_reference;
7795           if (attribute_flag[2] != 0)
7796             geometry.height=argument_list[2].integer_reference;
7797           image=SampleImage(image,geometry.width,geometry.height,exception);
7798           break;
7799         }
7800         case 25:  /* Scale */
7801         {
7802           if (attribute_flag[0] != 0)
7803             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7804               &geometry,exception);
7805           if (attribute_flag[1] != 0)
7806             geometry.width=argument_list[1].integer_reference;
7807           if (attribute_flag[2] != 0)
7808             geometry.height=argument_list[2].integer_reference;
7809           image=ScaleImage(image,geometry.width,geometry.height,exception);
7810           break;
7811         }
7812         case 26:  /* Shade */
7813         {
7814           if (attribute_flag[0] != 0)
7815             {
7816               flags=ParseGeometry(argument_list[0].string_reference,
7817                 &geometry_info);
7818               if ((flags & SigmaValue) == 0)
7819                 geometry_info.sigma=0.0;
7820             }
7821           if (attribute_flag[1] != 0)
7822             geometry_info.rho=argument_list[1].real_reference;
7823           if (attribute_flag[2] != 0)
7824             geometry_info.sigma=argument_list[2].real_reference;
7825           image=ShadeImage(image,
7826             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
7827             geometry_info.rho,geometry_info.sigma,exception);
7828           break;
7829         }
7830         case 27:  /* Sharpen */
7831         {
7832           if (attribute_flag[0] != 0)
7833             {
7834               flags=ParseGeometry(argument_list[0].string_reference,
7835                 &geometry_info);
7836               if ((flags & SigmaValue) == 0)
7837                 geometry_info.sigma=1.0;
7838             }
7839           if (attribute_flag[1] != 0)
7840             geometry_info.rho=argument_list[1].real_reference;
7841           if (attribute_flag[2] != 0)
7842             geometry_info.sigma=argument_list[2].real_reference;
7843           if (attribute_flag[3] != 0)
7844             channel=(ChannelType) argument_list[3].integer_reference;
7845           PushPixelComponentMap(image,channel);
7846           image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
7847             exception);
7848           PopPixelComponentMap(image);
7849           break;
7850         }
7851         case 28:  /* Shear */
7852         {
7853           if (attribute_flag[0] != 0)
7854             {
7855               flags=ParseGeometry(argument_list[0].string_reference,
7856                 &geometry_info);
7857               if ((flags & SigmaValue) == 0)
7858                 geometry_info.sigma=geometry_info.rho;
7859             }
7860           if (attribute_flag[1] != 0)
7861             geometry_info.rho=argument_list[1].real_reference;
7862           if (attribute_flag[2] != 0)
7863             geometry_info.sigma=argument_list[2].real_reference;
7864           if (attribute_flag[3] != 0)
7865             QueryColorDatabase(argument_list[3].string_reference,
7866               &image->background_color,exception);
7867           if (attribute_flag[4] != 0)
7868             QueryColorDatabase(argument_list[4].string_reference,
7869               &image->background_color,exception);
7870           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
7871             exception);
7872           break;
7873         }
7874         case 29:  /* Spread */
7875         {
7876           if (attribute_flag[0] == 0)
7877             argument_list[0].real_reference=1.0;
7878           image=SpreadImage(image,argument_list[0].real_reference,exception);
7879           break;
7880         }
7881         case 30:  /* Swirl */
7882         {
7883           if (attribute_flag[0] == 0)
7884             argument_list[0].real_reference=50.0;
7885           if (attribute_flag[1] != 0)
7886             image->interpolate=(InterpolatePixelMethod)
7887               argument_list[1].integer_reference;
7888           image=SwirlImage(image,argument_list[0].real_reference,exception);
7889           break;
7890         }
7891         case 31:  /* Resize */
7892         case 32:  /* Zoom */
7893         {
7894           if (attribute_flag[0] != 0)
7895             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7896               &geometry,exception);
7897           if (attribute_flag[1] != 0)
7898             geometry.width=argument_list[1].integer_reference;
7899           if (attribute_flag[2] != 0)
7900             geometry.height=argument_list[2].integer_reference;
7901           if (attribute_flag[3] == 0)
7902             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
7903           if (attribute_flag[4] != 0)
7904             SetImageArtifact(image,"filter:support",
7905               argument_list[4].string_reference);
7906           if (attribute_flag[5] == 0)
7907             argument_list[5].real_reference=1.0;
7908           image=ResizeImage(image,geometry.width,geometry.height,
7909             (FilterTypes) argument_list[3].integer_reference,
7910             argument_list[5].real_reference,exception);
7911           break;
7912         }
7913         case 33:  /* Annotate */
7914         {
7915           DrawInfo
7916             *draw_info;
7917
7918           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
7919             (DrawInfo *) NULL);
7920           if (attribute_flag[0] != 0)
7921             {
7922               char
7923                 *text;
7924
7925               text=InterpretImageProperties(info ? info->image_info :
7926                 (ImageInfo *) NULL,image,argument_list[0].string_reference);
7927               (void) CloneString(&draw_info->text,text);
7928               text=DestroyString(text);
7929             }
7930           if (attribute_flag[1] != 0)
7931             (void) CloneString(&draw_info->font,
7932               argument_list[1].string_reference);
7933           if (attribute_flag[2] != 0)
7934             draw_info->pointsize=argument_list[2].real_reference;
7935           if (attribute_flag[3] != 0)
7936             (void) CloneString(&draw_info->density,
7937               argument_list[3].string_reference);
7938           if (attribute_flag[4] != 0)
7939             (void) QueryColorDatabase(argument_list[4].string_reference,
7940               &draw_info->undercolor,exception);
7941           if (attribute_flag[5] != 0)
7942             {
7943               (void) QueryColorDatabase(argument_list[5].string_reference,
7944                 &draw_info->stroke,exception);
7945               if (argument_list[5].image_reference != (Image *) NULL)
7946                 draw_info->stroke_pattern=CloneImage(
7947                   argument_list[5].image_reference,0,0,MagickTrue,exception);
7948             }
7949           if (attribute_flag[6] != 0)
7950             {
7951               (void) QueryColorDatabase(argument_list[6].string_reference,
7952                 &draw_info->fill,exception);
7953               if (argument_list[6].image_reference != (Image *) NULL)
7954                 draw_info->fill_pattern=CloneImage(
7955                   argument_list[6].image_reference,0,0,MagickTrue,exception);
7956             }
7957           if (attribute_flag[7] != 0)
7958             {
7959               (void) CloneString(&draw_info->geometry,
7960                 argument_list[7].string_reference);
7961               flags=ParsePageGeometry(image,argument_list[7].string_reference,
7962                 &geometry,exception);
7963               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
7964                 geometry_info.sigma=geometry_info.xi;
7965             }
7966           if (attribute_flag[8] != 0)
7967             (void) QueryColorDatabase(argument_list[8].string_reference,
7968               &draw_info->fill,exception);
7969           if (attribute_flag[11] != 0)
7970             draw_info->gravity=(GravityType) argument_list[11].integer_reference;
7971           if (attribute_flag[25] != 0)
7972             {
7973               AV
7974                 *av;
7975
7976               av=(AV *) argument_list[25].array_reference;
7977               if ((av_len(av) != 3) && (av_len(av) != 5))
7978                 {
7979                   ThrowPerlException(exception,OptionError,
7980                     "affine matrix must have 4 or 6 elements",PackageName);
7981                   goto PerlException;
7982                 }
7983               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
7984               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
7985               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
7986               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
7987               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
7988                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
7989                 {
7990                   ThrowPerlException(exception,OptionError,
7991                     "affine matrix is singular",PackageName);
7992                    goto PerlException;
7993                 }
7994               if (av_len(av) == 5)
7995                 {
7996                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
7997                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
7998                 }
7999             }
8000           for (j=12; j < 17; j++)
8001           {
8002             if (attribute_flag[j] == 0)
8003               continue;
8004             value=argument_list[j].string_reference;
8005             angle=argument_list[j].real_reference;
8006             current=draw_info->affine;
8007             GetAffineMatrix(&affine);
8008             switch (j)
8009             {
8010               case 12:
8011               {
8012                 /*
8013                   Translate.
8014                 */
8015                 flags=ParseGeometry(value,&geometry_info);
8016                 affine.tx=geometry_info.xi;
8017                 affine.ty=geometry_info.psi;
8018                 if ((flags & PsiValue) == 0)
8019                   affine.ty=affine.tx;
8020                 break;
8021               }
8022               case 13:
8023               {
8024                 /*
8025                   Scale.
8026                 */
8027                 flags=ParseGeometry(value,&geometry_info);
8028                 affine.sx=geometry_info.rho;
8029                 affine.sy=geometry_info.sigma;
8030                 if ((flags & SigmaValue) == 0)
8031                   affine.sy=affine.sx;
8032                 break;
8033               }
8034               case 14:
8035               {
8036                 /*
8037                   Rotate.
8038                 */
8039                 if (angle == 0.0)
8040                   break;
8041                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8042                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8043                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8044                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8045                 break;
8046               }
8047               case 15:
8048               {
8049                 /*
8050                   SkewX.
8051                 */
8052                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8053                 break;
8054               }
8055               case 16:
8056               {
8057                 /*
8058                   SkewY.
8059                 */
8060                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8061                 break;
8062               }
8063             }
8064             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8065             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8066             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8067             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8068             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8069               current.tx;
8070             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8071               current.ty;
8072           }
8073           if (attribute_flag[9] == 0)
8074             argument_list[9].real_reference=0.0;
8075           if (attribute_flag[10] == 0)
8076             argument_list[10].real_reference=0.0;
8077           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8078             {
8079               char
8080                 geometry[MaxTextExtent];
8081
8082               (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
8083                 (double) argument_list[9].real_reference+draw_info->affine.tx,
8084                 (double) argument_list[10].real_reference+draw_info->affine.ty);
8085               (void) CloneString(&draw_info->geometry,geometry);
8086             }
8087           if (attribute_flag[17] != 0)
8088             draw_info->stroke_width=argument_list[17].real_reference;
8089           if (attribute_flag[18] != 0)
8090             {
8091               draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8092                 MagickTrue : MagickFalse;
8093               draw_info->stroke_antialias=draw_info->text_antialias;
8094             }
8095           if (attribute_flag[19] != 0)
8096             (void) CloneString(&draw_info->family,
8097               argument_list[19].string_reference);
8098           if (attribute_flag[20] != 0)
8099             draw_info->style=(StyleType) argument_list[20].integer_reference;
8100           if (attribute_flag[21] != 0)
8101             draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8102           if (attribute_flag[22] != 0)
8103             draw_info->weight=argument_list[22].integer_reference;
8104           if (attribute_flag[23] != 0)
8105             draw_info->align=(AlignType) argument_list[23].integer_reference;
8106           if (attribute_flag[24] != 0)
8107             (void) CloneString(&draw_info->encoding,
8108               argument_list[24].string_reference);
8109           if (attribute_flag[25] != 0)
8110             draw_info->fill_pattern=CloneImage(
8111               argument_list[25].image_reference,0,0,MagickTrue,exception);
8112           if (attribute_flag[26] != 0)
8113             draw_info->fill_pattern=CloneImage(
8114               argument_list[26].image_reference,0,0,MagickTrue,exception);
8115           if (attribute_flag[27] != 0)
8116             draw_info->stroke_pattern=CloneImage(
8117               argument_list[27].image_reference,0,0,MagickTrue,exception);
8118           if (attribute_flag[29] != 0)
8119             draw_info->kerning=argument_list[29].real_reference;
8120           if (attribute_flag[30] != 0)
8121             draw_info->interline_spacing=argument_list[30].real_reference;
8122           if (attribute_flag[31] != 0)
8123             draw_info->interword_spacing=argument_list[31].real_reference;
8124           if (attribute_flag[32] != 0)
8125             draw_info->direction=(DirectionType)
8126               argument_list[32].integer_reference;
8127           (void) AnnotateImage(image,draw_info);
8128           draw_info=DestroyDrawInfo(draw_info);
8129           break;
8130         }
8131         case 34:  /* ColorFloodfill */
8132         {
8133           DrawInfo
8134             *draw_info;
8135
8136           MagickBooleanType
8137             invert;
8138
8139           PixelInfo
8140             target;
8141
8142           draw_info=CloneDrawInfo(info ? info->image_info :
8143             (ImageInfo *) NULL,(DrawInfo *) NULL);
8144           if (attribute_flag[0] != 0)
8145             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8146               &geometry,exception);
8147           if (attribute_flag[1] != 0)
8148             geometry.x=argument_list[1].integer_reference;
8149           if (attribute_flag[2] != 0)
8150             geometry.y=argument_list[2].integer_reference;
8151           if (attribute_flag[3] != 0)
8152             (void) QueryColorDatabase(argument_list[3].string_reference,
8153               &draw_info->fill,exception);
8154           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
8155             exception);
8156           invert=MagickFalse;
8157           if (attribute_flag[4] != 0)
8158             {
8159               QueryMagickColor(argument_list[4].string_reference,&target,
8160                 exception);
8161               invert=MagickTrue;
8162             }
8163           if (attribute_flag[5] != 0)
8164             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
8165               QuantumRange);
8166           if (attribute_flag[6] != 0)
8167             invert=(MagickBooleanType) argument_list[6].integer_reference;
8168           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8169             geometry.y,invert);
8170           draw_info=DestroyDrawInfo(draw_info);
8171           break;
8172         }
8173         case 35:  /* Composite */
8174         {
8175           char
8176             composite_geometry[MaxTextExtent];
8177
8178           Image
8179             *composite_image,
8180             *rotate_image;
8181
8182           compose=OverCompositeOp;
8183           if (attribute_flag[0] != 0)
8184             composite_image=argument_list[0].image_reference;
8185           else
8186             {
8187               ThrowPerlException(exception,OptionError,
8188                 "CompositeImageRequired",PackageName);
8189               goto PerlException;
8190             }
8191           /*
8192             Parameter Handling used for BOTH normal and tiled composition.
8193           */
8194           if (attribute_flag[1] != 0) /* compose */
8195             compose=(CompositeOperator) argument_list[1].integer_reference;
8196           if (attribute_flag[6] != 0) /* opacity  */
8197             {
8198               if (compose != DissolveCompositeOp)
8199                 (void) SetImageOpacity(composite_image,(Quantum)
8200                   SiPrefixToDouble(argument_list[6].string_reference,
8201                   QuantumRange));
8202               else
8203                 {
8204                   CacheView
8205                     *composite_view;
8206
8207                   double
8208                     opacity;
8209
8210                   MagickBooleanType
8211                     sync;
8212
8213                   register ssize_t
8214                     x;
8215
8216                   register Quantum
8217                     *q;
8218
8219                   ssize_t
8220                     y;
8221
8222                   /*
8223                     Handle dissolve composite operator (patch by
8224                     Kevin A. McGrail).
8225                   */
8226                   (void) CloneString(&image->geometry,
8227                     argument_list[6].string_reference);
8228                   opacity=(Quantum) SiPrefixToDouble(
8229                     argument_list[6].string_reference,QuantumRange);
8230                   if (composite_image->matte != MagickTrue)
8231                     (void) SetImageOpacity(composite_image,OpaqueAlpha);
8232                   composite_view=AcquireCacheView(composite_image);
8233                   for (y=0; y < (ssize_t) composite_image->rows ; y++)
8234                   {
8235                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8236                       composite_image->columns,1,exception);
8237                     for (x=0; x < (ssize_t) composite_image->columns; x++)
8238                     {
8239                       if (GetPixelAlpha(image,q) == OpaqueAlpha)
8240                         SetPixelAlpha(composite_image,ClampToQuantum(opacity),q);
8241                       q+=GetPixelComponents(composite_image);
8242                     }
8243                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8244                     if (sync == MagickFalse)
8245                       break;
8246                   }
8247                   composite_view=DestroyCacheView(composite_view);
8248                 }
8249             }
8250           if (attribute_flag[9] != 0)    /* "color=>" */
8251             QueryColorDatabase(argument_list[9].string_reference,
8252               &composite_image->background_color,exception);
8253           if (attribute_flag[12] != 0) /* "interpolate=>" */
8254             image->interpolate=(InterpolatePixelMethod)
8255               argument_list[12].integer_reference;
8256           if (attribute_flag[13] != 0)   /* "args=>" */
8257             (void) SetImageArtifact(composite_image,"compose:args",
8258               argument_list[13].string_reference);
8259           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8260             (void) SetImageArtifact(composite_image,"compose:args",
8261               argument_list[14].string_reference);
8262           /*
8263             Tiling Composition (with orthogonal rotate).
8264           */
8265           rotate_image=(Image *) NULL;
8266           if (attribute_flag[8] != 0)   /* "rotate=>" */
8267             {
8268                /*
8269                  Rotate image.
8270                */
8271                rotate_image=RotateImage(composite_image,
8272                  argument_list[8].real_reference,exception);
8273                if (rotate_image == (Image *) NULL)
8274                  break;
8275             }
8276           if (attribute_flag[7] && argument_list[7].integer_reference) /* tile */
8277             {
8278               ssize_t
8279                 x,
8280                 y;
8281
8282               /*
8283                 Tile the composite image.
8284               */
8285              if (attribute_flag[8] != 0)   /* "tile=>" */
8286                (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8287                  "false");
8288              else
8289                (void) SetImageArtifact(composite_image,
8290                  "compose:outside-overlay","false");
8291              for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8292                 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8293                 {
8294                   if (attribute_flag[8] != 0) /* rotate */
8295                     (void) CompositeImage(image,compose,rotate_image,x,y);
8296                   else
8297                     (void) CompositeImage(image,compose,composite_image,x,y);
8298                 }
8299               if (attribute_flag[8] != 0) /* rotate */
8300                 rotate_image=DestroyImage(rotate_image);
8301               break;
8302             }
8303           /*
8304             Parameter Handling used used ONLY for normal composition.
8305           */
8306           if (attribute_flag[5] != 0) /* gravity */
8307             image->gravity=(GravityType) argument_list[5].integer_reference;
8308           if (attribute_flag[2] != 0) /* geometry offset */
8309             {
8310               SetGeometry(image,&geometry);
8311               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8312                 &geometry);
8313               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8314                 &geometry);
8315             }
8316           if (attribute_flag[3] != 0) /* x offset */
8317             geometry.x=argument_list[3].integer_reference;
8318           if (attribute_flag[4] != 0) /* y offset */
8319             geometry.y=argument_list[4].integer_reference;
8320           if (attribute_flag[10] != 0) /* mask */
8321             {
8322               if ((image->compose == DisplaceCompositeOp) ||
8323                   (image->compose == DistortCompositeOp))
8324                 {
8325                   /*
8326                     Merge Y displacement into X displacement image.
8327                   */
8328                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8329                     &image->exception);
8330                   (void) CompositeImage(composite_image,CopyGreenCompositeOp,
8331                     argument_list[10].image_reference,0,0);
8332                 }
8333               else
8334                 {
8335                   /*
8336                     Set a blending mask for the composition.
8337                   */
8338                   image->mask=CloneImage(argument_list[10].image_reference,0,0,
8339                     MagickTrue,&image->exception);
8340                   (void) NegateImage(image->mask,MagickFalse);
8341                 }
8342             }
8343           if (attribute_flag[11] != 0) /* channel */
8344             channel=(ChannelType) argument_list[11].integer_reference;
8345           /*
8346             Composite two images (normal composition).
8347           */
8348           (void) FormatLocaleString(composite_geometry,MaxTextExtent,
8349             "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8350             (double) composite_image->rows,(double) geometry.x,(double)
8351             geometry.y);
8352           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8353             exception);
8354           PushPixelComponentMap(image,channel);
8355           if (attribute_flag[8] == 0) /* no rotate */
8356             CompositeImage(image,compose,composite_image,geometry.x,geometry.y);
8357           else
8358             {
8359               /*
8360                 Position adjust rotated image then composite.
8361               */
8362               geometry.x-=(ssize_t) (rotate_image->columns-
8363                 composite_image->columns)/2;
8364               geometry.y-=(ssize_t) (rotate_image->rows-
8365                 composite_image->rows)/2;
8366               CompositeImage(image,compose,rotate_image,geometry.x,geometry.y);
8367               rotate_image=DestroyImage(rotate_image);
8368             }
8369           if (attribute_flag[10] != 0) /* mask */
8370             {
8371               if ((image->compose == DisplaceCompositeOp) ||
8372                   (image->compose == DistortCompositeOp))
8373                 composite_image=DestroyImage(composite_image);
8374               else
8375                 image->mask=DestroyImage(image->mask);
8376             }
8377           PopPixelComponentMap(image);
8378           break;
8379         }
8380         case 36:  /* Contrast */
8381         {
8382           if (attribute_flag[0] == 0)
8383             argument_list[0].integer_reference=0;
8384           (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8385             MagickTrue : MagickFalse);
8386           break;
8387         }
8388         case 37:  /* CycleColormap */
8389         {
8390           if (attribute_flag[0] == 0)
8391             argument_list[0].integer_reference=6;
8392           (void) CycleColormapImage(image,argument_list[0].integer_reference);
8393           break;
8394         }
8395         case 38:  /* Draw */
8396         {
8397           DrawInfo
8398             *draw_info;
8399
8400           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8401             (DrawInfo *) NULL);
8402           (void) CloneString(&draw_info->primitive,"point");
8403           if (attribute_flag[0] != 0)
8404             {
8405               if (argument_list[0].integer_reference < 0)
8406                 (void) CloneString(&draw_info->primitive,
8407                   argument_list[0].string_reference);
8408               else
8409                 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8410                   MagickPrimitiveOptions,argument_list[0].integer_reference));
8411             }
8412           if (attribute_flag[1] != 0)
8413             {
8414               if (LocaleCompare(draw_info->primitive,"path") == 0)
8415                 {
8416                   (void) ConcatenateString(&draw_info->primitive," '");
8417                   ConcatenateString(&draw_info->primitive,
8418                     argument_list[1].string_reference);
8419                   (void) ConcatenateString(&draw_info->primitive,"'");
8420                 }
8421               else
8422                 {
8423                   (void) ConcatenateString(&draw_info->primitive," ");
8424                   ConcatenateString(&draw_info->primitive,
8425                     argument_list[1].string_reference);
8426                 }
8427             }
8428           if (attribute_flag[2] != 0)
8429             {
8430               (void) ConcatenateString(&draw_info->primitive," ");
8431               (void) ConcatenateString(&draw_info->primitive,
8432                 CommandOptionToMnemonic(MagickMethodOptions,
8433                 argument_list[2].integer_reference));
8434             }
8435           if (attribute_flag[3] != 0)
8436             {
8437               (void) QueryColorDatabase(argument_list[3].string_reference,
8438                 &draw_info->stroke,exception);
8439               if (argument_list[3].image_reference != (Image *) NULL)
8440                 draw_info->stroke_pattern=CloneImage(
8441                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8442             }
8443           if (attribute_flag[4] != 0)
8444             {
8445               (void) QueryColorDatabase(argument_list[4].string_reference,
8446                 &draw_info->fill,exception);
8447               if (argument_list[4].image_reference != (Image *) NULL)
8448                 draw_info->fill_pattern=CloneImage(
8449                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8450             }
8451           if (attribute_flag[5] != 0)
8452             draw_info->stroke_width=argument_list[5].real_reference;
8453           if (attribute_flag[6] != 0)
8454             (void) CloneString(&draw_info->font,
8455               argument_list[6].string_reference);
8456           if (attribute_flag[7] != 0)
8457             (void) QueryColorDatabase(argument_list[7].string_reference,
8458               &draw_info->border_color,exception);
8459           if (attribute_flag[8] != 0)
8460             draw_info->affine.tx=argument_list[8].real_reference;
8461           if (attribute_flag[9] != 0)
8462             draw_info->affine.ty=argument_list[9].real_reference;
8463           if (attribute_flag[20] != 0)
8464             {
8465               AV
8466                 *av;
8467
8468               av=(AV *) argument_list[20].array_reference;
8469               if ((av_len(av) != 3) && (av_len(av) != 5))
8470                 {
8471                   ThrowPerlException(exception,OptionError,
8472                     "affine matrix must have 4 or 6 elements",PackageName);
8473                   goto PerlException;
8474                 }
8475               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8476               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8477               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8478               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8479               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8480                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8481                 {
8482                   ThrowPerlException(exception,OptionError,
8483                     "affine matrix is singular",PackageName);
8484                    goto PerlException;
8485                 }
8486               if (av_len(av) == 5)
8487                 {
8488                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8489                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8490                 }
8491             }
8492           for (j=10; j < 15; j++)
8493           {
8494             if (attribute_flag[j] == 0)
8495               continue;
8496             value=argument_list[j].string_reference;
8497             angle=argument_list[j].real_reference;
8498             current=draw_info->affine;
8499             GetAffineMatrix(&affine);
8500             switch (j)
8501             {
8502               case 10:
8503               {
8504                 /*
8505                   Translate.
8506                 */
8507                 flags=ParseGeometry(value,&geometry_info);
8508                 affine.tx=geometry_info.xi;
8509                 affine.ty=geometry_info.psi;
8510                 if ((flags & PsiValue) == 0)
8511                   affine.ty=affine.tx;
8512                 break;
8513               }
8514               case 11:
8515               {
8516                 /*
8517                   Scale.
8518                 */
8519                 flags=ParseGeometry(value,&geometry_info);
8520                 affine.sx=geometry_info.rho;
8521                 affine.sy=geometry_info.sigma;
8522                 if ((flags & SigmaValue) == 0)
8523                   affine.sy=affine.sx;
8524                 break;
8525               }
8526               case 12:
8527               {
8528                 /*
8529                   Rotate.
8530                 */
8531                 if (angle == 0.0)
8532                   break;
8533                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8534                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8535                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8536                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8537                 break;
8538               }
8539               case 13:
8540               {
8541                 /*
8542                   SkewX.
8543                 */
8544                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8545                 break;
8546               }
8547               case 14:
8548               {
8549                 /*
8550                   SkewY.
8551                 */
8552                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8553                 break;
8554               }
8555             }
8556             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8557             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8558             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8559             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8560             draw_info->affine.tx=
8561               current.sx*affine.tx+current.ry*affine.ty+current.tx;
8562             draw_info->affine.ty=
8563               current.rx*affine.tx+current.sy*affine.ty+current.ty;
8564           }
8565           if (attribute_flag[15] != 0)
8566             draw_info->fill_pattern=CloneImage(
8567               argument_list[15].image_reference,0,0,MagickTrue,exception);
8568           if (attribute_flag[16] != 0)
8569             draw_info->pointsize=argument_list[16].real_reference;
8570           if (attribute_flag[17] != 0)
8571             {
8572               draw_info->stroke_antialias=argument_list[17].integer_reference != 0
8573                 ? MagickTrue : MagickFalse;
8574               draw_info->text_antialias=draw_info->stroke_antialias;
8575             }
8576           if (attribute_flag[18] != 0)
8577             (void) CloneString(&draw_info->density,
8578               argument_list[18].string_reference);
8579           if (attribute_flag[19] != 0)
8580             draw_info->stroke_width=argument_list[19].real_reference;
8581           if (attribute_flag[21] != 0)
8582             draw_info->dash_offset=argument_list[21].real_reference;
8583           if (attribute_flag[22] != 0)
8584             {
8585               AV
8586                 *av;
8587
8588               av=(AV *) argument_list[22].array_reference;
8589               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
8590                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
8591               if (draw_info->dash_pattern != (double *) NULL)
8592                 {
8593                   for (i=0; i <= av_len(av); i++)
8594                     draw_info->dash_pattern[i]=(double)
8595                       SvNV(*(av_fetch(av,i,0)));
8596                   draw_info->dash_pattern[i]=0.0;
8597                 }
8598             }
8599           if (attribute_flag[23] != 0)
8600             image->interpolate=(InterpolatePixelMethod)
8601               argument_list[23].integer_reference;
8602           if ((attribute_flag[24] != 0) &&
8603               (draw_info->fill_pattern != (Image *) NULL))
8604             flags=ParsePageGeometry(draw_info->fill_pattern,
8605               argument_list[24].string_reference,
8606               &draw_info->fill_pattern->tile_offset,exception);
8607           if (attribute_flag[25] != 0)
8608             {
8609               (void) ConcatenateString(&draw_info->primitive," '");
8610               (void) ConcatenateString(&draw_info->primitive,
8611                 argument_list[25].string_reference);
8612               (void) ConcatenateString(&draw_info->primitive,"'");
8613             }
8614           if (attribute_flag[26] != 0)
8615             draw_info->fill_pattern=CloneImage(
8616               argument_list[26].image_reference,0,0,MagickTrue,exception);
8617           if (attribute_flag[27] != 0)
8618             draw_info->stroke_pattern=CloneImage(
8619               argument_list[27].image_reference,0,0,MagickTrue,exception);
8620           if (attribute_flag[28] != 0)
8621             (void) CloneString(&draw_info->primitive,
8622               argument_list[28].string_reference);
8623           if (attribute_flag[29] != 0)
8624             draw_info->kerning=argument_list[29].real_reference;
8625           if (attribute_flag[30] != 0)
8626             draw_info->interline_spacing=argument_list[30].real_reference;
8627           if (attribute_flag[31] != 0)
8628             draw_info->interword_spacing=argument_list[31].real_reference;
8629           if (attribute_flag[32] != 0)
8630             draw_info->direction=(DirectionType)
8631               argument_list[32].integer_reference;
8632           DrawImage(image,draw_info);
8633           draw_info=DestroyDrawInfo(draw_info);
8634           break;
8635         }
8636         case 39:  /* Equalize */
8637         {
8638           if (attribute_flag[0] != 0)
8639             channel=(ChannelType) argument_list[0].integer_reference;
8640           PushPixelComponentMap(image,channel);
8641           EqualizeImage(image);
8642           PopPixelComponentMap(image);
8643           break;
8644         }
8645         case 40:  /* Gamma */
8646         {
8647           if (attribute_flag[1] != 0)
8648             channel=(ChannelType) argument_list[1].integer_reference;
8649           if (attribute_flag[2] == 0)
8650             argument_list[2].real_reference=1.0;
8651           if (attribute_flag[3] == 0)
8652             argument_list[3].real_reference=1.0;
8653           if (attribute_flag[4] == 0)
8654             argument_list[4].real_reference=1.0;
8655           if (attribute_flag[0] == 0)
8656             {
8657               (void) FormatLocaleString(message,MaxTextExtent,
8658                 "%.15g,%.15g,%.15g",(double) argument_list[2].real_reference,
8659                 (double) argument_list[3].real_reference,
8660                 (double) argument_list[4].real_reference);
8661               argument_list[0].string_reference=message;
8662             }
8663           (void) GammaImage(image,InterpretLocaleValue(
8664             argument_list[0].string_reference,(char **) NULL));
8665           break;
8666         }
8667         case 41:  /* Map */
8668         {
8669           QuantizeInfo
8670             *quantize_info;
8671
8672           if (attribute_flag[0] == 0)
8673             {
8674               ThrowPerlException(exception,OptionError,"MapImageRequired",
8675                 PackageName);
8676               goto PerlException;
8677             }
8678           quantize_info=AcquireQuantizeInfo(info->image_info);
8679           if (attribute_flag[1] != 0)
8680             quantize_info->dither=(MagickBooleanType)
8681               argument_list[1].integer_reference;
8682           if (attribute_flag[2] != 0)
8683             quantize_info->dither_method=(DitherMethod)
8684               argument_list[2].integer_reference;
8685           (void) RemapImages(quantize_info,image,
8686             argument_list[0].image_reference);
8687           quantize_info=DestroyQuantizeInfo(quantize_info);
8688           break;
8689         }
8690         case 42:  /* MatteFloodfill */
8691         {
8692           DrawInfo
8693             *draw_info;
8694
8695           MagickBooleanType
8696             invert;
8697
8698           PixelInfo
8699             target;
8700
8701           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8702             (DrawInfo *) NULL);
8703           if (attribute_flag[0] != 0)
8704             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8705               &geometry,exception);
8706           if (attribute_flag[1] != 0)
8707             geometry.x=argument_list[1].integer_reference;
8708           if (attribute_flag[2] != 0)
8709             geometry.y=argument_list[2].integer_reference;
8710           if (image->matte == MagickFalse)
8711             (void) SetImageOpacity(image,OpaqueAlpha);
8712           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
8713             exception);
8714           if (attribute_flag[4] != 0)
8715             QueryMagickColor(argument_list[4].string_reference,&target,
8716               exception);
8717           if (attribute_flag[3] != 0)
8718             target.alpha=SiPrefixToDouble(argument_list[3].string_reference,
8719               QuantumRange);
8720           if (attribute_flag[5] != 0)
8721             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
8722               QuantumRange);
8723           invert=MagickFalse;
8724           if (attribute_flag[6] != 0)
8725             invert=(MagickBooleanType) argument_list[6].integer_reference;
8726           PushPixelComponentMap(image,AlphaChannel);
8727           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8728             geometry.y,invert);
8729           PopPixelComponentMap(image);
8730           StandardPixelComponentMap(image);
8731           draw_info=DestroyDrawInfo(draw_info);
8732           break;
8733         }
8734         case 43:  /* Modulate */
8735         {
8736           char
8737             modulate[MaxTextExtent];
8738
8739           geometry_info.rho=100.0;
8740           geometry_info.sigma=100.0;
8741           geometry_info.xi=100.0;
8742           if (attribute_flag[0] != 0)
8743             (void)ParseGeometry(argument_list[0].string_reference,
8744               &geometry_info);
8745           if (attribute_flag[1] != 0)
8746             geometry_info.xi=argument_list[1].real_reference;
8747           if (attribute_flag[2] != 0)
8748             geometry_info.sigma=argument_list[2].real_reference;
8749           if (attribute_flag[3] != 0)
8750             {
8751               geometry_info.sigma=argument_list[3].real_reference;
8752               SetImageArtifact(image,"modulate:colorspace","HWB");
8753             }
8754           if (attribute_flag[4] != 0)
8755             {
8756               geometry_info.rho=argument_list[4].real_reference;
8757               SetImageArtifact(image,"modulate:colorspace","HSB");
8758             }
8759           if (attribute_flag[5] != 0)
8760             {
8761               geometry_info.sigma=argument_list[5].real_reference;
8762               SetImageArtifact(image,"modulate:colorspace","HSL");
8763             }
8764           if (attribute_flag[6] != 0)
8765             {
8766               geometry_info.rho=argument_list[6].real_reference;
8767               SetImageArtifact(image,"modulate:colorspace","HWB");
8768             }
8769           (void) FormatLocaleString(modulate,MaxTextExtent,"%.15g,%.15g,%.15g",
8770             geometry_info.rho,geometry_info.sigma,geometry_info.xi);
8771           (void) ModulateImage(image,modulate);
8772           break;
8773         }
8774         case 44:  /* Negate */
8775         {
8776           if (attribute_flag[0] == 0)
8777             argument_list[0].integer_reference=0;
8778           if (attribute_flag[1] != 0)
8779             channel=(ChannelType) argument_list[1].integer_reference;
8780           PushPixelComponentMap(image,channel);
8781           (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
8782             MagickTrue : MagickFalse);
8783           PopPixelComponentMap(image);
8784           break;
8785         }
8786         case 45:  /* Normalize */
8787         {
8788           if (attribute_flag[0] != 0)
8789             channel=(ChannelType) argument_list[0].integer_reference;
8790           PushPixelComponentMap(image,channel);
8791           NormalizeImage(image);
8792           PopPixelComponentMap(image);
8793           break;
8794         }
8795         case 46:  /* NumberColors */
8796           break;
8797         case 47:  /* Opaque */
8798         {
8799           MagickBooleanType
8800             invert;
8801
8802           PixelInfo
8803             fill_color,
8804             target;
8805
8806           (void) QueryMagickColor("none",&target,exception);
8807           (void) QueryMagickColor("none",&fill_color,exception);
8808           if (attribute_flag[0] != 0)
8809             (void) QueryMagickColor(argument_list[0].string_reference,
8810               &target,exception);
8811           if (attribute_flag[1] != 0)
8812             (void) QueryMagickColor(argument_list[1].string_reference,
8813               &fill_color,exception);
8814           if (attribute_flag[2] != 0)
8815             image->fuzz=SiPrefixToDouble(argument_list[2].string_reference,
8816               QuantumRange);
8817           if (attribute_flag[3] != 0)
8818             channel=(ChannelType) argument_list[3].integer_reference;
8819           invert=MagickFalse;
8820           if (attribute_flag[4] != 0)
8821             invert=(MagickBooleanType) argument_list[4].integer_reference;
8822           PushPixelComponentMap(image,channel);
8823           (void) OpaquePaintImage(image,&target,&fill_color,invert);
8824           PopPixelComponentMap(image);
8825           break;
8826         }
8827         case 48:  /* Quantize */
8828         {
8829           QuantizeInfo
8830             *quantize_info;
8831
8832           quantize_info=AcquireQuantizeInfo(info->image_info);
8833           if (attribute_flag[0] != 0)
8834             quantize_info->number_colors=(size_t)
8835               argument_list[0].integer_reference;
8836           if (attribute_flag[1] != 0)
8837             quantize_info->tree_depth=(size_t)
8838               argument_list[1].integer_reference;
8839           if (attribute_flag[2] != 0)
8840             quantize_info->colorspace=(ColorspaceType)
8841               argument_list[2].integer_reference;
8842           if (attribute_flag[3] != 0)
8843             quantize_info->dither=argument_list[3].integer_reference != 0 ?
8844               MagickTrue : MagickFalse;
8845           if (attribute_flag[4] != 0)
8846             quantize_info->measure_error=
8847               argument_list[4].integer_reference != 0 ? MagickTrue : MagickFalse;
8848           if (attribute_flag[5] != 0)
8849             (void) QueryColorDatabase(argument_list[5].string_reference,
8850               &image->transparent_color,exception);
8851           if (attribute_flag[5] && argument_list[5].integer_reference)
8852             {
8853               (void) QuantizeImages(quantize_info,image);
8854               goto PerlException;
8855             }
8856           if (attribute_flag[6] != 0)
8857             quantize_info->dither_method=(DitherMethod)
8858               argument_list[6].integer_reference;
8859           if ((image->storage_class == DirectClass) ||
8860               (image->colors > quantize_info->number_colors) ||
8861               (quantize_info->colorspace == GRAYColorspace))
8862             (void) QuantizeImage(quantize_info,image);
8863           else
8864             CompressImageColormap(image);
8865           quantize_info=DestroyQuantizeInfo(quantize_info);
8866           break;
8867         }
8868         case 49:  /* Raise */
8869         {
8870           if (attribute_flag[0] != 0)
8871             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8872               &geometry,exception);
8873           if (attribute_flag[1] != 0)
8874             geometry.width=argument_list[1].integer_reference;
8875           if (attribute_flag[2] != 0)
8876             geometry.height=argument_list[2].integer_reference;
8877           if (attribute_flag[3] == 0)
8878             argument_list[3].integer_reference=1;
8879           (void) RaiseImage(image,&geometry,argument_list[3].integer_reference !=
8880             0 ? MagickTrue : MagickFalse);
8881           break;
8882         }
8883         case 50:  /* Segment */
8884         {
8885           ColorspaceType
8886             colorspace;
8887
8888           double
8889             cluster_threshold,
8890             smoothing_threshold;
8891
8892           MagickBooleanType
8893             verbose;
8894
8895           cluster_threshold=1.0;
8896           smoothing_threshold=1.5;
8897           colorspace=RGBColorspace;
8898           verbose=MagickFalse;
8899           if (attribute_flag[0] != 0)
8900             {
8901               flags=ParseGeometry(argument_list[0].string_reference,
8902                 &geometry_info);
8903               cluster_threshold=geometry_info.rho;
8904               if (flags & SigmaValue)
8905                 smoothing_threshold=geometry_info.sigma;
8906             }
8907           if (attribute_flag[1] != 0)
8908             cluster_threshold=argument_list[1].real_reference;
8909           if (attribute_flag[2] != 0)
8910             smoothing_threshold=argument_list[2].real_reference;
8911           if (attribute_flag[3] != 0)
8912             colorspace=(ColorspaceType) argument_list[3].integer_reference;
8913           if (attribute_flag[4] != 0)
8914             verbose=argument_list[4].integer_reference != 0 ?
8915               MagickTrue : MagickFalse;
8916           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
8917             smoothing_threshold);
8918           break;
8919         }
8920         case 51:  /* Signature */
8921         {
8922           (void) SignatureImage(image);
8923           break;
8924         }
8925         case 52:  /* Solarize */
8926         {
8927           geometry_info.rho=QuantumRange/2.0;
8928           if (attribute_flag[0] != 0)
8929             flags=ParseGeometry(argument_list[0].string_reference,
8930               &geometry_info);
8931           if (attribute_flag[1] != 0)
8932             geometry_info.rho=SiPrefixToDouble(argument_list[1].string_reference,
8933              QuantumRange);
8934           (void) SolarizeImage(image,geometry_info.rho);
8935           break;
8936         }
8937         case 53:  /* Sync */
8938         {
8939           (void) SyncImage(image);
8940           break;
8941         }
8942         case 54:  /* Texture */
8943         {
8944           if (attribute_flag[0] == 0)
8945             break;
8946           TextureImage(image,argument_list[0].image_reference);
8947           break;
8948         }
8949         case 55:  /* Evalute */
8950         {
8951           MagickEvaluateOperator
8952             op;
8953
8954           op=SetEvaluateOperator;
8955           if (attribute_flag[0] == MagickFalse)
8956             argument_list[0].real_reference=0.0;
8957           if (attribute_flag[1] != MagickFalse)
8958             op=(MagickEvaluateOperator) argument_list[1].integer_reference;
8959           if (attribute_flag[2] != MagickFalse)
8960             channel=(ChannelType) argument_list[2].integer_reference;
8961           PushPixelComponentMap(image,channel);
8962           (void) EvaluateImage(image,op,argument_list[0].real_reference,
8963             exception);
8964           PopPixelComponentMap(image);
8965           break;
8966         }
8967         case 56:  /* Transparent */
8968         {
8969           double
8970             opacity;
8971
8972           MagickBooleanType
8973             invert;
8974
8975           PixelInfo
8976             target;
8977
8978           (void) QueryMagickColor("none",&target,exception);
8979           if (attribute_flag[0] != 0)
8980             (void) QueryMagickColor(argument_list[0].string_reference,&target,
8981               exception);
8982           opacity=TransparentAlpha;
8983           if (attribute_flag[1] != 0)
8984             opacity=SiPrefixToDouble(argument_list[1].string_reference,
8985               QuantumRange);
8986           if (attribute_flag[2] != 0)
8987             image->fuzz=SiPrefixToDouble(argument_list[2].string_reference,
8988               QuantumRange);
8989           if (attribute_flag[3] == 0)
8990             argument_list[3].integer_reference=0;
8991           invert=MagickFalse;
8992           if (attribute_flag[3] != 0)
8993             invert=(MagickBooleanType) argument_list[3].integer_reference;
8994           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
8995             invert);
8996           break;
8997         }
8998         case 57:  /* Threshold */
8999         {
9000           double
9001             threshold;
9002
9003           if (attribute_flag[0] == 0)
9004             argument_list[0].string_reference="50%";
9005           if (attribute_flag[1] != 0)
9006             channel=(ChannelType) argument_list[1].integer_reference;
9007           threshold=SiPrefixToDouble(argument_list[0].string_reference,
9008             QuantumRange);
9009           PushPixelComponentMap(image,channel);
9010           (void) BilevelImage(image,threshold);
9011           PopPixelComponentMap(image);
9012           break;
9013         }
9014         case 58:  /* Charcoal */
9015         {
9016           if (attribute_flag[0] != 0)
9017             {
9018               flags=ParseGeometry(argument_list[0].string_reference,
9019                 &geometry_info);
9020               if ((flags & SigmaValue) == 0)
9021                 geometry_info.sigma=1.0;
9022             }
9023           if (attribute_flag[1] != 0)
9024             geometry_info.rho=argument_list[1].real_reference;
9025           if (attribute_flag[2] != 0)
9026             geometry_info.sigma=argument_list[2].real_reference;
9027           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9028             exception);
9029           break;
9030         }
9031         case 59:  /* Trim */
9032         {
9033           if (attribute_flag[0] != 0)
9034             image->fuzz=SiPrefixToDouble(argument_list[0].string_reference,
9035               QuantumRange);
9036           image=TrimImage(image,exception);
9037           break;
9038         }
9039         case 60:  /* Wave */
9040         {
9041           if (attribute_flag[0] != 0)
9042             {
9043               flags=ParseGeometry(argument_list[0].string_reference,
9044                 &geometry_info);
9045               if ((flags & SigmaValue) == 0)
9046                 geometry_info.sigma=1.0;
9047             }
9048           if (attribute_flag[1] != 0)
9049             geometry_info.rho=argument_list[1].real_reference;
9050           if (attribute_flag[2] != 0)
9051             geometry_info.sigma=argument_list[2].real_reference;
9052           if (attribute_flag[3] != 0)
9053             image->interpolate=(InterpolatePixelMethod)
9054               argument_list[3].integer_reference;
9055           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9056             exception);
9057           break;
9058         }
9059         case 61:  /* Separate */
9060         {
9061           if (attribute_flag[0] != 0)
9062             channel=(ChannelType) argument_list[0].integer_reference;
9063           PushPixelComponentMap(image,channel);
9064           (void) SeparateImage(image);
9065           PopPixelComponentMap(image);
9066           break;
9067         }
9068         case 63:  /* Stereo */
9069         {
9070           if (attribute_flag[0] == 0)
9071             {
9072               ThrowPerlException(exception,OptionError,"StereoImageRequired",
9073                 PackageName);
9074               goto PerlException;
9075             }
9076           if (attribute_flag[1] != 0)
9077             geometry.x=argument_list[1].integer_reference;
9078           if (attribute_flag[2] != 0)
9079             geometry.y=argument_list[2].integer_reference;
9080           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9081             geometry.x,geometry.y,exception);
9082           break;
9083         }
9084         case 64:  /* Stegano */
9085         {
9086           if (attribute_flag[0] == 0)
9087             {
9088               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9089                 PackageName);
9090               goto PerlException;
9091             }
9092           if (attribute_flag[1] == 0)
9093             argument_list[1].integer_reference=0;
9094           image->offset=argument_list[1].integer_reference;
9095           image=SteganoImage(image,argument_list[0].image_reference,exception);
9096           break;
9097         }
9098         case 65:  /* Deconstruct */
9099         {
9100           image=CompareImagesLayers(image,CompareAnyLayer,exception);
9101           break;
9102         }
9103         case 66:  /* GaussianBlur */
9104         {
9105           if (attribute_flag[0] != 0)
9106             {
9107               flags=ParseGeometry(argument_list[0].string_reference,
9108                 &geometry_info);
9109               if ((flags & SigmaValue) == 0)
9110                 geometry_info.sigma=1.0;
9111             }
9112           if (attribute_flag[1] != 0)
9113             geometry_info.rho=argument_list[1].real_reference;
9114           if (attribute_flag[2] != 0)
9115             geometry_info.sigma=argument_list[2].real_reference;
9116           if (attribute_flag[3] != 0)
9117             channel=(ChannelType) argument_list[3].integer_reference;
9118           PushPixelComponentMap(image,channel);
9119           image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9120             exception);
9121           PopPixelComponentMap(image);
9122           break;
9123         }
9124         case 67:  /* Convolve */
9125         {
9126           AV
9127             *av;
9128
9129           double
9130             *kernel;
9131
9132           size_t
9133             order;
9134
9135           if (attribute_flag[0] == 0)
9136             break;
9137           if (attribute_flag[1] != 0)
9138             channel=(ChannelType) argument_list[1].integer_reference;
9139           if (attribute_flag[2] != 0)
9140             image->bias=SiPrefixToDouble(argument_list[2].string_reference,
9141               QuantumRange);
9142           av=(AV *) argument_list[0].array_reference;
9143           order=(size_t) sqrt(av_len(av)+1);
9144           kernel=(double *) AcquireQuantumMemory(order,order*sizeof(*kernel));
9145           if (kernel == (double *) NULL)
9146             {
9147               ThrowPerlException(exception,ResourceLimitFatalError,
9148                 "MemoryAllocationFailed",PackageName);
9149               goto PerlException;
9150             }
9151           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9152             kernel[j]=(double) SvNV(*(av_fetch(av,j,0)));
9153           for ( ; j < (ssize_t) (order*order); j++)
9154             kernel[j]=0.0;
9155           PushPixelComponentMap(image,channel);
9156           image=ConvolveImage(image,order,kernel,exception);
9157           PopPixelComponentMap(image);
9158           kernel=(double *) RelinquishMagickMemory(kernel);
9159           break;
9160         }
9161         case 68:  /* Profile */
9162         {
9163           const char
9164             *name;
9165
9166           Image
9167             *profile_image;
9168
9169           ImageInfo
9170             *profile_info;
9171
9172           StringInfo
9173             *profile;
9174
9175           name="*";
9176           if (attribute_flag[0] != 0)
9177             name=argument_list[0].string_reference;
9178           if (attribute_flag[2] != 0)
9179             image->rendering_intent=(RenderingIntent)
9180               argument_list[2].integer_reference;
9181           if (attribute_flag[3] != 0)
9182             image->black_point_compensation=
9183               argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9184           if (attribute_flag[1] != 0)
9185             {
9186               if (argument_list[1].length == 0)
9187                 {
9188                   /*
9189                     Remove a profile from the image.
9190                   */
9191                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9192                     MagickTrue);
9193                   break;
9194                 }
9195               /*
9196                 Associate user supplied profile with the image.
9197               */
9198               profile=AcquireStringInfo(argument_list[1].length);
9199               SetStringInfoDatum(profile,(const unsigned char *)
9200                 argument_list[1].string_reference);
9201               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9202                 (size_t) GetStringInfoLength(profile),MagickFalse);
9203               profile=DestroyStringInfo(profile);
9204               break;
9205             }
9206           /*
9207             Associate a profile with the image.
9208           */
9209           profile_info=
9210             CloneImageInfo(info ? info->image_info : (ImageInfo *) NULL);
9211           (void) CopyMagickString(profile_info->filename,name,MaxTextExtent);
9212           profile_image=ReadImages(profile_info,&image->exception);
9213           if (profile_image == (Image *) NULL)
9214             break;
9215           ResetImageProfileIterator(profile_image);
9216           name=GetNextImageProfile(profile_image);
9217           while (name != (const char *) NULL)
9218           {
9219             const StringInfo
9220               *profile;
9221
9222             profile=GetImageProfile(profile_image,name);
9223             if (profile != (const StringInfo *) NULL)
9224               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9225                 (size_t) GetStringInfoLength(profile),MagickFalse);
9226             name=GetNextImageProfile(profile_image);
9227           }
9228           profile_image=DestroyImage(profile_image);
9229           profile_info=DestroyImageInfo(profile_info);
9230           break;
9231         }
9232         case 69:  /* UnsharpMask */
9233         {
9234           if (attribute_flag[0] != 0)
9235             {
9236               flags=ParseGeometry(argument_list[0].string_reference,
9237                 &geometry_info);
9238               if ((flags & SigmaValue) == 0)
9239                 geometry_info.sigma=1.0;
9240               if ((flags & XiValue) == 0)
9241                 geometry_info.xi=1.0;
9242               if ((flags & PsiValue) == 0)
9243                 geometry_info.psi=0.5;
9244             }
9245           if (attribute_flag[1] != 0)
9246             geometry_info.rho=argument_list[1].real_reference;
9247           if (attribute_flag[2] != 0)
9248             geometry_info.sigma=argument_list[2].real_reference;
9249           if (attribute_flag[3] != 0)
9250             geometry_info.xi=argument_list[3].real_reference;
9251           if (attribute_flag[4] != 0)
9252             geometry_info.psi=argument_list[4].real_reference;
9253           if (attribute_flag[5] != 0)
9254             channel=(ChannelType) argument_list[5].integer_reference;
9255           PushPixelComponentMap(image,channel);
9256           image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9257             geometry_info.xi,geometry_info.psi,exception);
9258           PopPixelComponentMap(image);
9259           break;
9260         }
9261         case 70:  /* MotionBlur */
9262         {
9263           if (attribute_flag[0] != 0)
9264             {
9265               flags=ParseGeometry(argument_list[0].string_reference,
9266                 &geometry_info);
9267               if ((flags & SigmaValue) == 0)
9268                 geometry_info.sigma=1.0;
9269               if ((flags & XiValue) == 0)
9270                 geometry_info.xi=1.0;
9271             }
9272           if (attribute_flag[1] != 0)
9273             geometry_info.rho=argument_list[1].real_reference;
9274           if (attribute_flag[2] != 0)
9275             geometry_info.sigma=argument_list[2].real_reference;
9276           if (attribute_flag[3] != 0)
9277             geometry_info.xi=argument_list[3].real_reference;
9278           if (attribute_flag[4] != 0)
9279             channel=(ChannelType) argument_list[4].integer_reference;
9280           PushPixelComponentMap(image,channel);
9281           image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9282             geometry_info.xi,exception);
9283           PopPixelComponentMap(image);
9284           break;
9285         }
9286         case 71:  /* OrderedDither */
9287         {
9288           if (attribute_flag[0] == 0)
9289             argument_list[0].string_reference="o8x8";
9290           if (attribute_flag[1] != 0)
9291             channel=(ChannelType) argument_list[1].integer_reference;
9292           PushPixelComponentMap(image,channel);
9293           (void) OrderedPosterizeImage(image,argument_list[0].string_reference,
9294             exception);
9295           PopPixelComponentMap(image);
9296           break;
9297         }
9298         case 72:  /* Shave */
9299         {
9300           if (attribute_flag[0] != 0)
9301             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9302               &geometry,exception);
9303           if (attribute_flag[1] != 0)
9304             geometry.width=argument_list[1].integer_reference;
9305           if (attribute_flag[2] != 0)
9306             geometry.height=argument_list[2].integer_reference;
9307           image=ShaveImage(image,&geometry,exception);
9308           break;
9309         }
9310         case 73:  /* Level */
9311         {
9312           double
9313             black_point,
9314             gamma,
9315             white_point;
9316
9317           black_point=0.0;
9318           white_point=(MagickRealType) image->columns*image->rows;
9319           gamma=1.0;
9320           if (attribute_flag[0] != 0)
9321             {
9322               flags=ParseGeometry(argument_list[0].string_reference,
9323                 &geometry_info);
9324               black_point=geometry_info.rho;
9325               if ((flags & SigmaValue) != 0)
9326                 white_point=geometry_info.sigma;
9327               if ((flags & XiValue) != 0)
9328                 gamma=geometry_info.xi;
9329               if ((flags & PercentValue) != 0)
9330                 {
9331                   black_point*=(double) (QuantumRange/100.0);
9332                   white_point*=(double) (QuantumRange/100.0);
9333                 }
9334               if ((flags & SigmaValue) == 0)
9335                 white_point=(double) QuantumRange-black_point;
9336             }
9337           if (attribute_flag[1] != 0)
9338             black_point=argument_list[1].real_reference;
9339           if (attribute_flag[2] != 0)
9340             white_point=argument_list[2].real_reference;
9341           if (attribute_flag[3] != 0)
9342             gamma=argument_list[3].real_reference;
9343           if (attribute_flag[4] != 0)
9344             channel=(ChannelType) argument_list[4].integer_reference;
9345           if (attribute_flag[5] != 0)
9346             {
9347               argument_list[0].real_reference=argument_list[5].real_reference;
9348               attribute_flag[0]=attribute_flag[5];
9349             }
9350           PushPixelComponentMap(image,channel);
9351           (void) LevelImage(image,black_point,white_point,gamma);
9352           PopPixelComponentMap(image);
9353           break;
9354         }
9355         case 74:  /* Clip */
9356         {
9357           if (attribute_flag[0] == 0)
9358             argument_list[0].string_reference="#1";
9359           if (attribute_flag[1] == 0)
9360             argument_list[1].integer_reference=MagickTrue;
9361           (void) ClipImagePath(image,argument_list[0].string_reference,
9362             argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse);
9363           break;
9364         }
9365         case 75:  /* AffineTransform */
9366         {
9367           DrawInfo
9368             *draw_info;
9369
9370           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9371             (DrawInfo *) NULL);
9372           if (attribute_flag[0] != 0)
9373             {
9374               AV
9375                 *av;
9376
9377               av=(AV *) argument_list[0].array_reference;
9378               if ((av_len(av) != 3) && (av_len(av) != 5))
9379                 {
9380                   ThrowPerlException(exception,OptionError,
9381                     "affine matrix must have 4 or 6 elements",PackageName);
9382                   goto PerlException;
9383                 }
9384               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9385               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9386               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9387               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9388               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9389                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9390                 {
9391                   ThrowPerlException(exception,OptionError,
9392                     "affine matrix is singular",PackageName);
9393                    goto PerlException;
9394                 }
9395               if (av_len(av) == 5)
9396                 {
9397                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9398                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9399                 }
9400             }
9401           for (j=1; j < 6; j++)
9402           {
9403             if (attribute_flag[j] == 0)
9404               continue;
9405             value=argument_list[j].string_reference;
9406             angle=argument_list[j].real_reference;
9407             current=draw_info->affine;
9408             GetAffineMatrix(&affine);
9409             switch (j)
9410             {
9411               case 1:
9412               {
9413                 /*
9414                   Translate.
9415                 */
9416                 flags=ParseGeometry(value,&geometry_info);
9417                 affine.tx=geometry_info.xi;
9418                 affine.ty=geometry_info.psi;
9419                 if ((flags & PsiValue) == 0)
9420                   affine.ty=affine.tx;
9421                 break;
9422               }
9423               case 2:
9424               {
9425                 /*
9426                   Scale.
9427                 */
9428                 flags=ParseGeometry(value,&geometry_info);
9429                 affine.sx=geometry_info.rho;
9430                 affine.sy=geometry_info.sigma;
9431                 if ((flags & SigmaValue) == 0)
9432                   affine.sy=affine.sx;
9433                 break;
9434               }
9435               case 3:
9436               {
9437                 /*
9438                   Rotate.
9439                 */
9440                 if (angle == 0.0)
9441                   break;
9442                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9443                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9444                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9445                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9446                 break;
9447               }
9448               case 4:
9449               {
9450                 /*
9451                   SkewX.
9452                 */
9453                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9454                 break;
9455               }
9456               case 5:
9457               {
9458                 /*
9459                   SkewY.
9460                 */
9461                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9462                 break;
9463               }
9464             }
9465             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9466             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9467             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9468             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9469             draw_info->affine.tx=
9470               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9471             draw_info->affine.ty=
9472               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9473           }
9474           if (attribute_flag[6] != 0)
9475             image->interpolate=(InterpolatePixelMethod)
9476               argument_list[6].integer_reference;
9477           if (attribute_flag[7] != 0)
9478             QueryColorDatabase(argument_list[7].string_reference,
9479               &image->background_color,exception);
9480           image=AffineTransformImage(image,&draw_info->affine,exception);
9481           draw_info=DestroyDrawInfo(draw_info);
9482           break;
9483         }
9484         case 76:  /* Difference */
9485         {
9486           if (attribute_flag[0] == 0)
9487             {
9488               ThrowPerlException(exception,OptionError,
9489                 "ReferenceImageRequired",PackageName);
9490               goto PerlException;
9491             }
9492           if (attribute_flag[1] != 0)
9493             image->fuzz=SiPrefixToDouble(argument_list[1].string_reference,
9494               QuantumRange);
9495           (void) IsImagesEqual(image,argument_list[0].image_reference);
9496           break;
9497         }
9498         case 77:  /* AdaptiveThreshold */
9499         {
9500           if (attribute_flag[0] != 0)
9501             {
9502               flags=ParseGeometry(argument_list[0].string_reference,
9503                 &geometry_info);
9504               if ((flags & PercentValue) != 0)
9505                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9506             }
9507           if (attribute_flag[1] != 0)
9508             geometry_info.rho=argument_list[1].integer_reference;
9509           if (attribute_flag[2] != 0)
9510             geometry_info.sigma=argument_list[2].integer_reference;
9511           if (attribute_flag[3] != 0)
9512             geometry_info.xi=argument_list[3].integer_reference;;
9513           image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
9514             (size_t) geometry_info.sigma,(ssize_t) geometry_info.xi,
9515             exception);
9516           break;
9517         }
9518         case 78:  /* Resample */
9519         {
9520           size_t
9521             height,
9522             width;
9523
9524           if (attribute_flag[0] != 0)
9525             {
9526               flags=ParseGeometry(argument_list[0].string_reference,
9527                 &geometry_info);
9528               if ((flags & SigmaValue) == 0)
9529                 geometry_info.sigma=geometry_info.rho;
9530             }
9531           if (attribute_flag[1] != 0)
9532             geometry_info.rho=argument_list[1].real_reference;
9533           if (attribute_flag[2] != 0)
9534             geometry_info.sigma=argument_list[2].real_reference;
9535           if (attribute_flag[3] == 0)
9536             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
9537           if (attribute_flag[4] == 0)
9538             SetImageArtifact(image,"filter:support",
9539               argument_list[4].string_reference);
9540           if (attribute_flag[5] != 0)
9541             argument_list[5].real_reference=1.0;
9542           width=(size_t) (geometry_info.rho*image->columns/
9543             (image->x_resolution == 0.0 ? 72.0 : image->x_resolution)+0.5);
9544           height=(size_t) (geometry_info.sigma*image->rows/
9545             (image->y_resolution == 0.0 ? 72.0 : image->y_resolution)+0.5);
9546           image=ResizeImage(image,width,height,(FilterTypes)
9547             argument_list[3].integer_reference,argument_list[5].real_reference,
9548             exception);
9549           if (image != (Image *) NULL)
9550             {
9551               image->x_resolution=geometry_info.rho;
9552               image->y_resolution=geometry_info.sigma;
9553             }
9554           break;
9555         }
9556         case 79:  /* Describe */
9557         {
9558           if (attribute_flag[0] == 0)
9559             argument_list[0].file_reference=(FILE *) NULL;
9560           if (attribute_flag[1] != 0)
9561             (void) SetImageArtifact(image,"identify:features",
9562               argument_list[1].string_reference);
9563           (void) IdentifyImage(image,argument_list[0].file_reference,
9564             MagickTrue);
9565           break;
9566         }
9567         case 80:  /* BlackThreshold */
9568         {
9569           if (attribute_flag[0] == 0)
9570             argument_list[0].string_reference="50%";
9571           if (attribute_flag[2] != 0)
9572             channel=(ChannelType) argument_list[2].integer_reference;
9573           PushPixelComponentMap(image,channel);
9574           BlackThresholdImage(image,argument_list[0].string_reference,
9575             exception);
9576           PopPixelComponentMap(image);
9577           break;
9578         }
9579         case 81:  /* WhiteThreshold */
9580         {
9581           if (attribute_flag[0] == 0)
9582             argument_list[0].string_reference="50%";
9583           if (attribute_flag[2] != 0)
9584             channel=(ChannelType) argument_list[2].integer_reference;
9585           PushPixelComponentMap(image,channel);
9586           WhiteThresholdImage(image,argument_list[0].string_reference,
9587             exception);
9588           PopPixelComponentMap(image);
9589           break;
9590         }
9591         case 82:  /* RadialBlur */
9592         {
9593           if (attribute_flag[0] != 0)
9594             {
9595               flags=ParseGeometry(argument_list[0].string_reference,
9596                 &geometry_info);
9597               if ((flags & SigmaValue) == 0)
9598                 geometry_info.sigma=1.0;
9599             }
9600           if (attribute_flag[1] != 0)
9601             geometry_info.rho=argument_list[1].real_reference;
9602           if (attribute_flag[2] != 0)
9603             channel=(ChannelType) argument_list[2].integer_reference;
9604           PushPixelComponentMap(image,channel);
9605           image=RadialBlurImage(image,geometry_info.rho,exception);
9606           PopPixelComponentMap(image);
9607           break;
9608         }
9609         case 83:  /* Thumbnail */
9610         {
9611           if (attribute_flag[0] != 0)
9612             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
9613               &geometry,exception);
9614           if (attribute_flag[1] != 0)
9615             geometry.width=argument_list[1].integer_reference;
9616           if (attribute_flag[2] != 0)
9617             geometry.height=argument_list[2].integer_reference;
9618           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
9619           break;
9620         }
9621         case 84:  /* Strip */
9622         {
9623           (void) StripImage(image);
9624           break;
9625         }
9626         case 85:  /* Tint */
9627         {
9628           PixelPacket
9629             target;
9630
9631           (void) GetOneVirtualPixel(image,0,0,&target,exception);
9632           if (attribute_flag[0] != 0)
9633             (void) QueryColorDatabase(argument_list[0].string_reference,&target,
9634               exception);
9635           if (attribute_flag[1] == 0)
9636             argument_list[1].string_reference="100";
9637           image=TintImage(image,argument_list[1].string_reference,target,
9638             exception);
9639           break;
9640         }
9641         case 86:  /* Channel */
9642         {
9643           if (attribute_flag[0] != 0)
9644             channel=(ChannelType) argument_list[0].integer_reference;
9645           PushPixelComponentMap(image,channel);
9646           (void) SeparateImage(image);
9647           PopPixelComponentMap(image);
9648           break;
9649         }
9650         case 87:  /* Splice */
9651         {
9652           if (attribute_flag[0] != 0)
9653             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
9654               &geometry,exception);
9655           if (attribute_flag[1] != 0)
9656             geometry.width=argument_list[1].integer_reference;
9657           if (attribute_flag[2] != 0)
9658             geometry.height=argument_list[2].integer_reference;
9659           if (attribute_flag[3] != 0)
9660             geometry.x=argument_list[3].integer_reference;
9661           if (attribute_flag[4] != 0)
9662             geometry.y=argument_list[4].integer_reference;
9663           if (attribute_flag[5] != 0)
9664             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
9665               QuantumRange);
9666           if (attribute_flag[6] != 0)
9667             (void) QueryColorDatabase(argument_list[6].string_reference,
9668               &image->background_color,exception);
9669           if (attribute_flag[7] != 0)
9670             image->gravity=(GravityType) argument_list[7].integer_reference;
9671           image=SpliceImage(image,&geometry,exception);
9672           break;
9673         }
9674         case 88:  /* Posterize */
9675         {
9676           if (attribute_flag[0] == 0)
9677             argument_list[0].integer_reference=3;
9678           if (attribute_flag[1] == 0)
9679             argument_list[1].integer_reference=0;
9680           (void) PosterizeImage(image,argument_list[0].integer_reference,
9681             argument_list[1].integer_reference ? MagickTrue : MagickFalse);
9682           break;
9683         }
9684         case 89:  /* Shadow */
9685         {
9686           if (attribute_flag[0] != 0)
9687             {
9688               flags=ParseGeometry(argument_list[0].string_reference,
9689                 &geometry_info);
9690               if ((flags & SigmaValue) == 0)
9691                 geometry_info.sigma=1.0;
9692               if ((flags & XiValue) == 0)
9693                 geometry_info.xi=4.0;
9694               if ((flags & PsiValue) == 0)
9695                 geometry_info.psi=4.0;
9696             }
9697           if (attribute_flag[1] != 0)
9698             geometry_info.rho=argument_list[1].real_reference;
9699           if (attribute_flag[2] != 0)
9700             geometry_info.sigma=argument_list[2].real_reference;
9701           if (attribute_flag[3] != 0)
9702             geometry_info.xi=argument_list[3].integer_reference;
9703           if (attribute_flag[4] != 0)
9704             geometry_info.psi=argument_list[4].integer_reference;
9705           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
9706             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-
9707             0.5),exception);
9708           break;
9709         }
9710         case 90:  /* Identify */
9711         {
9712           if (attribute_flag[0] == 0)
9713             argument_list[0].file_reference=(FILE *) NULL;
9714           if (attribute_flag[1] != 0)
9715             (void) SetImageArtifact(image,"identify:features",
9716               argument_list[1].string_reference);
9717           if ((attribute_flag[2] != 0) &&
9718               (argument_list[2].integer_reference != 0))
9719             (void) SetImageArtifact(image,"identify:unique","true");
9720           (void) IdentifyImage(image,argument_list[0].file_reference,
9721             MagickTrue);
9722           break;
9723         }
9724         case 91:  /* SepiaTone */
9725         {
9726           if (attribute_flag[0] == 0)
9727             argument_list[0].real_reference=80.0*QuantumRange/100.0;
9728           image=SepiaToneImage(image,argument_list[0].real_reference,
9729             exception);
9730           break;
9731         }
9732         case 92:  /* SigmoidalContrast */
9733         {
9734           MagickBooleanType
9735             sharpen;
9736
9737           if (attribute_flag[0] != 0)
9738             {
9739               flags=ParseGeometry(argument_list[0].string_reference,
9740                 &geometry_info);
9741               if ((flags & SigmaValue) == 0)
9742                 geometry_info.sigma=QuantumRange/2.0;
9743               if ((flags & PercentValue) != 0)
9744                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
9745             }
9746           if (attribute_flag[1] != 0)
9747             geometry_info.rho=argument_list[1].real_reference;
9748           if (attribute_flag[2] != 0)
9749             geometry_info.sigma=argument_list[2].real_reference;
9750           if (attribute_flag[3] != 0)
9751             channel=(ChannelType) argument_list[3].integer_reference;
9752           sharpen=MagickTrue;
9753           if (attribute_flag[4] != 0)
9754             sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
9755               MagickFalse;
9756           PushPixelComponentMap(image,channel);
9757           (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
9758             geometry_info.sigma);
9759           PopPixelComponentMap(image);
9760           break;
9761         }
9762         case 93:  /* Extent */
9763         {
9764           if (attribute_flag[7] != 0)
9765             image->gravity=(GravityType) argument_list[7].integer_reference;
9766           if (attribute_flag[0] != 0)
9767             {
9768               int
9769                 flags;
9770
9771               flags=ParseGravityGeometry(image,
9772                 argument_list[0].string_reference,&geometry,exception);
9773               (void) flags;
9774               if (geometry.width == 0)
9775                 geometry.width=image->columns;
9776               if (geometry.height == 0)
9777                 geometry.height=image->rows;
9778             }
9779           if (attribute_flag[1] != 0)
9780             geometry.width=argument_list[1].integer_reference;
9781           if (attribute_flag[2] != 0)
9782             geometry.height=argument_list[2].integer_reference;
9783           if (attribute_flag[3] != 0)
9784             geometry.x=argument_list[3].integer_reference;
9785           if (attribute_flag[4] != 0)
9786             geometry.y=argument_list[4].integer_reference;
9787           if (attribute_flag[5] != 0)
9788             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
9789               QuantumRange);
9790           if (attribute_flag[6] != 0)
9791             (void) QueryColorDatabase(argument_list[6].string_reference,
9792               &image->background_color,exception);
9793           image=ExtentImage(image,&geometry,exception);
9794           break;
9795         }
9796         case 94:  /* Vignette */
9797         {
9798           if (attribute_flag[0] != 0)
9799             {
9800               flags=ParseGeometry(argument_list[0].string_reference,
9801                 &geometry_info);
9802               if ((flags & SigmaValue) == 0)
9803                 geometry_info.sigma=1.0;
9804               if ((flags & XiValue) == 0)
9805                 geometry_info.xi=0.1*image->columns;
9806               if ((flags & PsiValue) == 0)
9807                 geometry_info.psi=0.1*image->rows;
9808             }
9809           if (attribute_flag[1] != 0)
9810             geometry_info.rho=argument_list[1].real_reference;
9811           if (attribute_flag[2] != 0)
9812             geometry_info.sigma=argument_list[2].real_reference;
9813           if (attribute_flag[3] != 0)
9814             geometry_info.xi=argument_list[3].integer_reference;
9815           if (attribute_flag[4] != 0)
9816             geometry_info.psi=argument_list[4].integer_reference;
9817           if (attribute_flag[5] != 0)
9818             (void) QueryColorDatabase(argument_list[5].string_reference,
9819               &image->background_color,exception);
9820           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
9821             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-
9822             0.5),exception);
9823           break;
9824         }
9825         case 95:  /* ContrastStretch */
9826         {
9827           double
9828             black_point,
9829             white_point;
9830
9831           black_point=0.0;
9832           white_point=(MagickRealType) image->columns*image->rows;
9833           if (attribute_flag[0] != 0)
9834             {
9835               flags=ParseGeometry(argument_list[0].string_reference,
9836                 &geometry_info);
9837               black_point=geometry_info.rho;
9838               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
9839                 black_point;
9840               if ((flags & PercentValue) != 0)
9841                 {
9842                   black_point*=(double) image->columns*image->rows/100.0;
9843                   white_point*=(double) image->columns*image->rows/100.0;
9844                 }
9845               white_point=(MagickRealType) image->columns*image->rows-
9846                 white_point;
9847             }
9848           if (attribute_flag[1] != 0)
9849             black_point=argument_list[1].real_reference;
9850           if (attribute_flag[2] != 0)
9851             white_point=argument_list[2].real_reference;
9852           if (attribute_flag[4] != 0)
9853             channel=(ChannelType) argument_list[4].integer_reference;
9854           PushPixelComponentMap(image,channel);
9855           (void) ContrastStretchImage(image,black_point,white_point);
9856           PopPixelComponentMap(image);
9857           break;
9858         }
9859         case 96:  /* Sans0 */
9860         {
9861           break;
9862         }
9863         case 97:  /* Sans1 */
9864         {
9865           break;
9866         }
9867         case 98:  /* AdaptiveSharpen */
9868         {
9869           if (attribute_flag[0] != 0)
9870             {
9871               flags=ParseGeometry(argument_list[0].string_reference,
9872                 &geometry_info);
9873               if ((flags & SigmaValue) == 0)
9874                 geometry_info.sigma=1.0;
9875             }
9876           if (attribute_flag[1] != 0)
9877             geometry_info.rho=argument_list[1].real_reference;
9878           if (attribute_flag[2] != 0)
9879             geometry_info.sigma=argument_list[2].real_reference;
9880           if (attribute_flag[3] != 0)
9881             channel=(ChannelType) argument_list[3].integer_reference;
9882           PushPixelComponentMap(image,channel);
9883           image=AdaptiveSharpenImage(image,geometry_info.rho,
9884             geometry_info.sigma,exception);
9885           PopPixelComponentMap(image);
9886           break;
9887         }
9888         case 99:  /* Transpose */
9889         {
9890           image=TransposeImage(image,exception);
9891           break;
9892         }
9893         case 100:  /* Tranverse */
9894         {
9895           image=TransverseImage(image,exception);
9896           break;
9897         }
9898         case 101:  /* AutoOrient */
9899         {
9900           switch (image->orientation)
9901           {
9902             case TopRightOrientation:
9903             {
9904               image=FlopImage(image,exception);
9905               break;
9906             }
9907             case BottomRightOrientation:
9908             {
9909               image=RotateImage(image,180.0,exception);
9910               break;
9911             }
9912             case BottomLeftOrientation:
9913             {
9914               image=FlipImage(image,exception);
9915               break;
9916             }
9917             case LeftTopOrientation:
9918             {
9919               image=TransposeImage(image,exception);
9920               break;
9921             }
9922             case RightTopOrientation:
9923             {
9924               image=RotateImage(image,90.0,exception);
9925               break;
9926             }
9927             case RightBottomOrientation:
9928             {
9929               image=TransverseImage(image,exception);
9930               break;
9931             }
9932             case LeftBottomOrientation:
9933             {
9934               image=RotateImage(image,270.0,exception);
9935               break;
9936             }
9937             default:
9938               break;
9939           }
9940           break;
9941         }
9942         case 102:  /* AdaptiveBlur */
9943         {
9944           if (attribute_flag[0] != 0)
9945             {
9946               flags=ParseGeometry(argument_list[0].string_reference,
9947                 &geometry_info);
9948               if ((flags & SigmaValue) == 0)
9949                 geometry_info.sigma=1.0;
9950             }
9951           if (attribute_flag[1] != 0)
9952             geometry_info.rho=argument_list[1].real_reference;
9953           if (attribute_flag[2] != 0)
9954             geometry_info.sigma=argument_list[2].real_reference;
9955           if (attribute_flag[3] != 0)
9956             channel=(ChannelType) argument_list[3].integer_reference;
9957           PushPixelComponentMap(image,channel);
9958           image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
9959             exception);
9960           PopPixelComponentMap(image);
9961           break;
9962         }
9963         case 103:  /* Sketch */
9964         {
9965           if (attribute_flag[0] != 0)
9966             {
9967               flags=ParseGeometry(argument_list[0].string_reference,
9968                 &geometry_info);
9969               if ((flags & SigmaValue) == 0)
9970                 geometry_info.sigma=1.0;
9971               if ((flags & XiValue) == 0)
9972                 geometry_info.xi=1.0;
9973             }
9974           if (attribute_flag[1] != 0)
9975             geometry_info.rho=argument_list[1].real_reference;
9976           if (attribute_flag[2] != 0)
9977             geometry_info.sigma=argument_list[2].real_reference;
9978           if (attribute_flag[3] != 0)
9979             geometry_info.xi=argument_list[3].real_reference;
9980           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
9981             geometry_info.xi,exception);
9982           break;
9983         }
9984         case 104:  /* UniqueColors */
9985         {
9986           image=UniqueImageColors(image,exception);
9987           break;
9988         }
9989         case 105:  /* AdaptiveResize */
9990         {
9991           if (attribute_flag[0] != 0)
9992             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
9993               &geometry,exception);
9994           if (attribute_flag[1] != 0)
9995             geometry.width=argument_list[1].integer_reference;
9996           if (attribute_flag[2] != 0)
9997             geometry.height=argument_list[2].integer_reference;
9998           if (attribute_flag[3] != 0)
9999             image->filter=(FilterTypes) argument_list[4].integer_reference;
10000           if (attribute_flag[4] != 0)
10001             SetImageArtifact(image,"filter:support",
10002               argument_list[4].string_reference);
10003           if (attribute_flag[5] != 0)
10004             image->blur=argument_list[5].real_reference;
10005           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10006             exception);
10007           break;
10008         }
10009         case 106:  /* ClipMask */
10010         {
10011           if (attribute_flag[0] == 0)
10012             {
10013               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10014                 PackageName);
10015               goto PerlException;
10016             }
10017           image->clip_mask=CloneImage(argument_list[0].image_reference,0,0,
10018             MagickTrue,exception);
10019           (void) NegateImage(image->clip_mask,MagickFalse);
10020           break;
10021         }
10022         case 107:  /* LinearStretch */
10023         {
10024            double
10025              black_point,
10026              white_point;
10027
10028            black_point=0.0;
10029            white_point=(MagickRealType) image->columns*image->rows;
10030            if (attribute_flag[0] != 0)
10031              {
10032                flags=ParseGeometry(argument_list[0].string_reference,
10033                  &geometry_info);
10034                if ((flags & SigmaValue) != 0)
10035                   white_point=geometry_info.sigma;
10036                if ((flags & PercentValue) != 0)
10037                  {
10038                    black_point*=(double) image->columns*image->rows/100.0;
10039                    white_point*=(double) image->columns*image->rows/100.0;
10040                  }
10041                if ((flags & SigmaValue) == 0)
10042                  white_point=(double) image->columns*image->rows-black_point;
10043              }
10044           if (attribute_flag[1] != 0)
10045             black_point=argument_list[1].real_reference;
10046           if (attribute_flag[2] != 0)
10047             white_point=argument_list[2].real_reference;
10048           (void) LinearStretchImage(image,black_point,white_point);
10049           break;
10050         }
10051         case 109:  /* Mask */
10052         {
10053           if (attribute_flag[0] == 0)
10054             {
10055               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10056                 PackageName);
10057               goto PerlException;
10058             }
10059           image->mask=CloneImage(argument_list[0].image_reference,0,0,
10060             MagickTrue,exception);
10061           (void) NegateImage(image->mask,MagickFalse);
10062           break;
10063         }
10064         case 110:  /* Polaroid */
10065         {
10066           DrawInfo
10067             *draw_info;
10068
10069           double
10070             angle;
10071
10072           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10073             (DrawInfo *) NULL);
10074           if (attribute_flag[0] != 0)
10075             (void) SetImageProperty(image,"caption",InterpretImageProperties(
10076               info ? info->image_info : (ImageInfo *) NULL,image,
10077               argument_list[0].string_reference));
10078           angle=0.0;
10079           if (attribute_flag[1] != 0)
10080             angle=argument_list[1].real_reference;
10081           if (attribute_flag[2] != 0)
10082             (void) CloneString(&draw_info->font,
10083               argument_list[2].string_reference);
10084           if (attribute_flag[3] != 0)
10085             (void) QueryColorDatabase(argument_list[3].string_reference,
10086               &draw_info->stroke,exception);
10087           if (attribute_flag[4] != 0)
10088             (void) QueryColorDatabase(argument_list[4].string_reference,
10089               &draw_info->fill,exception);
10090           if (attribute_flag[5] != 0)
10091             draw_info->stroke_width=argument_list[5].real_reference;
10092           if (attribute_flag[6] != 0)
10093             draw_info->pointsize=argument_list[6].real_reference;
10094           if (attribute_flag[7] != 0)
10095             draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10096           if (attribute_flag[8] != 0)
10097             (void) QueryColorDatabase(argument_list[8].string_reference,
10098               &image->background_color,exception);
10099           image=PolaroidImage(image,draw_info,angle,exception);
10100           draw_info=DestroyDrawInfo(draw_info);
10101           break;
10102         }
10103         case 111:  /* FloodfillPaint */
10104         {
10105           DrawInfo
10106             *draw_info;
10107
10108           MagickBooleanType
10109             invert;
10110
10111           PixelInfo
10112             target;
10113
10114           draw_info=CloneDrawInfo(info ? info->image_info :
10115             (ImageInfo *) NULL,(DrawInfo *) NULL);
10116           if (attribute_flag[0] != 0)
10117             flags=ParsePageGeometry(image,argument_list[0].string_reference,
10118               &geometry,exception);
10119           if (attribute_flag[1] != 0)
10120             geometry.x=argument_list[1].integer_reference;
10121           if (attribute_flag[2] != 0)
10122             geometry.y=argument_list[2].integer_reference;
10123           if (attribute_flag[3] != 0)
10124             (void) QueryColorDatabase(argument_list[3].string_reference,
10125               &draw_info->fill,exception);
10126           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
10127             exception);
10128           if (attribute_flag[4] != 0)
10129             QueryMagickColor(argument_list[4].string_reference,&target,
10130               exception);
10131           if (attribute_flag[5] != 0)
10132             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
10133               QuantumRange);
10134           if (attribute_flag[6] != 0)
10135             channel=(ChannelType) argument_list[6].integer_reference;
10136           invert=MagickFalse;
10137           if (attribute_flag[7] != 0)
10138             invert=(MagickBooleanType) argument_list[7].integer_reference;
10139           PushPixelComponentMap(image,channel);
10140           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10141             geometry.y,invert);
10142           PopPixelComponentMap(image);
10143           draw_info=DestroyDrawInfo(draw_info);
10144           break;
10145         }
10146         case 112:  /* Distort */
10147         {
10148           AV
10149             *av;
10150
10151           double
10152             *coordinates;
10153
10154           DistortImageMethod
10155             method;
10156
10157           size_t
10158             number_coordinates;
10159
10160           VirtualPixelMethod
10161             virtual_pixel;
10162
10163           if (attribute_flag[0] == 0)
10164             break;
10165           method=UndefinedDistortion;
10166           if (attribute_flag[1] != 0)
10167             method=(DistortImageMethod) argument_list[1].integer_reference;
10168           av=(AV *) argument_list[0].array_reference;
10169           number_coordinates=(size_t) av_len(av)+1;
10170           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10171             sizeof(*coordinates));
10172           if (coordinates == (double *) NULL)
10173             {
10174               ThrowPerlException(exception,ResourceLimitFatalError,
10175                 "MemoryAllocationFailed",PackageName);
10176               goto PerlException;
10177             }
10178           for (j=0; j < (ssize_t) number_coordinates; j++)
10179             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10180           virtual_pixel=UndefinedVirtualPixelMethod;
10181           if (attribute_flag[2] != 0)
10182             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10183               argument_list[2].integer_reference);
10184           image=DistortImage(image,method,number_coordinates,coordinates,
10185             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10186             exception);
10187           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10188             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10189           coordinates=(double *) RelinquishMagickMemory(coordinates);
10190           break;
10191         }
10192         case 113:  /* Clut */
10193         {
10194           if (attribute_flag[0] == 0)
10195             {
10196               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10197                 PackageName);
10198               goto PerlException;
10199             }
10200           if (attribute_flag[1] != 0)
10201             channel=(ChannelType) argument_list[1].integer_reference;
10202           PushPixelComponentMap(image,channel);
10203           (void) ClutImage(image,argument_list[0].image_reference);
10204           PopPixelComponentMap(image);
10205           break;
10206         }
10207         case 114:  /* LiquidRescale */
10208         {
10209           if (attribute_flag[0] != 0)
10210             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10211               &geometry,exception);
10212           if (attribute_flag[1] != 0)
10213             geometry.width=argument_list[1].integer_reference;
10214           if (attribute_flag[2] != 0)
10215             geometry.height=argument_list[2].integer_reference;
10216           if (attribute_flag[3] == 0)
10217             argument_list[3].real_reference=1.0;
10218           if (attribute_flag[4] == 0)
10219             argument_list[4].real_reference=0.0;
10220           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10221             argument_list[3].real_reference,argument_list[4].real_reference,
10222             exception);
10223           break;
10224         }
10225         case 115:  /* EncipherImage */
10226         {
10227           (void) EncipherImage(image,argument_list[0].string_reference,
10228             exception);
10229           break;
10230         }
10231         case 116:  /* DecipherImage */
10232         {
10233           (void) DecipherImage(image,argument_list[0].string_reference,
10234             exception);
10235           break;
10236         }
10237         case 117:  /* Deskew */
10238         {
10239           geometry_info.rho=QuantumRange/2.0;
10240           if (attribute_flag[0] != 0)
10241             flags=ParseGeometry(argument_list[0].string_reference,
10242               &geometry_info);
10243           if (attribute_flag[1] != 0)
10244             geometry_info.rho=SiPrefixToDouble(
10245               argument_list[1].string_reference,QuantumRange);
10246           image=DeskewImage(image,geometry_info.rho,exception);
10247           break;
10248         }
10249         case 118:  /* Remap */
10250         {
10251           QuantizeInfo
10252             *quantize_info;
10253
10254           if (attribute_flag[0] == 0)
10255             {
10256               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10257                 PackageName);
10258               goto PerlException;
10259             }
10260           quantize_info=AcquireQuantizeInfo(info->image_info);
10261           if (attribute_flag[1] != 0)
10262             quantize_info->dither=(MagickBooleanType)
10263               argument_list[1].integer_reference;
10264           if (attribute_flag[2] != 0)
10265             quantize_info->dither_method=(DitherMethod)
10266               argument_list[2].integer_reference;
10267           (void) RemapImages(quantize_info,image,
10268             argument_list[0].image_reference);
10269           quantize_info=DestroyQuantizeInfo(quantize_info);
10270           break;
10271         }
10272         case 119:  /* SparseColor */
10273         {
10274           AV
10275             *av;
10276
10277           double
10278             *coordinates;
10279
10280           SparseColorMethod
10281             method;
10282
10283           size_t
10284             number_coordinates;
10285
10286           VirtualPixelMethod
10287             virtual_pixel;
10288
10289           if (attribute_flag[0] == 0)
10290             break;
10291           method=UndefinedColorInterpolate;
10292           if (attribute_flag[1] != 0)
10293             method=(SparseColorMethod) argument_list[1].integer_reference;
10294           av=(AV *) argument_list[0].array_reference;
10295           number_coordinates=(size_t) av_len(av)+1;
10296           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10297             sizeof(*coordinates));
10298           if (coordinates == (double *) NULL)
10299             {
10300               ThrowPerlException(exception,ResourceLimitFatalError,
10301                 "MemoryAllocationFailed",PackageName);
10302               goto PerlException;
10303             }
10304           for (j=0; j < (ssize_t) number_coordinates; j++)
10305             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10306           virtual_pixel=UndefinedVirtualPixelMethod;
10307           if (attribute_flag[2] != 0)
10308             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10309               argument_list[2].integer_reference);
10310           if (attribute_flag[3] != 0)
10311             channel=(ChannelType) argument_list[3].integer_reference;
10312           PushPixelComponentMap(image,channel);
10313           image=SparseColorImage(image,method,number_coordinates,coordinates,
10314             exception);
10315           PopPixelComponentMap(image);
10316           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10317             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10318           coordinates=(double *) RelinquishMagickMemory(coordinates);
10319           break;
10320         }
10321         case 120:  /* Function */
10322         {
10323           AV
10324             *av;
10325
10326           double
10327             *parameters;
10328
10329           MagickFunction
10330             function;
10331
10332           size_t
10333             number_parameters;
10334
10335           VirtualPixelMethod
10336             virtual_pixel;
10337
10338           if (attribute_flag[0] == 0)
10339             break;
10340           function=UndefinedFunction;
10341           if (attribute_flag[1] != 0)
10342             function=(MagickFunction) argument_list[1].integer_reference;
10343           av=(AV *) argument_list[0].array_reference;
10344           number_parameters=(size_t) av_len(av)+1;
10345           parameters=(double *) AcquireQuantumMemory(number_parameters,
10346             sizeof(*parameters));
10347           if (parameters == (double *) NULL)
10348             {
10349               ThrowPerlException(exception,ResourceLimitFatalError,
10350                 "MemoryAllocationFailed",PackageName);
10351               goto PerlException;
10352             }
10353           for (j=0; j < (ssize_t) number_parameters; j++)
10354             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10355           virtual_pixel=UndefinedVirtualPixelMethod;
10356           if (attribute_flag[2] != 0)
10357             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10358               argument_list[2].integer_reference);
10359           (void) FunctionImage(image,function,number_parameters,parameters,
10360             exception);
10361           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10362             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10363           parameters=(double *) RelinquishMagickMemory(parameters);
10364           break;
10365         }
10366         case 121:  /* SelectiveBlur */
10367         {
10368           if (attribute_flag[0] != 0)
10369             {
10370               flags=ParseGeometry(argument_list[0].string_reference,
10371                 &geometry_info);
10372               if ((flags & SigmaValue) == 0)
10373                 geometry_info.sigma=1.0;
10374               if ((flags & PercentValue) != 0)
10375                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10376             }
10377           if (attribute_flag[1] != 0)
10378             geometry_info.rho=argument_list[1].real_reference;
10379           if (attribute_flag[2] != 0)
10380             geometry_info.sigma=argument_list[2].real_reference;
10381           if (attribute_flag[3] != 0)
10382             geometry_info.xi=argument_list[3].integer_reference;;
10383           if (attribute_flag[4] != 0)
10384             channel=(ChannelType) argument_list[4].integer_reference;
10385           PushPixelComponentMap(image,channel);
10386           image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10387             geometry_info.xi,exception);
10388           PopPixelComponentMap(image);
10389           break;
10390         }
10391         case 122:  /* HaldClut */
10392         {
10393           if (attribute_flag[0] == 0)
10394             {
10395               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10396                 PackageName);
10397               goto PerlException;
10398             }
10399           if (attribute_flag[1] != 0)
10400             channel=(ChannelType) argument_list[1].integer_reference;
10401           PushPixelComponentMap(image,channel);
10402           (void) HaldClutImage(image,argument_list[0].image_reference);
10403           PopPixelComponentMap(image);
10404           break;
10405         }
10406         case 123:  /* BlueShift */
10407         {
10408           if (attribute_flag[0] != 0)
10409             (void) ParseGeometry(argument_list[0].string_reference,
10410               &geometry_info);
10411           image=BlueShiftImage(image,geometry_info.rho,exception);
10412           break;
10413         }
10414         case 124:  /* ForwardFourierTransformImage */
10415         {
10416           image=ForwardFourierTransformImage(image,
10417             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10418             exception);
10419           break;
10420         }
10421         case 125:  /* InverseFourierTransformImage */
10422         {
10423           image=InverseFourierTransformImage(image,image->next,
10424             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10425             exception);
10426           break;
10427         }
10428         case 126:  /* ColorDecisionList */
10429         {
10430           if (attribute_flag[0] == 0)
10431             argument_list[0].string_reference=(char *) NULL;
10432           (void) ColorDecisionListImage(image,
10433             argument_list[0].string_reference);
10434           break;
10435         }
10436         case 127:  /* AutoGamma */
10437         {
10438           if (attribute_flag[0] != 0)
10439             channel=(ChannelType) argument_list[0].integer_reference;
10440           PushPixelComponentMap(image,channel);
10441           (void) AutoGammaImage(image);
10442           PopPixelComponentMap(image);
10443           break;
10444         }
10445         case 128:  /* AutoLevel */
10446         {
10447           if (attribute_flag[0] != 0)
10448             channel=(ChannelType) argument_list[0].integer_reference;
10449           PushPixelComponentMap(image,channel);
10450           (void) AutoLevelImage(image);
10451           PopPixelComponentMap(image);
10452           break;
10453         }
10454         case 129:  /* LevelColors */
10455         {
10456           PixelInfo
10457             black_point,
10458             white_point;
10459
10460           (void) QueryMagickColor("#000000",&black_point,exception);
10461           (void) QueryMagickColor("#ffffff",&white_point,exception);
10462           if (attribute_flag[1] != 0)
10463              (void) QueryMagickColor(argument_list[1].string_reference,
10464                &black_point,exception);
10465           if (attribute_flag[2] != 0)
10466              (void) QueryMagickColor(argument_list[2].string_reference,
10467                &white_point,exception);
10468           if (attribute_flag[3] != 0)
10469             channel=(ChannelType) argument_list[3].integer_reference;
10470           PushPixelComponentMap(image,channel);
10471           (void) LevelImageColors(image,&black_point,&white_point,
10472             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse);
10473           PopPixelComponentMap(image);
10474           break;
10475         }
10476         case 130:  /* Clamp */
10477         {
10478           if (attribute_flag[0] != 0)
10479             channel=(ChannelType) argument_list[0].integer_reference;
10480           PushPixelComponentMap(image,channel);
10481           (void) ClampImage(image);
10482           PopPixelComponentMap(image);
10483           break;
10484         }
10485         case 131:  /* Filter */
10486         {
10487           KernelInfo
10488             *kernel;
10489
10490           if (attribute_flag[0] == 0)
10491             break;
10492           kernel=AcquireKernelInfo(argument_list[0].string_reference);
10493           if (kernel == (KernelInfo *) NULL)
10494             break;
10495           if (attribute_flag[1] != 0)
10496             channel=(ChannelType) argument_list[1].integer_reference;
10497           if (attribute_flag[2] != 0)
10498             image->bias=SiPrefixToDouble(argument_list[2].string_reference,
10499               QuantumRange);
10500           PushPixelComponentMap(image,channel);
10501           image=FilterImage(image,kernel,exception);
10502           PopPixelComponentMap(image);
10503           kernel=DestroyKernelInfo(kernel);
10504           break;
10505         }
10506         case 132:  /* BrightnessContrast */
10507         {
10508           double
10509             brightness,
10510             contrast;
10511
10512           brightness=0.0;
10513           contrast=0.0;
10514           if (attribute_flag[0] != 0)
10515             {
10516               flags=ParseGeometry(argument_list[0].string_reference,
10517                 &geometry_info);
10518               brightness=geometry_info.rho;
10519               if ((flags & SigmaValue) == 0)
10520                 contrast=geometry_info.sigma;
10521             }
10522           if (attribute_flag[1] != 0)
10523             brightness=argument_list[1].real_reference;
10524           if (attribute_flag[2] != 0)
10525             contrast=argument_list[2].real_reference;
10526           if (attribute_flag[4] != 0)
10527             channel=(ChannelType) argument_list[4].integer_reference;
10528           PushPixelComponentMap(image,channel);
10529           (void) BrightnessContrastImage(image,brightness,contrast);
10530           PopPixelComponentMap(image);
10531           break;
10532         }
10533         case 133:  /* Morphology */
10534         {
10535           KernelInfo
10536             *kernel;
10537
10538           MorphologyMethod
10539             method;
10540
10541           ssize_t
10542             iterations;
10543
10544           if (attribute_flag[0] == 0)
10545             break;
10546           kernel=AcquireKernelInfo(argument_list[0].string_reference);
10547           if (kernel == (KernelInfo *) NULL)
10548             break;
10549           if (attribute_flag[1] != 0)
10550             channel=(ChannelType) argument_list[1].integer_reference;
10551           method=UndefinedMorphology;
10552           if (attribute_flag[2] != 0)
10553             method=argument_list[2].integer_reference;
10554           iterations=1;
10555           if (attribute_flag[3] != 0)
10556             iterations=argument_list[4].integer_reference;
10557           PushPixelComponentMap(image,channel);
10558           image=MorphologyImage(image,method,iterations,kernel,exception);
10559           PopPixelComponentMap(image);
10560           kernel=DestroyKernelInfo(kernel);
10561           break;
10562         }
10563         case 108:  /* Recolor */
10564         case 134:  /* ColorMatrix */
10565         {
10566           AV
10567             *av;
10568
10569           double
10570             *color_matrix;
10571
10572           KernelInfo
10573             *kernel_info;
10574
10575           size_t
10576             order;
10577
10578           if (attribute_flag[0] == 0)
10579             break;
10580           av=(AV *) argument_list[0].array_reference;
10581           order=(size_t) sqrt(av_len(av)+1);
10582           color_matrix=(double *) AcquireQuantumMemory(order,order*
10583             sizeof(*color_matrix));
10584           if (color_matrix == (double *) NULL)
10585             {
10586               ThrowPerlException(exception,ResourceLimitFatalError,
10587                 "MemoryAllocationFailed",PackageName);
10588               goto PerlException;
10589            }
10590           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10591             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10592           for ( ; j < (ssize_t) (order*order); j++)
10593             color_matrix[j]=0.0;
10594           kernel_info=AcquireKernelInfo("1");
10595           if (kernel_info == (KernelInfo *) NULL)
10596             break;
10597           kernel_info->width=order;
10598           kernel_info->height=order;
10599           kernel_info->values=color_matrix;
10600           image=ColorMatrixImage(image,kernel_info,exception);
10601           kernel_info->values=(double *) NULL;
10602           kernel_info=DestroyKernelInfo(kernel_info);
10603           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10604           break;
10605         }
10606         case 135:  /* Color */
10607         {
10608           PixelInfo
10609             color;
10610
10611           (void) QueryMagickColor("none",&color,exception);
10612           if (attribute_flag[0] != 0)
10613             (void) QueryMagickColor(argument_list[0].string_reference,
10614               &color,exception);
10615           (void) SetImageColor(image,&color);
10616           break;
10617         }
10618         case 136:  /* Mode */
10619         {
10620           if (attribute_flag[0] != 0)
10621             {
10622               flags=ParseGeometry(argument_list[0].string_reference,
10623                 &geometry_info);
10624               if ((flags & SigmaValue) == 0)
10625                 geometry_info.sigma=1.0;
10626             }
10627           if (attribute_flag[1] != 0)
10628             geometry_info.rho=argument_list[1].real_reference;
10629           if (attribute_flag[2] != 0)
10630             geometry_info.sigma=argument_list[2].real_reference;
10631           if (attribute_flag[3] != 0)
10632             channel=(ChannelType) argument_list[3].integer_reference;
10633           PushPixelComponentMap(image,channel);
10634           image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
10635             (size_t) geometry_info.sigma,exception);
10636           PopPixelComponentMap(image);
10637           break;
10638         }
10639         case 137:  /* Statistic */
10640         {
10641           StatisticType
10642             statistic;
10643
10644           statistic=UndefinedStatistic;
10645           if (attribute_flag[0] != 0)
10646             {
10647               flags=ParseGeometry(argument_list[0].string_reference,
10648                 &geometry_info);
10649               if ((flags & SigmaValue) == 0)
10650                 geometry_info.sigma=1.0;
10651             }
10652           if (attribute_flag[1] != 0)
10653             geometry_info.rho=argument_list[1].real_reference;
10654           if (attribute_flag[2] != 0)
10655             geometry_info.sigma=argument_list[2].real_reference;
10656           if (attribute_flag[3] != 0)
10657             channel=(ChannelType) argument_list[3].integer_reference;
10658           if (attribute_flag[4] != 0)
10659             statistic=(StatisticType) argument_list[4].integer_reference;
10660           PushPixelComponentMap(image,channel);
10661           image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
10662             (size_t) geometry_info.sigma,exception);
10663           PopPixelComponentMap(image);
10664           break;
10665         }
10666       }
10667       if (next != (Image *) NULL)
10668         (void) CatchImageException(next);
10669       if (region_image != (Image *) NULL)
10670         {
10671           /*
10672             Composite region.
10673           */ 
10674           status=CompositeImage(region_image,CopyCompositeOp,image,
10675             region_info.x,region_info.y);
10676           (void) status;
10677           (void) CatchImageException(region_image);
10678           image=DestroyImage(image);
10679           image=region_image;
10680         }
10681       if (image != (Image *) NULL)
10682         {
10683           number_images++;
10684           if (next && (next != image))
10685             {
10686               image->next=next->next;
10687               DeleteImageFromRegistry(*pv,next);
10688             }
10689           sv_setiv(*pv,(IV) image);
10690           next=image;
10691         }
10692       if (*pv)
10693         pv++;
10694     }
10695
10696   PerlException:
10697     if (reference_vector)
10698       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
10699     InheritPerlException(exception,perl_exception);
10700     exception=DestroyExceptionInfo(exception);
10701     sv_setiv(perl_exception,(IV) number_images);
10702     SvPOK_on(perl_exception);
10703     ST(0)=sv_2mortal(perl_exception);
10704     XSRETURN(1);
10705   }
10706 \f
10707 #
10708 ###############################################################################
10709 #                                                                             #
10710 #                                                                             #
10711 #                                                                             #
10712 #   M o n t a g e                                                             #
10713 #                                                                             #
10714 #                                                                             #
10715 #                                                                             #
10716 ###############################################################################
10717 #
10718 #
10719 void
10720 Montage(ref,...)
10721   Image::Magick ref=NO_INIT
10722   ALIAS:
10723     MontageImage  = 1
10724     montage       = 2
10725     montageimage  = 3
10726   PPCODE:
10727   {
10728     AV
10729       *av;
10730
10731     char
10732       *attribute;
10733
10734     ExceptionInfo
10735       *exception;
10736
10737     HV
10738       *hv;
10739
10740     Image
10741       *image,
10742       *next;
10743
10744     PixelInfo
10745       transparent_color;
10746
10747     MontageInfo
10748       *montage_info;
10749
10750     register ssize_t
10751       i;
10752
10753     ssize_t
10754       sp;
10755
10756     struct PackageInfo
10757       *info;
10758
10759     SV
10760       *av_reference,
10761       *perl_exception,
10762       *reference,
10763       *rv,
10764       *sv;
10765
10766     PERL_UNUSED_VAR(ref);
10767     PERL_UNUSED_VAR(ix);
10768     exception=AcquireExceptionInfo();
10769     perl_exception=newSVpv("",0);
10770     sv=NULL;
10771     attribute=NULL;
10772     if (sv_isobject(ST(0)) == 0)
10773       {
10774         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
10775           PackageName);
10776         goto PerlException;
10777       }
10778     reference=SvRV(ST(0));
10779     hv=SvSTASH(reference);
10780     av=newAV();
10781     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
10782     SvREFCNT_dec(av);
10783     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
10784     if (image == (Image *) NULL)
10785       {
10786         ThrowPerlException(exception,OptionError,"NoImagesDefined",
10787           PackageName);
10788         goto PerlException;
10789       }
10790     /*
10791       Get options.
10792     */
10793     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
10794     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
10795     (void) QueryMagickColor("none",&transparent_color,exception);
10796     for (i=2; i < items; i+=2)
10797     {
10798       attribute=(char *) SvPV(ST(i-1),na);
10799       switch (*attribute)
10800       {
10801         case 'B':
10802         case 'b':
10803         {
10804           if (LocaleCompare(attribute,"background") == 0)
10805             {
10806               (void) QueryColorDatabase(SvPV(ST(i),na),
10807                 &montage_info->background_color,exception);
10808               for (next=image; next; next=next->next)
10809                 next->background_color=montage_info->background_color;
10810               break;
10811             }
10812           if (LocaleCompare(attribute,"border") == 0)
10813             {
10814               montage_info->border_width=SvIV(ST(i));
10815               break;
10816             }
10817           if (LocaleCompare(attribute,"bordercolor") == 0)
10818             {
10819               (void) QueryColorDatabase(SvPV(ST(i),na),
10820                 &montage_info->border_color,exception);
10821               for (next=image; next; next=next->next)
10822                 next->border_color=montage_info->border_color;
10823               break;
10824             }
10825           if (LocaleCompare(attribute,"borderwidth") == 0)
10826             {
10827               montage_info->border_width=SvIV(ST(i));
10828               break;
10829             }
10830           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10831             attribute);
10832           break;
10833         }
10834         case 'C':
10835         case 'c':
10836         {
10837           if (LocaleCompare(attribute,"compose") == 0)
10838             {
10839               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
10840                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
10841               if (sp < 0)
10842                 {
10843                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
10844                     SvPV(ST(i),na));
10845                   break;
10846                 }
10847               for (next=image; next; next=next->next)
10848                 next->compose=(CompositeOperator) sp;
10849               break;
10850             }
10851           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10852             attribute);
10853           break;
10854         }
10855         case 'F':
10856         case 'f':
10857         {
10858           if (LocaleCompare(attribute,"fill") == 0)
10859             {
10860               (void) QueryColorDatabase(SvPV(ST(i),na),&montage_info->fill,
10861                 exception);
10862               break;
10863             }
10864           if (LocaleCompare(attribute,"font") == 0)
10865             {
10866               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
10867               break;
10868             }
10869           if (LocaleCompare(attribute,"frame") == 0)
10870             {
10871               char
10872                 *p;
10873
10874               p=SvPV(ST(i),na);
10875               if (IsGeometry(p) == MagickFalse)
10876                 {
10877                   ThrowPerlException(exception,OptionError,"MissingGeometry",
10878                     p);
10879                   break;
10880                 }
10881               (void) CloneString(&montage_info->frame,p);
10882               if (*p == '\0')
10883                 montage_info->frame=(char *) NULL;
10884               break;
10885             }
10886           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10887             attribute);
10888           break;
10889         }
10890         case 'G':
10891         case 'g':
10892         {
10893           if (LocaleCompare(attribute,"geometry") == 0)
10894             {
10895               char
10896                 *p;
10897
10898               p=SvPV(ST(i),na);
10899               if (IsGeometry(p) == MagickFalse)
10900                 {
10901                   ThrowPerlException(exception,OptionError,"MissingGeometry",
10902                     p);
10903                   break;
10904                 }
10905              (void) CloneString(&montage_info->geometry,p);
10906              if (*p == '\0')
10907                montage_info->geometry=(char *) NULL;
10908              break;
10909            }
10910          if (LocaleCompare(attribute,"gravity") == 0)
10911            {
10912              ssize_t
10913                in;
10914
10915              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
10916                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
10917              if (in < 0)
10918                {
10919                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
10920                    SvPV(ST(i),na));
10921                  return;
10922                }
10923              montage_info->gravity=(GravityType) in;
10924              for (next=image; next; next=next->next)
10925                next->gravity=(GravityType) in;
10926              break;
10927            }
10928           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10929             attribute);
10930           break;
10931         }
10932         case 'L':
10933         case 'l':
10934         {
10935           if (LocaleCompare(attribute,"label") == 0)
10936             {
10937               for (next=image; next; next=next->next)
10938                 (void) SetImageProperty(next,"label",InterpretImageProperties(
10939                   info ? info->image_info : (ImageInfo *) NULL,next,
10940                   SvPV(ST(i),na)));
10941               break;
10942             }
10943           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10944             attribute);
10945           break;
10946         }
10947         case 'M':
10948         case 'm':
10949         {
10950           if (LocaleCompare(attribute,"mattecolor") == 0)
10951             {
10952               (void) QueryColorDatabase(SvPV(ST(i),na),
10953                 &montage_info->matte_color,exception);
10954               for (next=image; next; next=next->next)
10955                 next->matte_color=montage_info->matte_color;
10956               break;
10957             }
10958           if (LocaleCompare(attribute,"mode") == 0)
10959             {
10960               ssize_t
10961                 in;
10962
10963               in=!SvPOK(ST(i)) ? SvIV(ST(i)) :
10964                 ParseCommandOption(MagickModeOptions,MagickFalse,SvPV(ST(i),na));
10965               switch (in)
10966               {
10967                 default:
10968                 {
10969                   ThrowPerlException(exception,OptionError,
10970                     "UnrecognizedModeType",SvPV(ST(i),na));
10971                   break;
10972                 }
10973                 case FrameMode:
10974                 {
10975                   (void) CloneString(&montage_info->frame,"15x15+3+3");
10976                   montage_info->shadow=MagickTrue;
10977                   break;
10978                 }
10979                 case UnframeMode:
10980                 {
10981                   montage_info->frame=(char *) NULL;
10982                   montage_info->shadow=MagickFalse;
10983                   montage_info->border_width=0;
10984                   break;
10985                 }
10986                 case ConcatenateMode:
10987                 {
10988                   montage_info->frame=(char *) NULL;
10989                   montage_info->shadow=MagickFalse;
10990                   (void) CloneString(&montage_info->geometry,"+0+0");
10991                   montage_info->border_width=0;
10992                 }
10993               }
10994               break;
10995             }
10996           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10997             attribute);
10998           break;
10999         }
11000         case 'P':
11001         case 'p':
11002         {
11003           if (LocaleCompare(attribute,"pointsize") == 0)
11004             {
11005               montage_info->pointsize=SvIV(ST(i));
11006               break;
11007             }
11008           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11009             attribute);
11010           break;
11011         }
11012         case 'S':
11013         case 's':
11014         {
11015           if (LocaleCompare(attribute,"shadow") == 0)
11016             {
11017               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11018                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11019               if (sp < 0)
11020                 {
11021                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11022                     SvPV(ST(i),na));
11023                   break;
11024                 }
11025              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11026              break;
11027             }
11028           if (LocaleCompare(attribute,"stroke") == 0)
11029             {
11030               (void) QueryColorDatabase(SvPV(ST(i),na),&montage_info->stroke,
11031                 exception);
11032               break;
11033             }
11034           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11035             attribute);
11036           break;
11037         }
11038         case 'T':
11039         case 't':
11040         {
11041           if (LocaleCompare(attribute,"texture") == 0)
11042             {
11043               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11044               break;
11045             }
11046           if (LocaleCompare(attribute,"tile") == 0)
11047             {
11048               char *p=SvPV(ST(i),na);
11049               if (IsGeometry(p) == MagickFalse)
11050                 {
11051                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11052                     p);
11053                   break;
11054                 }
11055               (void) CloneString(&montage_info->tile,p);
11056               if (*p == '\0')
11057                 montage_info->tile=(char *) NULL;
11058               break;
11059             }
11060           if (LocaleCompare(attribute,"title") == 0)
11061             {
11062               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11063               break;
11064             }
11065           if (LocaleCompare(attribute,"transparent") == 0)
11066             {
11067               PixelInfo
11068                 transparent_color;
11069
11070               QueryMagickColor(SvPV(ST(i),na),&transparent_color,exception);
11071               for (next=image; next; next=next->next)
11072                 (void) TransparentPaintImage(next,&transparent_color,
11073                   TransparentAlpha,MagickFalse);
11074               break;
11075             }
11076           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11077             attribute);
11078           break;
11079         }
11080         default:
11081         {
11082           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11083             attribute);
11084           break;
11085         }
11086       }
11087     }
11088     image=MontageImageList(info->image_info,montage_info,image,exception);
11089     montage_info=DestroyMontageInfo(montage_info);
11090     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11091       goto PerlException;
11092     if (transparent_color.alpha != TransparentAlpha)
11093       for (next=image; next; next=next->next)
11094         (void) TransparentPaintImage(next,&transparent_color,
11095           TransparentAlpha,MagickFalse);
11096     for (  ; image; image=image->next)
11097     {
11098       AddImageToRegistry(sv,image);
11099       rv=newRV(sv);
11100       av_push(av,sv_bless(rv,hv));
11101       SvREFCNT_dec(sv);
11102     }
11103     exception=DestroyExceptionInfo(exception);
11104     ST(0)=av_reference;
11105     SvREFCNT_dec(perl_exception);
11106     XSRETURN(1);
11107
11108   PerlException:
11109     InheritPerlException(exception,perl_exception);
11110     exception=DestroyExceptionInfo(exception);
11111     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11112     SvPOK_on(perl_exception);
11113     ST(0)=sv_2mortal(perl_exception);
11114     XSRETURN(1);
11115   }
11116 \f
11117 #
11118 ###############################################################################
11119 #                                                                             #
11120 #                                                                             #
11121 #                                                                             #
11122 #   M o r p h                                                                 #
11123 #                                                                             #
11124 #                                                                             #
11125 #                                                                             #
11126 ###############################################################################
11127 #
11128 #
11129 void
11130 Morph(ref,...)
11131   Image::Magick ref=NO_INIT
11132   ALIAS:
11133     MorphImage  = 1
11134     morph       = 2
11135     morphimage  = 3
11136   PPCODE:
11137   {
11138     AV
11139       *av;
11140
11141     char
11142       *attribute;
11143
11144     ExceptionInfo
11145       *exception;
11146
11147     HV
11148       *hv;
11149
11150     Image
11151       *image;
11152
11153     register ssize_t
11154       i;
11155
11156     ssize_t
11157       number_frames;
11158
11159     struct PackageInfo
11160       *info;
11161
11162     SV
11163       *av_reference,
11164       *perl_exception,
11165       *reference,
11166       *rv,
11167       *sv;
11168
11169     PERL_UNUSED_VAR(ref);
11170     PERL_UNUSED_VAR(ix);
11171     exception=AcquireExceptionInfo();
11172     perl_exception=newSVpv("",0);
11173     sv=NULL;
11174     av=NULL;
11175     attribute=NULL;
11176     if (sv_isobject(ST(0)) == 0)
11177       {
11178         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11179           PackageName);
11180         goto PerlException;
11181       }
11182     reference=SvRV(ST(0));
11183     hv=SvSTASH(reference);
11184     av=newAV();
11185     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11186     SvREFCNT_dec(av);
11187     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11188     if (image == (Image *) NULL)
11189       {
11190         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11191           PackageName);
11192         goto PerlException;
11193       }
11194     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11195     /*
11196       Get attribute.
11197     */
11198     number_frames=30;
11199     for (i=2; i < items; i+=2)
11200     {
11201       attribute=(char *) SvPV(ST(i-1),na);
11202       switch (*attribute)
11203       {
11204         case 'F':
11205         case 'f':
11206         {
11207           if (LocaleCompare(attribute,"frames") == 0)
11208             {
11209               number_frames=SvIV(ST(i));
11210               break;
11211             }
11212           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11213             attribute);
11214           break;
11215         }
11216         default:
11217         {
11218           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11219             attribute);
11220           break;
11221         }
11222       }
11223     }
11224     image=MorphImages(image,number_frames,exception);
11225     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11226       goto PerlException;
11227     for ( ; image; image=image->next)
11228     {
11229       AddImageToRegistry(sv,image);
11230       rv=newRV(sv);
11231       av_push(av,sv_bless(rv,hv));
11232       SvREFCNT_dec(sv);
11233     }
11234     exception=DestroyExceptionInfo(exception);
11235     ST(0)=av_reference;
11236     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11237     XSRETURN(1);
11238
11239   PerlException:
11240     InheritPerlException(exception,perl_exception);
11241     exception=DestroyExceptionInfo(exception);
11242     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11243     SvPOK_on(perl_exception);
11244     ST(0)=sv_2mortal(perl_exception);
11245     XSRETURN(1);
11246   }
11247 \f
11248 #
11249 ###############################################################################
11250 #                                                                             #
11251 #                                                                             #
11252 #                                                                             #
11253 #   M o s a i c                                                               #
11254 #                                                                             #
11255 #                                                                             #
11256 #                                                                             #
11257 ###############################################################################
11258 #
11259 #
11260 void
11261 Mosaic(ref)
11262   Image::Magick ref=NO_INIT
11263   ALIAS:
11264     MosaicImage   = 1
11265     mosaic        = 2
11266     mosaicimage   = 3
11267   PPCODE:
11268   {
11269     AV
11270       *av;
11271
11272     ExceptionInfo
11273       *exception;
11274
11275     HV
11276       *hv;
11277
11278     Image
11279       *image;
11280
11281     struct PackageInfo
11282       *info;
11283
11284     SV
11285       *perl_exception,
11286       *reference,
11287       *rv,
11288       *sv;
11289
11290     PERL_UNUSED_VAR(ref);
11291     PERL_UNUSED_VAR(ix);
11292     exception=AcquireExceptionInfo();
11293     perl_exception=newSVpv("",0);
11294     sv=NULL;
11295     if (sv_isobject(ST(0)) == 0)
11296       {
11297         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11298           PackageName);
11299         goto PerlException;
11300       }
11301     reference=SvRV(ST(0));
11302     hv=SvSTASH(reference);
11303     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11304     if (image == (Image *) NULL)
11305       {
11306         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11307           PackageName);
11308         goto PerlException;
11309       }
11310     image=MergeImageLayers(image,MosaicLayer,exception);
11311     /*
11312       Create blessed Perl array for the returned image.
11313     */
11314     av=newAV();
11315     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11316     SvREFCNT_dec(av);
11317     AddImageToRegistry(sv,image);
11318     rv=newRV(sv);
11319     av_push(av,sv_bless(rv,hv));
11320     SvREFCNT_dec(sv);
11321     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11322     (void) CopyMagickString(image->filename,info->image_info->filename,
11323       MaxTextExtent);
11324     SetImageInfo(info->image_info,0,&image->exception);
11325     exception=DestroyExceptionInfo(exception);
11326     SvREFCNT_dec(perl_exception);
11327     XSRETURN(1);
11328
11329   PerlException:
11330     InheritPerlException(exception,perl_exception);
11331     exception=DestroyExceptionInfo(exception);
11332     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11333     SvPOK_on(perl_exception);  /* return messages in string context */
11334     ST(0)=sv_2mortal(perl_exception);
11335     XSRETURN(1);
11336   }
11337 \f
11338 #
11339 ###############################################################################
11340 #                                                                             #
11341 #                                                                             #
11342 #                                                                             #
11343 #   P i n g                                                                   #
11344 #                                                                             #
11345 #                                                                             #
11346 #                                                                             #
11347 ###############################################################################
11348 #
11349 #
11350 void
11351 Ping(ref,...)
11352   Image::Magick ref=NO_INIT
11353   ALIAS:
11354     PingImage  = 1
11355     ping       = 2
11356     pingimage  = 3
11357   PPCODE:
11358   {
11359     AV
11360       *av;
11361
11362     char
11363       **keep,
11364       **list;
11365
11366     ExceptionInfo
11367       *exception;
11368
11369     Image
11370       *image,
11371       *next;
11372
11373     int
11374       n;
11375
11376     MagickBooleanType
11377       status;
11378
11379     register char
11380       **p;
11381
11382     register ssize_t
11383       i;
11384
11385     ssize_t
11386       ac;
11387
11388     STRLEN
11389       *length;
11390
11391     struct PackageInfo
11392       *info,
11393       *package_info;
11394
11395     SV
11396       *perl_exception,
11397       *reference;
11398
11399     size_t
11400       count;
11401
11402     PERL_UNUSED_VAR(ref);
11403     PERL_UNUSED_VAR(ix);
11404     exception=AcquireExceptionInfo();
11405     perl_exception=newSVpv("",0);
11406     package_info=(struct PackageInfo *) NULL;
11407     ac=(items < 2) ? 1 : items-1;
11408     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
11409     keep=list;
11410     length=(STRLEN *) NULL;
11411     if (list == (char **) NULL)
11412       {
11413         ThrowPerlException(exception,ResourceLimitError,
11414           "MemoryAllocationFailed",PackageName);
11415         goto PerlException;
11416       }
11417     keep=list;
11418     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
11419     if (length == (STRLEN *) NULL)
11420       {
11421         ThrowPerlException(exception,ResourceLimitError,
11422           "MemoryAllocationFailed",PackageName);
11423         goto PerlException;
11424       }
11425     if (sv_isobject(ST(0)) == 0)
11426       {
11427         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11428           PackageName);
11429         goto PerlException;
11430       }
11431     reference=SvRV(ST(0));
11432     if (SvTYPE(reference) != SVt_PVAV)
11433       {
11434         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11435           PackageName);
11436         goto PerlException;
11437       }
11438     av=(AV *) reference;
11439     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11440       exception);
11441     package_info=ClonePackageInfo(info,exception);
11442     n=1;
11443     if (items <= 1)
11444       *list=(char *) (*package_info->image_info->filename ?
11445         package_info->image_info->filename : "XC:black");
11446     else
11447       for (n=0, i=0; i < ac; i++)
11448       {
11449         list[n]=(char *) SvPV(ST(i+1),length[n]);
11450         if ((items >= 3) && strEQcase(list[n],"blob"))
11451           {
11452             void
11453               *blob;
11454
11455             i++;
11456             blob=(void *) (SvPV(ST(i+1),length[n]));
11457             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
11458           }
11459         if ((items >= 3) && strEQcase(list[n],"filename"))
11460           continue;
11461         if ((items >= 3) && strEQcase(list[n],"file"))
11462           {
11463             FILE
11464               *file;
11465
11466             PerlIO
11467               *io_info;
11468
11469             i++;
11470             io_info=IoIFP(sv_2io(ST(i+1)));
11471             if (io_info == (PerlIO *) NULL)
11472               {
11473                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11474                   PackageName);
11475                 continue;
11476               }
11477             file=PerlIO_findFILE(io_info);
11478             if (file == (FILE *) NULL)
11479               {
11480                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11481                   PackageName);
11482                 continue;
11483               }
11484             SetImageInfoFile(package_info->image_info,file);
11485           }
11486         if ((items >= 3) && strEQcase(list[n],"magick"))
11487           continue;
11488         n++;
11489       }
11490     list[n]=(char *) NULL;
11491     keep=list;
11492     status=ExpandFilenames(&n,&list);
11493     if (status == MagickFalse)
11494       {
11495         ThrowPerlException(exception,ResourceLimitError,
11496           "MemoryAllocationFailed",PackageName);
11497         goto PerlException;
11498       }
11499     count=0;
11500     for (i=0; i < n; i++)
11501     {
11502       (void) CopyMagickString(package_info->image_info->filename,list[i],
11503         MaxTextExtent);
11504       image=PingImage(package_info->image_info,exception);
11505       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11506         break;
11507       if ((package_info->image_info->file != (FILE *) NULL) ||
11508           (package_info->image_info->blob != (void *) NULL))
11509         DisassociateImageStream(image);
11510       count+=GetImageListLength(image);
11511       EXTEND(sp,4*count);
11512       for (next=image; next; next=next->next)
11513       {
11514         PUSHs(sv_2mortal(newSViv(next->columns)));
11515         PUSHs(sv_2mortal(newSViv(next->rows)));
11516         PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
11517         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
11518       }
11519       image=DestroyImageList(image);
11520     }
11521     /*
11522       Free resources.
11523     */
11524     for (i=0; i < n; i++)
11525       if (list[i] != (char *) NULL)
11526         for (p=keep; list[i] != *p++; )
11527           if (*p == NULL)
11528             {
11529               list[i]=(char *) RelinquishMagickMemory(list[i]);
11530               break;
11531             }
11532
11533   PerlException:
11534     if (package_info != (struct PackageInfo *) NULL)
11535       DestroyPackageInfo(package_info);
11536     if (list && (list != keep))
11537       list=(char **) RelinquishMagickMemory(list);
11538     if (keep)
11539       keep=(char **) RelinquishMagickMemory(keep);
11540     if (length)
11541       length=(STRLEN *) RelinquishMagickMemory(length);
11542     InheritPerlException(exception,perl_exception);
11543     exception=DestroyExceptionInfo(exception);
11544     SvREFCNT_dec(perl_exception);  /* throw away all errors */
11545   }
11546 \f
11547 #
11548 ###############################################################################
11549 #                                                                             #
11550 #                                                                             #
11551 #                                                                             #
11552 #   P r e v i e w                                                             #
11553 #                                                                             #
11554 #                                                                             #
11555 #                                                                             #
11556 ###############################################################################
11557 #
11558 #
11559 void
11560 Preview(ref,...)
11561   Image::Magick ref=NO_INIT
11562   ALIAS:
11563     PreviewImage = 1
11564     preview      = 2
11565     previewimage = 3
11566   PPCODE:
11567   {
11568     AV
11569       *av;
11570
11571     ExceptionInfo
11572       *exception;
11573
11574     HV
11575       *hv;
11576
11577     Image
11578       *image,
11579       *preview_image;
11580
11581     PreviewType
11582       preview_type;
11583
11584     struct PackageInfo
11585       *info;
11586
11587     SV
11588       *av_reference,
11589       *perl_exception,
11590       *reference,
11591       *rv,
11592       *sv;
11593
11594     PERL_UNUSED_VAR(ref);
11595     PERL_UNUSED_VAR(ix);
11596     exception=AcquireExceptionInfo();
11597     perl_exception=newSVpv("",0);
11598     sv=NULL;
11599     av=NULL;
11600     if (sv_isobject(ST(0)) == 0)
11601       {
11602         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11603           PackageName);
11604         goto PerlException;
11605       }
11606     reference=SvRV(ST(0));
11607     hv=SvSTASH(reference);
11608     av=newAV();
11609     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11610     SvREFCNT_dec(av);
11611     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11612     if (image == (Image *) NULL)
11613       {
11614         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11615           PackageName);
11616         goto PerlException;
11617       }
11618     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11619     preview_type=GammaPreview;
11620     if (items > 1)
11621       preview_type=(PreviewType)
11622         ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
11623     for ( ; image; image=image->next)
11624     {
11625       preview_image=PreviewImage(image,preview_type,exception);
11626       if (preview_image == (Image *) NULL)
11627         goto PerlException;
11628       AddImageToRegistry(sv,preview_image);
11629       rv=newRV(sv);
11630       av_push(av,sv_bless(rv,hv));
11631       SvREFCNT_dec(sv);
11632     }
11633     exception=DestroyExceptionInfo(exception);
11634     ST(0)=av_reference;
11635     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11636     XSRETURN(1);
11637
11638   PerlException:
11639     InheritPerlException(exception,perl_exception);
11640     exception=DestroyExceptionInfo(exception);
11641     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11642     SvPOK_on(perl_exception);
11643     ST(0)=sv_2mortal(perl_exception);
11644     XSRETURN(1);
11645   }
11646 \f
11647 #
11648 ###############################################################################
11649 #                                                                             #
11650 #                                                                             #
11651 #                                                                             #
11652 #   Q u e r y C o l o r                                                       #
11653 #                                                                             #
11654 #                                                                             #
11655 #                                                                             #
11656 ###############################################################################
11657 #
11658 #
11659 void
11660 QueryColor(ref,...)
11661   Image::Magick ref=NO_INIT
11662   ALIAS:
11663     querycolor = 1
11664   PPCODE:
11665   {
11666     char
11667       *name;
11668
11669     ExceptionInfo
11670       *exception;
11671
11672     PixelInfo
11673       color;
11674
11675     register ssize_t
11676       i;
11677
11678     SV
11679       *perl_exception;
11680
11681     PERL_UNUSED_VAR(ref);
11682     PERL_UNUSED_VAR(ix);
11683     exception=AcquireExceptionInfo();
11684     perl_exception=newSVpv("",0);
11685     if (items == 1)
11686       {
11687         const ColorInfo
11688           **colorlist;
11689
11690         size_t
11691           colors;
11692
11693         colorlist=GetColorInfoList("*",&colors,exception);
11694         EXTEND(sp,colors);
11695         for (i=0; i < (ssize_t) colors; i++)
11696         {
11697           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
11698         }
11699         colorlist=(const ColorInfo **)
11700           RelinquishMagickMemory((ColorInfo **) colorlist);
11701         goto PerlException;
11702       }
11703     EXTEND(sp,5*items);
11704     for (i=1; i < items; i++)
11705     {
11706       name=(char *) SvPV(ST(i),na);
11707       if (QueryMagickColor(name,&color,exception) == MagickFalse)
11708         {
11709           PUSHs(&sv_undef);
11710           continue;
11711         }
11712       PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
11713       PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
11714       PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
11715       if (color.colorspace == CMYKColorspace)
11716         PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
11717       if (color.matte != MagickFalse)
11718         PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
11719     }
11720
11721   PerlException:
11722     InheritPerlException(exception,perl_exception);
11723     exception=DestroyExceptionInfo(exception);
11724     SvREFCNT_dec(perl_exception);
11725   }
11726 \f
11727 #
11728 ###############################################################################
11729 #                                                                             #
11730 #                                                                             #
11731 #                                                                             #
11732 #   Q u e r y C o l o r N a m e                                               #
11733 #                                                                             #
11734 #                                                                             #
11735 #                                                                             #
11736 ###############################################################################
11737 #
11738 #
11739 void
11740 QueryColorname(ref,...)
11741   Image::Magick ref=NO_INIT
11742   ALIAS:
11743     querycolorname = 1
11744   PPCODE:
11745   {
11746     AV
11747       *av;
11748
11749     char
11750       message[MaxTextExtent];
11751
11752     ExceptionInfo
11753       *exception;
11754
11755     Image
11756       *image;
11757
11758     PixelPacket
11759       target_color;
11760
11761     register ssize_t
11762       i;
11763
11764     struct PackageInfo
11765       *info;
11766
11767     SV
11768       *perl_exception,
11769       *reference;  /* reference is the SV* of ref=SvIV(reference) */
11770
11771     PERL_UNUSED_VAR(ref);
11772     PERL_UNUSED_VAR(ix);
11773     exception=AcquireExceptionInfo();
11774     perl_exception=newSVpv("",0);
11775     reference=SvRV(ST(0));
11776     av=(AV *) reference;
11777     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11778       exception);
11779     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11780     if (image == (Image *) NULL)
11781       {
11782         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11783           PackageName);
11784         goto PerlException;
11785       }
11786     EXTEND(sp,items);
11787     for (i=1; i < items; i++)
11788     {
11789       (void) QueryColorDatabase(SvPV(ST(i),na),&target_color,exception);
11790       (void) QueryColorname(image,&target_color,SVGCompliance,message,
11791         exception);
11792       PUSHs(sv_2mortal(newSVpv(message,0)));
11793     }
11794
11795   PerlException:
11796     InheritPerlException(exception,perl_exception);
11797     exception=DestroyExceptionInfo(exception);
11798     SvREFCNT_dec(perl_exception);
11799   }
11800 \f
11801 #
11802 ###############################################################################
11803 #                                                                             #
11804 #                                                                             #
11805 #                                                                             #
11806 #   Q u e r y F o n t                                                         #
11807 #                                                                             #
11808 #                                                                             #
11809 #                                                                             #
11810 ###############################################################################
11811 #
11812 #
11813 void
11814 QueryFont(ref,...)
11815   Image::Magick ref=NO_INIT
11816   ALIAS:
11817     queryfont = 1
11818   PPCODE:
11819   {
11820     char
11821       *name,
11822       message[MaxTextExtent];
11823
11824     ExceptionInfo
11825       *exception;
11826
11827     register ssize_t
11828       i;
11829
11830     SV
11831       *perl_exception;
11832
11833     volatile const TypeInfo
11834       *type_info;
11835
11836     PERL_UNUSED_VAR(ref);
11837     PERL_UNUSED_VAR(ix);
11838     exception=AcquireExceptionInfo();
11839     perl_exception=newSVpv("",0);
11840     if (items == 1)
11841       {
11842         const TypeInfo
11843           **typelist;
11844
11845         size_t
11846           types;
11847
11848         typelist=GetTypeInfoList("*",&types,exception);
11849         EXTEND(sp,types);
11850         for (i=0; i < (ssize_t) types; i++)
11851         {
11852           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
11853         }
11854         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
11855           typelist);
11856         goto PerlException;
11857       }
11858     EXTEND(sp,10*items);
11859     for (i=1; i < items; i++)
11860     {
11861       name=(char *) SvPV(ST(i),na);
11862       type_info=GetTypeInfo(name,exception);
11863       if (type_info == (TypeInfo *) NULL)
11864         {
11865           PUSHs(&sv_undef);
11866           continue;
11867         }
11868       if (type_info->name == (char *) NULL)
11869         PUSHs(&sv_undef);
11870       else
11871         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
11872       if (type_info->description == (char *) NULL)
11873         PUSHs(&sv_undef);
11874       else
11875         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
11876       if (type_info->family == (char *) NULL)
11877         PUSHs(&sv_undef);
11878       else
11879         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
11880       if (type_info->style == UndefinedStyle)
11881         PUSHs(&sv_undef);
11882       else
11883         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
11884           type_info->style),0)));
11885       if (type_info->stretch == UndefinedStretch)
11886         PUSHs(&sv_undef);
11887       else
11888         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
11889           type_info->stretch),0)));
11890       (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
11891         type_info->weight);
11892       PUSHs(sv_2mortal(newSVpv(message,0)));
11893       if (type_info->encoding == (char *) NULL)
11894         PUSHs(&sv_undef);
11895       else
11896         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
11897       if (type_info->foundry == (char *) NULL)
11898         PUSHs(&sv_undef);
11899       else
11900         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
11901       if (type_info->format == (char *) NULL)
11902         PUSHs(&sv_undef);
11903       else
11904         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
11905       if (type_info->metrics == (char *) NULL)
11906         PUSHs(&sv_undef);
11907       else
11908         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
11909       if (type_info->glyphs == (char *) NULL)
11910         PUSHs(&sv_undef);
11911       else
11912         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
11913     }
11914
11915   PerlException:
11916     InheritPerlException(exception,perl_exception);
11917     exception=DestroyExceptionInfo(exception);
11918     SvREFCNT_dec(perl_exception);
11919   }
11920 \f
11921 #
11922 ###############################################################################
11923 #                                                                             #
11924 #                                                                             #
11925 #                                                                             #
11926 #   Q u e r y F o n t M e t r i c s                                           #
11927 #                                                                             #
11928 #                                                                             #
11929 #                                                                             #
11930 ###############################################################################
11931 #
11932 #
11933 void
11934 QueryFontMetrics(ref,...)
11935   Image::Magick ref=NO_INIT
11936   ALIAS:
11937     queryfontmetrics = 1
11938   PPCODE:
11939   {
11940     AffineMatrix
11941       affine,
11942       current;
11943
11944     AV
11945       *av;
11946
11947     char
11948       *attribute;
11949
11950     double
11951       x,
11952       y;
11953
11954     DrawInfo
11955       *draw_info;
11956
11957     ExceptionInfo
11958       *exception;
11959
11960     GeometryInfo
11961       geometry_info;
11962
11963     Image
11964       *image;
11965
11966     MagickBooleanType
11967       status;
11968
11969     MagickStatusType
11970       flags;
11971
11972     register ssize_t
11973       i;
11974
11975     ssize_t
11976       type;
11977
11978     struct PackageInfo
11979       *info,
11980       *package_info;
11981
11982     SV
11983       *perl_exception,
11984       *reference;  /* reference is the SV* of ref=SvIV(reference) */
11985
11986     TypeMetric
11987       metrics;
11988
11989     PERL_UNUSED_VAR(ref);
11990     PERL_UNUSED_VAR(ix);
11991     exception=AcquireExceptionInfo();
11992     package_info=(struct PackageInfo *) NULL;
11993     perl_exception=newSVpv("",0);
11994     reference=SvRV(ST(0));
11995     av=(AV *) reference;
11996     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11997       exception);
11998     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11999     if (image == (Image *) NULL)
12000       {
12001         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12002           PackageName);
12003         goto PerlException;
12004       }
12005     package_info=ClonePackageInfo(info,exception);
12006     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12007     CloneString(&draw_info->text,"");
12008     current=draw_info->affine;
12009     GetAffineMatrix(&affine);
12010     x=0.0;
12011     y=0.0;
12012     EXTEND(sp,7*items);
12013     for (i=2; i < items; i+=2)
12014     {
12015       attribute=(char *) SvPV(ST(i-1),na);
12016       switch (*attribute)
12017       {
12018         case 'A':
12019         case 'a':
12020         {
12021           if (LocaleCompare(attribute,"antialias") == 0)
12022             {
12023               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12024                 SvPV(ST(i),na));
12025               if (type < 0)
12026                 {
12027                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12028                     SvPV(ST(i),na));
12029                   break;
12030                 }
12031               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12032               break;
12033             }
12034           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12035             attribute);
12036           break;
12037         }
12038         case 'd':
12039         case 'D':
12040         {
12041           if (LocaleCompare(attribute,"density") == 0)
12042             {
12043               CloneString(&draw_info->density,SvPV(ST(i),na));
12044               break;
12045             }
12046           if (LocaleCompare(attribute,"direction") == 0)
12047             {
12048               draw_info->direction=(DirectionType) ParseCommandOption(
12049                 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12050               break;
12051             }
12052           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12053             attribute);
12054           break;
12055         }
12056         case 'e':
12057         case 'E':
12058         {
12059           if (LocaleCompare(attribute,"encoding") == 0)
12060             {
12061               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12062               break;
12063             }
12064           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12065             attribute);
12066           break;
12067         }
12068         case 'f':
12069         case 'F':
12070         {
12071           if (LocaleCompare(attribute,"family") == 0)
12072             {
12073               CloneString(&draw_info->family,SvPV(ST(i),na));
12074               break;
12075             }
12076           if (LocaleCompare(attribute,"fill") == 0)
12077             {
12078               if (info)
12079                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->fill,
12080                   &image->exception);
12081               break;
12082             }
12083           if (LocaleCompare(attribute,"font") == 0)
12084             {
12085               CloneString(&draw_info->font,SvPV(ST(i),na));
12086               break;
12087             }
12088           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12089             attribute);
12090           break;
12091         }
12092         case 'g':
12093         case 'G':
12094         {
12095           if (LocaleCompare(attribute,"geometry") == 0)
12096             {
12097               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12098               break;
12099             }
12100           if (LocaleCompare(attribute,"gravity") == 0)
12101             {
12102               draw_info->gravity=(GravityType) ParseCommandOption(
12103                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12104               break;
12105             }
12106           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12107             attribute);
12108           break;
12109         }
12110         case 'i':
12111         case 'I':
12112         {
12113           if (LocaleCompare(attribute,"interline-spacing") == 0)
12114             {
12115               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12116               draw_info->interline_spacing=geometry_info.rho;
12117               break;
12118             }
12119           if (LocaleCompare(attribute,"interword-spacing") == 0)
12120             {
12121               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12122               draw_info->interword_spacing=geometry_info.rho;
12123               break;
12124             }
12125           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12126             attribute);
12127           break;
12128         }
12129         case 'k':
12130         case 'K':
12131         {
12132           if (LocaleCompare(attribute,"kerning") == 0)
12133             {
12134               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12135               draw_info->kerning=geometry_info.rho;
12136               break;
12137             }
12138           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12139             attribute);
12140           break;
12141         }
12142         case 'p':
12143         case 'P':
12144         {
12145           if (LocaleCompare(attribute,"pointsize") == 0)
12146             {
12147               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12148               draw_info->pointsize=geometry_info.rho;
12149               break;
12150             }
12151           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12152             attribute);
12153           break;
12154         }
12155         case 'r':
12156         case 'R':
12157         {
12158           if (LocaleCompare(attribute,"rotate") == 0)
12159             {
12160               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12161               affine.rx=geometry_info.rho;
12162               affine.ry=geometry_info.sigma;
12163               if ((flags & SigmaValue) == 0)
12164                 affine.ry=affine.rx;
12165               break;
12166             }
12167           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12168             attribute);
12169           break;
12170         }
12171         case 's':
12172         case 'S':
12173         {
12174           if (LocaleCompare(attribute,"scale") == 0)
12175             {
12176               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12177               affine.sx=geometry_info.rho;
12178               affine.sy=geometry_info.sigma;
12179               if ((flags & SigmaValue) == 0)
12180                 affine.sy=affine.sx;
12181               break;
12182             }
12183           if (LocaleCompare(attribute,"skew") == 0)
12184             {
12185               double
12186                 x_angle,
12187                 y_angle;
12188
12189               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12190               x_angle=geometry_info.rho;
12191               y_angle=geometry_info.sigma;
12192               if ((flags & SigmaValue) == 0)
12193                 y_angle=x_angle;
12194               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12195               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12196               break;
12197             }
12198           if (LocaleCompare(attribute,"stroke") == 0)
12199             {
12200               if (info)
12201                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->stroke,
12202                   &image->exception);
12203               break;
12204             }
12205           if (LocaleCompare(attribute,"style") == 0)
12206             {
12207               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12208                 SvPV(ST(i),na));
12209               if (type < 0)
12210                 {
12211                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12212                     SvPV(ST(i),na));
12213                   break;
12214                 }
12215               draw_info->style=(StyleType) type;
12216               break;
12217             }
12218           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12219             attribute);
12220           break;
12221         }
12222         case 't':
12223         case 'T':
12224         {
12225           if (LocaleCompare(attribute,"text") == 0)
12226             {
12227               CloneString(&draw_info->text,SvPV(ST(i),na));
12228               break;
12229             }
12230           if (LocaleCompare(attribute,"translate") == 0)
12231             {
12232               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12233               affine.tx=geometry_info.rho;
12234               affine.ty=geometry_info.sigma;
12235               if ((flags & SigmaValue) == 0)
12236                 affine.ty=affine.tx;
12237               break;
12238             }
12239           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12240             attribute);
12241           break;
12242         }
12243         case 'w':
12244         case 'W':
12245         {
12246           if (LocaleCompare(attribute,"weight") == 0)
12247             {
12248               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12249               draw_info->weight=(size_t) geometry_info.rho;
12250               break;
12251             }
12252           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12253             attribute);
12254           break;
12255         }
12256         case 'x':
12257         case 'X':
12258         {
12259           if (LocaleCompare(attribute,"x") == 0)
12260             {
12261               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12262               x=geometry_info.rho;
12263               break;
12264             }
12265           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12266             attribute);
12267           break;
12268         }
12269         case 'y':
12270         case 'Y':
12271         {
12272           if (LocaleCompare(attribute,"y") == 0)
12273             {
12274               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12275               y=geometry_info.rho;
12276               break;
12277             }
12278           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12279             attribute);
12280           break;
12281         }
12282         default:
12283         {
12284           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12285             attribute);
12286           break;
12287         }
12288       }
12289     }
12290     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12291     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12292     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12293     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12294     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12295     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12296     if (draw_info->geometry == (char *) NULL)
12297       {
12298         draw_info->geometry=AcquireString((char *) NULL);
12299         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12300           "%.15g,%.15g",x,y);
12301       }
12302     status=GetTypeMetrics(image,draw_info,&metrics);
12303     (void) CatchImageException(image);
12304     if (status == MagickFalse)
12305       PUSHs(&sv_undef);
12306     else
12307       {
12308         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12309         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12310         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12311         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12312         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12313         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12314         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12315         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12316         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12317         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12318         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12319         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12320         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12321       }
12322     draw_info=DestroyDrawInfo(draw_info);
12323
12324   PerlException:
12325     if (package_info != (struct PackageInfo *) NULL)
12326       DestroyPackageInfo(package_info);
12327     InheritPerlException(exception,perl_exception);
12328     exception=DestroyExceptionInfo(exception);
12329     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12330   }
12331 \f
12332 #
12333 ###############################################################################
12334 #                                                                             #
12335 #                                                                             #
12336 #                                                                             #
12337 #   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                         #
12338 #                                                                             #
12339 #                                                                             #
12340 #                                                                             #
12341 ###############################################################################
12342 #
12343 #
12344 void
12345 QueryMultilineFontMetrics(ref,...)
12346   Image::Magick ref=NO_INIT
12347   ALIAS:
12348     querymultilinefontmetrics = 1
12349   PPCODE:
12350   {
12351     AffineMatrix
12352       affine,
12353       current;
12354
12355     AV
12356       *av;
12357
12358     char
12359       *attribute;
12360
12361     double
12362       x,
12363       y;
12364
12365     DrawInfo
12366       *draw_info;
12367
12368     ExceptionInfo
12369       *exception;
12370
12371     GeometryInfo
12372       geometry_info;
12373
12374     Image
12375       *image;
12376
12377     MagickBooleanType
12378       status;
12379
12380     MagickStatusType
12381       flags;
12382
12383     register ssize_t
12384       i;
12385
12386     ssize_t
12387       type;
12388
12389     struct PackageInfo
12390       *info,
12391       *package_info;
12392
12393     SV
12394       *perl_exception,
12395       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12396
12397     TypeMetric
12398       metrics;
12399
12400     PERL_UNUSED_VAR(ref);
12401     PERL_UNUSED_VAR(ix);
12402     exception=AcquireExceptionInfo();
12403     package_info=(struct PackageInfo *) NULL;
12404     perl_exception=newSVpv("",0);
12405     reference=SvRV(ST(0));
12406     av=(AV *) reference;
12407     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12408       exception);
12409     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12410     if (image == (Image *) NULL)
12411       {
12412         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12413           PackageName);
12414         goto PerlException;
12415       }
12416     package_info=ClonePackageInfo(info,exception);
12417     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12418     CloneString(&draw_info->text,"");
12419     current=draw_info->affine;
12420     GetAffineMatrix(&affine);
12421     x=0.0;
12422     y=0.0;
12423     EXTEND(sp,7*items);
12424     for (i=2; i < items; i+=2)
12425     {
12426       attribute=(char *) SvPV(ST(i-1),na);
12427       switch (*attribute)
12428       {
12429         case 'A':
12430         case 'a':
12431         {
12432           if (LocaleCompare(attribute,"antialias") == 0)
12433             {
12434               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12435                 SvPV(ST(i),na));
12436               if (type < 0)
12437                 {
12438                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12439                     SvPV(ST(i),na));
12440                   break;
12441                 }
12442               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12443               break;
12444             }
12445           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12446             attribute);
12447           break;
12448         }
12449         case 'd':
12450         case 'D':
12451         {
12452           if (LocaleCompare(attribute,"density") == 0)
12453             {
12454               CloneString(&draw_info->density,SvPV(ST(i),na));
12455               break;
12456             }
12457           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12458             attribute);
12459           break;
12460         }
12461         case 'e':
12462         case 'E':
12463         {
12464           if (LocaleCompare(attribute,"encoding") == 0)
12465             {
12466               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12467               break;
12468             }
12469           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12470             attribute);
12471           break;
12472         }
12473         case 'f':
12474         case 'F':
12475         {
12476           if (LocaleCompare(attribute,"family") == 0)
12477             {
12478               CloneString(&draw_info->family,SvPV(ST(i),na));
12479               break;
12480             }
12481           if (LocaleCompare(attribute,"fill") == 0)
12482             {
12483               if (info)
12484                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->fill,
12485                   &image->exception);
12486               break;
12487             }
12488           if (LocaleCompare(attribute,"font") == 0)
12489             {
12490               CloneString(&draw_info->font,SvPV(ST(i),na));
12491               break;
12492             }
12493           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12494             attribute);
12495           break;
12496         }
12497         case 'g':
12498         case 'G':
12499         {
12500           if (LocaleCompare(attribute,"geometry") == 0)
12501             {
12502               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12503               break;
12504             }
12505           if (LocaleCompare(attribute,"gravity") == 0)
12506             {
12507               draw_info->gravity=(GravityType) ParseCommandOption(
12508                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12509               break;
12510             }
12511           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12512             attribute);
12513           break;
12514         }
12515         case 'p':
12516         case 'P':
12517         {
12518           if (LocaleCompare(attribute,"pointsize") == 0)
12519             {
12520               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12521               draw_info->pointsize=geometry_info.rho;
12522               break;
12523             }
12524           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12525             attribute);
12526           break;
12527         }
12528         case 'r':
12529         case 'R':
12530         {
12531           if (LocaleCompare(attribute,"rotate") == 0)
12532             {
12533               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12534               affine.rx=geometry_info.rho;
12535               affine.ry=geometry_info.sigma;
12536               if ((flags & SigmaValue) == 0)
12537                 affine.ry=affine.rx;
12538               break;
12539             }
12540           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12541             attribute);
12542           break;
12543         }
12544         case 's':
12545         case 'S':
12546         {
12547           if (LocaleCompare(attribute,"scale") == 0)
12548             {
12549               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12550               affine.sx=geometry_info.rho;
12551               affine.sy=geometry_info.sigma;
12552               if ((flags & SigmaValue) == 0)
12553                 affine.sy=affine.sx;
12554               break;
12555             }
12556           if (LocaleCompare(attribute,"skew") == 0)
12557             {
12558               double
12559                 x_angle,
12560                 y_angle;
12561
12562               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12563               x_angle=geometry_info.rho;
12564               y_angle=geometry_info.sigma;
12565               if ((flags & SigmaValue) == 0)
12566                 y_angle=x_angle;
12567               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12568               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12569               break;
12570             }
12571           if (LocaleCompare(attribute,"stroke") == 0)
12572             {
12573               if (info)
12574                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->stroke,
12575                   &image->exception);
12576               break;
12577             }
12578           if (LocaleCompare(attribute,"style") == 0)
12579             {
12580               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12581                 SvPV(ST(i),na));
12582               if (type < 0)
12583                 {
12584                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12585                     SvPV(ST(i),na));
12586                   break;
12587                 }
12588               draw_info->style=(StyleType) type;
12589               break;
12590             }
12591           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12592             attribute);
12593           break;
12594         }
12595         case 't':
12596         case 'T':
12597         {
12598           if (LocaleCompare(attribute,"text") == 0)
12599             {
12600               CloneString(&draw_info->text,SvPV(ST(i),na));
12601               break;
12602             }
12603           if (LocaleCompare(attribute,"translate") == 0)
12604             {
12605               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12606               affine.tx=geometry_info.rho;
12607               affine.ty=geometry_info.sigma;
12608               if ((flags & SigmaValue) == 0)
12609                 affine.ty=affine.tx;
12610               break;
12611             }
12612           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12613             attribute);
12614           break;
12615         }
12616         case 'w':
12617         case 'W':
12618         {
12619           if (LocaleCompare(attribute,"weight") == 0)
12620             {
12621               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12622               draw_info->weight=(size_t) geometry_info.rho;
12623               break;
12624             }
12625           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12626             attribute);
12627           break;
12628         }
12629         case 'x':
12630         case 'X':
12631         {
12632           if (LocaleCompare(attribute,"x") == 0)
12633             {
12634               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12635               x=geometry_info.rho;
12636               break;
12637             }
12638           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12639             attribute);
12640           break;
12641         }
12642         case 'y':
12643         case 'Y':
12644         {
12645           if (LocaleCompare(attribute,"y") == 0)
12646             {
12647               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12648               y=geometry_info.rho;
12649               break;
12650             }
12651           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12652             attribute);
12653           break;
12654         }
12655         default:
12656         {
12657           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12658             attribute);
12659           break;
12660         }
12661       }
12662     }
12663     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12664     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12665     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12666     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12667     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12668     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12669     if (draw_info->geometry == (char *) NULL)
12670       {
12671         draw_info->geometry=AcquireString((char *) NULL);
12672         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12673           "%.15g,%.15g",x,y);
12674       }
12675     status=GetMultilineTypeMetrics(image,draw_info,&metrics);
12676     (void) CatchImageException(image);
12677     if (status == MagickFalse)
12678       PUSHs(&sv_undef);
12679     else
12680       {
12681         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12682         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12683         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12684         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12685         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12686         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12687         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12688         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12689         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12690         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12691         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12692         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12693         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12694       }
12695     draw_info=DestroyDrawInfo(draw_info);
12696
12697   PerlException:
12698     if (package_info != (struct PackageInfo *) NULL)
12699       DestroyPackageInfo(package_info);
12700     InheritPerlException(exception,perl_exception);
12701     exception=DestroyExceptionInfo(exception);
12702     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12703   }
12704 \f
12705 #
12706 ###############################################################################
12707 #                                                                             #
12708 #                                                                             #
12709 #                                                                             #
12710 #   Q u e r y F o r m a t                                                     #
12711 #                                                                             #
12712 #                                                                             #
12713 #                                                                             #
12714 ###############################################################################
12715 #
12716 #
12717 void
12718 QueryFormat(ref,...)
12719   Image::Magick ref=NO_INIT
12720   ALIAS:
12721     queryformat = 1
12722   PPCODE:
12723   {
12724     char
12725       *name;
12726
12727     ExceptionInfo
12728       *exception;
12729
12730     register ssize_t
12731       i;
12732
12733     SV
12734       *perl_exception;
12735
12736     volatile const MagickInfo
12737       *magick_info;
12738
12739     PERL_UNUSED_VAR(ref);
12740     PERL_UNUSED_VAR(ix);
12741     exception=AcquireExceptionInfo();
12742     perl_exception=newSVpv("",0);
12743     if (items == 1)
12744       {
12745         char
12746           format[MaxTextExtent];
12747
12748         const MagickInfo
12749           **format_list;
12750
12751         size_t
12752           types;
12753
12754         format_list=GetMagickInfoList("*",&types,exception);
12755         EXTEND(sp,types);
12756         for (i=0; i < (ssize_t) types; i++)
12757         {
12758           (void) CopyMagickString(format,format_list[i]->name,MaxTextExtent);
12759           LocaleLower(format);
12760           PUSHs(sv_2mortal(newSVpv(format,0)));
12761         }
12762         format_list=(const MagickInfo **)
12763           RelinquishMagickMemory((MagickInfo *) format_list);
12764         goto PerlException;
12765       }
12766     EXTEND(sp,8*items);
12767     for (i=1; i < items; i++)
12768     {
12769       name=(char *) SvPV(ST(i),na);
12770       magick_info=GetMagickInfo(name,exception);
12771       if (magick_info == (const MagickInfo *) NULL)
12772         {
12773           PUSHs(&sv_undef);
12774           continue;
12775         }
12776       PUSHs(sv_2mortal(newSViv(magick_info->adjoin)));
12777       PUSHs(sv_2mortal(newSViv(magick_info->blob_support)));
12778       PUSHs(sv_2mortal(newSViv(magick_info->raw)));
12779       PUSHs(sv_2mortal(newSViv((long) magick_info->decoder)));
12780       PUSHs(sv_2mortal(newSViv((long) magick_info->encoder)));
12781       if (magick_info->description == (char *) NULL)
12782         PUSHs(&sv_undef);
12783       else
12784         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
12785       if (magick_info->module == (char *) NULL)
12786         PUSHs(&sv_undef);
12787       else
12788         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
12789     }
12790
12791   PerlException:
12792     InheritPerlException(exception,perl_exception);
12793     exception=DestroyExceptionInfo(exception);
12794     SvREFCNT_dec(perl_exception);
12795   }
12796 \f
12797 #
12798 ###############################################################################
12799 #                                                                             #
12800 #                                                                             #
12801 #                                                                             #
12802 #   Q u e r y O p t i o n                                                     #
12803 #                                                                             #
12804 #                                                                             #
12805 #                                                                             #
12806 ###############################################################################
12807 #
12808 #
12809 void
12810 QueryOption(ref,...)
12811   Image::Magick ref=NO_INIT
12812   ALIAS:
12813     queryoption = 1
12814   PPCODE:
12815   {
12816     char
12817       **options;
12818
12819     ExceptionInfo
12820       *exception;
12821
12822     register ssize_t
12823       i;
12824
12825     ssize_t
12826       j,
12827       option;
12828
12829     SV
12830       *perl_exception;
12831
12832     PERL_UNUSED_VAR(ref);
12833     PERL_UNUSED_VAR(ix);
12834     exception=AcquireExceptionInfo();
12835     perl_exception=newSVpv("",0);
12836     EXTEND(sp,8*items);
12837     for (i=1; i < items; i++)
12838     {
12839       option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
12840         SvPV(ST(i),na));
12841       options=GetCommandOptions((CommandOption) option);
12842       if (options == (char **) NULL)
12843         PUSHs(&sv_undef);
12844       else
12845         {
12846           for (j=0; options[j] != (char *) NULL; j++)
12847             PUSHs(sv_2mortal(newSVpv(options[j],0)));
12848           options=DestroyStringList(options);
12849         }
12850     }
12851
12852     InheritPerlException(exception,perl_exception);
12853     exception=DestroyExceptionInfo(exception);
12854     SvREFCNT_dec(perl_exception);
12855   }
12856 \f
12857 #
12858 ###############################################################################
12859 #                                                                             #
12860 #                                                                             #
12861 #                                                                             #
12862 #   R e a d                                                                   #
12863 #                                                                             #
12864 #                                                                             #
12865 #                                                                             #
12866 ###############################################################################
12867 #
12868 #
12869 void
12870 Read(ref,...)
12871   Image::Magick ref=NO_INIT
12872   ALIAS:
12873     ReadImage  = 1
12874     read       = 2
12875     readimage  = 3
12876   PPCODE:
12877   {
12878     AV
12879       *av;
12880
12881     char
12882       **keep,
12883       **list;
12884
12885     ExceptionInfo
12886       *exception;
12887
12888     HV
12889       *hv;
12890
12891     Image
12892       *image;
12893
12894     int
12895       n;
12896
12897     MagickBooleanType
12898       status;
12899
12900     register char
12901       **p;
12902
12903     register ssize_t
12904       i;
12905
12906     ssize_t
12907       ac,
12908       number_images;
12909
12910     STRLEN
12911       *length;
12912
12913     struct PackageInfo
12914       *info,
12915       *package_info;
12916
12917     SV
12918       *perl_exception,  /* Perl variable for storing messages */
12919       *reference,
12920       *rv,
12921       *sv;
12922
12923     PERL_UNUSED_VAR(ref);
12924     PERL_UNUSED_VAR(ix);
12925     exception=AcquireExceptionInfo();
12926     perl_exception=newSVpv("",0);
12927     sv=NULL;
12928     package_info=(struct PackageInfo *) NULL;
12929     number_images=0;
12930     ac=(items < 2) ? 1 : items-1;
12931     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
12932     keep=list;
12933     length=(STRLEN *) NULL;
12934     if (list == (char **) NULL)
12935       {
12936         ThrowPerlException(exception,ResourceLimitError,
12937           "MemoryAllocationFailed",PackageName);
12938         goto PerlException;
12939       }
12940     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
12941     if (length == (STRLEN *) NULL)
12942       {
12943         ThrowPerlException(exception,ResourceLimitError,
12944           "MemoryAllocationFailed",PackageName);
12945         goto PerlException;
12946       }
12947     if (sv_isobject(ST(0)) == 0)
12948       {
12949         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12950           PackageName);
12951         goto PerlException;
12952       }
12953     reference=SvRV(ST(0));
12954     hv=SvSTASH(reference);
12955     if (SvTYPE(reference) != SVt_PVAV)
12956       {
12957         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12958           PackageName);
12959         goto PerlException;
12960       }
12961     av=(AV *) reference;
12962     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12963       exception);
12964     package_info=ClonePackageInfo(info,exception);
12965     n=1;
12966     if (items <= 1)
12967       *list=(char *) (*package_info->image_info->filename ?
12968         package_info->image_info->filename : "XC:black");
12969     else
12970       for (n=0, i=0; i < ac; i++)
12971       {
12972         list[n]=(char *) SvPV(ST(i+1),length[n]);
12973         if ((items >= 3) && strEQcase(list[n],"blob"))
12974           {
12975             void
12976               *blob;
12977
12978             i++;
12979             blob=(void *) (SvPV(ST(i+1),length[n]));
12980             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
12981           }
12982         if ((items >= 3) && strEQcase(list[n],"filename"))
12983           continue;
12984         if ((items >= 3) && strEQcase(list[n],"file"))
12985           {
12986             FILE
12987               *file;
12988
12989             PerlIO
12990               *io_info;
12991
12992             i++;
12993             io_info=IoIFP(sv_2io(ST(i+1)));
12994             if (io_info == (PerlIO *) NULL)
12995               {
12996                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12997                   PackageName);
12998                 continue;
12999               }
13000             file=PerlIO_findFILE(io_info);
13001             if (file == (FILE *) NULL)
13002               {
13003                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13004                   PackageName);
13005                 continue;
13006               }
13007             SetImageInfoFile(package_info->image_info,file);
13008           }
13009         if ((items >= 3) && strEQcase(list[n],"magick"))
13010           continue;
13011         n++;
13012       }
13013     list[n]=(char *) NULL;
13014     keep=list;
13015     status=ExpandFilenames(&n,&list);
13016     if (status == MagickFalse)
13017       {
13018         ThrowPerlException(exception,ResourceLimitError,
13019           "MemoryAllocationFailed",PackageName);
13020         goto PerlException;
13021       }
13022     number_images=0;
13023     for (i=0; i < n; i++)
13024     {
13025       if ((package_info->image_info->file != (FILE *) NULL) ||
13026           (package_info->image_info->blob != (void *) NULL))
13027         {
13028           image=ReadImages(package_info->image_info,exception);
13029           if (image != (Image *) NULL)
13030             DisassociateImageStream(image);
13031         }
13032       else
13033         {
13034           (void) CopyMagickString(package_info->image_info->filename,list[i],
13035             MaxTextExtent);
13036           image=ReadImages(package_info->image_info,exception);
13037         }
13038       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
13039         break;
13040       for ( ; image; image=image->next)
13041       {
13042         AddImageToRegistry(sv,image);
13043         rv=newRV(sv);
13044         av_push(av,sv_bless(rv,hv));
13045         SvREFCNT_dec(sv);
13046         number_images++;
13047       }
13048     }
13049     /*
13050       Free resources.
13051     */
13052     for (i=0; i < n; i++)
13053       if (list[i] != (char *) NULL)
13054         for (p=keep; list[i] != *p++; )
13055           if (*p == (char *) NULL)
13056             {
13057               list[i]=(char *) RelinquishMagickMemory(list[i]);
13058               break;
13059             }
13060
13061   PerlException:
13062     if (package_info != (struct PackageInfo *) NULL)
13063       DestroyPackageInfo(package_info);
13064     if (list && (list != keep))
13065       list=(char **) RelinquishMagickMemory(list);
13066     if (keep)
13067       keep=(char **) RelinquishMagickMemory(keep);
13068     if (length)
13069       length=(STRLEN *) RelinquishMagickMemory(length);
13070     InheritPerlException(exception,perl_exception);
13071     exception=DestroyExceptionInfo(exception);
13072     sv_setiv(perl_exception,(IV) number_images);
13073     SvPOK_on(perl_exception);
13074     ST(0)=sv_2mortal(perl_exception);
13075     XSRETURN(1);
13076   }
13077 \f
13078 #
13079 ###############################################################################
13080 #                                                                             #
13081 #                                                                             #
13082 #                                                                             #
13083 #   R e m o t e                                                               #
13084 #                                                                             #
13085 #                                                                             #
13086 #                                                                             #
13087 ###############################################################################
13088 #
13089 #
13090 void
13091 Remote(ref,...)
13092   Image::Magick ref=NO_INIT
13093   ALIAS:
13094     RemoteCommand  = 1
13095     remote         = 2
13096     remoteCommand  = 3
13097   PPCODE:
13098   {
13099     AV
13100       *av;
13101
13102     ExceptionInfo
13103       *exception;
13104
13105     register ssize_t
13106       i;
13107
13108     SV
13109       *perl_exception,
13110       *reference;
13111
13112     struct PackageInfo
13113       *info;
13114
13115     PERL_UNUSED_VAR(ref);
13116     PERL_UNUSED_VAR(ix);
13117     exception=AcquireExceptionInfo();
13118     perl_exception=newSVpv("",0);
13119     reference=SvRV(ST(0));
13120     av=(AV *) reference;
13121     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13122       exception);
13123     for (i=1; i < items; i++)
13124       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13125         SvPV(ST(i),na),exception);
13126     InheritPerlException(exception,perl_exception);
13127     exception=DestroyExceptionInfo(exception);
13128     SvREFCNT_dec(perl_exception);    /* throw away all errors */
13129   }
13130 \f
13131 #
13132 ###############################################################################
13133 #                                                                             #
13134 #                                                                             #
13135 #                                                                             #
13136 #   S e t                                                                     #
13137 #                                                                             #
13138 #                                                                             #
13139 #                                                                             #
13140 ###############################################################################
13141 #
13142 #
13143 void
13144 Set(ref,...)
13145   Image::Magick ref=NO_INIT
13146   ALIAS:
13147     SetAttributes  = 1
13148     SetAttribute   = 2
13149     set            = 3
13150     setattributes  = 4
13151     setattribute   = 5
13152   PPCODE:
13153   {
13154     ExceptionInfo
13155       *exception;
13156
13157     Image
13158       *image;
13159
13160     register ssize_t
13161       i;
13162
13163     struct PackageInfo
13164       *info;
13165
13166     SV
13167       *perl_exception,
13168       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13169
13170     PERL_UNUSED_VAR(ref);
13171     PERL_UNUSED_VAR(ix);
13172     exception=AcquireExceptionInfo();
13173     perl_exception=newSVpv("",0);
13174     if (sv_isobject(ST(0)) == 0)
13175       {
13176         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13177           PackageName);
13178         goto PerlException;
13179       }
13180     reference=SvRV(ST(0));
13181     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13182     if (items == 2)
13183       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13184     else
13185       for (i=2; i < items; i+=2)
13186         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13187
13188   PerlException:
13189     InheritPerlException(exception,perl_exception);
13190     exception=DestroyExceptionInfo(exception);
13191     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13192     SvPOK_on(perl_exception);
13193     ST(0)=sv_2mortal(perl_exception);
13194     XSRETURN(1);
13195   }
13196 \f
13197 #
13198 ###############################################################################
13199 #                                                                             #
13200 #                                                                             #
13201 #                                                                             #
13202 #   S e t P i x e l                                                           #
13203 #                                                                             #
13204 #                                                                             #
13205 #                                                                             #
13206 ###############################################################################
13207 #
13208 #
13209 void
13210 SetPixel(ref,...)
13211   Image::Magick ref=NO_INIT
13212   ALIAS:
13213     setpixel = 1
13214     setPixel = 2
13215   PPCODE:
13216   {
13217     AV
13218       *av;
13219
13220     char
13221       *attribute;
13222
13223     ChannelType
13224       channel;
13225
13226     ExceptionInfo
13227       *exception;
13228
13229     Image
13230       *image;
13231
13232     MagickBooleanType
13233       normalize;
13234
13235     RectangleInfo
13236       region;
13237
13238     register ssize_t
13239       i;
13240
13241     register Quantum
13242       *q;
13243
13244     ssize_t
13245       option;
13246
13247     struct PackageInfo
13248       *info;
13249
13250     SV
13251       *perl_exception,
13252       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13253
13254     PERL_UNUSED_VAR(ref);
13255     PERL_UNUSED_VAR(ix);
13256     exception=AcquireExceptionInfo();
13257     perl_exception=newSVpv("",0);
13258     reference=SvRV(ST(0));
13259     av=(AV *) reference;
13260     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13261       exception);
13262     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13263     if (image == (Image *) NULL)
13264       {
13265         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13266           PackageName);
13267         goto PerlException;
13268       }
13269     av=(AV *) NULL;
13270     normalize=MagickTrue;
13271     region.x=0;
13272     region.y=0;
13273     region.width=image->columns;
13274     region.height=1;
13275     if (items == 1)
13276       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13277     channel=DefaultChannels;
13278     for (i=2; i < items; i+=2)
13279     {
13280       attribute=(char *) SvPV(ST(i-1),na);
13281       switch (*attribute)
13282       {
13283         case 'C':
13284         case 'c':
13285         {
13286           if (LocaleCompare(attribute,"channel") == 0)
13287             {
13288               ssize_t
13289                 option;
13290
13291               option=ParseChannelOption(SvPV(ST(i),na));
13292               if (option < 0)
13293                 {
13294                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13295                     SvPV(ST(i),na));
13296                   return;
13297                 }
13298               channel=(ChannelType) option;
13299               break;
13300             }
13301           if (LocaleCompare(attribute,"color") == 0)
13302             {
13303               if (SvTYPE(ST(i)) != SVt_RV)
13304                 {
13305                   char
13306                     message[MaxTextExtent];
13307
13308                   (void) FormatLocaleString(message,MaxTextExtent,
13309                     "invalid %.60s value",attribute);
13310                   ThrowPerlException(exception,OptionError,message,
13311                     SvPV(ST(i),na));
13312                 }
13313               av=(AV *) SvRV(ST(i));
13314               break;
13315             }
13316           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13317             attribute);
13318           break;
13319         }
13320         case 'g':
13321         case 'G':
13322         {
13323           if (LocaleCompare(attribute,"geometry") == 0)
13324             {
13325               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
13326               break;
13327             }
13328           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13329             attribute);
13330           break;
13331         }
13332         case 'N':
13333         case 'n':
13334         {
13335           if (LocaleCompare(attribute,"normalize") == 0)
13336             {
13337               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13338                 SvPV(ST(i),na));
13339               if (option < 0)
13340                 {
13341                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13342                     SvPV(ST(i),na));
13343                   break;
13344                 }
13345              normalize=option != 0 ? MagickTrue : MagickFalse;
13346              break;
13347             }
13348           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13349             attribute);
13350           break;
13351         }
13352         case 'x':
13353         case 'X':
13354         {
13355           if (LocaleCompare(attribute,"x") == 0)
13356             {
13357               region.x=SvIV(ST(i));
13358               break;
13359             }
13360           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13361             attribute);
13362           break;
13363         }
13364         case 'y':
13365         case 'Y':
13366         {
13367           if (LocaleCompare(attribute,"y") == 0)
13368             {
13369               region.y=SvIV(ST(i));
13370               break;
13371             }
13372           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13373             attribute);
13374           break;
13375         }
13376         default:
13377         {
13378           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13379             attribute);
13380           break;
13381         }
13382       }
13383     }
13384     (void) SetImageStorageClass(image,DirectClass);
13385     PushPixelComponentMap(image,channel);
13386     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
13387     if ((q == (const Quantum *) NULL) || (av == (AV *) NULL) ||
13388         (SvTYPE(av) != SVt_PVAV))
13389       PUSHs(&sv_undef);
13390     else
13391       {
13392         double
13393           scale;
13394
13395         register ssize_t
13396           i;
13397
13398         i=0;
13399         scale=1.0;
13400         if (normalize != MagickFalse)
13401           scale=QuantumRange;
13402         if (((GetPixelRedTraits(image) & ActivePixelTrait) != 0) &&
13403             (i <= av_len(av)))
13404           {
13405             SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
13406               av_fetch(av,i,0)))),q);
13407             i++;
13408           }
13409         if (((GetPixelGreenTraits(image) & ActivePixelTrait) != 0) &&
13410             (i <= av_len(av)))
13411           {
13412             SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
13413               av_fetch(av,i,0)))),q);
13414             i++;
13415           }
13416         if (((GetPixelBlueTraits(image) & ActivePixelTrait) != 0) &&
13417             (i <= av_len(av)))
13418           {
13419             SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
13420               av_fetch(av,i,0)))),q);
13421             i++;
13422           }
13423         if ((((GetPixelBlackTraits(image) & ActivePixelTrait) != 0) &&
13424             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
13425           {
13426             SetPixelBlack(image,ClampToQuantum(scale*
13427               SvNV(*(av_fetch(av,i,0)))),q);
13428             i++;
13429           }
13430         if (((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0) &&
13431             (i <= av_len(av)))
13432           {
13433             SetPixelAlpha(image,ClampToQuantum(scale*
13434               SvNV(*(av_fetch(av,i,0)))),q);
13435             i++;
13436           }
13437         (void) SyncAuthenticPixels(image,exception);
13438       }
13439     PopPixelComponentMap(image);
13440
13441   PerlException:
13442     InheritPerlException(exception,perl_exception);
13443     exception=DestroyExceptionInfo(exception);
13444     SvREFCNT_dec(perl_exception);
13445   }
13446 \f
13447 #
13448 ###############################################################################
13449 #                                                                             #
13450 #                                                                             #
13451 #                                                                             #
13452 #   S m u s h                                                                 #
13453 #                                                                             #
13454 #                                                                             #
13455 #                                                                             #
13456 ###############################################################################
13457 #
13458 #
13459 void
13460 Smush(ref,...)
13461   Image::Magick ref=NO_INIT
13462   ALIAS:
13463     SmushImage  = 1
13464     smush       = 2
13465     smushimage  = 3
13466   PPCODE:
13467   {
13468     AV
13469       *av;
13470
13471     char
13472       *attribute;
13473
13474     ExceptionInfo
13475       *exception;
13476
13477     HV
13478       *hv;
13479
13480     Image
13481       *image;
13482
13483     register ssize_t
13484       i;
13485
13486     ssize_t
13487       offset,
13488       stack;
13489
13490     struct PackageInfo
13491       *info;
13492
13493     SV
13494       *av_reference,
13495       *perl_exception,
13496       *reference,
13497       *rv,
13498       *sv;
13499
13500     PERL_UNUSED_VAR(ref);
13501     PERL_UNUSED_VAR(ix);
13502     exception=AcquireExceptionInfo();
13503     perl_exception=newSVpv("",0);
13504     sv=NULL;
13505     attribute=NULL;
13506     av=NULL;
13507     if (sv_isobject(ST(0)) == 0)
13508       {
13509         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13510           PackageName);
13511         goto PerlException;
13512       }
13513     reference=SvRV(ST(0));
13514     hv=SvSTASH(reference);
13515     av=newAV();
13516     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13517     SvREFCNT_dec(av);
13518     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13519     if (image == (Image *) NULL)
13520       {
13521         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13522           PackageName);
13523         goto PerlException;
13524       }
13525     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13526     /*
13527       Get options.
13528     */
13529     offset=0;
13530     stack=MagickTrue;
13531     for (i=2; i < items; i+=2)
13532     {
13533       attribute=(char *) SvPV(ST(i-1),na);
13534       switch (*attribute)
13535       {
13536         case 'O':
13537         case 'o':
13538         {
13539           if (LocaleCompare(attribute,"offset") == 0)
13540             {
13541               offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
13542               break;
13543             }
13544           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13545             attribute);
13546           break;
13547         }
13548         case 'S':
13549         case 's':
13550         {
13551           if (LocaleCompare(attribute,"stack") == 0)
13552             {
13553               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13554                 SvPV(ST(i),na));
13555               if (stack < 0)
13556                 {
13557                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13558                     SvPV(ST(i),na));
13559                   return;
13560                 }
13561               break;
13562             }
13563           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13564             attribute);
13565           break;
13566         }
13567         default:
13568         {
13569           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13570             attribute);
13571           break;
13572         }
13573       }
13574     }
13575     image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
13576       exception);
13577     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
13578       goto PerlException;
13579     for ( ; image; image=image->next)
13580     {
13581       AddImageToRegistry(sv,image);
13582       rv=newRV(sv);
13583       av_push(av,sv_bless(rv,hv));
13584       SvREFCNT_dec(sv);
13585     }
13586     exception=DestroyExceptionInfo(exception);
13587     ST(0)=av_reference;
13588     SvREFCNT_dec(perl_exception);
13589     XSRETURN(1);
13590
13591   PerlException:
13592     InheritPerlException(exception,perl_exception);
13593     exception=DestroyExceptionInfo(exception);
13594     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
13595     SvPOK_on(perl_exception);
13596     ST(0)=sv_2mortal(perl_exception);
13597     XSRETURN(1);
13598   }
13599 \f
13600 #
13601 ###############################################################################
13602 #                                                                             #
13603 #                                                                             #
13604 #                                                                             #
13605 #   S t a t i s t i c s                                                       #
13606 #                                                                             #
13607 #                                                                             #
13608 #                                                                             #
13609 ###############################################################################
13610 #
13611 #
13612 void
13613 Statistics(ref,...)
13614   Image::Magick ref=NO_INIT
13615   ALIAS:
13616     StatisticsImage = 1
13617     statistics      = 2
13618     statisticsimage = 3
13619   PPCODE:
13620   {
13621 #define ChannelStatistics(channel) \
13622 { \
13623   (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
13624     (double) channel_statistics[channel].depth); \
13625   PUSHs(sv_2mortal(newSVpv(message,0))); \
13626   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13627     channel_statistics[channel].minima/scale); \
13628   PUSHs(sv_2mortal(newSVpv(message,0))); \
13629   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13630     channel_statistics[channel].maxima/scale); \
13631   PUSHs(sv_2mortal(newSVpv(message,0))); \
13632   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13633     channel_statistics[channel].mean/scale); \
13634   PUSHs(sv_2mortal(newSVpv(message,0))); \
13635   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13636     channel_statistics[channel].standard_deviation/scale); \
13637   PUSHs(sv_2mortal(newSVpv(message,0))); \
13638   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13639     channel_statistics[channel].kurtosis); \
13640   PUSHs(sv_2mortal(newSVpv(message,0))); \
13641   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13642     channel_statistics[channel].skewness); \
13643   PUSHs(sv_2mortal(newSVpv(message,0))); \
13644 }
13645
13646     AV
13647       *av;
13648
13649     char
13650       message[MaxTextExtent];
13651
13652     ChannelStatistics
13653       *channel_statistics;
13654
13655     double
13656       scale;
13657
13658     ExceptionInfo
13659       *exception;
13660
13661     Image
13662       *image;
13663
13664     ssize_t
13665       count;
13666
13667     struct PackageInfo
13668       *info;
13669
13670     SV
13671       *perl_exception,
13672       *reference;
13673
13674     PERL_UNUSED_VAR(ref);
13675     PERL_UNUSED_VAR(ix);
13676     exception=AcquireExceptionInfo();
13677     perl_exception=newSVpv("",0);
13678     av=NULL;
13679     if (sv_isobject(ST(0)) == 0)
13680       {
13681         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13682           PackageName);
13683         goto PerlException;
13684       }
13685     reference=SvRV(ST(0));
13686     av=newAV();
13687     SvREFCNT_dec(av);
13688     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13689     if (image == (Image *) NULL)
13690       {
13691         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13692           PackageName);
13693         goto PerlException;
13694       }
13695     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13696     count=0;
13697     for ( ; image; image=image->next)
13698     {
13699       channel_statistics=GetImageStatistics(image,&image->exception);
13700       if (channel_statistics == (ChannelStatistics *) NULL)
13701         continue;
13702       count++;
13703       EXTEND(sp,35*count);
13704       scale=(double) QuantumRange;
13705       ChannelStatistics(RedChannel);
13706       ChannelStatistics(GreenChannel);
13707       ChannelStatistics(BlueChannel);
13708       if (image->colorspace == CMYKColorspace)
13709         ChannelStatistics(BlackChannel);
13710       if (image->matte != MagickFalse)
13711         ChannelStatistics(AlphaChannel);
13712       channel_statistics=(ChannelStatistics *)
13713         RelinquishMagickMemory(channel_statistics);
13714     }
13715
13716   PerlException:
13717     InheritPerlException(exception,perl_exception);
13718     exception=DestroyExceptionInfo(exception);
13719     SvREFCNT_dec(perl_exception);
13720   }
13721 \f
13722 #
13723 ###############################################################################
13724 #                                                                             #
13725 #                                                                             #
13726 #                                                                             #
13727 #   S y n c A u t h e n t i c P i x e l s                                     #
13728 #                                                                             #
13729 #                                                                             #
13730 #                                                                             #
13731 ###############################################################################
13732 #
13733 #
13734 void
13735 SyncAuthenticPixels(ref,...)
13736   Image::Magick ref = NO_INIT
13737   ALIAS:
13738     Syncauthenticpixels = 1
13739     SyncImagePixels = 2
13740     syncimagepixels = 3
13741   CODE:
13742   {
13743     ExceptionInfo
13744       *exception;
13745
13746     Image
13747       *image;
13748
13749     MagickBooleanType
13750       status;
13751
13752     struct PackageInfo
13753       *info;
13754
13755     SV
13756       *perl_exception,
13757       *reference;
13758
13759     PERL_UNUSED_VAR(ref);
13760     PERL_UNUSED_VAR(ix);
13761     exception=AcquireExceptionInfo();
13762     perl_exception=newSVpv("",0);
13763     if (sv_isobject(ST(0)) == 0)
13764       {
13765         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13766           PackageName);
13767         goto PerlException;
13768       }
13769
13770     reference=SvRV(ST(0));
13771     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13772     if (image == (Image *) NULL)
13773       {
13774         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13775           PackageName);
13776         goto PerlException;
13777       }
13778
13779     status=SyncAuthenticPixels(image,exception);
13780     if (status != MagickFalse)
13781       return;
13782     InheritException(exception,&image->exception);
13783
13784   PerlException:
13785     InheritPerlException(exception,perl_exception);
13786     exception=DestroyExceptionInfo(exception);
13787     SvREFCNT_dec(perl_exception);  /* throw away all errors */
13788   }
13789 \f
13790 #
13791 ###############################################################################
13792 #                                                                             #
13793 #                                                                             #
13794 #                                                                             #
13795 #   T r a n s f o r m                                                         #
13796 #                                                                             #
13797 #                                                                             #
13798 #                                                                             #
13799 ###############################################################################
13800 #
13801 #
13802 void
13803 Transform(ref,...)
13804   Image::Magick ref=NO_INIT
13805   ALIAS:
13806     TransformImage = 1
13807     transform      = 2
13808     transformimage = 3
13809   PPCODE:
13810   {
13811     AV
13812       *av;
13813
13814     char
13815       *attribute,
13816       *crop_geometry,
13817       *geometry;
13818
13819     ExceptionInfo
13820       *exception;
13821
13822     HV
13823       *hv;
13824
13825     Image
13826       *clone,
13827       *image;
13828
13829     register ssize_t
13830       i;
13831
13832     struct PackageInfo
13833       *info;
13834
13835     SV
13836       *av_reference,
13837       *perl_exception,
13838       *reference,
13839       *rv,
13840       *sv;
13841
13842     PERL_UNUSED_VAR(ref);
13843     PERL_UNUSED_VAR(ix);
13844     exception=AcquireExceptionInfo();
13845     perl_exception=newSVpv("",0);
13846     sv=NULL;
13847     av=NULL;
13848     attribute=NULL;
13849     if (sv_isobject(ST(0)) == 0)
13850       {
13851         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13852           PackageName);
13853         goto PerlException;
13854       }
13855     reference=SvRV(ST(0));
13856     hv=SvSTASH(reference);
13857     av=newAV();
13858     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13859     SvREFCNT_dec(av);
13860     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13861     if (image == (Image *) NULL)
13862       {
13863         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13864           PackageName);
13865         goto PerlException;
13866       }
13867     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13868     /*
13869       Get attribute.
13870     */
13871     crop_geometry=(char *) NULL;
13872     geometry=(char *) NULL;
13873     for (i=2; i < items; i+=2)
13874     {
13875       attribute=(char *) SvPV(ST(i-1),na);
13876       switch (*attribute)
13877       {
13878         case 'c':
13879         case 'C':
13880         {
13881           if (LocaleCompare(attribute,"crop") == 0)
13882             {
13883               crop_geometry=SvPV(ST(i),na);
13884               break;
13885             }
13886           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13887             attribute);
13888           break;
13889         }
13890         case 'g':
13891         case 'G':
13892         {
13893           if (LocaleCompare(attribute,"geometry") == 0)
13894             {
13895               geometry=SvPV(ST(i),na);
13896               break;
13897             }
13898          if (LocaleCompare(attribute,"gravity") == 0)
13899            {
13900              Image
13901                *next;
13902
13903              ssize_t
13904                in;
13905
13906              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
13907                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13908              if (in < 0)
13909                {
13910                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
13911                    SvPV(ST(i),na));
13912                  return;
13913                }
13914              for (next=image; next; next=next->next)
13915                next->gravity=(GravityType) in;
13916              break;
13917            }
13918           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13919             attribute);
13920           break;
13921         }
13922         default:
13923         {
13924           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13925             attribute);
13926           break;
13927         }
13928       }
13929     }
13930     for ( ; image; image=image->next)
13931     {
13932       clone=CloneImage(image,0,0,MagickTrue,exception);
13933       if ((clone == (Image *) NULL) || (exception->severity >= ErrorException))
13934         goto PerlException;
13935       TransformImage(&clone,crop_geometry,geometry);
13936       for ( ; clone; clone=clone->next)
13937       {
13938         AddImageToRegistry(sv,clone);
13939         rv=newRV(sv);
13940         av_push(av,sv_bless(rv,hv));
13941         SvREFCNT_dec(sv);
13942       }
13943     }
13944     exception=DestroyExceptionInfo(exception);
13945     ST(0)=av_reference;
13946     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13947     XSRETURN(1);
13948
13949   PerlException:
13950     InheritPerlException(exception,perl_exception);
13951     exception=DestroyExceptionInfo(exception);
13952     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
13953     SvPOK_on(perl_exception);
13954     ST(0)=sv_2mortal(perl_exception);
13955     XSRETURN(1);
13956   }
13957 \f
13958 #
13959 ###############################################################################
13960 #                                                                             #
13961 #                                                                             #
13962 #                                                                             #
13963 #   W r i t e                                                                 #
13964 #                                                                             #
13965 #                                                                             #
13966 #                                                                             #
13967 ###############################################################################
13968 #
13969 #
13970 void
13971 Write(ref,...)
13972   Image::Magick ref=NO_INIT
13973   ALIAS:
13974     WriteImage    = 1
13975     write         = 2
13976     writeimage    = 3
13977   PPCODE:
13978   {
13979     char
13980       filename[MaxTextExtent];
13981
13982     ExceptionInfo
13983       *exception;
13984
13985     Image
13986       *image,
13987       *next;
13988
13989     register ssize_t
13990       i;
13991
13992     ssize_t
13993       number_images,
13994       scene;
13995
13996     struct PackageInfo
13997       *info,
13998       *package_info;
13999
14000     SV
14001       *perl_exception,
14002       *reference;
14003
14004     PERL_UNUSED_VAR(ref);
14005     PERL_UNUSED_VAR(ix);
14006     exception=AcquireExceptionInfo();
14007     perl_exception=newSVpv("",0);
14008     number_images=0;
14009     package_info=(struct PackageInfo *) NULL;
14010     if (sv_isobject(ST(0)) == 0)
14011       {
14012         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14013           PackageName);
14014         goto PerlException;
14015       }
14016     reference=SvRV(ST(0));
14017     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14018     if (image == (Image *) NULL)
14019       {
14020         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14021           PackageName);
14022         goto PerlException;
14023       }
14024     package_info=ClonePackageInfo(info,exception);
14025     if (items == 2)
14026       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14027     else
14028       if (items > 2)
14029         for (i=2; i < items; i+=2)
14030           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14031             exception);
14032     (void) CopyMagickString(filename,package_info->image_info->filename,
14033       MaxTextExtent);
14034     scene=0;
14035     for (next=image; next; next=next->next)
14036     {
14037       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
14038       next->scene=scene++;
14039     }
14040     SetImageInfo(package_info->image_info,(unsigned int)
14041       GetImageListLength(image),&image->exception);
14042     for (next=image; next; next=next->next)
14043     {
14044       (void) WriteImage(package_info->image_info,next);
14045       if (next->exception.severity >= ErrorException)
14046         InheritException(exception,&next->exception);
14047       GetImageException(next,exception);
14048       number_images++;
14049       if (package_info->image_info->adjoin)
14050         break;
14051     }
14052
14053   PerlException:
14054     if (package_info != (struct PackageInfo *) NULL)
14055       DestroyPackageInfo(package_info);
14056     InheritPerlException(exception,perl_exception);
14057     exception=DestroyExceptionInfo(exception);
14058     sv_setiv(perl_exception,(IV) number_images);
14059     SvPOK_on(perl_exception);
14060     ST(0)=sv_2mortal(perl_exception);
14061     XSRETURN(1);
14062   }