]> granicus.if.org Git - imagemagick/blob - PerlMagick/Magick.xs
(no commit message)
[imagemagick] / PerlMagick / Magick.xs
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                         PPPP   EEEEE  RRRR   L                              %
6 %                         P   P  E      R   R  L                              %
7 %                         PPPP   EEE    RRRR   L                              %
8 %                         P      E      R  R   L                              %
9 %                         P      EEEEE  R   R  LLLLL                          %
10 %                                                                             %
11 %                  M   M   AAA    GGGG  IIIII   CCCC  K   K                   %
12 %                  MM MM  A   A  G        I    C      K  K                    %
13 %                  M M M  AAAAA  G GGG    I    C      KKK                     %
14 %                  M   M  A   A  G   G    I    C      K  K                    %
15 %                  M   M  A   A   GGGG  IIIII   CCCC  K   K                   %
16 %                                                                             %
17 %                                                                             %
18 %                Object-oriented Perl interface to ImageMagick                %
19 %                                                                             %
20 %                            Software Design                                  %
21 %                              Kyle Shorter                                   %
22 %                              John Cristy                                    %
23 %                             February 1997                                   %
24 %                                                                             %
25 %                                                                             %
26 %  Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization      %
27 %  dedicated to making software imaging solutions freely available.           %
28 %                                                                             %
29 %  You may not use this file except in compliance with the License.  You may  %
30 %  obtain a copy of the License at                                            %
31 %                                                                             %
32 %    http://www.imagemagick.org/script/license.php                            %
33 %                                                                             %
34 %  Unless required by applicable law or agreed to in writing, software        %
35 %  distributed under the License is distributed on an "AS IS" BASIS,          %
36 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
37 %  See the License for the specific language governing permissions and        %
38 %  limitations under the License.                                             %
39 %                                                                             %
40 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
41 %
42 %  PerlMagick is an objected-oriented Perl interface to ImageMagick.  Use
43 %  the module to read, manipulate, or write an image or image sequence from
44 %  within a Perl script.  This makes PerlMagick suitable for Web CGI scripts.
45 %
46 */
47 \f
48 /*
49   Include declarations.
50 */
51 #if !defined(WIN32)
52 #define MagickExport
53 #endif
54
55 #if defined(__cplusplus) || defined(c_plusplus)
56 extern "C" {
57 #endif
58
59 #define PERL_NO_GET_CONTEXT
60 #include "EXTERN.h"
61 #include "perl.h"
62 #include "XSUB.h"
63 #include <math.h>
64 #include <MagickCore/MagickCore.h>
65 #undef tainted
66
67 #if defined(__cplusplus) || defined(c_plusplus)
68 }
69 #endif
70 \f
71 /*
72   Define declarations.
73 */
74 #ifndef aTHX_
75 #define aTHX_
76 #define pTHX_
77 #define dTHX
78 #endif
79 #define DegreesToRadians(x)  (MagickPI*(x)/180.0)
80 #define EndOf(array)  (&array[NumberOf(array)])
81 #define MaxArguments  33
82 #ifndef na
83 #define na  PL_na
84 #endif
85 #define NumberOf(array)  (sizeof(array)/sizeof(*array))
86 #define PackageName   "Image::Magick"
87 #if PERL_VERSION <= 6
88 #define PerlIO  FILE
89 #define PerlIO_importFILE(f, fl)  (f)
90 #define PerlIO_findFILE(f)  NULL
91 #endif
92 #ifndef sv_undef
93 #define sv_undef  PL_sv_undef
94 #endif
95
96 #define AddImageToRegistry(sv,image) \
97 { \
98   if (magick_registry != (SplayTreeInfo *) NULL) \
99     { \
100       (void) AddValueToSplayTree(magick_registry,image,image); \
101       (sv)=newSViv((IV) image); \
102     } \
103 }
104
105 #define DeleteImageFromRegistry(reference,image) \
106 { \
107   if (magick_registry != (SplayTreeInfo *) NULL) \
108     { \
109       if (GetImageReferenceCount(image) == 1) \
110        (void) DeleteNodeByValueFromSplayTree(magick_registry,image); \
111       image=DestroyImage(image); \
112       sv_setiv(reference,0); \
113     } \
114 }
115
116 #define InheritPerlException(exception,perl_exception) \
117 { \
118   char \
119     message[MaxTextExtent]; \
120  \
121   if ((exception)->severity != UndefinedException) \
122     { \
123       (void) FormatLocaleString(message,MaxTextExtent,"Exception %d: %s%s%s%s",\
124         (exception)->severity, (exception)->reason ? \
125         GetLocaleExceptionMessage((exception)->severity,(exception)->reason) : \
126         "Unknown", (exception)->description ? " (" : "", \
127         (exception)->description ? GetLocaleExceptionMessage( \
128         (exception)->severity,(exception)->description) : "", \
129         (exception)->description ? ")" : ""); \
130       if ((perl_exception) != (SV *) NULL) \
131         { \
132           if (SvCUR(perl_exception)) \
133             sv_catpv(perl_exception,"\n"); \
134           sv_catpv(perl_exception,message); \
135         } \
136     } \
137 }
138
139 #define ThrowPerlException(exception,severity,tag,reason) \
140   (void) ThrowMagickException(exception,GetMagickModule(),severity, \
141     tag,"`%s'",reason); \
142 \f
143 /*
144   Typedef and structure declarations.
145 */
146 typedef enum
147 {
148   ArrayReference = (~0),
149   RealReference = (~0)-1,
150   FileReference = (~0)-2,
151   ImageReference = (~0)-3,
152   IntegerReference = (~0)-4,
153   StringReference = (~0)-5
154 } MagickReference;
155
156 typedef struct _Arguments
157 {
158   const char
159     *method;
160
161   ssize_t
162     type;
163 } Arguments;
164
165 struct ArgumentList
166 {
167   ssize_t
168     integer_reference;
169
170   MagickRealType
171     real_reference;
172
173   const char
174     *string_reference;
175
176   Image
177     *image_reference;
178
179   SV
180     *array_reference;
181
182   FILE
183     *file_reference;
184
185   size_t
186     length;
187 };
188
189 struct PackageInfo
190 {
191   ImageInfo
192     *image_info;
193 };
194
195 typedef void
196   *Image__Magick;  /* data type for the Image::Magick package */
197 \f
198 /*
199   Static declarations.
200 */
201 static struct
202   Methods
203   {
204     const char
205       *name;
206
207     Arguments
208       arguments[MaxArguments];
209   } Methods[] =
210   {
211     { "Comment", { {"comment", StringReference} } },
212     { "Label", { {"label", StringReference} } },
213     { "AddNoise", { {"noise", MagickNoiseOptions},
214       {"channel", MagickChannelOptions} } },
215     { "Colorize", { {"fill", StringReference}, {"opacity", StringReference} } },
216     { "Border", { {"geometry", StringReference}, {"width", IntegerReference},
217       {"height", IntegerReference}, {"fill", StringReference},
218       {"bordercolor", StringReference}, {"color", StringReference},
219       {"compose", MagickComposeOptions} } },
220     { "Blur", { {"geometry", StringReference}, {"radius", RealReference},
221       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
222     { "Chop", { {"geometry", StringReference}, {"width", IntegerReference},
223       {"height", IntegerReference}, {"x", IntegerReference},
224       {"y", IntegerReference} } },
225     { "Crop", { {"geometry", StringReference}, {"width", IntegerReference},
226       {"height", IntegerReference}, {"x", IntegerReference},
227       {"y", IntegerReference}, {"fuzz", StringReference},
228       {"gravity", MagickGravityOptions} } },
229     { "Despeckle", },
230     { "Edge", { {"radius", RealReference} } },
231     { "Emboss", { {"geometry", StringReference}, {"radius", RealReference},
232       {"sigma", RealReference} } },
233     { "Enhance", },
234     { "Flip", },
235     { "Flop", },
236     { "Frame", { {"geometry", StringReference}, {"width", IntegerReference},
237       {"height", IntegerReference}, {"inner", IntegerReference},
238       {"outer", IntegerReference}, {"fill", StringReference},
239       {"color", StringReference}, {"compose", MagickComposeOptions} } },
240     { "Implode", { {"amount", RealReference},
241       {"interpolate", MagickInterpolateOptions} } },
242     { "Magnify", },
243     { "MedianFilter", { {"geometry", StringReference},
244       {"width", IntegerReference}, {"height", IntegerReference},
245       {"channel", MagickChannelOptions} } },
246     { "Minify", },
247     { "OilPaint", { {"radius", RealReference}, {"sigma", RealReference} } },
248     { "ReduceNoise", { {"geometry", StringReference},
249       {"width", IntegerReference},{"height", IntegerReference},
250       {"channel", MagickChannelOptions} } },
251     { "Roll", { {"geometry", StringReference}, {"x", IntegerReference},
252       {"y", IntegerReference} } },
253     { "Rotate", { {"degrees", RealReference}, {"fill", StringReference},
254       {"color", StringReference}, {"background", StringReference} } },
255     { "Sample", { {"geometry", StringReference}, {"width", IntegerReference},
256       {"height", IntegerReference} } },
257     { "Scale", { {"geometry", StringReference}, {"width", IntegerReference},
258       {"height", IntegerReference} } },
259     { "Shade", { {"geometry", StringReference}, {"azimuth", RealReference},
260       {"elevation", RealReference}, {"gray", MagickBooleanOptions} } },
261     { "Sharpen", { {"geometry", StringReference}, {"radius", RealReference},
262       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
263     { "Shear", { {"geometry", StringReference}, {"x", RealReference},
264       {"y", RealReference}, { "fill", StringReference},
265       {"color", StringReference} } },
266     { "Spread", { {"radius", RealReference} } },
267     { "Swirl", { {"degrees", RealReference},
268       {"interpolate", MagickInterpolateOptions} } },
269     { "Resize", { {"geometry", StringReference}, {"width", IntegerReference},
270       {"height", IntegerReference}, {"filter", MagickFilterOptions},
271       {"support", StringReference }, {"blur", RealReference } } },
272     { "Zoom", { {"geometry", StringReference}, {"width", IntegerReference},
273       {"height", IntegerReference}, {"filter", MagickFilterOptions},
274       {"support", RealReference }, {"blur", RealReference } } },
275     { "Annotate", { {"text", StringReference}, {"font", StringReference},
276       {"pointsize", RealReference}, {"density", StringReference},
277       {"undercolor", StringReference}, {"stroke", StringReference},
278       {"fill", StringReference}, {"geometry", StringReference},
279       {"pen", StringReference}, {"x", RealReference},
280       {"y", RealReference}, {"gravity", MagickGravityOptions},
281       {"translate", StringReference}, {"scale", StringReference},
282       {"rotate", RealReference}, {"skewX", RealReference},
283       {"skewY", RealReference}, {"strokewidth", RealReference},
284       {"antialias", MagickBooleanOptions}, {"family", StringReference},
285       {"style", MagickStyleOptions}, {"stretch", MagickStretchOptions},
286       {"weight", IntegerReference}, {"align", MagickAlignOptions},
287       {"encoding", StringReference}, {"affine", ArrayReference},
288       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
289       {"tile", ImageReference}, {"kerning", RealReference},
290       {"interline-spacing", RealReference},
291       {"interword-spacing", RealReference},
292       {"direction", MagickDirectionOptions} } },
293     { "ColorFloodfill", { {"geometry", StringReference},
294       {"x", IntegerReference}, {"y", IntegerReference},
295       {"fill", StringReference}, {"bordercolor", StringReference},
296       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
297     { "Composite", { {"image", ImageReference},
298       {"compose", MagickComposeOptions}, {"geometry", StringReference},
299       {"x", IntegerReference}, {"y", IntegerReference},
300       {"gravity", MagickGravityOptions}, {"opacity", StringReference},
301       {"tile", MagickBooleanOptions}, {"rotate", RealReference},
302       {"color", StringReference}, {"mask", ImageReference},
303       {"channel", MagickChannelOptions},
304       {"interpolate", MagickInterpolateOptions}, {"args", StringReference},
305       {"blend", StringReference} } },
306     { "Contrast", { {"sharpen", MagickBooleanOptions} } },
307     { "CycleColormap", { {"display", IntegerReference} } },
308     { "Draw", { {"primitive", MagickPrimitiveOptions},
309       {"points", StringReference}, {"method", MagickMethodOptions},
310       {"stroke", StringReference}, {"fill", StringReference},
311       {"strokewidth", RealReference}, {"font", StringReference},
312       {"bordercolor", StringReference}, {"x", RealReference},
313       {"y", RealReference}, {"translate", StringReference},
314       {"scale", StringReference}, {"rotate", RealReference},
315       {"skewX", RealReference}, {"skewY", RealReference},
316       {"tile", ImageReference}, {"pointsize", RealReference},
317       {"antialias", MagickBooleanOptions}, {"density", StringReference},
318       {"linewidth", RealReference}, {"affine", ArrayReference},
319       {"stroke-dashoffset", RealReference},
320       {"stroke-dasharray", ArrayReference},
321       {"interpolate", MagickInterpolateOptions},
322       {"origin", StringReference}, {"text", StringReference},
323       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
324       {"vector-graphics", StringReference}, {"kerning", RealReference},
325       {"interline-spacing", RealReference},
326       {"interword-spacing", RealReference},
327       {"direction", MagickDirectionOptions} } },
328     { "Equalize", { {"channel", MagickChannelOptions} } },
329     { "Gamma", { {"gamma", StringReference}, {"channel", MagickChannelOptions},
330       {"red", RealReference}, {"green", RealReference},
331       {"blue", RealReference} } },
332     { "Map", { {"image", ImageReference}, {"dither", MagickBooleanOptions},
333       {"dither-method", MagickDitherOptions} } },
334     { "MatteFloodfill", { {"geometry", StringReference},
335       {"x", IntegerReference}, {"y", IntegerReference},
336       {"opacity", StringReference}, {"bordercolor", StringReference},
337       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
338     { "Modulate", { {"factor", StringReference}, {"hue", RealReference},
339       {"saturation", RealReference}, {"whiteness", RealReference},
340       {"brightness", RealReference}, {"lightness", RealReference},
341       {"blackness", RealReference} } },
342     { "Negate", { {"gray", MagickBooleanOptions},
343       {"channel", MagickChannelOptions} } },
344     { "Normalize", { {"channel", MagickChannelOptions} } },
345     { "NumberColors", },
346     { "Opaque", { {"color", StringReference}, {"fill", StringReference},
347       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
348       {"invert", MagickBooleanOptions} } },
349     { "Quantize", { {"colors", IntegerReference},
350       {"treedepth", IntegerReference}, {"colorspace", MagickColorspaceOptions},
351       {"dither", MagickBooleanOptions}, {"measure", MagickBooleanOptions},
352       {"global", MagickBooleanOptions}, {"transparent-color", StringReference},
353       {"dither-method", MagickDitherOptions} } },
354     { "Raise", { {"geometry", StringReference}, {"width", IntegerReference},
355       {"height", IntegerReference}, {"raise", MagickBooleanOptions} } },
356     { "Segment", { {"geometry", StringReference},
357       {"cluster-threshold", RealReference},
358       {"smoothing-threshold", RealReference},
359       {"colorspace", MagickColorspaceOptions},
360       {"verbose", MagickBooleanOptions} } },
361     { "Signature", },
362     { "Solarize", { {"geometry", StringReference},
363       {"threshold", StringReference} } },
364     { "Sync", },
365     { "Texture", { {"texture", ImageReference} } },
366     { "Evaluate", { {"value", RealReference},
367       {"operator", MagickEvaluateOptions},
368       {"channel", MagickChannelOptions} } },
369     { "Transparent", { {"color", StringReference}, {"opacity", StringReference},
370       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
371     { "Threshold", { {"threshold", StringReference},
372       {"channel", MagickChannelOptions} } },
373     { "Charcoal", { {"geometry", StringReference}, {"radius", RealReference},
374       {"sigma", RealReference} } },
375     { "Trim", { {"fuzz", StringReference} } },
376     { "Wave", { {"geometry", StringReference}, {"amplitude", RealReference},
377       {"wavelength", RealReference},
378       {"interpolate", MagickInterpolateOptions} } },
379     { "Separate", { {"channel", MagickChannelOptions} } },
380     { "Condense", },
381     { "Stereo", { {"image", ImageReference}, {"x", IntegerReference},
382       {"y", IntegerReference} } },
383     { "Stegano", { {"image", ImageReference}, {"offset", IntegerReference} } },
384     { "Deconstruct", },
385     { "GaussianBlur", { {"geometry", StringReference},
386       {"radius", RealReference}, {"sigma", RealReference},
387       {"channel", MagickChannelOptions} } },
388     { "Convolve", { {"coefficients", ArrayReference},
389       {"channel", MagickChannelOptions}, {"bias", StringReference},
390       {"kernel", StringReference} } },
391     { "Profile", { {"name", StringReference}, {"profile", StringReference},
392       { "rendering-intent", MagickIntentOptions},
393       { "black-point-compensation", MagickBooleanOptions} } },
394     { "UnsharpMask", { {"geometry", StringReference},
395       {"radius", RealReference}, {"sigma", RealReference},
396       {"amount", RealReference}, {"threshold", RealReference},
397       {"channel", MagickChannelOptions} } },
398     { "MotionBlur", { {"geometry", StringReference},
399       {"radius", RealReference}, {"sigma", RealReference},
400       {"angle", RealReference}, {"channel", MagickChannelOptions} } },
401     { "OrderedDither", { {"threshold", StringReference},
402       {"channel", MagickChannelOptions} } },
403     { "Shave", { {"geometry", StringReference}, {"width", IntegerReference},
404       {"height", IntegerReference} } },
405     { "Level", { {"levels", StringReference}, {"black-point", RealReference},
406       {"white-point", RealReference}, {"gamma", RealReference},
407       {"channel", MagickChannelOptions}, {"level", StringReference} } },
408     { "Clip", { {"id", StringReference}, {"inside", MagickBooleanOptions} } },
409     { "AffineTransform", { {"affine", ArrayReference},
410       {"translate", StringReference}, {"scale", StringReference},
411       {"rotate", RealReference}, {"skewX", RealReference},
412       {"skewY", RealReference}, {"interpolate", MagickInterpolateOptions},
413       {"background", StringReference} } },
414     { "Difference", { {"image", ImageReference}, {"fuzz", StringReference} } },
415     { "AdaptiveThreshold", { {"geometry", StringReference},
416       {"width", IntegerReference}, {"height", IntegerReference},
417       {"bias", RealReference} } },
418     { "Resample", { {"density", StringReference}, {"x", RealReference},
419       {"y", RealReference}, {"filter", MagickFilterOptions},
420       {"support", RealReference }, {"blur", RealReference } } },
421     { "Describe", { {"file", FileReference} } },
422     { "BlackThreshold", { {"threshold", StringReference},
423       {"channel", MagickChannelOptions} } },
424     { "WhiteThreshold", { {"threshold", StringReference},
425       {"channel", MagickChannelOptions} } },
426     { "RadialBlur", { {"geometry", StringReference}, {"angle", RealReference},
427       {"channel", MagickChannelOptions} } },
428     { "Thumbnail", { {"geometry", StringReference}, {"width", IntegerReference},
429       {"height", IntegerReference} } },
430     { "Strip", },
431     { "Tint", { {"fill", StringReference}, {"opacity", StringReference} } },
432     { "Channel", { {"channel", MagickChannelOptions} } },
433     { "Splice", { {"geometry", StringReference}, {"width", IntegerReference},
434       {"height", IntegerReference}, {"x", IntegerReference},
435       {"y", IntegerReference}, {"fuzz", StringReference},
436       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
437     { "Posterize", { {"levels", IntegerReference},
438       {"dither", MagickBooleanOptions} } },
439     { "Shadow", { {"geometry", StringReference}, {"opacity", RealReference},
440       {"sigma", RealReference}, {"x", IntegerReference},
441       {"y", IntegerReference} } },
442     { "Identify", { {"file", FileReference}, {"features", StringReference},
443       {"unique", MagickBooleanOptions} } },
444     { "SepiaTone", { {"threshold", RealReference} } },
445     { "SigmoidalContrast", { {"geometry", StringReference},
446       {"contrast", RealReference}, {"mid-point", RealReference},
447       {"channel", MagickChannelOptions}, {"sharpen", MagickBooleanOptions} } },
448     { "Extent", { {"geometry", StringReference}, {"width", IntegerReference},
449       {"height", IntegerReference}, {"x", IntegerReference},
450       {"y", IntegerReference}, {"fuzz", StringReference},
451       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
452     { "Vignette", { {"geometry", StringReference}, {"radius", RealReference},
453       {"sigma", RealReference}, {"x", IntegerReference},
454       {"y", IntegerReference}, {"background", StringReference} } },
455     { "ContrastStretch", { {"levels", StringReference},
456       {"black-point", RealReference},{"white-point", RealReference},
457       {"channel", MagickChannelOptions} } },
458     { "Sans0", },
459     { "Sans1", },
460     { "AdaptiveSharpen", { {"geometry", StringReference},
461       {"radius", RealReference}, {"sigma", RealReference},
462       {"channel", MagickChannelOptions} } },
463     { "Transpose", },
464     { "Transverse", },
465     { "AutoOrient", },
466     { "AdaptiveBlur", { {"geometry", StringReference},
467       {"radius", RealReference}, {"sigma", RealReference},
468       {"channel", MagickChannelOptions} } },
469     { "Sketch", { {"geometry", StringReference},
470       {"radius", RealReference}, {"sigma", RealReference},
471       {"angle", RealReference} } },
472     { "UniqueColors", },
473     { "AdaptiveResize", { {"geometry", StringReference},
474       {"width", IntegerReference}, {"height", IntegerReference},
475       {"filter", MagickFilterOptions}, {"support", StringReference },
476       {"blur", RealReference } } },
477     { "ClipMask", { {"mask", ImageReference} } },
478     { "LinearStretch", { {"levels", StringReference},
479       {"black-point", RealReference},{"white-point", RealReference} } },
480     { "Recolor", { {"matrix", ArrayReference} } },
481     { "Mask", { {"mask", ImageReference} } },
482     { "Polaroid", { {"caption", StringReference}, {"angle", RealReference},
483       {"font", StringReference}, {"stroke", StringReference},
484       {"fill", StringReference}, {"strokewidth", RealReference},
485       {"pointsize", RealReference}, {"gravity", MagickGravityOptions},
486       {"background", StringReference} } },
487     { "FloodfillPaint", { {"geometry", StringReference},
488       {"x", IntegerReference}, {"y", IntegerReference},
489       {"fill", StringReference}, {"bordercolor", StringReference},
490       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
491       {"invert", MagickBooleanOptions} } },
492     { "Distort", { {"points", ArrayReference}, {"method", MagickDistortOptions},
493       {"virtual-pixel", MagickVirtualPixelOptions},
494       {"best-fit", MagickBooleanOptions} } },
495     { "Clut", { {"image", ImageReference},
496       {"channel", MagickChannelOptions} } },
497     { "LiquidRescale", { {"geometry", StringReference},
498       {"width", IntegerReference}, {"height", IntegerReference},
499       {"delta-x", RealReference}, {"rigidity", RealReference } } },
500     { "Encipher", { {"passphrase", StringReference} } },
501     { "Decipher", { {"passphrase", StringReference} } },
502     { "Deskew", { {"geometry", StringReference},
503       {"threshold", StringReference} } },
504     { "Remap", { {"image", ImageReference}, {"dither", MagickBooleanOptions},
505       {"dither-method", MagickDitherOptions} } },
506     { "SparseColor", { {"points", ArrayReference},
507       {"method", MagickSparseColorOptions},
508       {"virtual-pixel", MagickVirtualPixelOptions},
509       {"channel", MagickChannelOptions} } },
510     { "Function", { {"parameters", ArrayReference},
511       {"function", MagickFunctionOptions},
512       {"virtual-pixel", MagickVirtualPixelOptions} } },
513     { "SelectiveBlur", { {"geometry", StringReference},
514       {"radius", RealReference}, {"sigma", RealReference},
515       {"threshold", RealReference}, {"channel", MagickChannelOptions} } },
516     { "HaldClut", { {"image", ImageReference},
517       {"channel", MagickChannelOptions} } },
518     { "BlueShift", { {"factor", StringReference} } },
519     { "ForwardFourierTransform", { {"magnitude", MagickBooleanOptions} } },
520     { "InverseFourierTransform", { {"magnitude", MagickBooleanOptions} } },
521     { "ColorDecisionList", {
522       {"color-correction-collection", StringReference} } },
523     { "AutoGamma", { {"channel", MagickChannelOptions} } },
524     { "AutoLevel", { {"channel", MagickChannelOptions} } },
525     { "LevelColors", { {"invert", MagickBooleanOptions},
526       {"black-point", StringReference}, {"white-point", StringReference},
527       {"channel", MagickChannelOptions}, {"invert", MagickBooleanOptions} } },
528     { "Clamp", { {"channel", MagickChannelOptions} } },
529     { "BrightnessContrast", { {"levels", StringReference},
530       {"brightness", RealReference},{"contrast", RealReference},
531       {"channel", MagickChannelOptions} } },
532     { "Morphology", { {"kernel", StringReference},
533       {"channel", MagickChannelOptions}, {"method", MagickMorphologyOptions},
534       {"iterations", IntegerReference} } },
535     { "ColorMatrix", { {"matrix", ArrayReference} } },
536     { "Color", { {"color", StringReference} } },
537     { "Mode", { {"geometry", StringReference},
538       {"width", IntegerReference},{"height", IntegerReference},
539       {"channel", MagickChannelOptions} } },
540     { "Statistic", { {"geometry", StringReference},
541       {"width", IntegerReference},{"height", IntegerReference},
542       {"channel", MagickChannelOptions}, {"type", MagickStatisticOptions} } }
543   };
544
545 static SplayTreeInfo
546   *magick_registry = (SplayTreeInfo *) NULL;
547 \f
548 /*
549   Forward declarations.
550 */
551 static Image
552   *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
553
554 static ssize_t
555   strEQcase(const char *,const char *);
556 \f
557 /*
558 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
559 %                                                                             %
560 %                                                                             %
561 %                                                                             %
562 %   C l o n e P a c k a g e I n f o                                           %
563 %                                                                             %
564 %                                                                             %
565 %                                                                             %
566 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
567 %
568 %  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
569 %  a new one.
570 %
571 %  The format of the ClonePackageInfo routine is:
572 %
573 %      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
574 %        exception)
575 %
576 %  A description of each parameter follows:
577 %
578 %    o info: a structure of type info.
579 %
580 %    o exception: Return any errors or warnings in this structure.
581 %
582 */
583 static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
584   ExceptionInfo *exception)
585 {
586   struct PackageInfo
587     *clone_info;
588
589   clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
590   if (clone_info == (struct PackageInfo *) NULL)
591     {
592       ThrowPerlException(exception,ResourceLimitError,
593         "UnableToClonePackageInfo",PackageName);
594       return((struct PackageInfo *) NULL);
595     }
596   if (info == (struct PackageInfo *) NULL)
597     {
598       clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
599       return(clone_info);
600     }
601   *clone_info=(*info);
602   clone_info->image_info=CloneImageInfo(info->image_info);
603   return(clone_info);
604 }
605 \f
606 /*
607 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
608 %                                                                             %
609 %                                                                             %
610 %                                                                             %
611 %   c o n s t a n t                                                           %
612 %                                                                             %
613 %                                                                             %
614 %                                                                             %
615 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
616 %
617 %  constant() returns a double value for the specified name.
618 %
619 %  The format of the constant routine is:
620 %
621 %      double constant(char *name,ssize_t sans)
622 %
623 %  A description of each parameter follows:
624 %
625 %    o value: Method constant returns a double value for the specified name.
626 %
627 %    o name: The name of the constant.
628 %
629 %    o sans: This integer value is not used.
630 %
631 */
632 static double constant(char *name,ssize_t sans)
633 {
634   (void) sans;
635   errno=0;
636   switch (*name)
637   {
638     case 'B':
639     {
640       if (strEQ(name,"BlobError"))
641         return(BlobError);
642       if (strEQ(name,"BlobWarning"))
643         return(BlobWarning);
644       break;
645     }
646     case 'C':
647     {
648       if (strEQ(name,"CacheError"))
649         return(CacheError);
650       if (strEQ(name,"CacheWarning"))
651         return(CacheWarning);
652       if (strEQ(name,"CoderError"))
653         return(CoderError);
654       if (strEQ(name,"CoderWarning"))
655         return(CoderWarning);
656       if (strEQ(name,"ConfigureError"))
657         return(ConfigureError);
658       if (strEQ(name,"ConfigureWarning"))
659         return(ConfigureWarning);
660       if (strEQ(name,"CorruptImageError"))
661         return(CorruptImageError);
662       if (strEQ(name,"CorruptImageWarning"))
663         return(CorruptImageWarning);
664       break;
665     }
666     case 'D':
667     {
668       if (strEQ(name,"DelegateError"))
669         return(DelegateError);
670       if (strEQ(name,"DelegateWarning"))
671         return(DelegateWarning);
672       if (strEQ(name,"DrawError"))
673         return(DrawError);
674       if (strEQ(name,"DrawWarning"))
675         return(DrawWarning);
676       break;
677     }
678     case 'E':
679     {
680       if (strEQ(name,"ErrorException"))
681         return(ErrorException);
682       if (strEQ(name,"ExceptionError"))
683         return(CoderError);
684       if (strEQ(name,"ExceptionWarning"))
685         return(CoderWarning);
686       break;
687     }
688     case 'F':
689     {
690       if (strEQ(name,"FatalErrorException"))
691         return(FatalErrorException);
692       if (strEQ(name,"FileOpenError"))
693         return(FileOpenError);
694       if (strEQ(name,"FileOpenWarning"))
695         return(FileOpenWarning);
696       break;
697     }
698     case 'I':
699     {
700       if (strEQ(name,"ImageError"))
701         return(ImageError);
702       if (strEQ(name,"ImageWarning"))
703         return(ImageWarning);
704       break;
705     }
706     case 'M':
707     {
708       if (strEQ(name,"MaxRGB"))
709         return(QuantumRange);
710       if (strEQ(name,"MissingDelegateError"))
711         return(MissingDelegateError);
712       if (strEQ(name,"MissingDelegateWarning"))
713         return(MissingDelegateWarning);
714       if (strEQ(name,"ModuleError"))
715         return(ModuleError);
716       if (strEQ(name,"ModuleWarning"))
717         return(ModuleWarning);
718       break;
719     }
720     case 'O':
721     {
722       if (strEQ(name,"Opaque"))
723         return(OpaqueAlpha);
724       if (strEQ(name,"OptionError"))
725         return(OptionError);
726       if (strEQ(name,"OptionWarning"))
727         return(OptionWarning);
728       break;
729     }
730     case 'Q':
731     {
732       if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
733         return(MAGICKCORE_QUANTUM_DEPTH);
734       if (strEQ(name,"QuantumDepth"))
735         return(MAGICKCORE_QUANTUM_DEPTH);
736       if (strEQ(name,"QuantumRange"))
737         return(QuantumRange);
738       break;
739     }
740     case 'R':
741     {
742       if (strEQ(name,"ResourceLimitError"))
743         return(ResourceLimitError);
744       if (strEQ(name,"ResourceLimitWarning"))
745         return(ResourceLimitWarning);
746       if (strEQ(name,"RegistryError"))
747         return(RegistryError);
748       if (strEQ(name,"RegistryWarning"))
749         return(RegistryWarning);
750       break;
751     }
752     case 'S':
753     {
754       if (strEQ(name,"StreamError"))
755         return(StreamError);
756       if (strEQ(name,"StreamWarning"))
757         return(StreamWarning);
758       if (strEQ(name,"Success"))
759         return(0);
760       break;
761     }
762     case 'T':
763     {
764       if (strEQ(name,"Transparent"))
765         return(TransparentAlpha);
766       if (strEQ(name,"TypeError"))
767         return(TypeError);
768       if (strEQ(name,"TypeWarning"))
769         return(TypeWarning);
770       break;
771     }
772     case 'W':
773     {
774       if (strEQ(name,"WarningException"))
775         return(WarningException);
776       break;
777     }
778     case 'X':
779     {
780       if (strEQ(name,"XServerError"))
781         return(XServerError);
782       if (strEQ(name,"XServerWarning"))
783         return(XServerWarning);
784       break;
785     }
786   }
787   errno=EINVAL;
788   return(0);
789 }
790 \f
791 /*
792 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
793 %                                                                             %
794 %                                                                             %
795 %                                                                             %
796 %   D e s t r o y P a c k a g e I n f o                                       %
797 %                                                                             %
798 %                                                                             %
799 %                                                                             %
800 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
801 %
802 %  Method DestroyPackageInfo frees a previously created info structure.
803 %
804 %  The format of the DestroyPackageInfo routine is:
805 %
806 %      DestroyPackageInfo(struct PackageInfo *info)
807 %
808 %  A description of each parameter follows:
809 %
810 %    o info: a structure of type info.
811 %
812 */
813 static void DestroyPackageInfo(struct PackageInfo *info)
814 {
815   info->image_info=DestroyImageInfo(info->image_info);
816   info=(struct PackageInfo *) RelinquishMagickMemory(info);
817 }
818 \f
819 /*
820 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
821 %                                                                             %
822 %                                                                             %
823 %                                                                             %
824 %   G e t L i s t                                                             %
825 %                                                                             %
826 %                                                                             %
827 %                                                                             %
828 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
829 %
830 %  Method GetList is recursively called by SetupList to traverse the
831 %  Image__Magick reference.  If building an reference_vector (see SetupList),
832 %  *current is the current position in *reference_vector and *last is the final
833 %  entry in *reference_vector.
834 %
835 %  The format of the GetList routine is:
836 %
837 %      GetList(info)
838 %
839 %  A description of each parameter follows:
840 %
841 %    o info: a structure of type info.
842 %
843 */
844 static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
845   ssize_t *current,ssize_t *last,ExceptionInfo *exception)
846 {
847   Image
848     *image;
849
850   if (reference == (SV *) NULL)
851     return(NULL);
852   switch (SvTYPE(reference))
853   {
854     case SVt_PVAV:
855     {
856       AV
857         *av;
858
859       Image
860         *head,
861         *previous;
862
863       register ssize_t
864         i;
865
866       ssize_t
867         n;
868
869       /*
870         Array of images.
871       */
872       previous=(Image *) NULL;
873       head=(Image *) NULL;
874       av=(AV *) reference;
875       n=av_len(av);
876       for (i=0; i <= n; i++)
877       {
878         SV
879           **rv;
880
881         rv=av_fetch(av,i,0);
882         if (rv && *rv && sv_isobject(*rv))
883           {
884             image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
885               exception);
886             if (image == (Image *) NULL)
887               continue;
888             if (image == previous)
889               {
890                 image=CloneImage(image,0,0,MagickTrue,exception);
891                 if (image == (Image *) NULL)
892                   return(NULL);
893               }
894             image->previous=previous;
895             *(previous ? &previous->next : &head)=image;
896             for (previous=image; previous->next; previous=previous->next) ;
897           }
898       }
899       return(head);
900     }
901     case SVt_PVMG:
902     {
903       /*
904         Blessed scalar, one image.
905       */
906       image=(Image *) SvIV(reference);
907       if (image == (Image *) NULL)
908         return(NULL);
909       image->previous=(Image *) NULL;
910       image->next=(Image *) NULL;
911       if (reference_vector)
912         {
913           if (*current == *last)
914             {
915               *last+=256;
916               if (*reference_vector == (SV **) NULL)
917                 *reference_vector=(SV **) AcquireQuantumMemory(*last,
918                   sizeof(*reference_vector));
919               else
920                 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
921                   *last,sizeof(*reference_vector));
922             }
923           if (*reference_vector == (SV **) NULL)
924             {
925               ThrowPerlException(exception,ResourceLimitError,
926                 "MemoryAllocationFailed",PackageName);
927               return((Image *) NULL);
928             }
929           (*reference_vector)[*current]=reference;
930           (*reference_vector)[++(*current)]=NULL;
931         }
932       return(image);
933     }
934     default:
935       break;
936   }
937   (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
938     (double) SvTYPE(reference));
939   return((Image *) NULL);
940 }
941 \f
942 /*
943 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
944 %                                                                             %
945 %                                                                             %
946 %                                                                             %
947 %   G e t P a c k a g e I n f o                                               %
948 %                                                                             %
949 %                                                                             %
950 %                                                                             %
951 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
952 %
953 %  Method GetPackageInfo looks up or creates an info structure for the given
954 %  Image__Magick reference.  If it does create a new one, the information in
955 %  package_info is used to initialize it.
956 %
957 %  The format of the GetPackageInfo routine is:
958 %
959 %      struct PackageInfo *GetPackageInfo(void *reference,
960 %        struct PackageInfo *package_info,ExceptionInfo *exception)
961 %
962 %  A description of each parameter follows:
963 %
964 %    o info: a structure of type info.
965 %
966 %    o exception: Return any errors or warnings in this structure.
967 %
968 */
969 static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
970   struct PackageInfo *package_info,ExceptionInfo *exception)
971 {
972   char
973     message[MaxTextExtent];
974
975   struct PackageInfo
976     *clone_info;
977
978   SV
979     *sv;
980
981   (void) FormatLocaleString(message,MaxTextExtent,"%s::package%s%p",
982     PackageName,XS_VERSION,reference);
983   sv=perl_get_sv(message,(TRUE | 0x02));
984   if (sv == (SV *) NULL)
985     {
986       ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
987         message);
988       return(package_info);
989     }
990   if (SvREFCNT(sv) == 0)
991     (void) SvREFCNT_inc(sv);
992   if (SvIOKp(sv) && (clone_info=(struct PackageInfo *) SvIV(sv)))
993     return(clone_info);
994   clone_info=ClonePackageInfo(package_info,exception);
995   sv_setiv(sv,(IV) clone_info);
996   return(clone_info);
997 }
998 \f
999 /*
1000 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1001 %                                                                             %
1002 %                                                                             %
1003 %                                                                             %
1004 %   S e t A t t r i b u t e                                                   %
1005 %                                                                             %
1006 %                                                                             %
1007 %                                                                             %
1008 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1009 %
1010 %  SetAttribute() sets the attribute to the value in sval.  This can change
1011 %  either or both of image or info.
1012 %
1013 %  The format of the SetAttribute routine is:
1014 %
1015 %      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1016 %        SV *sval,ExceptionInfo *exception)
1017 %
1018 %  A description of each parameter follows:
1019 %
1020 %    o list: a list of strings.
1021 %
1022 %    o string: a character string.
1023 %
1024 */
1025
1026 static double SiPrefixToDouble(const char *string,const double interval)
1027 {
1028   char
1029     *q;
1030
1031   double
1032     scale,
1033     value;
1034
1035   value=InterpretLocaleValue(string,&q);
1036   scale=1000.0;
1037   if ((*q != '\0') && (tolower((int) ((unsigned char) *(q+1))) == 'i'))
1038     scale=1024.0;
1039   switch (tolower((int) ((unsigned char) *q)))
1040   {
1041     case '%': value*=pow(scale,0)*interval/100.0; break;
1042     case 'k': value*=pow(scale,1); break;
1043     case 'm': value*=pow(scale,2); break;
1044     case 'g': value*=pow(scale,3); break;
1045     case 't': value*=pow(scale,4); break;
1046     case 'p': value*=pow(scale,5); break;
1047     case 'e': value*=pow(scale,6); break;
1048     case 'z': value*=pow(scale,7); break;
1049     case 'y': value*=pow(scale,8); break;
1050     default:  break;
1051   }
1052   return(value);
1053 }
1054
1055 static inline ssize_t StringToLong(const char *value)
1056 {
1057   return(strtol(value,(char **) NULL,10));
1058 }
1059
1060 static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1061   const char *attribute,SV *sval,ExceptionInfo *exception)
1062 {
1063   GeometryInfo
1064     geometry_info;
1065
1066   long
1067     x,
1068     y;
1069
1070   PixelInfo
1071     pixel;
1072
1073   MagickStatusType
1074     flags;
1075
1076   PixelPacket
1077     *color,
1078     target_color;
1079
1080   ssize_t
1081     sp;
1082
1083   switch (*attribute)
1084   {
1085     case 'A':
1086     case 'a':
1087     {
1088       if (LocaleCompare(attribute,"adjoin") == 0)
1089         {
1090           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1091             SvPV(sval,na)) : SvIV(sval);
1092           if (sp < 0)
1093             {
1094               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1095                 SvPV(sval,na));
1096               break;
1097             }
1098           if (info)
1099             info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1100           break;
1101         }
1102       if (LocaleCompare(attribute,"alpha") == 0)
1103         {
1104           sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaOptions,MagickFalse,
1105             SvPV(sval,na)) : SvIV(sval);
1106           if (sp < 0)
1107             {
1108               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1109                 SvPV(sval,na));
1110               break;
1111             }
1112           for ( ; image; image=image->next)
1113             (void) SetImageAlphaChannel(image,(AlphaChannelType) sp,exception);
1114           break;
1115         }
1116       if (LocaleCompare(attribute,"antialias") == 0)
1117         {
1118           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1119             SvPV(sval,na)) : SvIV(sval);
1120           if (sp < 0)
1121             {
1122               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1123                 SvPV(sval,na));
1124               break;
1125             }
1126           if (info)
1127             info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1128           break;
1129         }
1130       if (LocaleCompare(attribute,"area-limit") == 0)
1131         {
1132           MagickSizeType
1133             limit;
1134
1135           limit=MagickResourceInfinity;
1136           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1137             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1138           (void) SetMagickResourceLimit(AreaResource,limit);
1139           break;
1140         }
1141       if (LocaleCompare(attribute,"attenuate") == 0)
1142         {
1143           if (info)
1144             (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1145           break;
1146         }
1147       if (LocaleCompare(attribute,"authenticate") == 0)
1148         {
1149           if (info)
1150             (void) CloneString(&info->image_info->authenticate,SvPV(sval,na));
1151           break;
1152         }
1153       if (info)
1154         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1155       for ( ; image; image=image->next)
1156         SetImageProperty(image,attribute,SvPV(sval,na));
1157       break;
1158     }
1159     case 'B':
1160     case 'b':
1161     {
1162       if (LocaleCompare(attribute,"background") == 0)
1163         {
1164           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1165           if (info)
1166             info->image_info->background_color=target_color;
1167           for ( ; image; image=image->next)
1168             image->background_color=target_color;
1169           break;
1170         }
1171       if (LocaleCompare(attribute,"bias") == 0)
1172         {
1173           for ( ; image; image=image->next)
1174             image->bias=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1175           break;
1176         }
1177       if (LocaleCompare(attribute,"blue-primary") == 0)
1178         {
1179           for ( ; image; image=image->next)
1180           {
1181             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1182             image->chromaticity.blue_primary.x=geometry_info.rho;
1183             image->chromaticity.blue_primary.y=geometry_info.sigma;
1184             if ((flags & SigmaValue) == 0)
1185               image->chromaticity.blue_primary.y=
1186                 image->chromaticity.blue_primary.x;
1187           }
1188           break;
1189         }
1190       if (LocaleCompare(attribute,"bordercolor") == 0)
1191         {
1192           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1193           if (info)
1194             info->image_info->border_color=target_color;
1195           for ( ; image; image=image->next)
1196             image->border_color=target_color;
1197           break;
1198         }
1199       if (info)
1200         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1201       for ( ; image; image=image->next)
1202         SetImageProperty(image,attribute,SvPV(sval,na));
1203       break;
1204     }
1205     case 'C':
1206     case 'c':
1207     {
1208       if (LocaleCompare(attribute,"cache-threshold") == 0)
1209         {
1210           (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1211             SiPrefixToDouble(SvPV(sval,na),100.0));
1212           (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1213             (2*SiPrefixToDouble(SvPV(sval,na),100.0)));
1214           break;
1215         }
1216       if (LocaleCompare(attribute,"clip-mask") == 0)
1217         {
1218           Image
1219             *clip_mask;
1220
1221           clip_mask=(Image *) NULL;
1222           if (SvPOK(sval))
1223             clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1224           for ( ; image; image=image->next)
1225             SetImageClipMask(image,clip_mask);
1226           break;
1227         }
1228       if (LocaleNCompare(attribute,"colormap",8) == 0)
1229         {
1230           for ( ; image; image=image->next)
1231           {
1232             int
1233               items;
1234
1235             long
1236               i;
1237
1238             if (image->storage_class == DirectClass)
1239               continue;
1240             i=0;
1241             items=sscanf(attribute,"%*[^[][%ld",&i);
1242             (void) items;
1243             if (i > (ssize_t) image->colors)
1244               i%=image->colors;
1245             if ((strchr(SvPV(sval,na),',') == 0) ||
1246                 (strchr(SvPV(sval,na),')') != 0))
1247               QueryColorDatabase(SvPV(sval,na),image->colormap+i,exception);
1248             else
1249               {
1250                 color=image->colormap+i;
1251                 pixel.red=color->red;
1252                 pixel.green=color->green;
1253                 pixel.blue=color->blue;
1254                 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1255                 pixel.red=geometry_info.rho;
1256                 pixel.green=geometry_info.sigma;
1257                 pixel.blue=geometry_info.xi;
1258                 color->red=ClampToQuantum(pixel.red);
1259                 color->green=ClampToQuantum(pixel.green);
1260                 color->blue=ClampToQuantum(pixel.blue);
1261               }
1262           }
1263           break;
1264         }
1265       if (LocaleCompare(attribute,"colorspace") == 0)
1266         {
1267           sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1268             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1269           if (sp < 0)
1270             {
1271               ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1272                 SvPV(sval,na));
1273               break;
1274             }
1275           for ( ; image; image=image->next)
1276             (void) TransformImageColorspace(image,(ColorspaceType) sp);
1277           break;
1278         }
1279       if (LocaleCompare(attribute,"comment") == 0)
1280         {
1281           for ( ; image; image=image->next)
1282             (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1283               info ? info->image_info : (ImageInfo *) NULL,image,
1284               SvPV(sval,na)));
1285           break;
1286         }
1287       if (LocaleCompare(attribute,"compression") == 0)
1288         {
1289           sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1290             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1291           if (sp < 0)
1292             {
1293               ThrowPerlException(exception,OptionError,
1294                 "UnrecognizedImageCompression",SvPV(sval,na));
1295               break;
1296             }
1297           if (info)
1298             info->image_info->compression=(CompressionType) sp;
1299           for ( ; image; image=image->next)
1300             image->compression=(CompressionType) sp;
1301           break;
1302         }
1303       if (info)
1304         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1305       for ( ; image; image=image->next)
1306         SetImageProperty(image,attribute,SvPV(sval,na));
1307       break;
1308     }
1309     case 'D':
1310     case 'd':
1311     {
1312       if (LocaleCompare(attribute,"debug") == 0)
1313         {
1314           SetLogEventMask(SvPV(sval,na));
1315           break;
1316         }
1317       if (LocaleCompare(attribute,"delay") == 0)
1318         {
1319           flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1320           for ( ; image; image=image->next)
1321           {
1322             image->delay=(size_t) floor(geometry_info.rho+0.5);
1323             if ((flags & SigmaValue) != 0)
1324               image->ticks_per_second=(ssize_t)
1325                 floor(geometry_info.sigma+0.5);
1326           }
1327           break;
1328         }
1329       if (LocaleCompare(attribute,"disk-limit") == 0)
1330         {
1331           MagickSizeType
1332             limit;
1333
1334           limit=MagickResourceInfinity;
1335           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1336             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1337           (void) SetMagickResourceLimit(DiskResource,limit);
1338           break;
1339         }
1340       if (LocaleCompare(attribute,"density") == 0)
1341         {
1342           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1343             {
1344               ThrowPerlException(exception,OptionError,"MissingGeometry",
1345                 SvPV(sval,na));
1346               break;
1347             }
1348           if (info)
1349             (void) CloneString(&info->image_info->density,SvPV(sval,na));
1350           for ( ; image; image=image->next)
1351           {
1352             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1353             image->x_resolution=geometry_info.rho;
1354             image->y_resolution=geometry_info.sigma;
1355             if ((flags & SigmaValue) == 0)
1356               image->y_resolution=image->x_resolution;
1357           }
1358           break;
1359         }
1360       if (LocaleCompare(attribute,"depth") == 0)
1361         {
1362           if (info)
1363             info->image_info->depth=SvIV(sval);
1364           for ( ; image; image=image->next)
1365             (void) SetImageDepth(image,SvIV(sval));
1366           break;
1367         }
1368       if (LocaleCompare(attribute,"dispose") == 0)
1369         {
1370           sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1371             SvPV(sval,na)) : SvIV(sval);
1372           if (sp < 0)
1373             {
1374               ThrowPerlException(exception,OptionError,
1375                 "UnrecognizedDisposeMethod",SvPV(sval,na));
1376               break;
1377             }
1378           for ( ; image; image=image->next)
1379             image->dispose=(DisposeType) sp;
1380           break;
1381         }
1382       if (LocaleCompare(attribute,"dither") == 0)
1383         {
1384           if (info)
1385             {
1386               sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1387                 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1388               if (sp < 0)
1389                 {
1390                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
1391                     SvPV(sval,na));
1392                   break;
1393                 }
1394               info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1395             }
1396           break;
1397         }
1398       if (LocaleCompare(attribute,"display") == 0)
1399         {
1400           display:
1401           if (info)
1402             (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1403           break;
1404         }
1405       if (info)
1406         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1407       for ( ; image; image=image->next)
1408         SetImageProperty(image,attribute,SvPV(sval,na));
1409       break;
1410     }
1411     case 'E':
1412     case 'e':
1413     {
1414       if (LocaleCompare(attribute,"endian") == 0)
1415         {
1416           sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1417             SvPV(sval,na)) : SvIV(sval);
1418           if (sp < 0)
1419             {
1420               ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1421                 SvPV(sval,na));
1422               break;
1423             }
1424           if (info)
1425             info->image_info->endian=(EndianType) sp;
1426           for ( ; image; image=image->next)
1427             image->endian=(EndianType) sp;
1428           break;
1429         }
1430       if (LocaleCompare(attribute,"extract") == 0)
1431         {
1432           /*
1433             Set image extract geometry.
1434           */
1435           (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1436           break;
1437         }
1438       if (info)
1439         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1440       for ( ; image; image=image->next)
1441         SetImageProperty(image,attribute,SvPV(sval,na));
1442       break;
1443     }
1444     case 'F':
1445     case 'f':
1446     {
1447       if (LocaleCompare(attribute,"filename") == 0)
1448         {
1449           if (info)
1450             (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1451               MaxTextExtent);
1452           for ( ; image; image=image->next)
1453             (void) CopyMagickString(image->filename,SvPV(sval,na),
1454               MaxTextExtent);
1455           break;
1456         }
1457       if (LocaleCompare(attribute,"file") == 0)
1458         {
1459           FILE
1460             *file;
1461
1462           PerlIO
1463             *io_info;
1464
1465           if (info == (struct PackageInfo *) NULL)
1466             break;
1467           io_info=IoIFP(sv_2io(sval));
1468           if (io_info == (PerlIO *) NULL)
1469             {
1470               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1471                 PackageName);
1472               break;
1473             }
1474           file=PerlIO_findFILE(io_info);
1475           if (file == (FILE *) NULL)
1476             {
1477               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1478                 PackageName);
1479               break;
1480             }
1481           SetImageInfoFile(info->image_info,file);
1482           break;
1483         }
1484       if (LocaleCompare(attribute,"fill") == 0)
1485         {
1486           if (info)
1487             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1488           break;
1489         }
1490       if (LocaleCompare(attribute,"font") == 0)
1491         {
1492           if (info)
1493             (void) CloneString(&info->image_info->font,SvPV(sval,na));
1494           break;
1495         }
1496       if (LocaleCompare(attribute,"foreground") == 0)
1497         break;
1498       if (LocaleCompare(attribute,"fuzz") == 0)
1499         {
1500           if (info)
1501             info->image_info->fuzz=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1502           for ( ; image; image=image->next)
1503             image->fuzz=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1504           break;
1505         }
1506       if (info)
1507         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1508       for ( ; image; image=image->next)
1509         SetImageProperty(image,attribute,SvPV(sval,na));
1510       break;
1511     }
1512     case 'G':
1513     case 'g':
1514     {
1515       if (LocaleCompare(attribute,"gamma") == 0)
1516         {
1517           for ( ; image; image=image->next)
1518             image->gamma=SvNV(sval);
1519           break;
1520         }
1521       if (LocaleCompare(attribute,"gravity") == 0)
1522         {
1523           sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1524             SvPV(sval,na)) : SvIV(sval);
1525           if (sp < 0)
1526             {
1527               ThrowPerlException(exception,OptionError,
1528                 "UnrecognizedGravityType",SvPV(sval,na));
1529               break;
1530             }
1531           if (info)
1532             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1533           for ( ; image; image=image->next)
1534             image->gravity=(GravityType) sp;
1535           break;
1536         }
1537       if (LocaleCompare(attribute,"green-primary") == 0)
1538         {
1539           for ( ; image; image=image->next)
1540           {
1541             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1542             image->chromaticity.green_primary.x=geometry_info.rho;
1543             image->chromaticity.green_primary.y=geometry_info.sigma;
1544             if ((flags & SigmaValue) == 0)
1545               image->chromaticity.green_primary.y=
1546                 image->chromaticity.green_primary.x;
1547           }
1548           break;
1549         }
1550       if (info)
1551         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1552       for ( ; image; image=image->next)
1553         SetImageProperty(image,attribute,SvPV(sval,na));
1554       break;
1555     }
1556     case 'I':
1557     case 'i':
1558     {
1559       if (LocaleNCompare(attribute,"index",5) == 0)
1560         {
1561           int
1562             items;
1563
1564           long
1565             index;
1566
1567           register Quantum
1568             *q;
1569
1570           CacheView
1571             *image_view;
1572
1573           for ( ; image; image=image->next)
1574           {
1575             if (image->storage_class != PseudoClass)
1576               continue;
1577             x=0;
1578             y=0;
1579             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1580             (void) items;
1581             image_view=AcquireCacheView(image);
1582             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1583             if (q != (Quantum *) NULL)
1584               {
1585                 items=sscanf(SvPV(sval,na),"%ld",&index);
1586                 if ((index >= 0) && (index < (ssize_t) image->colors))
1587                   SetPixelIndex(image,index,q);
1588                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1589               }
1590             image_view=DestroyCacheView(image_view);
1591           }
1592           break;
1593         }
1594       if (LocaleCompare(attribute,"iterations") == 0)
1595         {
1596   iterations:
1597           for ( ; image; image=image->next)
1598             image->iterations=SvIV(sval);
1599           break;
1600         }
1601       if (LocaleCompare(attribute,"interlace") == 0)
1602         {
1603           sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1604             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1605           if (sp < 0)
1606             {
1607               ThrowPerlException(exception,OptionError,
1608                 "UnrecognizedInterlaceType",SvPV(sval,na));
1609               break;
1610             }
1611           if (info)
1612             info->image_info->interlace=(InterlaceType) sp;
1613           for ( ; image; image=image->next)
1614             image->interlace=(InterlaceType) sp;
1615           break;
1616         }
1617       if (info)
1618         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1619       for ( ; image; image=image->next)
1620         SetImageProperty(image,attribute,SvPV(sval,na));
1621       break;
1622     }
1623     case 'L':
1624     case 'l':
1625     {
1626       if (LocaleCompare(attribute,"label") == 0)
1627         {
1628           for ( ; image; image=image->next)
1629             (void) SetImageProperty(image,"label",InterpretImageProperties(
1630               info ? info->image_info : (ImageInfo *) NULL,image,
1631               SvPV(sval,na)));
1632           break;
1633         }
1634       if (LocaleCompare(attribute,"loop") == 0)
1635         goto iterations;
1636       if (info)
1637         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1638       for ( ; image; image=image->next)
1639         SetImageProperty(image,attribute,SvPV(sval,na));
1640       break;
1641     }
1642     case 'M':
1643     case 'm':
1644     {
1645       if (LocaleCompare(attribute,"magick") == 0)
1646         {
1647           if (info)
1648             (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
1649               "%s:",SvPV(sval,na));
1650           for ( ; image; image=image->next)
1651             (void) CopyMagickString(image->magick,SvPV(sval,na),MaxTextExtent);
1652           break;
1653         }
1654       if (LocaleCompare(attribute,"map-limit") == 0)
1655         {
1656           MagickSizeType
1657             limit;
1658
1659           limit=MagickResourceInfinity;
1660           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1661             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1662           (void) SetMagickResourceLimit(MapResource,limit);
1663           break;
1664         }
1665       if (LocaleCompare(attribute,"mask") == 0)
1666         {
1667           Image
1668             *mask;
1669
1670           mask=(Image *) NULL;
1671           if (SvPOK(sval))
1672             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1673           for ( ; image; image=image->next)
1674             SetImageMask(image,mask);
1675           break;
1676         }
1677       if (LocaleCompare(attribute,"mattecolor") == 0)
1678         {
1679           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1680           if (info)
1681             info->image_info->matte_color=target_color;
1682           for ( ; image; image=image->next)
1683             image->matte_color=target_color;
1684           break;
1685         }
1686       if (LocaleCompare(attribute,"matte") == 0)
1687         {
1688           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1689             SvPV(sval,na)) : SvIV(sval);
1690           if (sp < 0)
1691             {
1692               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1693                 SvPV(sval,na));
1694               break;
1695             }
1696           for ( ; image; image=image->next)
1697             image->matte=sp != 0 ? MagickTrue : MagickFalse;
1698           break;
1699         }
1700       if (LocaleCompare(attribute,"memory-limit") == 0)
1701         {
1702           MagickSizeType
1703             limit;
1704
1705           limit=MagickResourceInfinity;
1706           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1707             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1708           (void) SetMagickResourceLimit(MemoryResource,limit);
1709           break;
1710         }
1711       if (LocaleCompare(attribute,"monochrome") == 0)
1712         {
1713           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1714             SvPV(sval,na)) : SvIV(sval);
1715           if (sp < 0)
1716             {
1717               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1718                 SvPV(sval,na));
1719               break;
1720             }
1721           if (info)
1722             info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1723           for ( ; image; image=image->next)
1724             (void) SetImageType(image,BilevelType);
1725           break;
1726         }
1727       if (info)
1728         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1729       for ( ; image; image=image->next)
1730         SetImageProperty(image,attribute,SvPV(sval,na));
1731       break;
1732     }
1733     case 'O':
1734     case 'o':
1735     {
1736       if (LocaleCompare(attribute,"option") == 0)
1737         {
1738           if (info)
1739             DefineImageOption(info->image_info,SvPV(sval,na));
1740           break;
1741         }
1742       if (LocaleCompare(attribute,"orientation") == 0)
1743         {
1744           sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1745             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1746           if (sp < 0)
1747             {
1748               ThrowPerlException(exception,OptionError,
1749                 "UnrecognizedOrientationType",SvPV(sval,na));
1750               break;
1751             }
1752           if (info)
1753             info->image_info->orientation=(OrientationType) sp;
1754           for ( ; image; image=image->next)
1755             image->orientation=(OrientationType) sp;
1756           break;
1757         }
1758       if (info)
1759         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1760       for ( ; image; image=image->next)
1761         SetImageProperty(image,attribute,SvPV(sval,na));
1762       break;
1763     }
1764     case 'P':
1765     case 'p':
1766     {
1767       if (LocaleCompare(attribute,"page") == 0)
1768         {
1769           char
1770             *geometry;
1771
1772           geometry=GetPageGeometry(SvPV(sval,na));
1773           if (info)
1774             (void) CloneString(&info->image_info->page,geometry);
1775           for ( ; image; image=image->next)
1776             (void) ParsePageGeometry(image,geometry,&image->page,exception);
1777           geometry=(char *) RelinquishMagickMemory(geometry);
1778           break;
1779         }
1780       if (LocaleCompare(attribute,"pen") == 0)
1781         {
1782           if (info)
1783             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1784           break;
1785         }
1786       if (LocaleNCompare(attribute,"pixel",5) == 0)
1787         {
1788           int
1789             items;
1790
1791           PixelInfo
1792             pixel;
1793
1794           register Quantum
1795             *q;
1796
1797           CacheView
1798             *image_view;
1799
1800           for ( ; image; image=image->next)
1801           {
1802             if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1803               break;
1804             x=0;
1805             y=0;
1806             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1807             (void) items;
1808             image_view=AcquireCacheView(image);
1809             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1810             if (q != (Quantum *) NULL)
1811               {
1812                 if ((strchr(SvPV(sval,na),',') == 0) ||
1813                     (strchr(SvPV(sval,na),')') != 0))
1814                   QueryMagickColor(SvPV(sval,na),&pixel,exception);
1815                 else
1816                   {
1817                     GetPixelInfo(image,&pixel);
1818                     flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1819                     pixel.red=geometry_info.rho;
1820                     if ((flags & SigmaValue) != 0)
1821                       pixel.green=geometry_info.sigma;
1822                     if ((flags & XiValue) != 0)
1823                       pixel.blue=geometry_info.xi;
1824                     if ((flags & PsiValue) != 0)
1825                       pixel.alpha=geometry_info.psi;
1826                     if ((flags & ChiValue) != 0)
1827                       pixel.black=geometry_info.chi;
1828                   }
1829                 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1830                 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1831                 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1832                 if (image->colorspace == CMYKColorspace)
1833                   SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1834                 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1835                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1836               }
1837             image_view=DestroyCacheView(image_view);
1838           }
1839           break;
1840         }
1841       if (LocaleCompare(attribute,"pointsize") == 0)
1842         {
1843           if (info)
1844             {
1845               (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1846               info->image_info->pointsize=geometry_info.rho;
1847             }
1848           break;
1849         }
1850       if (LocaleCompare(attribute,"preview") == 0)
1851         {
1852           sp=SvPOK(sval) ? ParseCommandOption(MagickPreviewOptions,MagickFalse,
1853             SvPV(sval,na)) : SvIV(sval);
1854           if (sp < 0)
1855             {
1856               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1857                 SvPV(sval,na));
1858               break;
1859             }
1860           if (info)
1861             info->image_info->preview_type=(PreviewType) sp;
1862           break;
1863         }
1864       if (info)
1865         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1866       for ( ; image; image=image->next)
1867         SetImageProperty(image,attribute,SvPV(sval,na));
1868       break;
1869     }
1870     case 'Q':
1871     case 'q':
1872     {
1873       if (LocaleCompare(attribute,"quality") == 0)
1874         {
1875           if (info)
1876             info->image_info->quality=SvIV(sval);
1877           for ( ; image; image=image->next)
1878             image->quality=SvIV(sval);
1879           break;
1880         }
1881       if (info)
1882         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1883       for ( ; image; image=image->next)
1884         SetImageProperty(image,attribute,SvPV(sval,na));
1885       break;
1886     }
1887     case 'R':
1888     case 'r':
1889     {
1890       if (LocaleCompare(attribute,"red-primary") == 0)
1891         {
1892           for ( ; image; image=image->next)
1893           {
1894             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1895             image->chromaticity.red_primary.x=geometry_info.rho;
1896             image->chromaticity.red_primary.y=geometry_info.sigma;
1897             if ((flags & SigmaValue) == 0)
1898               image->chromaticity.red_primary.y=
1899                 image->chromaticity.red_primary.x;
1900           }
1901           break;
1902         }
1903       if (LocaleCompare(attribute,"render") == 0)
1904         {
1905           sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1906             SvPV(sval,na)) : SvIV(sval);
1907           if (sp < 0)
1908             {
1909               ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1910                 SvPV(sval,na));
1911               break;
1912             }
1913          for ( ; image; image=image->next)
1914            image->rendering_intent=(RenderingIntent) sp;
1915          break;
1916        }
1917       if (LocaleCompare(attribute,"repage") == 0)
1918         {
1919           RectangleInfo
1920             geometry;
1921
1922           for ( ; image; image=image->next)
1923           {
1924             flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
1925             if ((flags & WidthValue) != 0)
1926               {
1927                 if ((flags & HeightValue) == 0)
1928                   geometry.height=geometry.width;
1929                 image->page.width=geometry.width;
1930                 image->page.height=geometry.height;
1931               }
1932             if ((flags & AspectValue) != 0)
1933               {
1934                 if ((flags & XValue) != 0)
1935                   image->page.x+=geometry.x;
1936                 if ((flags & YValue) != 0)
1937                   image->page.y+=geometry.y;
1938               }
1939             else
1940               {
1941                 if ((flags & XValue) != 0)
1942                   {
1943                     image->page.x=geometry.x;
1944                     if (((flags & WidthValue) != 0) && (geometry.x > 0))
1945                       image->page.width=image->columns+geometry.x;
1946                   }
1947                 if ((flags & YValue) != 0)
1948                   {
1949                     image->page.y=geometry.y;
1950                     if (((flags & HeightValue) != 0) && (geometry.y > 0))
1951                       image->page.height=image->rows+geometry.y;
1952                   }
1953               }
1954           }
1955           break;
1956         }
1957       if (info)
1958         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1959       for ( ; image; image=image->next)
1960         SetImageProperty(image,attribute,SvPV(sval,na));
1961       break;
1962     }
1963     case 'S':
1964     case 's':
1965     {
1966       if (LocaleCompare(attribute,"sampling-factor") == 0)
1967         {
1968           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1969             {
1970               ThrowPerlException(exception,OptionError,"MissingGeometry",
1971                 SvPV(sval,na));
1972               break;
1973             }
1974           if (info)
1975             (void) CloneString(&info->image_info->sampling_factor,
1976               SvPV(sval,na));
1977           break;
1978         }
1979       if (LocaleCompare(attribute,"scene") == 0)
1980         {
1981           for ( ; image; image=image->next)
1982             image->scene=SvIV(sval);
1983           break;
1984         }
1985       if (LocaleCompare(attribute,"server") == 0)
1986         goto display;
1987       if (LocaleCompare(attribute,"size") == 0)
1988         {
1989           if (info)
1990             {
1991               if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1992                 {
1993                   ThrowPerlException(exception,OptionError,"MissingGeometry",
1994                     SvPV(sval,na));
1995                   break;
1996                 }
1997               (void) CloneString(&info->image_info->size,SvPV(sval,na));
1998             }
1999           break;
2000         }
2001       if (LocaleCompare(attribute,"stroke") == 0)
2002         {
2003           if (info)
2004             (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2005           break;
2006         }
2007       if (info)
2008         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2009       for ( ; image; image=image->next)
2010         SetImageProperty(image,attribute,SvPV(sval,na));
2011       break;
2012     }
2013     case 'T':
2014     case 't':
2015     {
2016       if (LocaleCompare(attribute,"texture") == 0)
2017         {
2018           if (info)
2019             (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2020           break;
2021         }
2022       if (LocaleCompare(attribute,"thread-limit") == 0)
2023         {
2024           MagickSizeType
2025             limit;
2026
2027           limit=MagickResourceInfinity;
2028           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2029             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
2030           (void) SetMagickResourceLimit(ThreadResource,limit);
2031           break;
2032         }
2033       if (LocaleCompare(attribute,"tile-offset") == 0)
2034         {
2035           char
2036             *geometry;
2037
2038           geometry=GetPageGeometry(SvPV(sval,na));
2039           if (info)
2040             (void) CloneString(&info->image_info->page,geometry);
2041           for ( ; image; image=image->next)
2042             (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2043               exception);
2044           geometry=(char *) RelinquishMagickMemory(geometry);
2045           break;
2046         }
2047       if (LocaleCompare(attribute,"time-limit") == 0)
2048         {
2049           MagickSizeType
2050             limit;
2051
2052           limit=MagickResourceInfinity;
2053           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2054             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
2055           (void) SetMagickResourceLimit(TimeResource,limit);
2056           break;
2057         }
2058       if (LocaleCompare(attribute,"transparent-color") == 0)
2059         {
2060           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
2061           if (info)
2062             info->image_info->transparent_color=target_color;
2063           for ( ; image; image=image->next)
2064             image->transparent_color=target_color;
2065           break;
2066         }
2067       if (LocaleCompare(attribute,"type") == 0)
2068         {
2069           sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2070             SvPV(sval,na)) : SvIV(sval);
2071           if (sp < 0)
2072             {
2073               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2074                 SvPV(sval,na));
2075               break;
2076             }
2077           if (info)
2078             info->image_info->type=(ImageType) sp;
2079           for ( ; image; image=image->next)
2080             SetImageType(image,(ImageType) sp);
2081           break;
2082         }
2083       if (info)
2084         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2085       for ( ; image; image=image->next)
2086         SetImageProperty(image,attribute,SvPV(sval,na));
2087       break;
2088     }
2089     case 'U':
2090     case 'u':
2091     {
2092       if (LocaleCompare(attribute,"units") == 0)
2093         {
2094           sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2095             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2096           if (sp < 0)
2097             {
2098               ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2099                 SvPV(sval,na));
2100               break;
2101             }
2102           if (info)
2103             info->image_info->units=(ResolutionType) sp;
2104           for ( ; image; image=image->next)
2105           {
2106             ResolutionType
2107               units;
2108
2109             units=(ResolutionType) sp;
2110             if (image->units != units)
2111               switch (image->units)
2112               {
2113                 case UndefinedResolution:
2114                 case PixelsPerInchResolution:
2115                 {
2116                   if (units == PixelsPerCentimeterResolution)
2117                     {
2118                       image->x_resolution*=2.54;
2119                       image->y_resolution*=2.54;
2120                     }
2121                   break;
2122                 }
2123                 case PixelsPerCentimeterResolution:
2124                 {
2125                   if (units == PixelsPerInchResolution)
2126                     {
2127                       image->x_resolution/=2.54;
2128                       image->y_resolution/=2.54;
2129                     }
2130                   break;
2131                 }
2132               }
2133             image->units=units;
2134           }
2135           break;
2136         }
2137       if (info)
2138         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2139       for ( ; image; image=image->next)
2140         SetImageProperty(image,attribute,SvPV(sval,na));
2141       break;
2142     }
2143     case 'V':
2144     case 'v':
2145     {
2146       if (LocaleCompare(attribute,"verbose") == 0)
2147         {
2148           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2149             SvPV(sval,na)) : SvIV(sval);
2150           if (sp < 0)
2151             {
2152               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2153                 SvPV(sval,na));
2154               break;
2155             }
2156           if (info)
2157             info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2158           break;
2159         }
2160       if (LocaleCompare(attribute,"view") == 0)
2161         {
2162           if (info)
2163             (void) CloneString(&info->image_info->view,SvPV(sval,na));
2164           break;
2165         }
2166       if (LocaleCompare(attribute,"virtual-pixel") == 0)
2167         {
2168           sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2169             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2170           if (sp < 0)
2171             {
2172               ThrowPerlException(exception,OptionError,
2173                 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2174               break;
2175             }
2176           if (info)
2177             info->image_info->virtual_pixel_method=(VirtualPixelMethod) sp;
2178           for ( ; image; image=image->next)
2179             SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp);
2180           break;
2181         }
2182       if (info)
2183         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2184       for ( ; image; image=image->next)
2185         SetImageProperty(image,attribute,SvPV(sval,na));
2186       break;
2187     }
2188     case 'W':
2189     case 'w':
2190     {
2191       if (LocaleCompare(attribute,"white-point") == 0)
2192         {
2193           for ( ; image; image=image->next)
2194           {
2195             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2196             image->chromaticity.white_point.x=geometry_info.rho;
2197             image->chromaticity.white_point.y=geometry_info.sigma;
2198             if ((flags & SigmaValue) == 0)
2199               image->chromaticity.white_point.y=
2200                 image->chromaticity.white_point.x;
2201           }
2202           break;
2203         }
2204       if (info)
2205         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2206       for ( ; image; image=image->next)
2207         SetImageProperty(image,attribute,SvPV(sval,na));
2208       break;
2209     }
2210     default:
2211     {
2212       if (info)
2213         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2214       for ( ; image; image=image->next)
2215         SetImageProperty(image,attribute,SvPV(sval,na));
2216       break;
2217     }
2218   }
2219 }
2220 \f
2221 /*
2222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2223 %                                                                             %
2224 %                                                                             %
2225 %                                                                             %
2226 %   S e t u p L i s t                                                         %
2227 %                                                                             %
2228 %                                                                             %
2229 %                                                                             %
2230 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2231 %
2232 %  Method SetupList returns the list of all the images linked by their
2233 %  image->next and image->previous link lists for use with ImageMagick.  If
2234 %  info is non-NULL, an info structure is returned in *info.  If
2235 %  reference_vector is non-NULL,an array of SV* are returned in
2236 %  *reference_vector.  Reference_vector is used when the images are going to be
2237 %  replaced with new Image*'s.
2238 %
2239 %  The format of the SetupList routine is:
2240 %
2241 %      Image *SetupList(SV *reference,struct PackageInfo **info,
2242 %        SV ***reference_vector,ExceptionInfo *exception)
2243 %
2244 %  A description of each parameter follows:
2245 %
2246 %    o list: a list of strings.
2247 %
2248 %    o string: a character string.
2249 %
2250 %    o exception: Return any errors or warnings in this structure.
2251 %
2252 */
2253 static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2254   SV ***reference_vector,ExceptionInfo *exception)
2255 {
2256   Image
2257     *image;
2258
2259   ssize_t
2260     current,
2261     last;
2262
2263   if (reference_vector)
2264     *reference_vector=NULL;
2265   if (info)
2266     *info=NULL;
2267   current=0;
2268   last=0;
2269   image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2270   if (info && (SvTYPE(reference) == SVt_PVAV))
2271     *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2272       exception);
2273   return(image);
2274 }
2275 \f
2276 /*
2277 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2278 %                                                                             %
2279 %                                                                             %
2280 %                                                                             %
2281 %   s t r E Q c a s e                                                         %
2282 %                                                                             %
2283 %                                                                             %
2284 %                                                                             %
2285 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2286 %
2287 %  strEQcase() compares two strings and returns 0 if they are the
2288 %  same or if the second string runs out first.  The comparison is case
2289 %  insensitive.
2290 %
2291 %  The format of the strEQcase routine is:
2292 %
2293 %      ssize_t strEQcase(const char *p,const char *q)
2294 %
2295 %  A description of each parameter follows:
2296 %
2297 %    o p: a character string.
2298 %
2299 %    o q: a character string.
2300 %
2301 %
2302 */
2303 static ssize_t strEQcase(const char *p,const char *q)
2304 {
2305   char
2306     c;
2307
2308   register ssize_t
2309     i;
2310
2311   for (i=0 ; (c=(*q)) != 0; i++)
2312   {
2313     if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2314         (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2315       return(0);
2316     p++;
2317     q++;
2318   }
2319   return(((*q == 0) && (*p == 0)) ? i : 0);
2320 }
2321 \f
2322 /*
2323 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2324 %                                                                             %
2325 %                                                                             %
2326 %                                                                             %
2327 %   I m a g e : : M a g i c k                                                 %
2328 %                                                                             %
2329 %                                                                             %
2330 %                                                                             %
2331 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2332 %
2333 %
2334 */
2335 MODULE = Image::Magick PACKAGE = Image::Magick
2336
2337 PROTOTYPES: ENABLE
2338
2339 BOOT:
2340   MagickCoreGenesis("PerlMagick",MagickFalse);
2341   SetWarningHandler(NULL);
2342   SetErrorHandler(NULL);
2343   magick_registry=NewSplayTree((int (*)(const void *,const void *))
2344     NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2345
2346 void
2347 UNLOAD()
2348   PPCODE:
2349   {
2350     if (magick_registry != (SplayTreeInfo *) NULL)
2351       magick_registry=DestroySplayTree(magick_registry);
2352     MagickCoreTerminus();
2353   }
2354
2355 double
2356 constant(name,argument)
2357   char *name
2358   ssize_t argument
2359 \f
2360 #
2361 ###############################################################################
2362 #                                                                             #
2363 #                                                                             #
2364 #                                                                             #
2365 #   A n i m a t e                                                             #
2366 #                                                                             #
2367 #                                                                             #
2368 #                                                                             #
2369 ###############################################################################
2370 #
2371 #
2372 void
2373 Animate(ref,...)
2374   Image::Magick ref=NO_INIT
2375   ALIAS:
2376     AnimateImage  = 1
2377     animate       = 2
2378     animateimage  = 3
2379   PPCODE:
2380   {
2381     ExceptionInfo
2382       *exception;
2383
2384     Image
2385       *image;
2386
2387     register ssize_t
2388       i;
2389
2390     struct PackageInfo
2391       *info,
2392       *package_info;
2393
2394     SV
2395       *perl_exception,
2396       *reference;
2397
2398     PERL_UNUSED_VAR(ref);
2399     PERL_UNUSED_VAR(ix);
2400     exception=AcquireExceptionInfo();
2401     perl_exception=newSVpv("",0);
2402     package_info=(struct PackageInfo *) NULL;
2403     if (sv_isobject(ST(0)) == 0)
2404       {
2405         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2406           PackageName);
2407         goto PerlException;
2408       }
2409     reference=SvRV(ST(0));
2410     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2411     if (image == (Image *) NULL)
2412       {
2413         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2414           PackageName);
2415         goto PerlException;
2416       }
2417     package_info=ClonePackageInfo(info,exception);
2418     if (items == 2)
2419       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2420     else
2421       if (items > 2)
2422         for (i=2; i < items; i+=2)
2423           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2424             exception);
2425     (void) AnimateImages(package_info->image_info,image);
2426     (void) CatchImageException(image);
2427     InheritException(exception,&image->exception);
2428
2429   PerlException:
2430     if (package_info != (struct PackageInfo *) NULL)
2431       DestroyPackageInfo(package_info);
2432     InheritPerlException(exception,perl_exception);
2433     exception=DestroyExceptionInfo(exception);
2434     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2435     SvPOK_on(perl_exception);
2436     ST(0)=sv_2mortal(perl_exception);
2437     XSRETURN(1);
2438   }
2439 \f
2440 #
2441 ###############################################################################
2442 #                                                                             #
2443 #                                                                             #
2444 #                                                                             #
2445 #   A p p e n d                                                               #
2446 #                                                                             #
2447 #                                                                             #
2448 #                                                                             #
2449 ###############################################################################
2450 #
2451 #
2452 void
2453 Append(ref,...)
2454   Image::Magick ref=NO_INIT
2455   ALIAS:
2456     AppendImage  = 1
2457     append       = 2
2458     appendimage  = 3
2459   PPCODE:
2460   {
2461     AV
2462       *av;
2463
2464     char
2465       *attribute;
2466
2467     ExceptionInfo
2468       *exception;
2469
2470     HV
2471       *hv;
2472
2473     Image
2474       *image;
2475
2476     register ssize_t
2477       i;
2478
2479     ssize_t
2480       stack;
2481
2482     struct PackageInfo
2483       *info;
2484
2485     SV
2486       *av_reference,
2487       *perl_exception,
2488       *reference,
2489       *rv,
2490       *sv;
2491
2492     PERL_UNUSED_VAR(ref);
2493     PERL_UNUSED_VAR(ix);
2494     exception=AcquireExceptionInfo();
2495     perl_exception=newSVpv("",0);
2496     sv=NULL;
2497     attribute=NULL;
2498     av=NULL;
2499     if (sv_isobject(ST(0)) == 0)
2500       {
2501         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2502           PackageName);
2503         goto PerlException;
2504       }
2505     reference=SvRV(ST(0));
2506     hv=SvSTASH(reference);
2507     av=newAV();
2508     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2509     SvREFCNT_dec(av);
2510     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2511     if (image == (Image *) NULL)
2512       {
2513         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2514           PackageName);
2515         goto PerlException;
2516       }
2517     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2518     /*
2519       Get options.
2520     */
2521     stack=MagickTrue;
2522     for (i=2; i < items; i+=2)
2523     {
2524       attribute=(char *) SvPV(ST(i-1),na);
2525       switch (*attribute)
2526       {
2527         case 'S':
2528         case 's':
2529         {
2530           if (LocaleCompare(attribute,"stack") == 0)
2531             {
2532               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2533                 SvPV(ST(i),na));
2534               if (stack < 0)
2535                 {
2536                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
2537                     SvPV(ST(i),na));
2538                   return;
2539                 }
2540               break;
2541             }
2542           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2543             attribute);
2544           break;
2545         }
2546         default:
2547         {
2548           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2549             attribute);
2550           break;
2551         }
2552       }
2553     }
2554     image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2555     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2556       goto PerlException;
2557     for ( ; image; image=image->next)
2558     {
2559       AddImageToRegistry(sv,image);
2560       rv=newRV(sv);
2561       av_push(av,sv_bless(rv,hv));
2562       SvREFCNT_dec(sv);
2563     }
2564     exception=DestroyExceptionInfo(exception);
2565     ST(0)=av_reference;
2566     SvREFCNT_dec(perl_exception);
2567     XSRETURN(1);
2568
2569   PerlException:
2570     InheritPerlException(exception,perl_exception);
2571     exception=DestroyExceptionInfo(exception);
2572     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2573     SvPOK_on(perl_exception);
2574     ST(0)=sv_2mortal(perl_exception);
2575     XSRETURN(1);
2576   }
2577 \f
2578 #
2579 ###############################################################################
2580 #                                                                             #
2581 #                                                                             #
2582 #                                                                             #
2583 #   A v e r a g e                                                             #
2584 #                                                                             #
2585 #                                                                             #
2586 #                                                                             #
2587 ###############################################################################
2588 #
2589 #
2590 void
2591 Average(ref)
2592   Image::Magick ref=NO_INIT
2593   ALIAS:
2594     AverageImage   = 1
2595     average        = 2
2596     averageimage   = 3
2597   PPCODE:
2598   {
2599     AV
2600       *av;
2601
2602     char
2603       *p;
2604
2605     ExceptionInfo
2606       *exception;
2607
2608     HV
2609       *hv;
2610
2611     Image
2612       *image;
2613
2614     struct PackageInfo
2615       *info;
2616
2617     SV
2618       *perl_exception,
2619       *reference,
2620       *rv,
2621       *sv;
2622
2623     PERL_UNUSED_VAR(ref);
2624     PERL_UNUSED_VAR(ix);
2625     exception=AcquireExceptionInfo();
2626     perl_exception=newSVpv("",0);
2627     sv=NULL;
2628     if (sv_isobject(ST(0)) == 0)
2629       {
2630         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2631           PackageName);
2632         goto PerlException;
2633       }
2634     reference=SvRV(ST(0));
2635     hv=SvSTASH(reference);
2636     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2637     if (image == (Image *) NULL)
2638       {
2639         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2640           PackageName);
2641         goto PerlException;
2642       }
2643     image=EvaluateImages(image,MeanEvaluateOperator,exception);
2644     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2645       goto PerlException;
2646     /*
2647       Create blessed Perl array for the returned image.
2648     */
2649     av=newAV();
2650     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2651     SvREFCNT_dec(av);
2652     AddImageToRegistry(sv,image);
2653     rv=newRV(sv);
2654     av_push(av,sv_bless(rv,hv));
2655     SvREFCNT_dec(sv);
2656     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2657     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
2658       "average-%.*s",(int) (MaxTextExtent-9),
2659       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2660     (void) CopyMagickString(image->filename,info->image_info->filename,
2661       MaxTextExtent);
2662     SetImageInfo(info->image_info,0,exception);
2663     exception=DestroyExceptionInfo(exception);
2664     SvREFCNT_dec(perl_exception);
2665     XSRETURN(1);
2666
2667   PerlException:
2668     InheritPerlException(exception,perl_exception);
2669     exception=DestroyExceptionInfo(exception);
2670     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2671     SvPOK_on(perl_exception);
2672     ST(0)=sv_2mortal(perl_exception);
2673     XSRETURN(1);
2674   }
2675 \f
2676 #
2677 ###############################################################################
2678 #                                                                             #
2679 #                                                                             #
2680 #                                                                             #
2681 #   B l o b T o I m a g e                                                     #
2682 #                                                                             #
2683 #                                                                             #
2684 #                                                                             #
2685 ###############################################################################
2686 #
2687 #
2688 void
2689 BlobToImage(ref,...)
2690   Image::Magick ref=NO_INIT
2691   ALIAS:
2692     BlobToImage  = 1
2693     blobtoimage  = 2
2694     blobto       = 3
2695   PPCODE:
2696   {
2697     AV
2698       *av;
2699
2700     char
2701       **keep,
2702       **list;
2703
2704     ExceptionInfo
2705       *exception;
2706
2707     HV
2708       *hv;
2709
2710     Image
2711       *image;
2712
2713     register char
2714       **p;
2715
2716     register ssize_t
2717       i;
2718
2719     ssize_t
2720       ac,
2721       n,
2722       number_images;
2723
2724     STRLEN
2725       *length;
2726
2727     struct PackageInfo
2728       *info;
2729
2730     SV
2731       *perl_exception,
2732       *reference,
2733       *rv,
2734       *sv;
2735
2736     PERL_UNUSED_VAR(ref);
2737     PERL_UNUSED_VAR(ix);
2738     exception=AcquireExceptionInfo();
2739     perl_exception=newSVpv("",0);
2740     sv=NULL;
2741     number_images=0;
2742     ac=(items < 2) ? 1 : items-1;
2743     length=(STRLEN *) NULL;
2744     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2745     if (list == (char **) NULL)
2746       {
2747         ThrowPerlException(exception,ResourceLimitError,
2748           "MemoryAllocationFailed",PackageName);
2749         goto PerlException;
2750       }
2751     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2752     if (length == (STRLEN *) NULL)
2753       {
2754         ThrowPerlException(exception,ResourceLimitError,
2755           "MemoryAllocationFailed",PackageName);
2756         goto PerlException;
2757       }
2758     if (sv_isobject(ST(0)) == 0)
2759       {
2760         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2761           PackageName);
2762         goto PerlException;
2763       }
2764     reference=SvRV(ST(0));
2765     hv=SvSTASH(reference);
2766     if (SvTYPE(reference) != SVt_PVAV)
2767       {
2768         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2769           PackageName);
2770         goto PerlException;
2771       }
2772     av=(AV *) reference;
2773     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2774       exception);
2775     n=1;
2776     if (items <= 1)
2777       {
2778         ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2779         goto PerlException;
2780       }
2781     for (n=0, i=0; i < ac; i++)
2782     {
2783       list[n]=(char *) (SvPV(ST(i+1),length[n]));
2784       if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2785         {
2786           list[n]=(char *) (SvPV(ST(i+2),length[n]));
2787           continue;
2788         }
2789       n++;
2790     }
2791     list[n]=(char *) NULL;
2792     keep=list;
2793     for (i=number_images=0; i < n; i++)
2794     {
2795       image=BlobToImage(info->image_info,list[i],length[i],exception);
2796       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2797         break;
2798       for ( ; image; image=image->next)
2799       {
2800         AddImageToRegistry(sv,image);
2801         rv=newRV(sv);
2802         av_push(av,sv_bless(rv,hv));
2803         SvREFCNT_dec(sv);
2804         number_images++;
2805       }
2806     }
2807     /*
2808       Free resources.
2809     */
2810     for (i=0; i < n; i++)
2811       if (list[i] != (char *) NULL)
2812         for (p=keep; list[i] != *p++; )
2813           if (*p == (char *) NULL)
2814             {
2815               list[i]=(char *) RelinquishMagickMemory(list[i]);
2816               break;
2817             }
2818
2819   PerlException:
2820     if (list)
2821       list=(char **) RelinquishMagickMemory(list);
2822     if (length)
2823       length=(STRLEN *) RelinquishMagickMemory(length);
2824     InheritPerlException(exception,perl_exception);
2825     exception=DestroyExceptionInfo(exception);
2826     sv_setiv(perl_exception,(IV) number_images);
2827     SvPOK_on(perl_exception);
2828     ST(0)=sv_2mortal(perl_exception);
2829     XSRETURN(1);
2830   }
2831 \f
2832 #
2833 ###############################################################################
2834 #                                                                             #
2835 #                                                                             #
2836 #                                                                             #
2837 #   C l o n e                                                                 #
2838 #                                                                             #
2839 #                                                                             #
2840 #                                                                             #
2841 ###############################################################################
2842 #
2843 #
2844 void
2845 Clone(ref)
2846   Image::Magick ref=NO_INIT
2847   ALIAS:
2848     CopyImage   = 1
2849     copy        = 2
2850     copyimage   = 3
2851     CloneImage  = 4
2852     clone       = 5
2853     cloneimage  = 6
2854     Clone       = 7
2855   PPCODE:
2856   {
2857     AV
2858       *av;
2859
2860     ExceptionInfo
2861       *exception;
2862
2863     HV
2864       *hv;
2865
2866     Image
2867       *clone,
2868       *image;
2869
2870     struct PackageInfo
2871       *info;
2872
2873     SV
2874       *perl_exception,
2875       *reference,
2876       *rv,
2877       *sv;
2878
2879     PERL_UNUSED_VAR(ref);
2880     PERL_UNUSED_VAR(ix);
2881     exception=AcquireExceptionInfo();
2882     perl_exception=newSVpv("",0);
2883     sv=NULL;
2884     if (sv_isobject(ST(0)) == 0)
2885       {
2886         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2887           PackageName);
2888         goto PerlException;
2889       }
2890     reference=SvRV(ST(0));
2891     hv=SvSTASH(reference);
2892     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2893     if (image == (Image *) NULL)
2894       {
2895         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2896           PackageName);
2897         goto PerlException;
2898       }
2899     /*
2900       Create blessed Perl array for the returned image.
2901     */
2902     av=newAV();
2903     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2904     SvREFCNT_dec(av);
2905     for ( ; image; image=image->next)
2906     {
2907       clone=CloneImage(image,0,0,MagickTrue,exception);
2908       if ((clone == (Image *) NULL) || (exception->severity >= ErrorException))
2909         break;
2910       AddImageToRegistry(sv,clone);
2911       rv=newRV(sv);
2912       av_push(av,sv_bless(rv,hv));
2913       SvREFCNT_dec(sv);
2914     }
2915     exception=DestroyExceptionInfo(exception);
2916     SvREFCNT_dec(perl_exception);
2917     XSRETURN(1);
2918
2919   PerlException:
2920     InheritPerlException(exception,perl_exception);
2921     exception=DestroyExceptionInfo(exception);
2922     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2923     SvPOK_on(perl_exception);
2924     ST(0)=sv_2mortal(perl_exception);
2925     XSRETURN(1);
2926   }
2927 \f
2928 #
2929 ###############################################################################
2930 #                                                                             #
2931 #                                                                             #
2932 #                                                                             #
2933 #   C L O N E                                                                 #
2934 #                                                                             #
2935 #                                                                             #
2936 #                                                                             #
2937 ###############################################################################
2938 #
2939 #
2940 void
2941 CLONE(ref,...)
2942   SV *ref;
2943   CODE:
2944   {
2945     PERL_UNUSED_VAR(ref);
2946     if (magick_registry != (SplayTreeInfo *) NULL)
2947       {
2948         register Image
2949           *p;
2950
2951         ResetSplayTreeIterator(magick_registry);
2952         p=(Image *) GetNextKeyInSplayTree(magick_registry);
2953         while (p != (Image *) NULL)
2954         {
2955           ReferenceImage(p);
2956           p=(Image *) GetNextKeyInSplayTree(magick_registry);
2957         }
2958       }
2959   }
2960 \f
2961 #
2962 ###############################################################################
2963 #                                                                             #
2964 #                                                                             #
2965 #                                                                             #
2966 #   C o a l e s c e                                                           #
2967 #                                                                             #
2968 #                                                                             #
2969 #                                                                             #
2970 ###############################################################################
2971 #
2972 #
2973 void
2974 Coalesce(ref)
2975   Image::Magick ref=NO_INIT
2976   ALIAS:
2977     CoalesceImage   = 1
2978     coalesce        = 2
2979     coalesceimage   = 3
2980   PPCODE:
2981   {
2982     AV
2983       *av;
2984
2985     ExceptionInfo
2986       *exception;
2987
2988     HV
2989       *hv;
2990
2991     Image
2992       *image;
2993
2994     struct PackageInfo
2995       *info;
2996
2997     SV
2998       *av_reference,
2999       *perl_exception,
3000       *reference,
3001       *rv,
3002       *sv;
3003
3004     PERL_UNUSED_VAR(ref);
3005     PERL_UNUSED_VAR(ix);
3006     exception=AcquireExceptionInfo();
3007     perl_exception=newSVpv("",0);
3008     sv=NULL;
3009     if (sv_isobject(ST(0)) == 0)
3010       {
3011         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3012           PackageName);
3013         goto PerlException;
3014       }
3015     reference=SvRV(ST(0));
3016     hv=SvSTASH(reference);
3017     av=newAV();
3018     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3019     SvREFCNT_dec(av);
3020     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3021     if (image == (Image *) NULL)
3022       {
3023         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3024           PackageName);
3025         goto PerlException;
3026       }
3027     image=CoalesceImages(image,exception);
3028     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3029       goto PerlException;
3030     for ( ; image; image=image->next)
3031     {
3032       AddImageToRegistry(sv,image);
3033       rv=newRV(sv);
3034       av_push(av,sv_bless(rv,hv));
3035       SvREFCNT_dec(sv);
3036     }
3037     exception=DestroyExceptionInfo(exception);
3038     ST(0)=av_reference;
3039     SvREFCNT_dec(perl_exception);
3040     XSRETURN(1);
3041
3042   PerlException:
3043     InheritPerlException(exception,perl_exception);
3044     exception=DestroyExceptionInfo(exception);
3045     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3046     SvPOK_on(perl_exception);
3047     ST(0)=sv_2mortal(perl_exception);
3048     XSRETURN(1);
3049   }
3050 \f
3051 #
3052 ###############################################################################
3053 #                                                                             #
3054 #                                                                             #
3055 #                                                                             #
3056 #   C o m p a r e                                                             #
3057 #                                                                             #
3058 #                                                                             #
3059 #                                                                             #
3060 ###############################################################################
3061 #
3062 #
3063 void
3064 Compare(ref,...)
3065   Image::Magick ref=NO_INIT
3066   ALIAS:
3067     CompareImages = 1
3068     compare      = 2
3069     compareimage = 3
3070   PPCODE:
3071   {
3072     AV
3073       *av;
3074
3075     char
3076       *attribute;
3077
3078     double
3079       distortion;
3080
3081     ExceptionInfo
3082       *exception;
3083
3084     HV
3085       *hv;
3086
3087     Image
3088       *difference_image,
3089       *image,
3090       *reconstruct_image;
3091
3092     MetricType
3093       metric;
3094
3095     register ssize_t
3096       i;
3097
3098     ssize_t
3099       option;
3100
3101     struct PackageInfo
3102       *info;
3103
3104     SV
3105       *av_reference,
3106       *perl_exception,
3107       *reference,
3108       *rv,
3109       *sv;
3110
3111     PERL_UNUSED_VAR(ref);
3112     PERL_UNUSED_VAR(ix);
3113     exception=AcquireExceptionInfo();
3114     perl_exception=newSVpv("",0);
3115     sv=NULL;
3116     av=NULL;
3117     attribute=NULL;
3118     if (sv_isobject(ST(0)) == 0)
3119       {
3120         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3121           PackageName);
3122         goto PerlException;
3123       }
3124     reference=SvRV(ST(0));
3125     hv=SvSTASH(reference);
3126     av=newAV();
3127     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3128     SvREFCNT_dec(av);
3129     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3130     if (image == (Image *) NULL)
3131       {
3132         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3133           PackageName);
3134         goto PerlException;
3135       }
3136     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3137     /*
3138       Get attribute.
3139     */
3140     reconstruct_image=image;
3141     metric=RootMeanSquaredErrorMetric;
3142     for (i=2; i < items; i+=2)
3143     {
3144       attribute=(char *) SvPV(ST(i-1),na);
3145       switch (*attribute)
3146       {
3147         case 'C':
3148         case 'c':
3149         {
3150           if (LocaleCompare(attribute,"channel") == 0)
3151             {
3152               ssize_t
3153                 option;
3154
3155               option=ParseChannelOption(SvPV(ST(i),na));
3156               if (option < 0)
3157                 {
3158                   ThrowPerlException(exception,OptionError,
3159                     "UnrecognizedType",SvPV(ST(i),na));
3160                   return;
3161                 }
3162               SetPixelChannelMap(image,(ChannelType) option);
3163               break;
3164             }
3165           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3166             attribute);
3167           break;
3168         }
3169         case 'F':
3170         case 'f':
3171         {
3172           if (LocaleCompare(attribute,"fuzz") == 0)
3173             {
3174               image->fuzz=SiPrefixToDouble(SvPV(ST(i),na),100.0);
3175               break;
3176             }
3177           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3178             attribute);
3179           break;
3180         }
3181         case 'I':
3182         case 'i':
3183         {
3184           if (LocaleCompare(attribute,"image") == 0)
3185             {
3186               reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3187                 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3188               break;
3189             }
3190           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3191             attribute);
3192           break;
3193         }
3194         case 'M':
3195         case 'm':
3196         {
3197           if (LocaleCompare(attribute,"metric") == 0)
3198             {
3199               option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3200                 SvPV(ST(i),na));
3201               if (option < 0)
3202                 {
3203                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3204                     SvPV(ST(i),na));
3205                   break;
3206                 }
3207               metric=(MetricType) option;
3208               break;
3209             }
3210           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3211             attribute);
3212           break;
3213         }
3214         default:
3215         {
3216           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3217             attribute);
3218           break;
3219         }
3220       }
3221     }
3222     difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3223       exception);
3224     if (difference_image != (Image *) NULL)
3225       {
3226         difference_image->error.mean_error_per_pixel=distortion;
3227         AddImageToRegistry(sv,difference_image);
3228         rv=newRV(sv);
3229         av_push(av,sv_bless(rv,hv));
3230         SvREFCNT_dec(sv);
3231       }
3232     exception=DestroyExceptionInfo(exception);
3233     ST(0)=av_reference;
3234     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3235     XSRETURN(1);
3236
3237   PerlException:
3238     InheritPerlException(exception,perl_exception);
3239     exception=DestroyExceptionInfo(exception);
3240     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3241     SvPOK_on(perl_exception);
3242     ST(0)=sv_2mortal(perl_exception);
3243     XSRETURN(1);
3244   }
3245 \f
3246 #
3247 ###############################################################################
3248 #                                                                             #
3249 #                                                                             #
3250 #                                                                             #
3251 #   C o m p a r e L a y e r s                                                 #
3252 #                                                                             #
3253 #                                                                             #
3254 #                                                                             #
3255 ###############################################################################
3256 #
3257 #
3258 void
3259 CompareLayers(ref)
3260   Image::Magick ref=NO_INIT
3261   ALIAS:
3262     CompareImagesLayers   = 1
3263     comparelayers        = 2
3264     compareimagelayers   = 3
3265   PPCODE:
3266   {
3267     AV
3268       *av;
3269
3270     char
3271       *attribute;
3272
3273     ExceptionInfo
3274       *exception;
3275
3276     HV
3277       *hv;
3278
3279     Image
3280       *image;
3281
3282     ImageLayerMethod
3283       method;
3284
3285     register ssize_t
3286       i;
3287
3288     ssize_t
3289       option;
3290
3291     struct PackageInfo
3292       *info;
3293
3294     SV
3295       *av_reference,
3296       *perl_exception,
3297       *reference,
3298       *rv,
3299       *sv;
3300
3301     PERL_UNUSED_VAR(ref);
3302     PERL_UNUSED_VAR(ix);
3303     exception=AcquireExceptionInfo();
3304     perl_exception=newSVpv("",0);
3305     sv=NULL;
3306     if (sv_isobject(ST(0)) == 0)
3307       {
3308         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3309           PackageName);
3310         goto PerlException;
3311       }
3312     reference=SvRV(ST(0));
3313     hv=SvSTASH(reference);
3314     av=newAV();
3315     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3316     SvREFCNT_dec(av);
3317     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3318     if (image == (Image *) NULL)
3319       {
3320         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3321           PackageName);
3322         goto PerlException;
3323       }
3324     method=CompareAnyLayer;
3325     for (i=2; i < items; i+=2)
3326     {
3327       attribute=(char *) SvPV(ST(i-1),na);
3328       switch (*attribute)
3329       {
3330         case 'M':
3331         case 'm':
3332         {
3333           if (LocaleCompare(attribute,"method") == 0)
3334             {
3335               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3336                 SvPV(ST(i),na));
3337               if (option < 0)
3338                 {
3339                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3340                     SvPV(ST(i),na));
3341                   break;
3342                 }
3343                method=(ImageLayerMethod) option;
3344               break;
3345             }
3346           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3347             attribute);
3348           break;
3349         }
3350         default:
3351         {
3352           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3353             attribute);
3354           break;
3355         }
3356       }
3357     }
3358     image=CompareImagesLayers(image,method,exception);
3359     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3360       goto PerlException;
3361     for ( ; image; image=image->next)
3362     {
3363       AddImageToRegistry(sv,image);
3364       rv=newRV(sv);
3365       av_push(av,sv_bless(rv,hv));
3366       SvREFCNT_dec(sv);
3367     }
3368     exception=DestroyExceptionInfo(exception);
3369     ST(0)=av_reference;
3370     SvREFCNT_dec(perl_exception);
3371     XSRETURN(1);
3372
3373   PerlException:
3374     InheritPerlException(exception,perl_exception);
3375     exception=DestroyExceptionInfo(exception);
3376     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3377     SvPOK_on(perl_exception);
3378     ST(0)=sv_2mortal(perl_exception);
3379     XSRETURN(1);
3380   }
3381 \f
3382 #
3383 ###############################################################################
3384 #                                                                             #
3385 #                                                                             #
3386 #                                                                             #
3387 #   D e s t r o y                                                             #
3388 #                                                                             #
3389 #                                                                             #
3390 #                                                                             #
3391 ###############################################################################
3392 #
3393 #
3394 void
3395 DESTROY(ref)
3396   Image::Magick ref=NO_INIT
3397   PPCODE:
3398   {
3399     SV
3400       *reference;
3401
3402     PERL_UNUSED_VAR(ref);
3403     if (sv_isobject(ST(0)) == 0)
3404       croak("ReferenceIsNotMyType");
3405     reference=SvRV(ST(0));
3406     switch (SvTYPE(reference))
3407     {
3408       case SVt_PVAV:
3409       {
3410         char
3411           message[MaxTextExtent];
3412
3413         const SV
3414           *key;
3415
3416         HV
3417           *hv;
3418
3419         GV
3420           **gvp;
3421
3422         struct PackageInfo
3423           *info;
3424
3425         SV
3426           *sv;
3427
3428         /*
3429           Array (AV *) reference
3430         */
3431         (void) FormatLocaleString(message,MaxTextExtent,"package%s%p",
3432           XS_VERSION,reference);
3433         hv=gv_stashpv(PackageName, FALSE);
3434         if (!hv)
3435           break;
3436         gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3437         if (!gvp)
3438           break;
3439         sv=GvSV(*gvp);
3440         if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3441           {
3442             info=(struct PackageInfo *) SvIV(sv);
3443             DestroyPackageInfo(info);
3444           }
3445         key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3446         (void) key;
3447         break;
3448       }
3449       case SVt_PVMG:
3450       {
3451         Image
3452           *image;
3453
3454         /*
3455           Blessed scalar = (Image *) SvIV(reference)
3456         */
3457         image=(Image *) SvIV(reference);
3458         if (image != (Image *) NULL)
3459           DeleteImageFromRegistry(reference,image);
3460         break;
3461       }
3462       default:
3463         break;
3464     }
3465   }
3466 \f
3467 #
3468 ###############################################################################
3469 #                                                                             #
3470 #                                                                             #
3471 #                                                                             #
3472 #   D i s p l a y                                                             #
3473 #                                                                             #
3474 #                                                                             #
3475 #                                                                             #
3476 ###############################################################################
3477 #
3478 #
3479 void
3480 Display(ref,...)
3481   Image::Magick ref=NO_INIT
3482   ALIAS:
3483     DisplayImage  = 1
3484     display       = 2
3485     displayimage  = 3
3486   PPCODE:
3487   {
3488     ExceptionInfo
3489       *exception;
3490
3491     Image
3492       *image;
3493
3494     register ssize_t
3495       i;
3496
3497     struct PackageInfo
3498       *info,
3499       *package_info;
3500
3501     SV
3502       *perl_exception,
3503       *reference;
3504
3505     PERL_UNUSED_VAR(ref);
3506     PERL_UNUSED_VAR(ix);
3507     exception=AcquireExceptionInfo();
3508     perl_exception=newSVpv("",0);
3509     package_info=(struct PackageInfo *) NULL;
3510     if (sv_isobject(ST(0)) == 0)
3511       {
3512         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3513           PackageName);
3514         goto PerlException;
3515       }
3516     reference=SvRV(ST(0));
3517     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3518     if (image == (Image *) NULL)
3519       {
3520         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3521           PackageName);
3522         goto PerlException;
3523       }
3524     package_info=ClonePackageInfo(info,exception);
3525     if (items == 2)
3526       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3527     else
3528       if (items > 2)
3529         for (i=2; i < items; i+=2)
3530           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3531             exception);
3532     (void) DisplayImages(package_info->image_info,image);
3533     (void) CatchImageException(image);
3534     InheritException(exception,&image->exception);
3535
3536   PerlException:
3537     if (package_info != (struct PackageInfo *) NULL)
3538       DestroyPackageInfo(package_info);
3539     InheritPerlException(exception,perl_exception);
3540     exception=DestroyExceptionInfo(exception);
3541     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3542     SvPOK_on(perl_exception);
3543     ST(0)=sv_2mortal(perl_exception);
3544     XSRETURN(1);
3545   }
3546 \f
3547 #
3548 ###############################################################################
3549 #                                                                             #
3550 #                                                                             #
3551 #                                                                             #
3552 #   E v a l u a t e I m a g e s                                               #
3553 #                                                                             #
3554 #                                                                             #
3555 #                                                                             #
3556 ###############################################################################
3557 #
3558 #
3559 void
3560 EvaluateImages(ref)
3561   Image::Magick ref=NO_INIT
3562   ALIAS:
3563     EvaluateImages   = 1
3564     evaluateimages   = 2
3565   PPCODE:
3566   {
3567     AV
3568       *av;
3569
3570     char
3571       *attribute,
3572       *p;
3573
3574     ExceptionInfo
3575       *exception;
3576
3577     HV
3578       *hv;
3579
3580     Image
3581       *image;
3582
3583     MagickEvaluateOperator
3584       op;
3585
3586     register ssize_t
3587       i;
3588
3589     struct PackageInfo
3590       *info;
3591
3592     SV
3593       *perl_exception,
3594       *reference,
3595       *rv,
3596       *sv;
3597
3598     PERL_UNUSED_VAR(ref);
3599     PERL_UNUSED_VAR(ix);
3600     exception=AcquireExceptionInfo();
3601     perl_exception=newSVpv("",0);
3602     sv=NULL;
3603     if (sv_isobject(ST(0)) == 0)
3604       {
3605         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3606           PackageName);
3607         goto PerlException;
3608       }
3609     reference=SvRV(ST(0));
3610     hv=SvSTASH(reference);
3611     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3612     if (image == (Image *) NULL)
3613       {
3614         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3615           PackageName);
3616         goto PerlException;
3617       }
3618     op=MeanEvaluateOperator;
3619     if (items == 2)
3620       {
3621         ssize_t
3622           in;
3623
3624         in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
3625           SvPV(ST(1),na));
3626         if (in < 0)
3627           {
3628             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3629               SvPV(ST(1),na));
3630             return;
3631           }
3632         op=(MagickEvaluateOperator) in;
3633       }
3634     else
3635       for (i=2; i < items; i+=2)
3636       {
3637         attribute=(char *) SvPV(ST(i-1),na);
3638         switch (*attribute)
3639         {
3640           case 'O':
3641           case 'o':
3642           {
3643             if (LocaleCompare(attribute,"operator") == 0)
3644               {
3645                 ssize_t
3646                   in;
3647
3648                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3649                   MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
3650                 if (in < 0)
3651                   {
3652                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3653                       SvPV(ST(i),na));
3654                     return;
3655                   }
3656                 op=(MagickEvaluateOperator) in;
3657                 break;
3658               }
3659             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3660               attribute);
3661             break;
3662           }
3663           default:
3664           {
3665             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3666               attribute);
3667             break;
3668           }
3669         }
3670       }
3671     image=EvaluateImages(image,op,exception);
3672     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3673       goto PerlException;
3674     /*
3675       Create blessed Perl array for the returned image.
3676     */
3677     av=newAV();
3678     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3679     SvREFCNT_dec(av);
3680     AddImageToRegistry(sv,image);
3681     rv=newRV(sv);
3682     av_push(av,sv_bless(rv,hv));
3683     SvREFCNT_dec(sv);
3684     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3685     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
3686       "evaluate-%.*s",(int) (MaxTextExtent-9),
3687       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3688     (void) CopyMagickString(image->filename,info->image_info->filename,
3689       MaxTextExtent);
3690     SetImageInfo(info->image_info,0,exception);
3691     exception=DestroyExceptionInfo(exception);
3692     SvREFCNT_dec(perl_exception);
3693     XSRETURN(1);
3694
3695   PerlException:
3696     InheritPerlException(exception,perl_exception);
3697     exception=DestroyExceptionInfo(exception);
3698     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3699     SvPOK_on(perl_exception);
3700     ST(0)=sv_2mortal(perl_exception);
3701     XSRETURN(1);
3702   }
3703 \f
3704 #
3705 ###############################################################################
3706 #                                                                             #
3707 #                                                                             #
3708 #                                                                             #
3709 #   F e a t u r e s                                                           #
3710 #                                                                             #
3711 #                                                                             #
3712 #                                                                             #
3713 ###############################################################################
3714 #
3715 #
3716 void
3717 Features(ref,...)
3718   Image::Magick ref=NO_INIT
3719   ALIAS:
3720     FeaturesImage = 1
3721     features      = 2
3722     featuresimage = 3
3723   PPCODE:
3724   {
3725 #define ChannelFeatures(channel,direction) \
3726 { \
3727   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3728     channel_features[channel].angular_second_moment[direction]); \
3729   PUSHs(sv_2mortal(newSVpv(message,0))); \
3730   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3731     channel_features[channel].contrast[direction]); \
3732   PUSHs(sv_2mortal(newSVpv(message,0))); \
3733   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3734     channel_features[channel].contrast[direction]); \
3735   PUSHs(sv_2mortal(newSVpv(message,0))); \
3736   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3737     channel_features[channel].variance_sum_of_squares[direction]); \
3738   PUSHs(sv_2mortal(newSVpv(message,0))); \
3739   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3740     channel_features[channel].inverse_difference_moment[direction]); \
3741   PUSHs(sv_2mortal(newSVpv(message,0))); \
3742   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3743     channel_features[channel].sum_average[direction]); \
3744   PUSHs(sv_2mortal(newSVpv(message,0))); \
3745   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3746     channel_features[channel].sum_variance[direction]); \
3747   PUSHs(sv_2mortal(newSVpv(message,0))); \
3748   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3749     channel_features[channel].sum_entropy[direction]); \
3750   PUSHs(sv_2mortal(newSVpv(message,0))); \
3751   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3752     channel_features[channel].entropy[direction]); \
3753   PUSHs(sv_2mortal(newSVpv(message,0))); \
3754   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3755     channel_features[channel].difference_variance[direction]); \
3756   PUSHs(sv_2mortal(newSVpv(message,0))); \
3757   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3758     channel_features[channel].difference_entropy[direction]); \
3759   PUSHs(sv_2mortal(newSVpv(message,0))); \
3760   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3761     channel_features[channel].measure_of_correlation_1[direction]); \
3762   PUSHs(sv_2mortal(newSVpv(message,0))); \
3763   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3764     channel_features[channel].measure_of_correlation_2[direction]); \
3765   PUSHs(sv_2mortal(newSVpv(message,0))); \
3766   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3767     channel_features[channel].maximum_correlation_coefficient[direction]); \
3768   PUSHs(sv_2mortal(newSVpv(message,0))); \
3769 }
3770
3771     AV
3772       *av;
3773
3774     char
3775       *attribute,
3776       message[MaxTextExtent];
3777
3778     ChannelFeatures
3779       *channel_features;
3780
3781     double
3782       distance;
3783
3784     ExceptionInfo
3785       *exception;
3786
3787     Image
3788       *image;
3789
3790     register ssize_t
3791       i;
3792
3793     ssize_t
3794       count;
3795
3796     struct PackageInfo
3797       *info;
3798
3799     SV
3800       *perl_exception,
3801       *reference;
3802
3803     PERL_UNUSED_VAR(ref);
3804     PERL_UNUSED_VAR(ix);
3805     exception=AcquireExceptionInfo();
3806     perl_exception=newSVpv("",0);
3807     av=NULL;
3808     if (sv_isobject(ST(0)) == 0)
3809       {
3810         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3811           PackageName);
3812         goto PerlException;
3813       }
3814     reference=SvRV(ST(0));
3815     av=newAV();
3816     SvREFCNT_dec(av);
3817     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3818     if (image == (Image *) NULL)
3819       {
3820         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3821           PackageName);
3822         goto PerlException;
3823       }
3824     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3825     distance=1;
3826     for (i=2; i < items; i+=2)
3827     {
3828       attribute=(char *) SvPV(ST(i-1),na);
3829       switch (*attribute)
3830       {
3831         case 'D':
3832         case 'd':
3833         {
3834           if (LocaleCompare(attribute,"distance") == 0)
3835             {
3836               distance=StringToLong((char *) SvPV(ST(1),na));
3837               break;
3838             }
3839           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3840             attribute);
3841           break;
3842         }
3843         default:
3844         {
3845           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3846             attribute);
3847           break;
3848         }
3849       }
3850     }
3851     count=0;
3852     for ( ; image; image=image->next)
3853     {
3854       channel_features=GetImageFeatures(image,distance,
3855         &image->exception);
3856       if (channel_features == (ChannelFeatures *) NULL)
3857         continue;
3858       count++;
3859       EXTEND(sp,75*count);
3860       for (i=0; i < 4; i++)
3861       {
3862         ChannelFeatures(RedChannel,i);
3863         ChannelFeatures(GreenChannel,i);
3864         ChannelFeatures(BlueChannel,i);
3865         if (image->colorspace == CMYKColorspace)
3866           ChannelFeatures(BlackChannel,i);
3867         if (image->matte != MagickFalse)
3868           ChannelFeatures(AlphaChannel,i);
3869       }
3870       channel_features=(ChannelFeatures *)
3871         RelinquishMagickMemory(channel_features);
3872     }
3873
3874   PerlException:
3875     InheritPerlException(exception,perl_exception);
3876     exception=DestroyExceptionInfo(exception);
3877     SvREFCNT_dec(perl_exception);
3878   }
3879 \f
3880 #
3881 ###############################################################################
3882 #                                                                             #
3883 #                                                                             #
3884 #                                                                             #
3885 #   F l a t t e n                                                             #
3886 #                                                                             #
3887 #                                                                             #
3888 #                                                                             #
3889 ###############################################################################
3890 #
3891 #
3892 void
3893 Flatten(ref)
3894   Image::Magick ref=NO_INIT
3895   ALIAS:
3896     FlattenImage   = 1
3897     flatten        = 2
3898     flattenimage   = 3
3899   PPCODE:
3900   {
3901     AV
3902       *av;
3903
3904     char
3905       *attribute,
3906       *p;
3907
3908     ExceptionInfo
3909       *exception;
3910
3911     HV
3912       *hv;
3913
3914     Image
3915       *image;
3916
3917     PixelPacket
3918       background_color;
3919
3920     register ssize_t
3921       i;
3922
3923     struct PackageInfo
3924       *info;
3925
3926     SV
3927       *perl_exception,
3928       *reference,
3929       *rv,
3930       *sv;
3931
3932     PERL_UNUSED_VAR(ref);
3933     PERL_UNUSED_VAR(ix);
3934     exception=AcquireExceptionInfo();
3935     perl_exception=newSVpv("",0);
3936     sv=NULL;
3937     if (sv_isobject(ST(0)) == 0)
3938       {
3939         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3940           PackageName);
3941         goto PerlException;
3942       }
3943     reference=SvRV(ST(0));
3944     hv=SvSTASH(reference);
3945     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3946     if (image == (Image *) NULL)
3947       {
3948         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3949           PackageName);
3950         goto PerlException;
3951       }
3952     background_color=image->background_color;
3953     if (items == 2)
3954       (void) QueryColorDatabase((char *) SvPV(ST(1),na),&background_color,
3955         exception);
3956     else
3957       for (i=2; i < items; i+=2)
3958       {
3959         attribute=(char *) SvPV(ST(i-1),na);
3960         switch (*attribute)
3961         {
3962           case 'B':
3963           case 'b':
3964           {
3965             if (LocaleCompare(attribute,"background") == 0)
3966               {
3967                 (void) QueryColorDatabase((char *) SvPV(ST(1),na),
3968                   &background_color,exception);
3969                 break;
3970               }
3971             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3972               attribute);
3973             break;
3974           }
3975           default:
3976           {
3977             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3978               attribute);
3979             break;
3980           }
3981         }
3982       }
3983     image->background_color=background_color;
3984     image=MergeImageLayers(image,FlattenLayer,exception);
3985     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3986       goto PerlException;
3987     /*
3988       Create blessed Perl array for the returned image.
3989     */
3990     av=newAV();
3991     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3992     SvREFCNT_dec(av);
3993     AddImageToRegistry(sv,image);
3994     rv=newRV(sv);
3995     av_push(av,sv_bless(rv,hv));
3996     SvREFCNT_dec(sv);
3997     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3998     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
3999       "flatten-%.*s",(int) (MaxTextExtent-9),
4000       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4001     (void) CopyMagickString(image->filename,info->image_info->filename,
4002       MaxTextExtent);
4003     SetImageInfo(info->image_info,0,exception);
4004     exception=DestroyExceptionInfo(exception);
4005     SvREFCNT_dec(perl_exception);
4006     XSRETURN(1);
4007
4008   PerlException:
4009     InheritPerlException(exception,perl_exception);
4010     exception=DestroyExceptionInfo(exception);
4011     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4012     SvPOK_on(perl_exception);  /* return messages in string context */
4013     ST(0)=sv_2mortal(perl_exception);
4014     XSRETURN(1);
4015   }
4016 \f
4017 #
4018 ###############################################################################
4019 #                                                                             #
4020 #                                                                             #
4021 #                                                                             #
4022 #   F x                                                                       #
4023 #                                                                             #
4024 #                                                                             #
4025 #                                                                             #
4026 ###############################################################################
4027 #
4028 #
4029 void
4030 Fx(ref,...)
4031   Image::Magick ref=NO_INIT
4032   ALIAS:
4033     FxImage  = 1
4034     fx       = 2
4035     fximage  = 3
4036   PPCODE:
4037   {
4038     AV
4039       *av;
4040
4041     char
4042       *attribute,
4043       expression[MaxTextExtent];
4044
4045     ChannelType
4046       channel,
4047       channel_mask;
4048
4049     ExceptionInfo
4050       *exception;
4051
4052     HV
4053       *hv;
4054
4055     Image
4056       *image;
4057
4058     register ssize_t
4059       i;
4060
4061     struct PackageInfo
4062       *info;
4063
4064     SV
4065       *av_reference,
4066       *perl_exception,
4067       *reference,
4068       *rv,
4069       *sv;
4070
4071     PERL_UNUSED_VAR(ref);
4072     PERL_UNUSED_VAR(ix);
4073     exception=AcquireExceptionInfo();
4074     perl_exception=newSVpv("",0);
4075     sv=NULL;
4076     attribute=NULL;
4077     av=NULL;
4078     if (sv_isobject(ST(0)) == 0)
4079       {
4080         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4081           PackageName);
4082         goto PerlException;
4083       }
4084     reference=SvRV(ST(0));
4085     hv=SvSTASH(reference);
4086     av=newAV();
4087     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4088     SvREFCNT_dec(av);
4089     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4090     if (image == (Image *) NULL)
4091       {
4092         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4093           PackageName);
4094         goto PerlException;
4095       }
4096     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4097     /*
4098       Get options.
4099     */
4100     channel=DefaultChannels;
4101     (void) CopyMagickString(expression,"u",MaxTextExtent);
4102     if (items == 2)
4103       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MaxTextExtent);
4104     else
4105       for (i=2; i < items; i+=2)
4106       {
4107         attribute=(char *) SvPV(ST(i-1),na);
4108         switch (*attribute)
4109         {
4110           case 'C':
4111           case 'c':
4112           {
4113             if (LocaleCompare(attribute,"channel") == 0)
4114               {
4115                 ssize_t
4116                   option;
4117
4118                 option=ParseChannelOption(SvPV(ST(i),na));
4119                 if (option < 0)
4120                   {
4121                     ThrowPerlException(exception,OptionError,
4122                       "UnrecognizedType",SvPV(ST(i),na));
4123                     return;
4124                   }
4125                 channel=(ChannelType) option;
4126                 break;
4127               }
4128             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4129               attribute);
4130             break;
4131           }
4132           case 'E':
4133           case 'e':
4134           {
4135             if (LocaleCompare(attribute,"expression") == 0)
4136               {
4137                 (void) CopyMagickString(expression,SvPV(ST(i),na),
4138                   MaxTextExtent);
4139                 break;
4140               }
4141             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4142               attribute);
4143             break;
4144           }
4145           default:
4146           {
4147             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4148               attribute);
4149             break;
4150           }
4151         }
4152       }
4153     channel_mask=SetPixelChannelMask(image,channel);
4154     image=FxImage(image,expression,exception);
4155     if (image != (Image *) NULL)
4156       (void) SetPixelChannelMask(image,channel_mask);
4157     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
4158       goto PerlException;
4159     for ( ; image; image=image->next)
4160     {
4161       AddImageToRegistry(sv,image);
4162       rv=newRV(sv);
4163       av_push(av,sv_bless(rv,hv));
4164       SvREFCNT_dec(sv);
4165     }
4166     exception=DestroyExceptionInfo(exception);
4167     ST(0)=av_reference;
4168     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4169     XSRETURN(1);
4170
4171   PerlException:
4172     InheritPerlException(exception,perl_exception);
4173     exception=DestroyExceptionInfo(exception);
4174     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4175     SvPOK_on(perl_exception);
4176     ST(0)=sv_2mortal(perl_exception);
4177     XSRETURN(1);
4178   }
4179 \f
4180 #
4181 ###############################################################################
4182 #                                                                             #
4183 #                                                                             #
4184 #                                                                             #
4185 #   G e t                                                                     #
4186 #                                                                             #
4187 #                                                                             #
4188 #                                                                             #
4189 ###############################################################################
4190 #
4191 #
4192 void
4193 Get(ref,...)
4194   Image::Magick ref=NO_INIT
4195   ALIAS:
4196     GetAttributes = 1
4197     GetAttribute  = 2
4198     get           = 3
4199     getattributes = 4
4200     getattribute  = 5
4201   PPCODE:
4202   {
4203     char
4204       *attribute,
4205       color[MaxTextExtent];
4206
4207     const char
4208       *value;
4209
4210     ExceptionInfo
4211       *exception;
4212
4213     Image
4214       *image;
4215
4216     long
4217       j;
4218
4219     register ssize_t
4220       i;
4221
4222     struct PackageInfo
4223       *info;
4224
4225     SV
4226       *perl_exception,
4227       *reference,
4228       *s;
4229
4230     PERL_UNUSED_VAR(ref);
4231     PERL_UNUSED_VAR(ix);
4232     exception=AcquireExceptionInfo();
4233     perl_exception=newSVpv("",0);
4234     if (sv_isobject(ST(0)) == 0)
4235       {
4236         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4237           PackageName);
4238         XSRETURN_EMPTY;
4239       }
4240     reference=SvRV(ST(0));
4241     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4242     if (image == (Image *) NULL && !info)
4243       XSRETURN_EMPTY;
4244     EXTEND(sp,items);
4245     for (i=1; i < items; i++)
4246     {
4247       attribute=(char *) SvPV(ST(i),na);
4248       s=NULL;
4249       switch (*attribute)
4250       {
4251         case 'A':
4252         case 'a':
4253         {
4254           if (LocaleCompare(attribute,"adjoin") == 0)
4255             {
4256               if (info)
4257                 s=newSViv((ssize_t) info->image_info->adjoin);
4258               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4259               continue;
4260             }
4261           if (LocaleCompare(attribute,"antialias") == 0)
4262             {
4263               if (info)
4264                 s=newSViv((ssize_t) info->image_info->antialias);
4265               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4266               continue;
4267             }
4268           if (LocaleCompare(attribute,"area") == 0)
4269             {
4270               s=newSViv(GetMagickResource(AreaResource));
4271               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4272               continue;
4273             }
4274           if (LocaleCompare(attribute,"attenuate") == 0)
4275             {
4276               const char
4277                 *value;
4278
4279               value=GetImageProperty(image,attribute);
4280               if (value != (const char *) NULL)
4281                 s=newSVpv(value,0);
4282               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4283               continue;
4284             }
4285           if (LocaleCompare(attribute,"authenticate") == 0)
4286             {
4287               if (info)
4288                 s=newSVpv(info->image_info->authenticate,0);
4289               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4290               continue;
4291             }
4292           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4293             attribute);
4294           break;
4295         }
4296         case 'B':
4297         case 'b':
4298         {
4299           if (LocaleCompare(attribute,"background") == 0)
4300             {
4301               if (image == (Image *) NULL)
4302                 break;
4303               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4304                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4305                 image->background_color.red,image->background_color.green,
4306                 image->background_color.blue,image->background_color.alpha);
4307               s=newSVpv(color,0);
4308               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4309               continue;
4310             }
4311           if (LocaleCompare(attribute,"base-columns") == 0)
4312             {
4313               if (image != (Image *) NULL)
4314                 s=newSViv((ssize_t) image->magick_columns);
4315               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4316               continue;
4317             }
4318           if (LocaleCompare(attribute,"base-filename") == 0)
4319             {
4320               if (image != (Image *) NULL)
4321                 s=newSVpv(image->magick_filename,0);
4322               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4323               continue;
4324             }
4325           if (LocaleCompare(attribute,"base-height") == 0)
4326             {
4327               if (image != (Image *) NULL)
4328                 s=newSViv((ssize_t) image->magick_rows);
4329               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4330               continue;
4331             }
4332           if (LocaleCompare(attribute,"base-rows") == 0)
4333             {
4334               if (image != (Image *) NULL)
4335                 s=newSViv((ssize_t) image->magick_rows);
4336               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4337               continue;
4338             }
4339           if (LocaleCompare(attribute,"base-width") == 0)
4340             {
4341               if (image != (Image *) NULL)
4342                 s=newSViv((ssize_t) image->magick_columns);
4343               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4344               continue;
4345             }
4346           if (LocaleCompare(attribute,"bias") == 0)
4347             {
4348               if (image != (Image *) NULL)
4349                 s=newSVnv(image->bias);
4350               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4351               continue;
4352             }
4353           if (LocaleCompare(attribute,"blue-primary") == 0)
4354             {
4355               if (image == (Image *) NULL)
4356                 break;
4357               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4358                 image->chromaticity.blue_primary.x,
4359                 image->chromaticity.blue_primary.y);
4360               s=newSVpv(color,0);
4361               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4362               continue;
4363             }
4364           if (LocaleCompare(attribute,"bordercolor") == 0)
4365             {
4366               if (image == (Image *) NULL)
4367                 break;
4368               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4369                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4370                 image->border_color.red,image->border_color.green,
4371                 image->border_color.blue,image->border_color.alpha);
4372               s=newSVpv(color,0);
4373               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4374               continue;
4375             }
4376           if (LocaleCompare(attribute,"bounding-box") == 0)
4377             {
4378               char
4379                 geometry[MaxTextExtent];
4380
4381               RectangleInfo
4382                 page;
4383
4384               if (image == (Image *) NULL)
4385                 break;
4386               page=GetImageBoundingBox(image,&image->exception);
4387               (void) FormatLocaleString(geometry,MaxTextExtent,
4388                 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4389                 page.height,(double) page.x,(double) page.y);
4390               s=newSVpv(geometry,0);
4391               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4392               continue;
4393             }
4394           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4395             attribute);
4396           break;
4397         }
4398         case 'C':
4399         case 'c':
4400         {
4401           if (LocaleCompare(attribute,"class") == 0)
4402             {
4403               if (image == (Image *) NULL)
4404                 break;
4405               s=newSViv(image->storage_class);
4406               (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4407                 image->storage_class));
4408               SvIOK_on(s);
4409               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4410               continue;
4411             }
4412           if (LocaleCompare(attribute,"clip-mask") == 0)
4413             {
4414               if (image != (Image *) NULL)
4415                 {
4416                   SV
4417                     *sv;
4418
4419                   sv=NULL;
4420                   if (image->mask == (Image *) NULL)
4421                     ClipImage(image);
4422                   if (image->mask != (Image *) NULL)
4423                     {
4424                       AddImageToRegistry(sv,image->mask);
4425                       s=sv_bless(newRV(sv),SvSTASH(reference));
4426                     }
4427                 }
4428               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4429               continue;
4430             }
4431           if (LocaleCompare(attribute,"clip-path") == 0)
4432             {
4433               if (image != (Image *) NULL)
4434                 {
4435                   SV
4436                     *sv;
4437
4438                   sv=NULL;
4439                   if (image->clip_mask == (Image *) NULL)
4440                     ClipImage(image);
4441                   if (image->clip_mask != (Image *) NULL)
4442                     {
4443                       AddImageToRegistry(sv,image->clip_mask);
4444                       s=sv_bless(newRV(sv),SvSTASH(reference));
4445                     }
4446                 }
4447               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4448               continue;
4449             }
4450           if (LocaleCompare(attribute,"compression") == 0)
4451             {
4452               j=info ? info->image_info->compression : image ?
4453                 image->compression : UndefinedCompression;
4454               if (info)
4455                 if (info->image_info->compression == UndefinedCompression)
4456                   j=image->compression;
4457               s=newSViv(j);
4458               (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4459                 j));
4460               SvIOK_on(s);
4461               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4462               continue;
4463             }
4464           if (LocaleCompare(attribute,"colorspace") == 0)
4465             {
4466               j=image ? image->colorspace : RGBColorspace;
4467               s=newSViv(j);
4468               (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4469                 j));
4470               SvIOK_on(s);
4471               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4472               continue;
4473             }
4474           if (LocaleCompare(attribute,"colors") == 0)
4475             {
4476               if (image != (Image *) NULL)
4477                 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4478                   &image->exception));
4479               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4480               continue;
4481             }
4482           if (LocaleNCompare(attribute,"colormap",8) == 0)
4483             {
4484               int
4485                 items;
4486
4487               if (image == (Image *) NULL || !image->colormap)
4488                 break;
4489               j=0;
4490               items=sscanf(attribute,"%*[^[][%ld",&j);
4491               (void) items;
4492               if (j > (ssize_t) image->colors)
4493                 j%=image->colors;
4494               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4495                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4496                 image->colormap[j].red,image->colormap[j].green,
4497                 image->colormap[j].blue,image->colormap[j].alpha);
4498               s=newSVpv(color,0);
4499               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4500               continue;
4501             }
4502           if (LocaleCompare(attribute,"columns") == 0)
4503             {
4504               if (image != (Image *) NULL)
4505                 s=newSViv((ssize_t) image->columns);
4506               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4507               continue;
4508             }
4509           if (LocaleCompare(attribute,"comment") == 0)
4510             {
4511               const char
4512                 *value;
4513
4514               value=GetImageProperty(image,attribute);
4515               if (value != (const char *) NULL)
4516                 s=newSVpv(value,0);
4517               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4518               continue;
4519             }
4520           if (LocaleCompare(attribute,"copyright") == 0)
4521             {
4522               s=newSVpv(GetMagickCopyright(),0);
4523               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4524               continue;
4525             }
4526           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4527             attribute);
4528           break;
4529         }
4530         case 'D':
4531         case 'd':
4532         {
4533           if (LocaleCompare(attribute,"density") == 0)
4534             {
4535               char
4536                 geometry[MaxTextExtent];
4537
4538               if (image == (Image *) NULL)
4539                 break;
4540               (void) FormatLocaleString(geometry,MaxTextExtent,"%.15gx%.15g",
4541                 image->x_resolution,image->y_resolution);
4542               s=newSVpv(geometry,0);
4543               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4544               continue;
4545             }
4546           if (LocaleCompare(attribute,"delay") == 0)
4547             {
4548               if (image != (Image *) NULL)
4549                 s=newSViv((ssize_t) image->delay);
4550               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4551               continue;
4552             }
4553           if (LocaleCompare(attribute,"depth") == 0)
4554             {
4555               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4556               if (image != (Image *) NULL)
4557                 s=newSViv((ssize_t) GetImageDepth(image,&image->exception));
4558               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4559               continue;
4560             }
4561           if (LocaleCompare(attribute,"directory") == 0)
4562             {
4563               if (image && image->directory)
4564                 s=newSVpv(image->directory,0);
4565               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4566               continue;
4567             }
4568           if (LocaleCompare(attribute,"dispose") == 0)
4569             {
4570               if (image == (Image *) NULL)
4571                 break;
4572
4573               s=newSViv(image->dispose);
4574               (void) sv_setpv(s,
4575                 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
4576               SvIOK_on(s);
4577               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4578               continue;
4579             }
4580           if (LocaleCompare(attribute,"disk") == 0)
4581             {
4582               s=newSViv(GetMagickResource(DiskResource));
4583               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4584               continue;
4585             }
4586           if (LocaleCompare(attribute,"dither") == 0)
4587             {
4588               if (info)
4589                 s=newSViv((ssize_t) info->image_info->dither);
4590               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4591               continue;
4592             }
4593           if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4594             {
4595               if (info && info->image_info->server_name)
4596                 s=newSVpv(info->image_info->server_name,0);
4597               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4598               continue;
4599             }
4600           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4601             attribute);
4602           break;
4603         }
4604         case 'E':
4605         case 'e':
4606         {
4607           if (LocaleCompare(attribute,"elapsed-time") == 0)
4608             {
4609               if (image != (Image *) NULL)
4610                 s=newSVnv(GetElapsedTime(&image->timer));
4611               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4612               continue;
4613             }
4614           if (LocaleCompare(attribute,"endian") == 0)
4615             {
4616               j=info ? info->image_info->endian : image ? image->endian :
4617                 UndefinedEndian;
4618               s=newSViv(j);
4619               (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
4620               SvIOK_on(s);
4621               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4622               continue;
4623             }
4624           if (LocaleCompare(attribute,"error") == 0)
4625             {
4626               if (image != (Image *) NULL)
4627                 s=newSVnv(image->error.mean_error_per_pixel);
4628               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4629               continue;
4630             }
4631           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4632             attribute);
4633           break;
4634         }
4635         case 'F':
4636         case 'f':
4637         {
4638           if (LocaleCompare(attribute,"filesize") == 0)
4639             {
4640               if (image != (Image *) NULL)
4641                 s=newSViv((ssize_t) GetBlobSize(image));
4642               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4643               continue;
4644             }
4645           if (LocaleCompare(attribute,"filename") == 0)
4646             {
4647               if (info && info->image_info->filename &&
4648                   *info->image_info->filename)
4649                 s=newSVpv(info->image_info->filename,0);
4650               if (image != (Image *) NULL)
4651                 s=newSVpv(image->filename,0);
4652               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4653               continue;
4654             }
4655           if (LocaleCompare(attribute,"filter") == 0)
4656             {
4657               s=image ? newSViv(image->filter) : newSViv(0);
4658               (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
4659                 image->filter));
4660               SvIOK_on(s);
4661               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4662               continue;
4663             }
4664           if (LocaleCompare(attribute,"font") == 0)
4665             {
4666               if (info && info->image_info->font)
4667                 s=newSVpv(info->image_info->font,0);
4668               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4669               continue;
4670             }
4671           if (LocaleCompare(attribute,"foreground") == 0)
4672             continue;
4673           if (LocaleCompare(attribute,"format") == 0)
4674             {
4675               const MagickInfo
4676                 *magick_info;
4677
4678               magick_info=(const MagickInfo *) NULL;
4679               if (info && (*info->image_info->magick != '\0'))
4680                 magick_info=GetMagickInfo(info->image_info->magick,exception);
4681               if (image != (Image *) NULL)
4682                 magick_info=GetMagickInfo(image->magick,&image->exception);
4683               if ((magick_info != (const MagickInfo *) NULL) &&
4684                   (*magick_info->description != '\0'))
4685                 s=newSVpv((char *) magick_info->description,0);
4686               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4687               continue;
4688             }
4689           if (LocaleCompare(attribute,"fuzz") == 0)
4690             {
4691               if (info)
4692                 s=newSVnv(info->image_info->fuzz);
4693               if (image != (Image *) NULL)
4694                 s=newSVnv(image->fuzz);
4695               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4696               continue;
4697             }
4698           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4699             attribute);
4700           break;
4701         }
4702         case 'G':
4703         case 'g':
4704         {
4705           if (LocaleCompare(attribute,"gamma") == 0)
4706             {
4707               if (image != (Image *) NULL)
4708                 s=newSVnv(image->gamma);
4709               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4710               continue;
4711             }
4712           if (LocaleCompare(attribute,"geometry") == 0)
4713             {
4714               if (image && image->geometry)
4715                 s=newSVpv(image->geometry,0);
4716               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4717               continue;
4718             }
4719           if (LocaleCompare(attribute,"gravity") == 0)
4720             {
4721               s=image ? newSViv(image->gravity) : newSViv(0);
4722               (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
4723                 image->gravity));
4724               SvIOK_on(s);
4725               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4726               continue;
4727             }
4728           if (LocaleCompare(attribute,"green-primary") == 0)
4729             {
4730               if (image == (Image *) NULL)
4731                 break;
4732               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4733                 image->chromaticity.green_primary.x,
4734                 image->chromaticity.green_primary.y);
4735               s=newSVpv(color,0);
4736               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4737               continue;
4738             }
4739           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4740             attribute);
4741           break;
4742         }
4743         case 'H':
4744         case 'h':
4745         {
4746           if (LocaleCompare(attribute,"height") == 0)
4747             {
4748               if (image != (Image *) NULL)
4749                 s=newSViv((ssize_t) image->rows);
4750               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4751               continue;
4752             }
4753           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4754             attribute);
4755           break;
4756         }
4757         case 'I':
4758         case 'i':
4759         {
4760           if (LocaleCompare(attribute,"icc") == 0)
4761             {
4762               if (image != (Image *) NULL)
4763                 {
4764                   const StringInfo
4765                     *profile;
4766
4767                   profile=GetImageProfile(image,"icc");
4768                   if (profile != (StringInfo *) NULL)
4769                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4770                       GetStringInfoLength(profile));
4771                 }
4772               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4773               continue;
4774             }
4775           if (LocaleCompare(attribute,"icm") == 0)
4776             {
4777               if (image != (Image *) NULL)
4778                 {
4779                   const StringInfo
4780                     *profile;
4781
4782                   profile=GetImageProfile(image,"icm");
4783                   if (profile != (const StringInfo *) NULL)
4784                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4785                       GetStringInfoLength(profile));
4786                 }
4787               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4788               continue;
4789             }
4790           if (LocaleCompare(attribute,"id") == 0)
4791             {
4792               if (image != (Image *) NULL)
4793                 {
4794                   char
4795                     key[MaxTextExtent];
4796
4797                   MagickBooleanType
4798                     status;
4799
4800                   static ssize_t
4801                     id = 0;
4802
4803                   (void) FormatLocaleString(key,MaxTextExtent,"%.20g\n",(double)
4804                     id);
4805                   status=SetImageRegistry(ImageRegistryType,key,image,
4806                     &image->exception);
4807                   (void) status;
4808                   s=newSViv(id++);
4809                 }
4810               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4811               continue;
4812             }
4813           if (LocaleNCompare(attribute,"index",5) == 0)
4814             {
4815               char
4816                 name[MaxTextExtent];
4817
4818               int
4819                 items;
4820
4821               long
4822                 x,
4823                 y;
4824
4825               register const Quantum
4826                 *p;
4827
4828               CacheView
4829                 *image_view;
4830
4831               if (image == (Image *) NULL)
4832                 break;
4833               if (image->storage_class != PseudoClass)
4834                 break;
4835               x=0;
4836               y=0;
4837               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
4838               (void) items;
4839               image_view=AcquireCacheView(image);
4840               p=GetCacheViewVirtualPixels(image_view,x,y,1,1,&image->exception);
4841               if (p != (const Quantum *) NULL)
4842                 {
4843                   (void) FormatLocaleString(name,MaxTextExtent,QuantumFormat,
4844                     GetPixelIndex(image,p));
4845                   s=newSVpv(name,0);
4846                   PUSHs(s ? sv_2mortal(s) : &sv_undef);
4847                 }
4848               image_view=DestroyCacheView(image_view);
4849               continue;
4850             }
4851           if (LocaleCompare(attribute,"iptc") == 0)
4852             {
4853               if (image != (Image *) NULL)
4854                 {
4855                   const StringInfo
4856                     *profile;
4857
4858                   profile=GetImageProfile(image,"iptc");
4859                   if (profile != (const StringInfo *) NULL)
4860                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4861                       GetStringInfoLength(profile));
4862                 }
4863               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4864               continue;
4865             }
4866           if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
4867             {
4868               if (image != (Image *) NULL)
4869                 s=newSViv((ssize_t) image->iterations);
4870               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4871               continue;
4872             }
4873           if (LocaleCompare(attribute,"interlace") == 0)
4874             {
4875               j=info ? info->image_info->interlace : image ? image->interlace :
4876                 UndefinedInterlace;
4877               s=newSViv(j);
4878               (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
4879                 j));
4880               SvIOK_on(s);
4881               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4882               continue;
4883             }
4884           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4885             attribute);
4886           break;
4887         }
4888         case 'L':
4889         case 'l':
4890         {
4891           if (LocaleCompare(attribute,"label") == 0)
4892             {
4893               const char
4894                 *value;
4895
4896               if (image == (Image *) NULL)
4897                 break;
4898               value=GetImageProperty(image,"Label");
4899               if (value != (const char *) NULL)
4900                 s=newSVpv(value,0);
4901               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4902               continue;
4903             }
4904           if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
4905             {
4906               if (image != (Image *) NULL)
4907                 s=newSViv((ssize_t) image->iterations);
4908               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4909               continue;
4910             }
4911           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4912             attribute);
4913           break;
4914         }
4915         case 'M':
4916         case 'm':
4917         {
4918           if (LocaleCompare(attribute,"magick") == 0)
4919             {
4920               if (info && *info->image_info->magick)
4921                 s=newSVpv(info->image_info->magick,0);
4922               if (image != (Image *) NULL)
4923                 s=newSVpv(image->magick,0);
4924               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4925               continue;
4926             }
4927           if (LocaleCompare(attribute,"map") == 0)
4928             {
4929               s=newSViv(GetMagickResource(MapResource));
4930               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4931               continue;
4932             }
4933           if (LocaleCompare(attribute,"maximum-error") == 0)
4934             {
4935               if (image != (Image *) NULL)
4936                 s=newSVnv(image->error.normalized_maximum_error);
4937               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4938               continue;
4939             }
4940           if (LocaleCompare(attribute,"memory") == 0)
4941             {
4942               s=newSViv(GetMagickResource(MemoryResource));
4943               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4944               continue;
4945             }
4946           if (LocaleCompare(attribute,"mean-error") == 0)
4947             {
4948               if (image != (Image *) NULL)
4949                 s=newSVnv(image->error.normalized_mean_error);
4950               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4951               continue;
4952             }
4953           if (LocaleCompare(attribute,"mime") == 0)
4954             {
4955               if (info && *info->image_info->magick)
4956                 s=newSVpv(MagickToMime(info->image_info->magick),0);
4957               if (image != (Image *) NULL)
4958                 s=newSVpv(MagickToMime(image->magick),0);
4959               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4960               continue;
4961             }
4962           if (LocaleCompare(attribute,"mattecolor") == 0)
4963             {
4964               if (image == (Image *) NULL)
4965                 break;
4966               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4967                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4968                 image->matte_color.red,image->matte_color.green,
4969                 image->matte_color.blue,image->matte_color.alpha);
4970               s=newSVpv(color,0);
4971               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4972               continue;
4973             }
4974           if (LocaleCompare(attribute,"matte") == 0)
4975             {
4976               if (image != (Image *) NULL)
4977                 s=newSViv((ssize_t) image->matte);
4978               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4979               continue;
4980             }
4981           if (LocaleCompare(attribute,"mime") == 0)
4982             {
4983               const char
4984                 *magick;
4985
4986               magick=NULL;
4987               if (info && *info->image_info->magick)
4988                 magick=info->image_info->magick;
4989               if (image != (Image *) NULL)
4990                 magick=image->magick;
4991               if (magick)
4992                 {
4993                   char
4994                     *mime;
4995
4996                   mime=MagickToMime(magick);
4997                   s=newSVpv(mime,0);
4998                   mime=(char *) RelinquishMagickMemory(mime);
4999                 }
5000               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5001               continue;
5002             }
5003           if (LocaleCompare(attribute,"monochrome") == 0)
5004             {
5005               if (image == (Image *) NULL)
5006                 continue;
5007               j=info ? info->image_info->monochrome :
5008                 IsImageMonochrome(image,&image->exception);
5009               s=newSViv(j);
5010               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5011               continue;
5012             }
5013           if (LocaleCompare(attribute,"montage") == 0)
5014             {
5015               if (image && image->montage)
5016                 s=newSVpv(image->montage,0);
5017               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5018               continue;
5019             }
5020           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5021             attribute);
5022           break;
5023         }
5024         case 'O':
5025         case 'o':
5026         {
5027           if (LocaleCompare(attribute,"orientation") == 0)
5028             {
5029               j=info ? info->image_info->orientation : image ?
5030                 image->orientation : UndefinedOrientation;
5031               s=newSViv(j);
5032               (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5033                 j));
5034               SvIOK_on(s);
5035               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5036               continue;
5037             }
5038           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5039             attribute);
5040           break;
5041         }
5042         case 'P':
5043         case 'p':
5044         {
5045           if (LocaleCompare(attribute,"page") == 0)
5046             {
5047               if (info && info->image_info->page)
5048                 s=newSVpv(info->image_info->page,0);
5049               if (image != (Image *) NULL)
5050                 {
5051                   char
5052                     geometry[MaxTextExtent];
5053
5054                   (void) FormatLocaleString(geometry,MaxTextExtent,
5055                     "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5056                     (double) image->page.height,(double) image->page.x,(double)
5057                     image->page.y);
5058                   s=newSVpv(geometry,0);
5059                 }
5060               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5061               continue;
5062             }
5063           if (LocaleCompare(attribute,"page.x") == 0)
5064             {
5065               if (image != (Image *) NULL)
5066                 s=newSViv((ssize_t) image->page.x);
5067               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5068               continue;
5069             }
5070           if (LocaleCompare(attribute,"page.y") == 0)
5071             {
5072               if (image != (Image *) NULL)
5073                 s=newSViv((ssize_t) image->page.y);
5074               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5075               continue;
5076             }
5077           if (LocaleNCompare(attribute,"pixel",5) == 0)
5078             {
5079               char
5080                 tuple[MaxTextExtent];
5081
5082               int
5083                 items;
5084
5085               long
5086                 x,
5087                 y;
5088
5089               register const Quantum
5090                 *p;
5091
5092               if (image == (Image *) NULL)
5093                 break;
5094               x=0;
5095               y=0;
5096               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5097               (void) items;
5098               p=GetVirtualPixels(image,x,y,1,1,exception);
5099               if (image->colorspace != CMYKColorspace)
5100                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5101                   QuantumFormat "," QuantumFormat "," QuantumFormat,
5102                   GetPixelRed(image,p),GetPixelGreen(image,p),
5103                   GetPixelBlue(image,p),GetPixelAlpha(image,p));
5104               else
5105                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5106                   QuantumFormat "," QuantumFormat "," QuantumFormat ","
5107                   QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5108                   GetPixelBlue(image,p),GetPixelBlack(image,p),
5109                   GetPixelAlpha(image,p));
5110               s=newSVpv(tuple,0);
5111               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5112               continue;
5113             }
5114           if (LocaleCompare(attribute,"pointsize") == 0)
5115             {
5116               if (info)
5117                 s=newSViv((ssize_t) info->image_info->pointsize);
5118               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5119               continue;
5120             }
5121           if (LocaleCompare(attribute,"preview") == 0)
5122             {
5123               s=newSViv(info->image_info->preview_type);
5124               (void) sv_setpv(s,CommandOptionToMnemonic(MagickPreviewOptions,
5125                 info->image_info->preview_type));
5126               SvIOK_on(s);
5127               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5128               continue;
5129             }
5130           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5131             attribute);
5132           break;
5133         }
5134         case 'Q':
5135         case 'q':
5136         {
5137           if (LocaleCompare(attribute,"quality") == 0)
5138             {
5139               if (info)
5140                 s=newSViv((ssize_t) info->image_info->quality);
5141               if (image != (Image *) NULL)
5142                 s=newSViv((ssize_t) image->quality);
5143               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5144               continue;
5145             }
5146           if (LocaleCompare(attribute,"quantum") == 0)
5147             {
5148               if (info)
5149                 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5150               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5151               continue;
5152             }
5153           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5154             attribute);
5155           break;
5156         }
5157         case 'R':
5158         case 'r':
5159         {
5160           if (LocaleCompare(attribute,"rendering-intent") == 0)
5161             {
5162               s=newSViv(image->rendering_intent);
5163               (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5164                 image->rendering_intent));
5165               SvIOK_on(s);
5166               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5167               continue;
5168             }
5169           if (LocaleCompare(attribute,"red-primary") == 0)
5170             {
5171               if (image == (Image *) NULL)
5172                 break;
5173               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5174                 image->chromaticity.red_primary.x,
5175                 image->chromaticity.red_primary.y);
5176               s=newSVpv(color,0);
5177               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5178               continue;
5179             }
5180           if (LocaleCompare(attribute,"rows") == 0)
5181             {
5182               if (image != (Image *) NULL)
5183                 s=newSViv((ssize_t) image->rows);
5184               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5185               continue;
5186             }
5187           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5188             attribute);
5189           break;
5190         }
5191         case 'S':
5192         case 's':
5193         {
5194           if (LocaleCompare(attribute,"sampling-factor") == 0)
5195             {
5196               if (info && info->image_info->sampling_factor)
5197                 s=newSVpv(info->image_info->sampling_factor,0);
5198               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5199               continue;
5200             }
5201           if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5202             {
5203               if (info && info->image_info->server_name)
5204                 s=newSVpv(info->image_info->server_name,0);
5205               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5206               continue;
5207             }
5208           if (LocaleCompare(attribute,"size") == 0)
5209             {
5210               if (info && info->image_info->size)
5211                 s=newSVpv(info->image_info->size,0);
5212               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5213               continue;
5214             }
5215           if (LocaleCompare(attribute,"scene") == 0)
5216             {
5217               if (image != (Image *) NULL)
5218                 s=newSViv((ssize_t) image->scene);
5219               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5220               continue;
5221             }
5222           if (LocaleCompare(attribute,"scenes") == 0)
5223             {
5224               if (image != (Image *) NULL)
5225                 s=newSViv((ssize_t) info->image_info->number_scenes);
5226               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5227               continue;
5228             }
5229           if (LocaleCompare(attribute,"signature") == 0)
5230             {
5231               const char
5232                 *value;
5233
5234               if (image == (Image *) NULL)
5235                 break;
5236               (void) SignatureImage(image);
5237               value=GetImageProperty(image,"Signature");
5238               if (value != (const char *) NULL)
5239                 s=newSVpv(value,0);
5240               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5241               continue;
5242             }
5243           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5244             attribute);
5245           break;
5246         }
5247         case 'T':
5248         case 't':
5249         {
5250           if (LocaleCompare(attribute,"taint") == 0)
5251             {
5252               if (image != (Image *) NULL)
5253                 s=newSViv((ssize_t) IsTaintImage(image));
5254               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5255               continue;
5256             }
5257           if (LocaleCompare(attribute,"texture") == 0)
5258             {
5259               if (info && info->image_info->texture)
5260                 s=newSVpv(info->image_info->texture,0);
5261               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5262               continue;
5263             }
5264           if (LocaleCompare(attribute,"total-ink-density") == 0)
5265             {
5266               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5267               if (image != (Image *) NULL)
5268                 s=newSVnv(GetImageTotalInkDensity(image));
5269               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5270               continue;
5271             }
5272           if (LocaleCompare(attribute,"transparent-color") == 0)
5273             {
5274               if (image == (Image *) NULL)
5275                 break;
5276               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
5277                 QuantumFormat "," QuantumFormat "," QuantumFormat,
5278                 image->transparent_color.red,image->transparent_color.green,
5279                 image->transparent_color.blue,image->transparent_color.alpha);
5280               s=newSVpv(color,0);
5281               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5282               continue;
5283             }
5284           if (LocaleCompare(attribute,"type") == 0)
5285             {
5286               if (image == (Image *) NULL)
5287                 break;
5288               j=(ssize_t) GetImageType(image,&image->exception);
5289               s=newSViv(j);
5290               (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5291               SvIOK_on(s);
5292               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5293               continue;
5294             }
5295           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5296             attribute);
5297           break;
5298         }
5299         case 'U':
5300         case 'u':
5301         {
5302           if (LocaleCompare(attribute,"units") == 0)
5303             {
5304               j=info ? info->image_info->units : image ? image->units :
5305                 UndefinedResolution;
5306               if (info && (info->image_info->units == UndefinedResolution))
5307                 if (image)
5308                   j=image->units;
5309               if (j == UndefinedResolution)
5310                 s=newSVpv("undefined units",0);
5311               else
5312                 if (j == PixelsPerInchResolution)
5313                   s=newSVpv("pixels / inch",0);
5314                 else
5315                   s=newSVpv("pixels / centimeter",0);
5316               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5317               continue;
5318             }
5319           if (LocaleCompare(attribute,"user-time") == 0)
5320             {
5321               if (image != (Image *) NULL)
5322                 s=newSVnv(GetUserTime(&image->timer));
5323               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5324               continue;
5325             }
5326           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5327             attribute);
5328           break;
5329         }
5330         case 'V':
5331         case 'v':
5332         {
5333           if (LocaleCompare(attribute,"verbose") == 0)
5334             {
5335               if (info)
5336                 s=newSViv((ssize_t) info->image_info->verbose);
5337               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5338               continue;
5339             }
5340           if (LocaleCompare(attribute,"version") == 0)
5341             {
5342               s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5343               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5344               continue;
5345             }
5346           if (LocaleCompare(attribute,"view") == 0)
5347             {
5348               if (info && info->image_info->view)
5349                 s=newSVpv(info->image_info->view,0);
5350               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5351               continue;
5352             }
5353           if (LocaleCompare(attribute,"virtual-pixel") == 0)
5354             {
5355               if (image == (Image *) NULL)
5356                 break;
5357               j=(ssize_t) GetImageVirtualPixelMethod(image);
5358               s=newSViv(j);
5359               (void) sv_setpv(s,CommandOptionToMnemonic(
5360                 MagickVirtualPixelOptions,j));
5361               SvIOK_on(s);
5362               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5363               continue;
5364             }
5365           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5366             attribute);
5367           break;
5368         }
5369         case 'W':
5370         case 'w':
5371         {
5372           if (LocaleCompare(attribute,"white-point") == 0)
5373             {
5374               if (image == (Image *) NULL)
5375                 break;
5376               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5377                 image->chromaticity.white_point.x,
5378                 image->chromaticity.white_point.y);
5379               s=newSVpv(color,0);
5380               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5381               continue;
5382             }
5383           if (LocaleCompare(attribute,"width") == 0)
5384             {
5385               if (image != (Image *) NULL)
5386                 s=newSViv((ssize_t) image->columns);
5387               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5388               continue;
5389             }
5390           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5391              attribute);
5392           break;
5393         }
5394         case 'X':
5395         case 'x':
5396         {
5397           if (LocaleCompare(attribute,"x-resolution") == 0)
5398             {
5399               if (image != (Image *) NULL)
5400                 s=newSVnv(image->x_resolution);
5401               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5402               continue;
5403             }
5404           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5405             attribute);
5406           break;
5407         }
5408         case 'Y':
5409         case 'y':
5410         {
5411           if (LocaleCompare(attribute,"y-resolution") == 0)
5412             {
5413               if (image != (Image *) NULL)
5414                 s=newSVnv(image->y_resolution);
5415               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5416               continue;
5417             }
5418           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5419             attribute);
5420           break;
5421         }
5422         default:
5423           break;
5424       }
5425       if (image == (Image *) NULL)
5426         ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5427           attribute)
5428       else
5429         {
5430           value=GetImageProperty(image,attribute);
5431           if (value != (const char *) NULL)
5432             {
5433               s=newSVpv(value,0);
5434               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5435             }
5436           else
5437             if (*attribute != '%')
5438               ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5439                 attribute)
5440             else
5441               {
5442                  char
5443                    *meta;
5444
5445                  meta=InterpretImageProperties(info ? info->image_info :
5446                    (ImageInfo *) NULL,image,attribute);
5447                  s=newSVpv(meta,0);
5448                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5449                  meta=(char *) RelinquishMagickMemory(meta);
5450               }
5451         }
5452     }
5453     exception=DestroyExceptionInfo(exception);
5454     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5455   }
5456 \f
5457 #
5458 ###############################################################################
5459 #                                                                             #
5460 #                                                                             #
5461 #                                                                             #
5462 #   G e t A u t h e n t i c P i x e l s                                       #
5463 #                                                                             #
5464 #                                                                             #
5465 #                                                                             #
5466 ###############################################################################
5467 #
5468 #
5469 void *
5470 GetAuthenticPixels(ref,...)
5471   Image::Magick ref = NO_INIT
5472   ALIAS:
5473     getauthenticpixels = 1
5474     GetImagePixels = 2
5475     getimagepixels = 3
5476   CODE:
5477   {
5478     char
5479       *attribute;
5480
5481     ExceptionInfo
5482       *exception;
5483
5484     Image
5485       *image;
5486
5487     RectangleInfo
5488       region;
5489
5490     ssize_t
5491       i;
5492
5493     struct PackageInfo
5494       *info;
5495
5496     SV
5497       *perl_exception,
5498       *reference;
5499
5500     void
5501       *blob = NULL;
5502
5503     PERL_UNUSED_VAR(ref);
5504     PERL_UNUSED_VAR(ix);
5505     exception=AcquireExceptionInfo();
5506     perl_exception=newSVpv("",0);
5507     if (sv_isobject(ST(0)) == 0)
5508       {
5509         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5510           PackageName);
5511         goto PerlException;
5512       }
5513     reference=SvRV(ST(0));
5514
5515     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5516     if (image == (Image *) NULL)
5517       {
5518         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5519           PackageName);
5520         goto PerlException;
5521       }
5522
5523     region.x=0;
5524     region.y=0;
5525     region.width=image->columns;
5526     region.height=1;
5527     if (items == 1)
5528       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5529     for (i=2; i < items; i+=2)
5530     {
5531       attribute=(char *) SvPV(ST(i-1),na);
5532       switch (*attribute)
5533       {
5534         case 'g':
5535         case 'G':
5536         {
5537           if (LocaleCompare(attribute,"geometry") == 0)
5538             {
5539               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5540               break;
5541             }
5542           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5543             attribute);
5544           break;
5545         }
5546         case 'H':
5547         case 'h':
5548         {
5549           if (LocaleCompare(attribute,"height") == 0)
5550             {
5551               region.height=SvIV(ST(i));
5552               continue;
5553             }
5554           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5555             attribute);
5556           break;
5557         }
5558         case 'X':
5559         case 'x':
5560         {
5561           if (LocaleCompare(attribute,"x") == 0)
5562             {
5563               region.x=SvIV(ST(i));
5564               continue;
5565             }
5566           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5567             attribute);
5568           break;
5569         }
5570         case 'Y':
5571         case 'y':
5572         {
5573           if (LocaleCompare(attribute,"y") == 0)
5574             {
5575               region.y=SvIV(ST(i));
5576               continue;
5577             }
5578           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5579             attribute);
5580           break;
5581         }
5582         case 'W':
5583         case 'w':
5584         {
5585           if (LocaleCompare(attribute,"width") == 0)
5586             {
5587               region.width=SvIV(ST(i));
5588               continue;
5589             }
5590           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5591             attribute);
5592           break;
5593         }
5594       }
5595     }
5596     blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5597       region.height,exception);
5598     if (blob != (void *) NULL)
5599       goto PerlEnd;
5600
5601   PerlException:
5602     InheritPerlException(exception,perl_exception);
5603     exception=DestroyExceptionInfo(exception);
5604     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5605
5606   PerlEnd:
5607     RETVAL = blob;
5608   }
5609   OUTPUT:
5610     RETVAL
5611 \f
5612 #
5613 ###############################################################################
5614 #                                                                             #
5615 #                                                                             #
5616 #                                                                             #
5617 #   G e t V i r t u a l P i x e l s                                           #
5618 #                                                                             #
5619 #                                                                             #
5620 #                                                                             #
5621 ###############################################################################
5622 #
5623 #
5624 void *
5625 GetVirtualPixels(ref,...)
5626   Image::Magick ref = NO_INIT
5627   ALIAS:
5628     getvirtualpixels = 1
5629     AcquireImagePixels = 2
5630     acquireimagepixels = 3
5631   CODE:
5632   {
5633     char
5634       *attribute;
5635
5636     const void
5637       *blob = NULL;
5638
5639     ExceptionInfo
5640       *exception;
5641
5642     Image
5643       *image;
5644
5645     RectangleInfo
5646       region;
5647
5648     ssize_t
5649       i;
5650
5651     struct PackageInfo
5652       *info;
5653
5654     SV
5655       *perl_exception,
5656       *reference;
5657
5658     PERL_UNUSED_VAR(ref);
5659     PERL_UNUSED_VAR(ix);
5660     exception=AcquireExceptionInfo();
5661     perl_exception=newSVpv("",0);
5662     if (sv_isobject(ST(0)) == 0)
5663       {
5664         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5665           PackageName);
5666         goto PerlException;
5667       }
5668     reference=SvRV(ST(0));
5669
5670     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5671     if (image == (Image *) NULL)
5672       {
5673         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5674           PackageName);
5675         goto PerlException;
5676       }
5677
5678     region.x=0;
5679     region.y=0;
5680     region.width=image->columns;
5681     region.height=1;
5682     if (items == 1)
5683       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5684     for (i=2; i < items; i+=2)
5685     {
5686       attribute=(char *) SvPV(ST(i-1),na);
5687       switch (*attribute)
5688       {
5689         case 'g':
5690         case 'G':
5691         {
5692           if (LocaleCompare(attribute,"geometry") == 0)
5693             {
5694               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5695               break;
5696             }
5697           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5698             attribute);
5699           break;
5700         }
5701         case 'H':
5702         case 'h':
5703         {
5704           if (LocaleCompare(attribute,"height") == 0)
5705             {
5706               region.height=SvIV(ST(i));
5707               continue;
5708             }
5709           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5710             attribute);
5711           break;
5712         }
5713         case 'X':
5714         case 'x':
5715         {
5716           if (LocaleCompare(attribute,"x") == 0)
5717             {
5718               region.x=SvIV(ST(i));
5719               continue;
5720             }
5721           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5722             attribute);
5723           break;
5724         }
5725         case 'Y':
5726         case 'y':
5727         {
5728           if (LocaleCompare(attribute,"y") == 0)
5729             {
5730               region.y=SvIV(ST(i));
5731               continue;
5732             }
5733           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5734             attribute);
5735           break;
5736         }
5737         case 'W':
5738         case 'w':
5739         {
5740           if (LocaleCompare(attribute,"width") == 0)
5741             {
5742               region.width=SvIV(ST(i));
5743               continue;
5744             }
5745           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5746             attribute);
5747           break;
5748         }
5749       }
5750     }
5751     blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
5752       region.height,exception);
5753     if (blob != (void *) NULL)
5754       goto PerlEnd;
5755
5756   PerlException:
5757     InheritPerlException(exception,perl_exception);
5758     exception=DestroyExceptionInfo(exception);
5759     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5760
5761   PerlEnd:
5762     RETVAL = (void *) blob;
5763   }
5764   OUTPUT:
5765     RETVAL
5766 \f
5767 #
5768 ###############################################################################
5769 #                                                                             #
5770 #                                                                             #
5771 #                                                                             #
5772 #   G e t A u t h e n t i c M e t a c o n t e n t                             #
5773 #                                                                             #
5774 #                                                                             #
5775 #                                                                             #
5776 ###############################################################################
5777 #
5778 #
5779 void *
5780 GetAuthenticMetacontent(ref,...)
5781   Image::Magick ref = NO_INIT
5782   ALIAS:
5783     getauthenticmetacontent = 1
5784     GetMetacontent = 2
5785     getmetacontent = 3
5786   CODE:
5787   {
5788     ExceptionInfo
5789       *exception;
5790
5791     Image
5792       *image;
5793
5794     struct PackageInfo
5795       *info;
5796
5797     SV
5798       *perl_exception,
5799       *reference;
5800
5801     void
5802       *blob = NULL;
5803
5804     PERL_UNUSED_VAR(ref);
5805     PERL_UNUSED_VAR(ix);
5806     exception=AcquireExceptionInfo();
5807     perl_exception=newSVpv("",0);
5808     if (sv_isobject(ST(0)) == 0)
5809       {
5810         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5811           PackageName);
5812         goto PerlException;
5813       }
5814     reference=SvRV(ST(0));
5815
5816     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5817     if (image == (Image *) NULL)
5818       {
5819         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5820           PackageName);
5821         goto PerlException;
5822       }
5823
5824     blob=(void *) GetAuthenticMetacontent(image);
5825     if (blob != (void *) NULL)
5826       goto PerlEnd;
5827
5828   PerlException:
5829     InheritPerlException(exception,perl_exception);
5830     exception=DestroyExceptionInfo(exception);
5831     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5832
5833   PerlEnd:
5834     RETVAL = blob;
5835   }
5836   OUTPUT:
5837     RETVAL
5838 \f
5839 #
5840 ###############################################################################
5841 #                                                                             #
5842 #                                                                             #
5843 #                                                                             #
5844 #   G e t V i r t u a l M e t a c o n t e n t                                 #
5845 #                                                                             #
5846 #                                                                             #
5847 #                                                                             #
5848 ###############################################################################
5849 #
5850 #
5851 void *
5852 GetVirtualMetacontent(ref,...)
5853   Image::Magick ref = NO_INIT
5854   ALIAS:
5855     getvirtualmetacontent = 1
5856   CODE:
5857   {
5858     ExceptionInfo
5859       *exception;
5860
5861     Image
5862       *image;
5863
5864     struct PackageInfo
5865       *info;
5866
5867     SV
5868       *perl_exception,
5869       *reference;
5870
5871     void
5872       *blob = NULL;
5873
5874     PERL_UNUSED_VAR(ref);
5875     PERL_UNUSED_VAR(ix);
5876     exception=AcquireExceptionInfo();
5877     perl_exception=newSVpv("",0);
5878     if (sv_isobject(ST(0)) == 0)
5879       {
5880         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5881           PackageName);
5882         goto PerlException;
5883       }
5884     reference=SvRV(ST(0));
5885
5886     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5887     if (image == (Image *) NULL)
5888       {
5889         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5890           PackageName);
5891         goto PerlException;
5892       }
5893
5894     blob=(void *) GetVirtualMetacontent(image);
5895     if (blob != (void *) NULL)
5896       goto PerlEnd;
5897
5898   PerlException:
5899     InheritPerlException(exception,perl_exception);
5900     exception=DestroyExceptionInfo(exception);
5901     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5902
5903   PerlEnd:
5904     RETVAL = blob;
5905   }
5906   OUTPUT:
5907     RETVAL
5908 \f
5909 #
5910 ###############################################################################
5911 #                                                                             #
5912 #                                                                             #
5913 #                                                                             #
5914 #   H i s t o g r a m                                                         #
5915 #                                                                             #
5916 #                                                                             #
5917 #                                                                             #
5918 ###############################################################################
5919 #
5920 #
5921 void
5922 Histogram(ref,...)
5923   Image::Magick ref=NO_INIT
5924   ALIAS:
5925     HistogramImage = 1
5926     histogram      = 2
5927     histogramimage = 3
5928   PPCODE:
5929   {
5930     AV
5931       *av;
5932
5933     char
5934       message[MaxTextExtent];
5935
5936     PixelPacket
5937       *histogram;
5938
5939     ExceptionInfo
5940       *exception;
5941
5942     Image
5943       *image;
5944
5945     register ssize_t
5946       i;
5947
5948     ssize_t
5949       count;
5950
5951     struct PackageInfo
5952       *info;
5953
5954     SV
5955       *perl_exception,
5956       *reference;
5957
5958     size_t
5959       number_colors;
5960
5961     PERL_UNUSED_VAR(ref);
5962     PERL_UNUSED_VAR(ix);
5963     exception=AcquireExceptionInfo();
5964     perl_exception=newSVpv("",0);
5965     av=NULL;
5966     if (sv_isobject(ST(0)) == 0)
5967       {
5968         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5969           PackageName);
5970         goto PerlException;
5971       }
5972     reference=SvRV(ST(0));
5973     av=newAV();
5974     SvREFCNT_dec(av);
5975     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5976     if (image == (Image *) NULL)
5977       {
5978         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5979           PackageName);
5980         goto PerlException;
5981       }
5982     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
5983     count=0;
5984     for ( ; image; image=image->next)
5985     {
5986       histogram=GetImageHistogram(image,&number_colors,&image->exception);
5987       if (histogram == (PixelPacket *) NULL)
5988         continue;
5989       count+=(ssize_t) number_colors;
5990       EXTEND(sp,6*count);
5991       for (i=0; i < (ssize_t) number_colors; i++)
5992       {
5993         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
5994           histogram[i].red);
5995         PUSHs(sv_2mortal(newSVpv(message,0)));
5996         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
5997           histogram[i].green);
5998         PUSHs(sv_2mortal(newSVpv(message,0)));
5999         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
6000           histogram[i].blue);
6001         PUSHs(sv_2mortal(newSVpv(message,0)));
6002         if (image->colorspace == CMYKColorspace)
6003           {
6004             (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
6005               histogram[i].black);
6006             PUSHs(sv_2mortal(newSVpv(message,0)));
6007           }
6008         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
6009           histogram[i].alpha);
6010         PUSHs(sv_2mortal(newSVpv(message,0)));
6011         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
6012           histogram[i].count);
6013         PUSHs(sv_2mortal(newSVpv(message,0)));
6014       }
6015       histogram=(PixelPacket *) RelinquishMagickMemory(histogram);
6016     }
6017
6018   PerlException:
6019     InheritPerlException(exception,perl_exception);
6020     exception=DestroyExceptionInfo(exception);
6021     SvREFCNT_dec(perl_exception);
6022   }
6023 \f
6024 #
6025 ###############################################################################
6026 #                                                                             #
6027 #                                                                             #
6028 #                                                                             #
6029 #   G e t P i x e l                                                           #
6030 #                                                                             #
6031 #                                                                             #
6032 #                                                                             #
6033 ###############################################################################
6034 #
6035 #
6036 void
6037 GetPixel(ref,...)
6038   Image::Magick ref=NO_INIT
6039   ALIAS:
6040     getpixel = 1
6041     getPixel = 2
6042   PPCODE:
6043   {
6044     AV
6045       *av;
6046
6047     char
6048       *attribute;
6049
6050     ExceptionInfo
6051       *exception;
6052
6053     Image
6054       *image;
6055
6056     MagickBooleanType
6057       normalize;
6058
6059     RectangleInfo
6060       region;
6061
6062     register const Quantum
6063       *p;
6064
6065     register ssize_t
6066       i;
6067
6068     ssize_t
6069       option;
6070
6071     struct PackageInfo
6072       *info;
6073
6074     SV
6075       *perl_exception,
6076       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6077
6078     PERL_UNUSED_VAR(ref);
6079     PERL_UNUSED_VAR(ix);
6080     exception=AcquireExceptionInfo();
6081     perl_exception=newSVpv("",0);
6082     reference=SvRV(ST(0));
6083     av=(AV *) reference;
6084     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6085       exception);
6086     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6087     if (image == (Image *) NULL)
6088       {
6089         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6090           PackageName);
6091         goto PerlException;
6092       }
6093     normalize=MagickTrue;
6094     region.x=0;
6095     region.y=0;
6096     region.width=image->columns;
6097     region.height=1;
6098     if (items == 1)
6099       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6100     for (i=2; i < items; i+=2)
6101     {
6102       attribute=(char *) SvPV(ST(i-1),na);
6103       switch (*attribute)
6104       {
6105         case 'C':
6106         case 'c':
6107         {
6108           if (LocaleCompare(attribute,"channel") == 0)
6109             {
6110               ssize_t
6111                 option;
6112
6113               option=ParseChannelOption(SvPV(ST(i),na));
6114               if (option < 0)
6115                 {
6116                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6117                     SvPV(ST(i),na));
6118                   return;
6119                 }
6120               SetPixelChannelMap(image,(ChannelType) option);
6121               break;
6122             }
6123           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6124             attribute);
6125           break;
6126         }
6127         case 'g':
6128         case 'G':
6129         {
6130           if (LocaleCompare(attribute,"geometry") == 0)
6131             {
6132               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6133               break;
6134             }
6135           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6136             attribute);
6137           break;
6138         }
6139         case 'N':
6140         case 'n':
6141         {
6142           if (LocaleCompare(attribute,"normalize") == 0)
6143             {
6144               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6145                 SvPV(ST(i),na));
6146               if (option < 0)
6147                 {
6148                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6149                     SvPV(ST(i),na));
6150                   break;
6151                 }
6152              normalize=option != 0 ? MagickTrue : MagickFalse;
6153              break;
6154             }
6155           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6156             attribute);
6157           break;
6158         }
6159         case 'x':
6160         case 'X':
6161         {
6162           if (LocaleCompare(attribute,"x") == 0)
6163             {
6164               region.x=SvIV(ST(i));
6165               break;
6166             }
6167           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6168             attribute);
6169           break;
6170         }
6171         case 'y':
6172         case 'Y':
6173         {
6174           if (LocaleCompare(attribute,"y") == 0)
6175             {
6176               region.y=SvIV(ST(i));
6177               break;
6178             }
6179           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6180             attribute);
6181           break;
6182         }
6183         default:
6184         {
6185           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6186             attribute);
6187           break;
6188         }
6189       }
6190     }
6191     p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6192     if (p == (const Quantum *) NULL)
6193       PUSHs(&sv_undef);
6194     else
6195       {
6196         double
6197           scale;
6198
6199         scale=1.0;
6200         if (normalize != MagickFalse)
6201           scale=1.0/QuantumRange;
6202         if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
6203           PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6204         if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6205           PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6206         if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6207           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6208         if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6209             (image->colorspace == CMYKColorspace))
6210           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6211         if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
6212           PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6213       }
6214
6215   PerlException:
6216     InheritPerlException(exception,perl_exception);
6217     exception=DestroyExceptionInfo(exception);
6218     SvREFCNT_dec(perl_exception);
6219   }
6220 \f
6221 #
6222 ###############################################################################
6223 #                                                                             #
6224 #                                                                             #
6225 #                                                                             #
6226 #   G e t P i x e l s                                                         #
6227 #                                                                             #
6228 #                                                                             #
6229 #                                                                             #
6230 ###############################################################################
6231 #
6232 #
6233 void
6234 GetPixels(ref,...)
6235   Image::Magick ref=NO_INIT
6236   ALIAS:
6237     getpixels = 1
6238     getPixels = 2
6239   PPCODE:
6240   {
6241     AV
6242       *av;
6243
6244     char
6245       *attribute;
6246
6247     const char
6248       *map;
6249
6250     ExceptionInfo
6251       *exception;
6252
6253     Image
6254       *image;
6255
6256     MagickBooleanType
6257       normalize,
6258       status;
6259
6260     RectangleInfo
6261       region;
6262
6263     register ssize_t
6264       i;
6265
6266     ssize_t
6267       option;
6268
6269     struct PackageInfo
6270       *info;
6271
6272     SV
6273       *perl_exception,
6274       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6275
6276     PERL_UNUSED_VAR(ref);
6277     PERL_UNUSED_VAR(ix);
6278     exception=AcquireExceptionInfo();
6279     perl_exception=newSVpv("",0);
6280     reference=SvRV(ST(0));
6281     av=(AV *) reference;
6282     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6283       exception);
6284     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6285     if (image == (Image *) NULL)
6286       {
6287         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6288           PackageName);
6289         goto PerlException;
6290       }
6291     map="RGB";
6292     if (image->matte != MagickFalse)
6293       map="RGBA";
6294     if (image->colorspace == CMYKColorspace)
6295       {
6296         map="CMYK";
6297         if (image->matte != MagickFalse)
6298           map="CMYKA";
6299       }
6300     normalize=MagickFalse;
6301     region.x=0;
6302     region.y=0;
6303     region.width=image->columns;
6304     region.height=1;
6305     if (items == 1)
6306       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6307     for (i=2; i < items; i+=2)
6308     {
6309       attribute=(char *) SvPV(ST(i-1),na);
6310       switch (*attribute)
6311       {
6312         case 'g':
6313         case 'G':
6314         {
6315           if (LocaleCompare(attribute,"geometry") == 0)
6316             {
6317               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6318               break;
6319             }
6320           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6321             attribute);
6322           break;
6323         }
6324         case 'H':
6325         case 'h':
6326         {
6327           if (LocaleCompare(attribute,"height") == 0)
6328             {
6329               region.height=SvIV(ST(i));
6330               break;
6331             }
6332           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6333             attribute);
6334           break;
6335         }
6336         case 'M':
6337         case 'm':
6338         {
6339           if (LocaleCompare(attribute,"map") == 0)
6340             {
6341               map=SvPV(ST(i),na);
6342               break;
6343             }
6344           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6345             attribute);
6346           break;
6347         }
6348         case 'N':
6349         case 'n':
6350         {
6351           if (LocaleCompare(attribute,"normalize") == 0)
6352             {
6353               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6354                 SvPV(ST(i),na));
6355               if (option < 0)
6356                 {
6357                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6358                     SvPV(ST(i),na));
6359                   break;
6360                 }
6361              normalize=option != 0 ? MagickTrue : MagickFalse;
6362              break;
6363             }
6364           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6365             attribute);
6366           break;
6367         }
6368         case 'W':
6369         case 'w':
6370         {
6371           if (LocaleCompare(attribute,"width") == 0)
6372             {
6373               region.width=SvIV(ST(i));
6374               break;
6375             }
6376           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6377             attribute);
6378           break;
6379         }
6380         case 'x':
6381         case 'X':
6382         {
6383           if (LocaleCompare(attribute,"x") == 0)
6384             {
6385               region.x=SvIV(ST(i));
6386               break;
6387             }
6388           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6389             attribute);
6390           break;
6391         }
6392         case 'y':
6393         case 'Y':
6394         {
6395           if (LocaleCompare(attribute,"y") == 0)
6396             {
6397               region.y=SvIV(ST(i));
6398               break;
6399             }
6400           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6401             attribute);
6402           break;
6403         }
6404         default:
6405         {
6406           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6407             attribute);
6408           break;
6409         }
6410       }
6411     }
6412     if (normalize != MagickFalse)
6413       {
6414         float
6415           *pixels;
6416
6417         pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6418           region.height*sizeof(*pixels));
6419         if (pixels == (float *) NULL)
6420           {
6421             ThrowPerlException(exception,ResourceLimitError,
6422               "MemoryAllocationFailed",PackageName);
6423             goto PerlException;
6424           }
6425         status=ExportImagePixels(image,region.x,region.y,region.width,
6426           region.height,map,FloatPixel,pixels,exception);
6427         if (status == MagickFalse)
6428           PUSHs(&sv_undef);
6429         else
6430           {
6431             EXTEND(sp,strlen(map)*region.width*region.height);
6432             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6433               PUSHs(sv_2mortal(newSVnv(pixels[i])));
6434           }
6435         pixels=(float *) RelinquishMagickMemory(pixels);
6436       }
6437     else
6438       {
6439         Quantum
6440           *pixels;
6441
6442         pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6443           region.height*sizeof(*pixels));
6444         if (pixels == (Quantum *) NULL)
6445           {
6446             ThrowPerlException(exception,ResourceLimitError,
6447               "MemoryAllocationFailed",PackageName);
6448             goto PerlException;
6449           }
6450         status=ExportImagePixels(image,region.x,region.y,region.width,
6451           region.height,map,QuantumPixel,pixels,exception);
6452         if (status == MagickFalse)
6453           PUSHs(&sv_undef);
6454         else
6455           {
6456             EXTEND(sp,strlen(map)*region.width*region.height);
6457             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6458               PUSHs(sv_2mortal(newSViv(pixels[i])));
6459           }
6460         pixels=(Quantum *) RelinquishMagickMemory(pixels);
6461       }
6462
6463   PerlException:
6464     InheritPerlException(exception,perl_exception);
6465     exception=DestroyExceptionInfo(exception);
6466     SvREFCNT_dec(perl_exception);
6467   }
6468 \f
6469 #
6470 ###############################################################################
6471 #                                                                             #
6472 #                                                                             #
6473 #                                                                             #
6474 #   I m a g e T o B l o b                                                     #
6475 #                                                                             #
6476 #                                                                             #
6477 #                                                                             #
6478 ###############################################################################
6479 #
6480 #
6481 void
6482 ImageToBlob(ref,...)
6483   Image::Magick ref=NO_INIT
6484   ALIAS:
6485     ImageToBlob  = 1
6486     imagetoblob  = 2
6487     toblob       = 3
6488     blob         = 4
6489   PPCODE:
6490   {
6491     char
6492       filename[MaxTextExtent];
6493
6494     ExceptionInfo
6495       *exception;
6496
6497     Image
6498       *image,
6499       *next;
6500
6501     register ssize_t
6502       i;
6503
6504     struct PackageInfo
6505       *info,
6506       *package_info;
6507
6508     size_t
6509       length;
6510
6511     ssize_t
6512       scene;
6513
6514     SV
6515       *perl_exception,
6516       *reference;
6517
6518     void
6519       *blob;
6520
6521     PERL_UNUSED_VAR(ref);
6522     PERL_UNUSED_VAR(ix);
6523     exception=AcquireExceptionInfo();
6524     perl_exception=newSVpv("",0);
6525     package_info=(struct PackageInfo *) NULL;
6526     if (sv_isobject(ST(0)) == 0)
6527       {
6528         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6529           PackageName);
6530         goto PerlException;
6531       }
6532     reference=SvRV(ST(0));
6533     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6534     if (image == (Image *) NULL)
6535       {
6536         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6537           PackageName);
6538         goto PerlException;
6539       }
6540     package_info=ClonePackageInfo(info,exception);
6541     for (i=2; i < items; i+=2)
6542       SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6543     (void) CopyMagickString(filename,package_info->image_info->filename,
6544       MaxTextExtent);
6545     scene=0;
6546     for (next=image; next; next=next->next)
6547     {
6548       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
6549       next->scene=scene++;
6550     }
6551     SetImageInfo(package_info->image_info,(unsigned int)
6552       GetImageListLength(image),&image->exception);
6553     EXTEND(sp,(ssize_t) GetImageListLength(image));
6554     for ( ; image; image=image->next)
6555     {
6556       length=0;
6557       blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6558       if (blob != (char *) NULL)
6559         {
6560           PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6561           blob=(unsigned char *) RelinquishMagickMemory(blob);
6562         }
6563       if (package_info->image_info->adjoin)
6564         break;
6565     }
6566
6567   PerlException:
6568     if (package_info != (struct PackageInfo *) NULL)
6569       DestroyPackageInfo(package_info);
6570     InheritPerlException(exception,perl_exception);
6571     exception=DestroyExceptionInfo(exception);
6572     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6573   }
6574 \f
6575 #
6576 ###############################################################################
6577 #                                                                             #
6578 #                                                                             #
6579 #                                                                             #
6580 #   L a y e r s                                                               #
6581 #                                                                             #
6582 #                                                                             #
6583 #                                                                             #
6584 ###############################################################################
6585 #
6586 #
6587 void
6588 Layers(ref,...)
6589   Image::Magick ref=NO_INIT
6590   ALIAS:
6591     Layers                = 1
6592     layers           = 2
6593     OptimizeImageLayers   = 3
6594     optimizelayers        = 4
6595     optimizeimagelayers   = 5
6596   PPCODE:
6597   {
6598     AV
6599       *av;
6600
6601     char
6602       *attribute;
6603
6604     CompositeOperator
6605       compose;
6606
6607     ExceptionInfo
6608       *exception;
6609
6610     HV
6611       *hv;
6612
6613     Image
6614       *image,
6615       *layers;
6616
6617     ImageLayerMethod
6618       method;
6619
6620     register ssize_t
6621       i;
6622
6623     ssize_t
6624       option,
6625       sp;
6626
6627     struct PackageInfo
6628       *info;
6629
6630     SV
6631       *av_reference,
6632       *perl_exception,
6633       *reference,
6634       *rv,
6635       *sv;
6636
6637     PERL_UNUSED_VAR(ref);
6638     PERL_UNUSED_VAR(ix);
6639     exception=AcquireExceptionInfo();
6640     perl_exception=newSVpv("",0);
6641     sv=NULL;
6642     if (sv_isobject(ST(0)) == 0)
6643       {
6644         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6645           PackageName);
6646         goto PerlException;
6647       }
6648     reference=SvRV(ST(0));
6649     hv=SvSTASH(reference);
6650     av=newAV();
6651     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
6652     SvREFCNT_dec(av);
6653     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6654     if (image == (Image *) NULL)
6655       {
6656         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6657           PackageName);
6658         goto PerlException;
6659       }
6660     compose=image->compose;
6661     method=OptimizeLayer;
6662     for (i=2; i < items; i+=2)
6663     {
6664       attribute=(char *) SvPV(ST(i-1),na);
6665       switch (*attribute)
6666       {
6667         case 'C':
6668         case 'c':
6669         {
6670           if (LocaleCompare(attribute,"compose") == 0)
6671             {
6672               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
6673                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
6674               if (sp < 0)
6675                 {
6676                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6677                     SvPV(ST(i),na));
6678                   break;
6679                 }
6680               compose=(CompositeOperator) sp;
6681               break;
6682             }
6683           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6684             attribute);
6685           break;
6686         }
6687         case 'M':
6688         case 'm':
6689         {
6690           if (LocaleCompare(attribute,"method") == 0)
6691             {
6692               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
6693                 SvPV(ST(i),na));
6694               if (option < 0)
6695                 {
6696                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6697                     SvPV(ST(i),na));
6698                   break;
6699                 }
6700               method=(ImageLayerMethod) option;
6701               break;
6702             }
6703           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6704             attribute);
6705           break;
6706         }
6707         default:
6708         {
6709           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6710             attribute);
6711           break;
6712         }
6713       }
6714     }
6715     layers=(Image *) NULL;
6716     switch (method)
6717     {
6718       case CompareAnyLayer:
6719       case CompareClearLayer:
6720       case CompareOverlayLayer:
6721       default:
6722       {
6723         layers=CompareImagesLayers(image,method,exception);
6724         break;
6725       }
6726       case MergeLayer:
6727       case FlattenLayer:
6728       case MosaicLayer:
6729       {
6730         layers=MergeImageLayers(image,method,exception);
6731         break;
6732       }
6733       case DisposeLayer:
6734       {
6735         layers=DisposeImages(image,exception);
6736         break;
6737       }
6738       case OptimizeImageLayer:
6739       {
6740         layers=OptimizeImageLayers(image,exception);
6741         break;
6742       }
6743       case OptimizePlusLayer:
6744       {
6745         layers=OptimizePlusImageLayers(image,exception);
6746         break;
6747       }
6748       case OptimizeTransLayer:
6749       {
6750         OptimizeImageTransparency(image,exception);
6751         InheritException(&(image->exception),exception);
6752         break;
6753       }
6754       case RemoveDupsLayer:
6755       {
6756         RemoveDuplicateLayers(&image,exception);
6757         InheritException(&(image->exception),exception);
6758         break;
6759       }
6760       case RemoveZeroLayer:
6761       {
6762         RemoveZeroDelayLayers(&image,exception);
6763         InheritException(&(image->exception),exception);
6764         break;
6765       }
6766       case OptimizeLayer:
6767       {
6768         QuantizeInfo
6769           *quantize_info;
6770
6771         /*
6772           General Purpose, GIF Animation Optimizer.
6773         */
6774         layers=CoalesceImages(image,exception);
6775         if (layers == (Image *) NULL)
6776           break;
6777         InheritException(&(layers->exception),exception);
6778         image=layers;
6779         layers=OptimizeImageLayers(image,exception);
6780         if (layers == (Image *) NULL)
6781           break;
6782         InheritException(&(layers->exception),exception);
6783         image=DestroyImageList(image);
6784         image=layers;
6785         layers=(Image *) NULL;
6786         OptimizeImageTransparency(image,exception);
6787         InheritException(&(image->exception),exception);
6788         quantize_info=AcquireQuantizeInfo(info->image_info);
6789         (void) RemapImages(quantize_info,image,(Image *) NULL);
6790         quantize_info=DestroyQuantizeInfo(quantize_info);
6791         break;
6792       }
6793       case CompositeLayer:
6794       {
6795         Image
6796           *source;
6797
6798         RectangleInfo
6799           geometry;
6800
6801         /*
6802           Split image sequence at the first 'NULL:' image.
6803         */
6804         source=image;
6805         while (source != (Image *) NULL)
6806         {
6807           source=GetNextImageInList(source);
6808           if ((source != (Image *) NULL) &&
6809               (LocaleCompare(source->magick,"NULL") == 0))
6810             break;
6811         }
6812         if (source != (Image *) NULL)
6813           {
6814             if ((GetPreviousImageInList(source) == (Image *) NULL) ||
6815                 (GetNextImageInList(source) == (Image *) NULL))
6816               source=(Image *) NULL;
6817             else
6818               {
6819                 /*
6820                   Separate the two lists, junk the null: image.
6821                 */
6822                 source=SplitImageList(source->previous);
6823                 DeleteImageFromList(&source);
6824               }
6825           }
6826         if (source == (Image *) NULL)
6827           {
6828             (void) ThrowMagickException(exception,GetMagickModule(),
6829               OptionError,"MissingNullSeparator","layers Composite");
6830             break;
6831           }
6832         /*
6833           Adjust offset with gravity and virtual canvas.
6834         */
6835         SetGeometry(image,&geometry);
6836         (void) ParseAbsoluteGeometry(image->geometry,&geometry);
6837         geometry.width=source->page.width != 0 ? source->page.width :
6838           source->columns;
6839         geometry.height=source->page.height != 0 ? source->page.height :
6840           source->rows;
6841         GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
6842           image->columns,image->page.height != 0 ? image->page.height :
6843           image->rows,image->gravity,&geometry);
6844         CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
6845         source=DestroyImageList(source);
6846         InheritException(&(image->exception),exception);
6847         break;
6848       }
6849     }
6850     if (layers != (Image *) NULL)
6851       {
6852         InheritException(&(layers->exception),exception);
6853         image=layers;
6854       }
6855     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
6856       goto PerlException;
6857     for ( ; image; image=image->next)
6858     {
6859       AddImageToRegistry(sv,image);
6860       rv=newRV(sv);
6861       av_push(av,sv_bless(rv,hv));
6862       SvREFCNT_dec(sv);
6863     }
6864     exception=DestroyExceptionInfo(exception);
6865     ST(0)=av_reference;
6866     SvREFCNT_dec(perl_exception);
6867     XSRETURN(1);
6868
6869   PerlException:
6870     InheritPerlException(exception,perl_exception);
6871     exception=DestroyExceptionInfo(exception);
6872     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
6873     SvPOK_on(perl_exception);
6874     ST(0)=sv_2mortal(perl_exception);
6875     XSRETURN(1);
6876   }
6877 \f
6878 #
6879 ###############################################################################
6880 #                                                                             #
6881 #                                                                             #
6882 #                                                                             #
6883 #   M a g i c k T o M i m e                                                   #
6884 #                                                                             #
6885 #                                                                             #
6886 #                                                                             #
6887 ###############################################################################
6888 #
6889 #
6890 SV *
6891 MagickToMime(ref,name)
6892   Image::Magick ref=NO_INIT
6893   char *name
6894   ALIAS:
6895     magicktomime = 1
6896   CODE:
6897   {
6898     char
6899       *mime;
6900
6901     PERL_UNUSED_VAR(ref);
6902     PERL_UNUSED_VAR(ix);
6903     mime=MagickToMime(name);
6904     RETVAL=newSVpv(mime,0);
6905     mime=(char *) RelinquishMagickMemory(mime);
6906   }
6907   OUTPUT:
6908     RETVAL
6909 \f
6910 #
6911 ###############################################################################
6912 #                                                                             #
6913 #                                                                             #
6914 #                                                                             #
6915 #   M o g r i f y                                                             #
6916 #                                                                             #
6917 #                                                                             #
6918 #                                                                             #
6919 ###############################################################################
6920 #
6921 #
6922 void
6923 Mogrify(ref,...)
6924   Image::Magick ref=NO_INIT
6925   ALIAS:
6926     Comment            =   1
6927     CommentImage       =   2
6928     Label              =   3
6929     LabelImage         =   4
6930     AddNoise           =   5
6931     AddNoiseImage      =   6
6932     Colorize           =   7
6933     ColorizeImage      =   8
6934     Border             =   9
6935     BorderImage        =  10
6936     Blur               =  11
6937     BlurImage          =  12
6938     Chop               =  13
6939     ChopImage          =  14
6940     Crop               =  15
6941     CropImage          =  16
6942     Despeckle          =  17
6943     DespeckleImage     =  18
6944     Edge               =  19
6945     EdgeImage          =  20
6946     Emboss             =  21
6947     EmbossImage        =  22
6948     Enhance            =  23
6949     EnhanceImage       =  24
6950     Flip               =  25
6951     FlipImage          =  26
6952     Flop               =  27
6953     FlopImage          =  28
6954     Frame              =  29
6955     FrameImage         =  30
6956     Implode            =  31
6957     ImplodeImage       =  32
6958     Magnify            =  33
6959     MagnifyImage       =  34
6960     MedianFilter       =  35
6961     MedianConvolveImage  =  36
6962     Minify             =  37
6963     MinifyImage        =  38
6964     OilPaint           =  39
6965     OilPaintImage      =  40
6966     ReduceNoise        =  41
6967     ReduceNoiseImage   =  42
6968     Roll               =  43
6969     RollImage          =  44
6970     Rotate             =  45
6971     RotateImage        =  46
6972     Sample             =  47
6973     SampleImage        =  48
6974     Scale              =  49
6975     ScaleImage         =  50
6976     Shade              =  51
6977     ShadeImage         =  52
6978     Sharpen            =  53
6979     SharpenImage       =  54
6980     Shear              =  55
6981     ShearImage         =  56
6982     Spread             =  57
6983     SpreadImage        =  58
6984     Swirl              =  59
6985     SwirlImage         =  60
6986     Resize             =  61
6987     ResizeImage        =  62
6988     Zoom               =  63
6989     ZoomImage          =  64
6990     Annotate           =  65
6991     AnnotateImage      =  66
6992     ColorFloodfill     =  67
6993     ColorFloodfillImage=  68
6994     Composite          =  69
6995     CompositeImage     =  70
6996     Contrast           =  71
6997     ContrastImage      =  72
6998     CycleColormap      =  73
6999     CycleColormapImage =  74
7000     Draw               =  75
7001     DrawImage          =  76
7002     Equalize           =  77
7003     EqualizeImage      =  78
7004     Gamma              =  79
7005     GammaImage         =  80
7006     Map                =  81
7007     MapImage           =  82
7008     MatteFloodfill     =  83
7009     MatteFloodfillImage=  84
7010     Modulate           =  85
7011     ModulateImage      =  86
7012     Negate             =  87
7013     NegateImage        =  88
7014     Normalize          =  89
7015     NormalizeImage     =  90
7016     NumberColors       =  91
7017     NumberColorsImage  =  92
7018     Opaque             =  93
7019     OpaqueImage        =  94
7020     Quantize           =  95
7021     QuantizeImage      =  96
7022     Raise              =  97
7023     RaiseImage         =  98
7024     Segment            =  99
7025     SegmentImage       = 100
7026     Signature          = 101
7027     SignatureImage     = 102
7028     Solarize           = 103
7029     SolarizeImage      = 104
7030     Sync               = 105
7031     SyncImage          = 106
7032     Texture            = 107
7033     TextureImage       = 108
7034     Evaluate           = 109
7035     EvaluateImage      = 110
7036     Transparent        = 111
7037     TransparentImage   = 112
7038     Threshold          = 113
7039     ThresholdImage     = 114
7040     Charcoal           = 115
7041     CharcoalImage      = 116
7042     Trim               = 117
7043     TrimImage          = 118
7044     Wave               = 119
7045     WaveImage          = 120
7046     Separate           = 121
7047     SeparateImage      = 122
7048     Stereo             = 125
7049     StereoImage        = 126
7050     Stegano            = 127
7051     SteganoImage       = 128
7052     Deconstruct        = 129
7053     DeconstructImage   = 130
7054     GaussianBlur       = 131
7055     GaussianBlurImage  = 132
7056     Convolve           = 133
7057     ConvolveImage      = 134
7058     Profile            = 135
7059     ProfileImage       = 136
7060     UnsharpMask        = 137
7061     UnsharpMaskImage   = 138
7062     MotionBlur         = 139
7063     MotionBlurImage    = 140
7064     OrderedDither      = 141
7065     OrderedDitherImage = 142
7066     Shave              = 143
7067     ShaveImage         = 144
7068     Level              = 145
7069     LevelImage         = 146
7070     Clip               = 147
7071     ClipImage          = 148
7072     AffineTransform    = 149
7073     AffineTransformImage = 150
7074     Difference         = 151
7075     DifferenceImage    = 152
7076     AdaptiveThreshold  = 153
7077     AdaptiveThresholdImage = 154
7078     Resample           = 155
7079     ResampleImage      = 156
7080     Describe           = 157
7081     DescribeImage      = 158
7082     BlackThreshold     = 159
7083     BlackThresholdImage= 160
7084     WhiteThreshold     = 161
7085     WhiteThresholdImage= 162
7086     RadialBlur         = 163
7087     RadialBlurImage    = 164
7088     Thumbnail          = 165
7089     ThumbnailImage     = 166
7090     Strip              = 167
7091     StripImage         = 168
7092     Tint               = 169
7093     TintImage          = 170
7094     Channel            = 171
7095     ChannelImage       = 172
7096     Splice             = 173
7097     SpliceImage        = 174
7098     Posterize          = 175
7099     PosterizeImage     = 176
7100     Shadow             = 177
7101     ShadowImage        = 178
7102     Identify           = 179
7103     IdentifyImage      = 180
7104     SepiaTone          = 181
7105     SepiaToneImage     = 182
7106     SigmoidalContrast  = 183
7107     SigmoidalContrastImage = 184
7108     Extent             = 185
7109     ExtentImage        = 186
7110     Vignette           = 187
7111     VignetteImage      = 188
7112     ContrastStretch    = 189
7113     ContrastStretchImage = 190
7114     Sans0              = 191
7115     Sans0Image         = 192
7116     Sans1              = 193
7117     Sans1Image         = 194
7118     AdaptiveSharpen    = 195
7119     AdaptiveSharpenImage = 196
7120     Transpose          = 197
7121     TransposeImage     = 198
7122     Transverse         = 199
7123     TransverseImage    = 200
7124     AutoOrient         = 201
7125     AutoOrientImage    = 202
7126     AdaptiveBlur       = 203
7127     AdaptiveBlurImage  = 204
7128     Sketch             = 205
7129     SketchImage        = 206
7130     UniqueColors       = 207
7131     UniqueColorsImage  = 208
7132     AdaptiveResize     = 209
7133     AdaptiveResizeImage= 210
7134     ClipMask           = 211
7135     ClipMaskImage      = 212
7136     LinearStretch      = 213
7137     LinearStretchImage = 214
7138     RecolorImage       = 215
7139     Recolor            = 216
7140     Mask               = 217
7141     MaskImage          = 218
7142     Polaroid           = 219
7143     PolaroidImage      = 220
7144     FloodfillPaint     = 221
7145     FloodfillPaintImage= 222
7146     Distort            = 223
7147     DistortImage       = 224
7148     Clut               = 225
7149     ClutImage          = 226
7150     LiquidRescale      = 227
7151     LiquidRescaleImage = 228
7152     Encipher           = 229
7153     EncipherImage      = 230
7154     Decipher           = 231
7155     DecipherImage      = 232
7156     Deskew             = 233
7157     DeskewImage        = 234
7158     Remap              = 235
7159     RemapImage         = 236
7160     SparseColor        = 237
7161     SparseColorImage   = 238
7162     Function           = 239
7163     FunctionImage      = 240
7164     SelectiveBlur      = 241
7165     SelectiveBlurImage = 242
7166     HaldClut           = 243
7167     HaldClutImage      = 244
7168     BlueShift          = 245
7169     BlueShiftImage     = 246
7170     ForwardFourierTransform  = 247
7171     ForwardFourierTransformImage = 248
7172     InverseFourierTransform = 249
7173     InverseFourierTransformImage = 250
7174     ColorDecisionList  = 251
7175     ColorDecisionListImage = 252
7176     AutoGamma          = 253
7177     AutoGammaImage     = 254
7178     AutoLevel          = 255
7179     AutoLevelImage     = 256
7180     LevelColors        = 257
7181     LevelImageColors   = 258
7182     Clamp              = 259
7183     ClampImage         = 260
7184     BrightnessContrast = 263
7185     BrightnessContrastImage = 264
7186     Morphology         = 265
7187     MorphologyImage    = 266
7188     ColorMatrix        = 267
7189     ColorMatrixImage   = 268
7190     Color              = 269
7191     ColorImage         = 270
7192     Mode               = 271
7193     ModeImage          = 272
7194     Statistic          = 273
7195     StatisticImage     = 274
7196     MogrifyRegion      = 666
7197   PPCODE:
7198   {
7199     AffineMatrix
7200       affine,
7201       current;
7202
7203     char
7204       attribute_flag[MaxArguments],
7205       message[MaxTextExtent];
7206
7207     ChannelType
7208       channel,
7209       channel_mask;
7210
7211     CompositeOperator
7212       compose;
7213
7214     const char
7215       *attribute,
7216       *value;
7217
7218     double
7219       angle;
7220
7221     ExceptionInfo
7222       *exception;
7223
7224     GeometryInfo
7225       geometry_info;
7226
7227     Image
7228       *image,
7229       *next,
7230       *region_image;
7231
7232     MagickBooleanType
7233       status;
7234
7235     MagickStatusType
7236       flags;
7237
7238     PixelPacket
7239       fill_color;
7240
7241     RectangleInfo
7242       geometry,
7243       region_info;
7244
7245     register ssize_t
7246       i;
7247
7248     ssize_t
7249       base,
7250       j,
7251       number_images;
7252
7253     struct Methods
7254       *rp;
7255
7256     struct PackageInfo
7257       *info;
7258
7259     SV
7260       *perl_exception,
7261       **pv,
7262       *reference,
7263       **reference_vector;
7264
7265     struct ArgumentList
7266       argument_list[MaxArguments];
7267
7268     PERL_UNUSED_VAR(ref);
7269     PERL_UNUSED_VAR(ix);
7270     exception=AcquireExceptionInfo();
7271     perl_exception=newSVpv("",0);
7272     reference_vector=NULL;
7273     region_image=NULL;
7274     number_images=0;
7275     base=2;
7276     if (sv_isobject(ST(0)) == 0)
7277       {
7278         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7279           PackageName);
7280         goto PerlException;
7281       }
7282     reference=SvRV(ST(0));
7283     region_info.width=0;
7284     region_info.height=0;
7285     region_info.x=0;
7286     region_info.y=0;
7287     region_image=(Image *) NULL;
7288     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7289     if (ix && (ix != 666))
7290       {
7291         /*
7292           Called as Method(...)
7293         */
7294         ix=(ix+1)/2;
7295         rp=(&Methods[ix-1]);
7296         attribute=rp->name;
7297       }
7298     else
7299       {
7300         /*
7301           Called as Mogrify("Method",...)
7302         */
7303         attribute=(char *) SvPV(ST(1),na);
7304         if (ix)
7305           {
7306             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7307             attribute=(char *) SvPV(ST(2),na);
7308             base++;
7309           }
7310         for (rp=Methods; ; rp++)
7311         {
7312           if (rp >= EndOf(Methods))
7313             {
7314               ThrowPerlException(exception,OptionError,
7315                 "UnrecognizedPerlMagickMethod",attribute);
7316               goto PerlException;
7317             }
7318           if (strEQcase(attribute,rp->name))
7319             break;
7320         }
7321         ix=rp-Methods+1;
7322         base++;
7323       }
7324     if (image == (Image *) NULL)
7325       {
7326         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7327         goto PerlException;
7328       }
7329     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7330     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7331     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7332     {
7333       Arguments
7334         *pp,
7335         *qq;
7336
7337       ssize_t
7338         ssize_test;
7339
7340       struct ArgumentList
7341         *al;
7342
7343       SV
7344         *sv;
7345
7346       sv=NULL;
7347       ssize_test=0;
7348       pp=(Arguments *) NULL;
7349       qq=rp->arguments;
7350       if (i == items)
7351         {
7352           pp=rp->arguments,
7353           sv=ST(i-1);
7354         }
7355       else
7356         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7357         {
7358           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7359             break;
7360           if (strEQcase(attribute,qq->method) > ssize_test)
7361             {
7362               pp=qq;
7363               ssize_test=strEQcase(attribute,qq->method);
7364             }
7365         }
7366       if (pp == (Arguments *) NULL)
7367         {
7368           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7369             attribute);
7370           goto continue_outer_loop;
7371         }
7372       al=(&argument_list[pp-rp->arguments]);
7373       switch (pp->type)
7374       {
7375         case ArrayReference:
7376         {
7377           if (SvTYPE(sv) != SVt_RV)
7378             {
7379               (void) FormatLocaleString(message,MaxTextExtent,
7380                 "invalid %.60s value",pp->method);
7381               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7382               goto continue_outer_loop;
7383             }
7384           al->array_reference=SvRV(sv);
7385           break;
7386         }
7387         case RealReference:
7388         {
7389           al->real_reference=SvNV(sv);
7390           break;
7391         }
7392         case FileReference:
7393         {
7394           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7395           break;
7396         }
7397         case ImageReference:
7398         {
7399           if (!sv_isobject(sv) ||
7400               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7401                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7402             {
7403               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7404                 PackageName);
7405               goto PerlException;
7406             }
7407           break;
7408         }
7409         case IntegerReference:
7410         {
7411           al->integer_reference=SvIV(sv);
7412           break;
7413         }
7414         case StringReference:
7415         {
7416           al->string_reference=(char *) SvPV(sv,al->length);
7417           if (sv_isobject(sv))
7418             al->image_reference=SetupList(aTHX_ SvRV(sv),
7419               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7420           break;
7421         }
7422         default:
7423         {
7424           /*
7425             Is a string; look up name.
7426           */
7427           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7428             {
7429               al->string_reference=(char *) SvPV(sv,al->length);
7430               al->integer_reference=(-1);
7431               break;
7432             }
7433           al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7434             MagickFalse,SvPV(sv,na));
7435           if (pp->type == MagickChannelOptions)
7436             al->integer_reference=ParseChannelOption(SvPV(sv,na));
7437           if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7438             {
7439               (void) FormatLocaleString(message,MaxTextExtent,
7440                 "invalid %.60s value",pp->method);
7441               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7442               goto continue_outer_loop;
7443             }
7444           break;
7445         }
7446       }
7447       attribute_flag[pp-rp->arguments]++;
7448       continue_outer_loop: ;
7449     }
7450     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7451     pv=reference_vector;
7452     SetGeometryInfo(&geometry_info);
7453     channel=DefaultChannels;
7454     for (next=image; next; next=next->next)
7455     {
7456       image=next;
7457       SetGeometry(image,&geometry);
7458       if ((region_info.width*region_info.height) != 0)
7459         {
7460           region_image=image;
7461           image=CropImage(image,&region_info,exception);
7462         }
7463       switch (ix)
7464       {
7465         default:
7466         {
7467           (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double) ix);
7468           ThrowPerlException(exception,OptionError,
7469             "UnrecognizedPerlMagickMethod",message);
7470           goto PerlException;
7471         }
7472         case 1:  /* Comment */
7473         {
7474           if (attribute_flag[0] == 0)
7475             argument_list[0].string_reference=(char *) NULL;
7476           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7477             info ? info->image_info : (ImageInfo *) NULL,image,
7478             argument_list[0].string_reference));
7479           break;
7480         }
7481         case 2:  /* Label */
7482         {
7483           if (attribute_flag[0] == 0)
7484             argument_list[0].string_reference=(char *) NULL;
7485           (void) SetImageProperty(image,"label",InterpretImageProperties(
7486             info ? info->image_info : (ImageInfo *) NULL,image,
7487             argument_list[0].string_reference));
7488           break;
7489         }
7490         case 3:  /* AddNoise */
7491         {
7492           if (attribute_flag[0] == 0)
7493             argument_list[0].integer_reference=UniformNoise;
7494           if (attribute_flag[1] != 0)
7495             channel=(ChannelType) argument_list[1].integer_reference;
7496           channel_mask=SetPixelChannelMask(image,channel);
7497           image=AddNoiseImage(image,(NoiseType)
7498             argument_list[0].integer_reference,exception);
7499           if (image != (Image *) NULL)
7500             (void) SetPixelChannelMask(image,channel_mask);
7501           break;
7502         }
7503         case 4:  /* Colorize */
7504         {
7505           PixelPacket
7506             target;
7507
7508           (void) GetOneVirtualPixel(image,0,0,&target,exception);
7509           if (attribute_flag[0] != 0)
7510             (void) QueryColorDatabase(argument_list[0].string_reference,&target,
7511               exception);
7512           if (attribute_flag[1] == 0)
7513             argument_list[1].string_reference="100%";
7514           image=ColorizeImage(image,argument_list[1].string_reference,target,
7515             exception);
7516           break;
7517         }
7518         case 5:  /* Border */
7519         {
7520           geometry.width=0;
7521           geometry.height=0;
7522           if (attribute_flag[0] != 0)
7523             {
7524               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7525                 &geometry,exception);
7526               if ((flags & HeightValue) == 0)
7527                 geometry.height=geometry.width;
7528             }
7529           if (attribute_flag[1] != 0)
7530             geometry.width=argument_list[1].integer_reference;
7531           if (attribute_flag[2] != 0)
7532             geometry.height=argument_list[2].integer_reference;
7533           if (attribute_flag[3] != 0)
7534             QueryColorDatabase(argument_list[3].string_reference,
7535               &image->border_color,exception);
7536           if (attribute_flag[4] != 0)
7537             QueryColorDatabase(argument_list[4].string_reference,
7538               &image->border_color,exception);
7539           if (attribute_flag[5] != 0)
7540             QueryColorDatabase(argument_list[5].string_reference,
7541               &image->border_color,exception);
7542           if (attribute_flag[6] != 0)
7543             image->compose=(CompositeOperator) argument_list[6].integer_reference;
7544           image=BorderImage(image,&geometry,exception);
7545           break;
7546         }
7547         case 6:  /* Blur */
7548         {
7549           if (attribute_flag[0] != 0)
7550             {
7551               flags=ParseGeometry(argument_list[0].string_reference,
7552                 &geometry_info);
7553               if ((flags & SigmaValue) == 0)
7554                 geometry_info.sigma=1.0;
7555             }
7556           if (attribute_flag[1] != 0)
7557             geometry_info.rho=argument_list[1].real_reference;
7558           if (attribute_flag[2] != 0)
7559             geometry_info.sigma=argument_list[2].real_reference;
7560           if (attribute_flag[3] != 0)
7561             channel=(ChannelType) argument_list[3].integer_reference;
7562           channel_mask=SetPixelChannelMask(image,channel);
7563           image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
7564             exception);
7565           if (image != (Image *) NULL)
7566             (void) SetPixelChannelMask(image,channel_mask);
7567           break;
7568         }
7569         case 7:  /* Chop */
7570         {
7571           if (attribute_flag[0] != 0)
7572             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7573               &geometry,exception);
7574           if (attribute_flag[1] != 0)
7575             geometry.width=argument_list[1].integer_reference;
7576           if (attribute_flag[2] != 0)
7577             geometry.height=argument_list[2].integer_reference;
7578           if (attribute_flag[3] != 0)
7579             geometry.x=argument_list[3].integer_reference;
7580           if (attribute_flag[4] != 0)
7581             geometry.y=argument_list[4].integer_reference;
7582           image=ChopImage(image,&geometry,exception);
7583           break;
7584         }
7585         case 8:  /* Crop */
7586         {
7587           if (attribute_flag[6] != 0)
7588             image->gravity=(GravityType) argument_list[6].integer_reference;
7589           if (attribute_flag[0] != 0)
7590             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7591               &geometry,exception);
7592           if (attribute_flag[1] != 0)
7593             geometry.width=argument_list[1].integer_reference;
7594           if (attribute_flag[2] != 0)
7595             geometry.height=argument_list[2].integer_reference;
7596           if (attribute_flag[3] != 0)
7597             geometry.x=argument_list[3].integer_reference;
7598           if (attribute_flag[4] != 0)
7599             geometry.y=argument_list[4].integer_reference;
7600           if (attribute_flag[5] != 0)
7601             image->fuzz=
7602               SiPrefixToDouble(argument_list[5].string_reference,QuantumRange);
7603           image=CropImage(image,&geometry,exception);
7604           break;
7605         }
7606         case 9:  /* Despeckle */
7607         {
7608           image=DespeckleImage(image,exception);
7609           break;
7610         }
7611         case 10:  /* Edge */
7612         {
7613           if (attribute_flag[0] != 0)
7614             geometry_info.rho=argument_list[0].real_reference;
7615           image=EdgeImage(image,geometry_info.rho,exception);
7616           break;
7617         }
7618         case 11:  /* Emboss */
7619         {
7620           if (attribute_flag[0] != 0)
7621             {
7622               flags=ParseGeometry(argument_list[0].string_reference,
7623                 &geometry_info);
7624               if ((flags & SigmaValue) == 0)
7625                 geometry_info.sigma=1.0;
7626             }
7627           if (attribute_flag[1] != 0)
7628             geometry_info.rho=argument_list[1].real_reference;
7629           if (attribute_flag[2] != 0)
7630             geometry_info.sigma=argument_list[2].real_reference;
7631           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
7632             exception);
7633           break;
7634         }
7635         case 12:  /* Enhance */
7636         {
7637           image=EnhanceImage(image,exception);
7638           break;
7639         }
7640         case 13:  /* Flip */
7641         {
7642           image=FlipImage(image,exception);
7643           break;
7644         }
7645         case 14:  /* Flop */
7646         {
7647           image=FlopImage(image,exception);
7648           break;
7649         }
7650         case 15:  /* Frame */
7651         {
7652           FrameInfo
7653             frame_info;
7654
7655           if (attribute_flag[0] != 0)
7656             {
7657               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7658                 &geometry,exception);
7659               if ((flags & HeightValue) == 0)
7660                 geometry.height=geometry.width;
7661               frame_info.width=geometry.width;
7662               frame_info.height=geometry.height;
7663               frame_info.outer_bevel=geometry.x;
7664               frame_info.inner_bevel=geometry.y;
7665             }
7666           if (attribute_flag[1] != 0)
7667             frame_info.width=argument_list[1].integer_reference;
7668           if (attribute_flag[2] != 0)
7669             frame_info.height=argument_list[2].integer_reference;
7670           if (attribute_flag[3] != 0)
7671             frame_info.inner_bevel=argument_list[3].integer_reference;
7672           if (attribute_flag[4] != 0)
7673             frame_info.outer_bevel=argument_list[4].integer_reference;
7674           if (attribute_flag[5] != 0)
7675             QueryColorDatabase(argument_list[5].string_reference,&fill_color,
7676               exception);
7677           if (attribute_flag[6] != 0)
7678             QueryColorDatabase(argument_list[6].string_reference,&fill_color,
7679               exception);
7680           frame_info.x=(ssize_t) frame_info.width;
7681           frame_info.y=(ssize_t) frame_info.height;
7682           frame_info.width=image->columns+2*frame_info.x;
7683           frame_info.height=image->rows+2*frame_info.y;
7684           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
7685             image->matte_color=fill_color;
7686           if (attribute_flag[7] != 0)
7687             image->compose=(CompositeOperator) argument_list[7].integer_reference;
7688           image=FrameImage(image,&frame_info,exception);
7689           break;
7690         }
7691         case 16:  /* Implode */
7692         {
7693           if (attribute_flag[0] == 0)
7694             argument_list[0].real_reference=0.5;
7695           if (attribute_flag[1] != 0)
7696             image->interpolate=(InterpolatePixelMethod)
7697               argument_list[1].integer_reference;
7698           image=ImplodeImage(image,argument_list[0].real_reference,
7699             exception);
7700           break;
7701         }
7702         case 17:  /* Magnify */
7703         {
7704           image=MagnifyImage(image,exception);
7705           break;
7706         }
7707         case 18:  /* MedianFilter */
7708         {
7709           if (attribute_flag[0] != 0)
7710             {
7711               flags=ParseGeometry(argument_list[0].string_reference,
7712                 &geometry_info);
7713               if ((flags & SigmaValue) == 0)
7714                 geometry_info.sigma=1.0;
7715             }
7716           if (attribute_flag[1] != 0)
7717             geometry_info.rho=argument_list[1].real_reference;
7718           if (attribute_flag[2] != 0)
7719             geometry_info.sigma=argument_list[2].real_reference;
7720           if (attribute_flag[3] != 0)
7721             channel=(ChannelType) argument_list[3].integer_reference;
7722           channel_mask=SetPixelChannelMask(image,channel);
7723           image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
7724             (size_t) geometry_info.sigma,exception);
7725           if (image != (Image *) NULL)
7726             (void) SetPixelChannelMask(image,channel_mask);
7727           break;
7728         }
7729         case 19:  /* Minify */
7730         {
7731           image=MinifyImage(image,exception);
7732           break;
7733         }
7734         case 20:  /* OilPaint */
7735         {
7736           if (attribute_flag[0] == 0)
7737             argument_list[0].real_reference=0.0;
7738           if (attribute_flag[1] == 0)
7739             argument_list[1].real_reference=1.0;
7740           image=OilPaintImage(image,argument_list[0].real_reference,
7741             argument_list[1].real_reference,exception);
7742           break;
7743         }
7744         case 21:  /* ReduceNoise */
7745         {
7746           if (attribute_flag[0] != 0)
7747             {
7748               flags=ParseGeometry(argument_list[0].string_reference,
7749                 &geometry_info);
7750               if ((flags & SigmaValue) == 0)
7751                 geometry_info.sigma=1.0;
7752             }
7753           if (attribute_flag[1] != 0)
7754             geometry_info.rho=argument_list[1].real_reference;
7755           if (attribute_flag[2] != 0)
7756             geometry_info.sigma=argument_list[2].real_reference;
7757           if (attribute_flag[3] != 0)
7758             channel=(ChannelType) argument_list[3].integer_reference;
7759           channel_mask=SetPixelChannelMask(image,channel);
7760           image=StatisticImage(image,NonpeakStatistic,(size_t)
7761             geometry_info.rho,(size_t) geometry_info.sigma,exception);
7762           if (image != (Image *) NULL)
7763             (void) SetPixelChannelMask(image,channel_mask);
7764           break;
7765         }
7766         case 22:  /* Roll */
7767         {
7768           if (attribute_flag[0] != 0)
7769             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7770               &geometry,exception);
7771           if (attribute_flag[1] != 0)
7772             geometry.x=argument_list[1].integer_reference;
7773           if (attribute_flag[2] != 0)
7774             geometry.y=argument_list[2].integer_reference;
7775           image=RollImage(image,geometry.x,geometry.y,exception);
7776           break;
7777         }
7778         case 23:  /* Rotate */
7779         {
7780           if (attribute_flag[0] == 0)
7781             argument_list[0].real_reference=90.0;
7782           if (attribute_flag[1] != 0)
7783             QueryColorDatabase(argument_list[1].string_reference,
7784               &image->background_color,exception);
7785           if (attribute_flag[2] != 0)
7786             QueryColorDatabase(argument_list[2].string_reference,
7787               &image->background_color,exception);
7788           if (attribute_flag[3] != 0)
7789             QueryColorDatabase(argument_list[3].string_reference,
7790               &image->background_color,exception);
7791           image=RotateImage(image,argument_list[0].real_reference,exception);
7792           break;
7793         }
7794         case 24:  /* Sample */
7795         {
7796           if (attribute_flag[0] != 0)
7797             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7798               &geometry,exception);
7799           if (attribute_flag[1] != 0)
7800             geometry.width=argument_list[1].integer_reference;
7801           if (attribute_flag[2] != 0)
7802             geometry.height=argument_list[2].integer_reference;
7803           image=SampleImage(image,geometry.width,geometry.height,exception);
7804           break;
7805         }
7806         case 25:  /* Scale */
7807         {
7808           if (attribute_flag[0] != 0)
7809             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7810               &geometry,exception);
7811           if (attribute_flag[1] != 0)
7812             geometry.width=argument_list[1].integer_reference;
7813           if (attribute_flag[2] != 0)
7814             geometry.height=argument_list[2].integer_reference;
7815           image=ScaleImage(image,geometry.width,geometry.height,exception);
7816           break;
7817         }
7818         case 26:  /* Shade */
7819         {
7820           if (attribute_flag[0] != 0)
7821             {
7822               flags=ParseGeometry(argument_list[0].string_reference,
7823                 &geometry_info);
7824               if ((flags & SigmaValue) == 0)
7825                 geometry_info.sigma=0.0;
7826             }
7827           if (attribute_flag[1] != 0)
7828             geometry_info.rho=argument_list[1].real_reference;
7829           if (attribute_flag[2] != 0)
7830             geometry_info.sigma=argument_list[2].real_reference;
7831           image=ShadeImage(image,
7832             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
7833             geometry_info.rho,geometry_info.sigma,exception);
7834           break;
7835         }
7836         case 27:  /* Sharpen */
7837         {
7838           if (attribute_flag[0] != 0)
7839             {
7840               flags=ParseGeometry(argument_list[0].string_reference,
7841                 &geometry_info);
7842               if ((flags & SigmaValue) == 0)
7843                 geometry_info.sigma=1.0;
7844             }
7845           if (attribute_flag[1] != 0)
7846             geometry_info.rho=argument_list[1].real_reference;
7847           if (attribute_flag[2] != 0)
7848             geometry_info.sigma=argument_list[2].real_reference;
7849           if (attribute_flag[3] != 0)
7850             channel=(ChannelType) argument_list[3].integer_reference;
7851           channel_mask=SetPixelChannelMask(image,channel);
7852           image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
7853             exception);
7854           if (image != (Image *) NULL)
7855             (void) SetPixelChannelMask(image,channel_mask);
7856           break;
7857         }
7858         case 28:  /* Shear */
7859         {
7860           if (attribute_flag[0] != 0)
7861             {
7862               flags=ParseGeometry(argument_list[0].string_reference,
7863                 &geometry_info);
7864               if ((flags & SigmaValue) == 0)
7865                 geometry_info.sigma=geometry_info.rho;
7866             }
7867           if (attribute_flag[1] != 0)
7868             geometry_info.rho=argument_list[1].real_reference;
7869           if (attribute_flag[2] != 0)
7870             geometry_info.sigma=argument_list[2].real_reference;
7871           if (attribute_flag[3] != 0)
7872             QueryColorDatabase(argument_list[3].string_reference,
7873               &image->background_color,exception);
7874           if (attribute_flag[4] != 0)
7875             QueryColorDatabase(argument_list[4].string_reference,
7876               &image->background_color,exception);
7877           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
7878             exception);
7879           break;
7880         }
7881         case 29:  /* Spread */
7882         {
7883           if (attribute_flag[0] == 0)
7884             argument_list[0].real_reference=1.0;
7885           image=SpreadImage(image,argument_list[0].real_reference,exception);
7886           break;
7887         }
7888         case 30:  /* Swirl */
7889         {
7890           if (attribute_flag[0] == 0)
7891             argument_list[0].real_reference=50.0;
7892           if (attribute_flag[1] != 0)
7893             image->interpolate=(InterpolatePixelMethod)
7894               argument_list[1].integer_reference;
7895           image=SwirlImage(image,argument_list[0].real_reference,exception);
7896           break;
7897         }
7898         case 31:  /* Resize */
7899         case 32:  /* Zoom */
7900         {
7901           if (attribute_flag[0] != 0)
7902             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7903               &geometry,exception);
7904           if (attribute_flag[1] != 0)
7905             geometry.width=argument_list[1].integer_reference;
7906           if (attribute_flag[2] != 0)
7907             geometry.height=argument_list[2].integer_reference;
7908           if (attribute_flag[3] == 0)
7909             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
7910           if (attribute_flag[4] != 0)
7911             SetImageArtifact(image,"filter:support",
7912               argument_list[4].string_reference);
7913           if (attribute_flag[5] == 0)
7914             argument_list[5].real_reference=1.0;
7915           image=ResizeImage(image,geometry.width,geometry.height,
7916             (FilterTypes) argument_list[3].integer_reference,
7917             argument_list[5].real_reference,exception);
7918           break;
7919         }
7920         case 33:  /* Annotate */
7921         {
7922           DrawInfo
7923             *draw_info;
7924
7925           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
7926             (DrawInfo *) NULL);
7927           if (attribute_flag[0] != 0)
7928             {
7929               char
7930                 *text;
7931
7932               text=InterpretImageProperties(info ? info->image_info :
7933                 (ImageInfo *) NULL,image,argument_list[0].string_reference);
7934               (void) CloneString(&draw_info->text,text);
7935               text=DestroyString(text);
7936             }
7937           if (attribute_flag[1] != 0)
7938             (void) CloneString(&draw_info->font,
7939               argument_list[1].string_reference);
7940           if (attribute_flag[2] != 0)
7941             draw_info->pointsize=argument_list[2].real_reference;
7942           if (attribute_flag[3] != 0)
7943             (void) CloneString(&draw_info->density,
7944               argument_list[3].string_reference);
7945           if (attribute_flag[4] != 0)
7946             (void) QueryColorDatabase(argument_list[4].string_reference,
7947               &draw_info->undercolor,exception);
7948           if (attribute_flag[5] != 0)
7949             {
7950               (void) QueryColorDatabase(argument_list[5].string_reference,
7951                 &draw_info->stroke,exception);
7952               if (argument_list[5].image_reference != (Image *) NULL)
7953                 draw_info->stroke_pattern=CloneImage(
7954                   argument_list[5].image_reference,0,0,MagickTrue,exception);
7955             }
7956           if (attribute_flag[6] != 0)
7957             {
7958               (void) QueryColorDatabase(argument_list[6].string_reference,
7959                 &draw_info->fill,exception);
7960               if (argument_list[6].image_reference != (Image *) NULL)
7961                 draw_info->fill_pattern=CloneImage(
7962                   argument_list[6].image_reference,0,0,MagickTrue,exception);
7963             }
7964           if (attribute_flag[7] != 0)
7965             {
7966               (void) CloneString(&draw_info->geometry,
7967                 argument_list[7].string_reference);
7968               flags=ParsePageGeometry(image,argument_list[7].string_reference,
7969                 &geometry,exception);
7970               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
7971                 geometry_info.sigma=geometry_info.xi;
7972             }
7973           if (attribute_flag[8] != 0)
7974             (void) QueryColorDatabase(argument_list[8].string_reference,
7975               &draw_info->fill,exception);
7976           if (attribute_flag[11] != 0)
7977             draw_info->gravity=(GravityType) argument_list[11].integer_reference;
7978           if (attribute_flag[25] != 0)
7979             {
7980               AV
7981                 *av;
7982
7983               av=(AV *) argument_list[25].array_reference;
7984               if ((av_len(av) != 3) && (av_len(av) != 5))
7985                 {
7986                   ThrowPerlException(exception,OptionError,
7987                     "affine matrix must have 4 or 6 elements",PackageName);
7988                   goto PerlException;
7989                 }
7990               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
7991               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
7992               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
7993               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
7994               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
7995                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
7996                 {
7997                   ThrowPerlException(exception,OptionError,
7998                     "affine matrix is singular",PackageName);
7999                    goto PerlException;
8000                 }
8001               if (av_len(av) == 5)
8002                 {
8003                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8004                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8005                 }
8006             }
8007           for (j=12; j < 17; j++)
8008           {
8009             if (attribute_flag[j] == 0)
8010               continue;
8011             value=argument_list[j].string_reference;
8012             angle=argument_list[j].real_reference;
8013             current=draw_info->affine;
8014             GetAffineMatrix(&affine);
8015             switch (j)
8016             {
8017               case 12:
8018               {
8019                 /*
8020                   Translate.
8021                 */
8022                 flags=ParseGeometry(value,&geometry_info);
8023                 affine.tx=geometry_info.xi;
8024                 affine.ty=geometry_info.psi;
8025                 if ((flags & PsiValue) == 0)
8026                   affine.ty=affine.tx;
8027                 break;
8028               }
8029               case 13:
8030               {
8031                 /*
8032                   Scale.
8033                 */
8034                 flags=ParseGeometry(value,&geometry_info);
8035                 affine.sx=geometry_info.rho;
8036                 affine.sy=geometry_info.sigma;
8037                 if ((flags & SigmaValue) == 0)
8038                   affine.sy=affine.sx;
8039                 break;
8040               }
8041               case 14:
8042               {
8043                 /*
8044                   Rotate.
8045                 */
8046                 if (angle == 0.0)
8047                   break;
8048                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8049                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8050                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8051                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8052                 break;
8053               }
8054               case 15:
8055               {
8056                 /*
8057                   SkewX.
8058                 */
8059                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8060                 break;
8061               }
8062               case 16:
8063               {
8064                 /*
8065                   SkewY.
8066                 */
8067                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8068                 break;
8069               }
8070             }
8071             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8072             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8073             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8074             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8075             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8076               current.tx;
8077             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8078               current.ty;
8079           }
8080           if (attribute_flag[9] == 0)
8081             argument_list[9].real_reference=0.0;
8082           if (attribute_flag[10] == 0)
8083             argument_list[10].real_reference=0.0;
8084           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8085             {
8086               char
8087                 geometry[MaxTextExtent];
8088
8089               (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
8090                 (double) argument_list[9].real_reference+draw_info->affine.tx,
8091                 (double) argument_list[10].real_reference+draw_info->affine.ty);
8092               (void) CloneString(&draw_info->geometry,geometry);
8093             }
8094           if (attribute_flag[17] != 0)
8095             draw_info->stroke_width=argument_list[17].real_reference;
8096           if (attribute_flag[18] != 0)
8097             {
8098               draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8099                 MagickTrue : MagickFalse;
8100               draw_info->stroke_antialias=draw_info->text_antialias;
8101             }
8102           if (attribute_flag[19] != 0)
8103             (void) CloneString(&draw_info->family,
8104               argument_list[19].string_reference);
8105           if (attribute_flag[20] != 0)
8106             draw_info->style=(StyleType) argument_list[20].integer_reference;
8107           if (attribute_flag[21] != 0)
8108             draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8109           if (attribute_flag[22] != 0)
8110             draw_info->weight=argument_list[22].integer_reference;
8111           if (attribute_flag[23] != 0)
8112             draw_info->align=(AlignType) argument_list[23].integer_reference;
8113           if (attribute_flag[24] != 0)
8114             (void) CloneString(&draw_info->encoding,
8115               argument_list[24].string_reference);
8116           if (attribute_flag[25] != 0)
8117             draw_info->fill_pattern=CloneImage(
8118               argument_list[25].image_reference,0,0,MagickTrue,exception);
8119           if (attribute_flag[26] != 0)
8120             draw_info->fill_pattern=CloneImage(
8121               argument_list[26].image_reference,0,0,MagickTrue,exception);
8122           if (attribute_flag[27] != 0)
8123             draw_info->stroke_pattern=CloneImage(
8124               argument_list[27].image_reference,0,0,MagickTrue,exception);
8125           if (attribute_flag[29] != 0)
8126             draw_info->kerning=argument_list[29].real_reference;
8127           if (attribute_flag[30] != 0)
8128             draw_info->interline_spacing=argument_list[30].real_reference;
8129           if (attribute_flag[31] != 0)
8130             draw_info->interword_spacing=argument_list[31].real_reference;
8131           if (attribute_flag[32] != 0)
8132             draw_info->direction=(DirectionType)
8133               argument_list[32].integer_reference;
8134           (void) AnnotateImage(image,draw_info);
8135           draw_info=DestroyDrawInfo(draw_info);
8136           break;
8137         }
8138         case 34:  /* ColorFloodfill */
8139         {
8140           DrawInfo
8141             *draw_info;
8142
8143           MagickBooleanType
8144             invert;
8145
8146           PixelInfo
8147             target;
8148
8149           draw_info=CloneDrawInfo(info ? info->image_info :
8150             (ImageInfo *) NULL,(DrawInfo *) NULL);
8151           if (attribute_flag[0] != 0)
8152             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8153               &geometry,exception);
8154           if (attribute_flag[1] != 0)
8155             geometry.x=argument_list[1].integer_reference;
8156           if (attribute_flag[2] != 0)
8157             geometry.y=argument_list[2].integer_reference;
8158           if (attribute_flag[3] != 0)
8159             (void) QueryColorDatabase(argument_list[3].string_reference,
8160               &draw_info->fill,exception);
8161           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
8162             exception);
8163           invert=MagickFalse;
8164           if (attribute_flag[4] != 0)
8165             {
8166               QueryMagickColor(argument_list[4].string_reference,&target,
8167                 exception);
8168               invert=MagickTrue;
8169             }
8170           if (attribute_flag[5] != 0)
8171             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
8172               QuantumRange);
8173           if (attribute_flag[6] != 0)
8174             invert=(MagickBooleanType) argument_list[6].integer_reference;
8175           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8176             geometry.y,invert,exception);
8177           draw_info=DestroyDrawInfo(draw_info);
8178           break;
8179         }
8180         case 35:  /* Composite */
8181         {
8182           char
8183             composite_geometry[MaxTextExtent];
8184
8185           Image
8186             *composite_image,
8187             *rotate_image;
8188
8189           compose=OverCompositeOp;
8190           if (attribute_flag[0] != 0)
8191             composite_image=argument_list[0].image_reference;
8192           else
8193             {
8194               ThrowPerlException(exception,OptionError,
8195                 "CompositeImageRequired",PackageName);
8196               goto PerlException;
8197             }
8198           /*
8199             Parameter Handling used for BOTH normal and tiled composition.
8200           */
8201           if (attribute_flag[1] != 0) /* compose */
8202             compose=(CompositeOperator) argument_list[1].integer_reference;
8203           if (attribute_flag[6] != 0) /* opacity  */
8204             {
8205               if (compose != DissolveCompositeOp)
8206                 (void) SetImageOpacity(composite_image,(Quantum)
8207                   SiPrefixToDouble(argument_list[6].string_reference,
8208                   QuantumRange));
8209               else
8210                 {
8211                   CacheView
8212                     *composite_view;
8213
8214                   double
8215                     opacity;
8216
8217                   MagickBooleanType
8218                     sync;
8219
8220                   register ssize_t
8221                     x;
8222
8223                   register Quantum
8224                     *q;
8225
8226                   ssize_t
8227                     y;
8228
8229                   /*
8230                     Handle dissolve composite operator (patch by
8231                     Kevin A. McGrail).
8232                   */
8233                   (void) CloneString(&image->geometry,
8234                     argument_list[6].string_reference);
8235                   opacity=(Quantum) SiPrefixToDouble(
8236                     argument_list[6].string_reference,QuantumRange);
8237                   if (composite_image->matte != MagickTrue)
8238                     (void) SetImageOpacity(composite_image,OpaqueAlpha);
8239                   composite_view=AcquireCacheView(composite_image);
8240                   for (y=0; y < (ssize_t) composite_image->rows ; y++)
8241                   {
8242                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8243                       composite_image->columns,1,exception);
8244                     for (x=0; x < (ssize_t) composite_image->columns; x++)
8245                     {
8246                       if (GetPixelAlpha(image,q) == OpaqueAlpha)
8247                         SetPixelAlpha(composite_image,ClampToQuantum(opacity),q);
8248                       q+=GetPixelChannels(composite_image);
8249                     }
8250                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8251                     if (sync == MagickFalse)
8252                       break;
8253                   }
8254                   composite_view=DestroyCacheView(composite_view);
8255                 }
8256             }
8257           if (attribute_flag[9] != 0)    /* "color=>" */
8258             QueryColorDatabase(argument_list[9].string_reference,
8259               &composite_image->background_color,exception);
8260           if (attribute_flag[12] != 0) /* "interpolate=>" */
8261             image->interpolate=(InterpolatePixelMethod)
8262               argument_list[12].integer_reference;
8263           if (attribute_flag[13] != 0)   /* "args=>" */
8264             (void) SetImageArtifact(composite_image,"compose:args",
8265               argument_list[13].string_reference);
8266           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8267             (void) SetImageArtifact(composite_image,"compose:args",
8268               argument_list[14].string_reference);
8269           /*
8270             Tiling Composition (with orthogonal rotate).
8271           */
8272           rotate_image=(Image *) NULL;
8273           if (attribute_flag[8] != 0)   /* "rotate=>" */
8274             {
8275                /*
8276                  Rotate image.
8277                */
8278                rotate_image=RotateImage(composite_image,
8279                  argument_list[8].real_reference,exception);
8280                if (rotate_image == (Image *) NULL)
8281                  break;
8282             }
8283           if (attribute_flag[7] && argument_list[7].integer_reference) /* tile */
8284             {
8285               ssize_t
8286                 x,
8287                 y;
8288
8289               /*
8290                 Tile the composite image.
8291               */
8292              if (attribute_flag[8] != 0)   /* "tile=>" */
8293                (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8294                  "false");
8295              else
8296                (void) SetImageArtifact(composite_image,
8297                  "compose:outside-overlay","false");
8298              for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8299                 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8300                 {
8301                   if (attribute_flag[8] != 0) /* rotate */
8302                     (void) CompositeImage(image,compose,rotate_image,x,y);
8303                   else
8304                     (void) CompositeImage(image,compose,composite_image,x,y);
8305                 }
8306               if (attribute_flag[8] != 0) /* rotate */
8307                 rotate_image=DestroyImage(rotate_image);
8308               break;
8309             }
8310           /*
8311             Parameter Handling used used ONLY for normal composition.
8312           */
8313           if (attribute_flag[5] != 0) /* gravity */
8314             image->gravity=(GravityType) argument_list[5].integer_reference;
8315           if (attribute_flag[2] != 0) /* geometry offset */
8316             {
8317               SetGeometry(image,&geometry);
8318               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8319                 &geometry);
8320               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8321                 &geometry);
8322             }
8323           if (attribute_flag[3] != 0) /* x offset */
8324             geometry.x=argument_list[3].integer_reference;
8325           if (attribute_flag[4] != 0) /* y offset */
8326             geometry.y=argument_list[4].integer_reference;
8327           if (attribute_flag[10] != 0) /* mask */
8328             {
8329               if ((image->compose == DisplaceCompositeOp) ||
8330                   (image->compose == DistortCompositeOp))
8331                 {
8332                   /*
8333                     Merge Y displacement into X displacement image.
8334                   */
8335                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8336                     &image->exception);
8337                   (void) CompositeImage(composite_image,CopyGreenCompositeOp,
8338                     argument_list[10].image_reference,0,0);
8339                 }
8340               else
8341                 {
8342                   /*
8343                     Set a blending mask for the composition.
8344                   */
8345                   image->mask=CloneImage(argument_list[10].image_reference,0,0,
8346                     MagickTrue,&image->exception);
8347                   (void) NegateImage(image->mask,MagickFalse,exception);
8348                 }
8349             }
8350           if (attribute_flag[11] != 0) /* channel */
8351             channel=(ChannelType) argument_list[11].integer_reference;
8352           /*
8353             Composite two images (normal composition).
8354           */
8355           (void) FormatLocaleString(composite_geometry,MaxTextExtent,
8356             "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8357             (double) composite_image->rows,(double) geometry.x,(double)
8358             geometry.y);
8359           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8360             exception);
8361           channel_mask=SetPixelChannelMask(image,channel);
8362           if (attribute_flag[8] == 0) /* no rotate */
8363             CompositeImage(image,compose,composite_image,geometry.x,geometry.y);
8364           else
8365             {
8366               /*
8367                 Position adjust rotated image then composite.
8368               */
8369               geometry.x-=(ssize_t) (rotate_image->columns-
8370                 composite_image->columns)/2;
8371               geometry.y-=(ssize_t) (rotate_image->rows-
8372                 composite_image->rows)/2;
8373               CompositeImage(image,compose,rotate_image,geometry.x,geometry.y);
8374               rotate_image=DestroyImage(rotate_image);
8375             }
8376           if (attribute_flag[10] != 0) /* mask */
8377             {
8378               if ((image->compose == DisplaceCompositeOp) ||
8379                   (image->compose == DistortCompositeOp))
8380                 composite_image=DestroyImage(composite_image);
8381               else
8382                 image->mask=DestroyImage(image->mask);
8383             }
8384           (void) SetPixelChannelMask(image,channel_mask);
8385           break;
8386         }
8387         case 36:  /* Contrast */
8388         {
8389           if (attribute_flag[0] == 0)
8390             argument_list[0].integer_reference=0;
8391           (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8392             MagickTrue : MagickFalse,exception);
8393           break;
8394         }
8395         case 37:  /* CycleColormap */
8396         {
8397           if (attribute_flag[0] == 0)
8398             argument_list[0].integer_reference=6;
8399           (void) CycleColormapImage(image,argument_list[0].integer_reference);
8400           break;
8401         }
8402         case 38:  /* Draw */
8403         {
8404           DrawInfo
8405             *draw_info;
8406
8407           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8408             (DrawInfo *) NULL);
8409           (void) CloneString(&draw_info->primitive,"point");
8410           if (attribute_flag[0] != 0)
8411             {
8412               if (argument_list[0].integer_reference < 0)
8413                 (void) CloneString(&draw_info->primitive,
8414                   argument_list[0].string_reference);
8415               else
8416                 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8417                   MagickPrimitiveOptions,argument_list[0].integer_reference));
8418             }
8419           if (attribute_flag[1] != 0)
8420             {
8421               if (LocaleCompare(draw_info->primitive,"path") == 0)
8422                 {
8423                   (void) ConcatenateString(&draw_info->primitive," '");
8424                   ConcatenateString(&draw_info->primitive,
8425                     argument_list[1].string_reference);
8426                   (void) ConcatenateString(&draw_info->primitive,"'");
8427                 }
8428               else
8429                 {
8430                   (void) ConcatenateString(&draw_info->primitive," ");
8431                   ConcatenateString(&draw_info->primitive,
8432                     argument_list[1].string_reference);
8433                 }
8434             }
8435           if (attribute_flag[2] != 0)
8436             {
8437               (void) ConcatenateString(&draw_info->primitive," ");
8438               (void) ConcatenateString(&draw_info->primitive,
8439                 CommandOptionToMnemonic(MagickMethodOptions,
8440                 argument_list[2].integer_reference));
8441             }
8442           if (attribute_flag[3] != 0)
8443             {
8444               (void) QueryColorDatabase(argument_list[3].string_reference,
8445                 &draw_info->stroke,exception);
8446               if (argument_list[3].image_reference != (Image *) NULL)
8447                 draw_info->stroke_pattern=CloneImage(
8448                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8449             }
8450           if (attribute_flag[4] != 0)
8451             {
8452               (void) QueryColorDatabase(argument_list[4].string_reference,
8453                 &draw_info->fill,exception);
8454               if (argument_list[4].image_reference != (Image *) NULL)
8455                 draw_info->fill_pattern=CloneImage(
8456                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8457             }
8458           if (attribute_flag[5] != 0)
8459             draw_info->stroke_width=argument_list[5].real_reference;
8460           if (attribute_flag[6] != 0)
8461             (void) CloneString(&draw_info->font,
8462               argument_list[6].string_reference);
8463           if (attribute_flag[7] != 0)
8464             (void) QueryColorDatabase(argument_list[7].string_reference,
8465               &draw_info->border_color,exception);
8466           if (attribute_flag[8] != 0)
8467             draw_info->affine.tx=argument_list[8].real_reference;
8468           if (attribute_flag[9] != 0)
8469             draw_info->affine.ty=argument_list[9].real_reference;
8470           if (attribute_flag[20] != 0)
8471             {
8472               AV
8473                 *av;
8474
8475               av=(AV *) argument_list[20].array_reference;
8476               if ((av_len(av) != 3) && (av_len(av) != 5))
8477                 {
8478                   ThrowPerlException(exception,OptionError,
8479                     "affine matrix must have 4 or 6 elements",PackageName);
8480                   goto PerlException;
8481                 }
8482               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8483               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8484               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8485               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8486               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8487                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8488                 {
8489                   ThrowPerlException(exception,OptionError,
8490                     "affine matrix is singular",PackageName);
8491                    goto PerlException;
8492                 }
8493               if (av_len(av) == 5)
8494                 {
8495                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8496                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8497                 }
8498             }
8499           for (j=10; j < 15; j++)
8500           {
8501             if (attribute_flag[j] == 0)
8502               continue;
8503             value=argument_list[j].string_reference;
8504             angle=argument_list[j].real_reference;
8505             current=draw_info->affine;
8506             GetAffineMatrix(&affine);
8507             switch (j)
8508             {
8509               case 10:
8510               {
8511                 /*
8512                   Translate.
8513                 */
8514                 flags=ParseGeometry(value,&geometry_info);
8515                 affine.tx=geometry_info.xi;
8516                 affine.ty=geometry_info.psi;
8517                 if ((flags & PsiValue) == 0)
8518                   affine.ty=affine.tx;
8519                 break;
8520               }
8521               case 11:
8522               {
8523                 /*
8524                   Scale.
8525                 */
8526                 flags=ParseGeometry(value,&geometry_info);
8527                 affine.sx=geometry_info.rho;
8528                 affine.sy=geometry_info.sigma;
8529                 if ((flags & SigmaValue) == 0)
8530                   affine.sy=affine.sx;
8531                 break;
8532               }
8533               case 12:
8534               {
8535                 /*
8536                   Rotate.
8537                 */
8538                 if (angle == 0.0)
8539                   break;
8540                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8541                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8542                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8543                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8544                 break;
8545               }
8546               case 13:
8547               {
8548                 /*
8549                   SkewX.
8550                 */
8551                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8552                 break;
8553               }
8554               case 14:
8555               {
8556                 /*
8557                   SkewY.
8558                 */
8559                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8560                 break;
8561               }
8562             }
8563             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8564             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8565             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8566             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8567             draw_info->affine.tx=
8568               current.sx*affine.tx+current.ry*affine.ty+current.tx;
8569             draw_info->affine.ty=
8570               current.rx*affine.tx+current.sy*affine.ty+current.ty;
8571           }
8572           if (attribute_flag[15] != 0)
8573             draw_info->fill_pattern=CloneImage(
8574               argument_list[15].image_reference,0,0,MagickTrue,exception);
8575           if (attribute_flag[16] != 0)
8576             draw_info->pointsize=argument_list[16].real_reference;
8577           if (attribute_flag[17] != 0)
8578             {
8579               draw_info->stroke_antialias=argument_list[17].integer_reference != 0
8580                 ? MagickTrue : MagickFalse;
8581               draw_info->text_antialias=draw_info->stroke_antialias;
8582             }
8583           if (attribute_flag[18] != 0)
8584             (void) CloneString(&draw_info->density,
8585               argument_list[18].string_reference);
8586           if (attribute_flag[19] != 0)
8587             draw_info->stroke_width=argument_list[19].real_reference;
8588           if (attribute_flag[21] != 0)
8589             draw_info->dash_offset=argument_list[21].real_reference;
8590           if (attribute_flag[22] != 0)
8591             {
8592               AV
8593                 *av;
8594
8595               av=(AV *) argument_list[22].array_reference;
8596               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
8597                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
8598               if (draw_info->dash_pattern != (double *) NULL)
8599                 {
8600                   for (i=0; i <= av_len(av); i++)
8601                     draw_info->dash_pattern[i]=(double)
8602                       SvNV(*(av_fetch(av,i,0)));
8603                   draw_info->dash_pattern[i]=0.0;
8604                 }
8605             }
8606           if (attribute_flag[23] != 0)
8607             image->interpolate=(InterpolatePixelMethod)
8608               argument_list[23].integer_reference;
8609           if ((attribute_flag[24] != 0) &&
8610               (draw_info->fill_pattern != (Image *) NULL))
8611             flags=ParsePageGeometry(draw_info->fill_pattern,
8612               argument_list[24].string_reference,
8613               &draw_info->fill_pattern->tile_offset,exception);
8614           if (attribute_flag[25] != 0)
8615             {
8616               (void) ConcatenateString(&draw_info->primitive," '");
8617               (void) ConcatenateString(&draw_info->primitive,
8618                 argument_list[25].string_reference);
8619               (void) ConcatenateString(&draw_info->primitive,"'");
8620             }
8621           if (attribute_flag[26] != 0)
8622             draw_info->fill_pattern=CloneImage(
8623               argument_list[26].image_reference,0,0,MagickTrue,exception);
8624           if (attribute_flag[27] != 0)
8625             draw_info->stroke_pattern=CloneImage(
8626               argument_list[27].image_reference,0,0,MagickTrue,exception);
8627           if (attribute_flag[28] != 0)
8628             (void) CloneString(&draw_info->primitive,
8629               argument_list[28].string_reference);
8630           if (attribute_flag[29] != 0)
8631             draw_info->kerning=argument_list[29].real_reference;
8632           if (attribute_flag[30] != 0)
8633             draw_info->interline_spacing=argument_list[30].real_reference;
8634           if (attribute_flag[31] != 0)
8635             draw_info->interword_spacing=argument_list[31].real_reference;
8636           if (attribute_flag[32] != 0)
8637             draw_info->direction=(DirectionType)
8638               argument_list[32].integer_reference;
8639           DrawImage(image,draw_info);
8640           draw_info=DestroyDrawInfo(draw_info);
8641           break;
8642         }
8643         case 39:  /* Equalize */
8644         {
8645           if (attribute_flag[0] != 0)
8646             channel=(ChannelType) argument_list[0].integer_reference;
8647           channel_mask=SetPixelChannelMask(image,channel);
8648           EqualizeImage(image,exception);
8649           (void) SetPixelChannelMask(image,channel_mask);
8650           break;
8651         }
8652         case 40:  /* Gamma */
8653         {
8654           if (attribute_flag[1] != 0)
8655             channel=(ChannelType) argument_list[1].integer_reference;
8656           if (attribute_flag[2] == 0)
8657             argument_list[2].real_reference=1.0;
8658           if (attribute_flag[3] == 0)
8659             argument_list[3].real_reference=1.0;
8660           if (attribute_flag[4] == 0)
8661             argument_list[4].real_reference=1.0;
8662           if (attribute_flag[0] == 0)
8663             {
8664               (void) FormatLocaleString(message,MaxTextExtent,
8665                 "%.15g,%.15g,%.15g",(double) argument_list[2].real_reference,
8666                 (double) argument_list[3].real_reference,
8667                 (double) argument_list[4].real_reference);
8668               argument_list[0].string_reference=message;
8669             }
8670           (void) GammaImage(image,InterpretLocaleValue(
8671             argument_list[0].string_reference,(char **) NULL),exception);
8672           break;
8673         }
8674         case 41:  /* Map */
8675         {
8676           QuantizeInfo
8677             *quantize_info;
8678
8679           if (attribute_flag[0] == 0)
8680             {
8681               ThrowPerlException(exception,OptionError,"MapImageRequired",
8682                 PackageName);
8683               goto PerlException;
8684             }
8685           quantize_info=AcquireQuantizeInfo(info->image_info);
8686           if (attribute_flag[1] != 0)
8687             quantize_info->dither=(MagickBooleanType)
8688               argument_list[1].integer_reference;
8689           if (attribute_flag[2] != 0)
8690             quantize_info->dither_method=(DitherMethod)
8691               argument_list[2].integer_reference;
8692           (void) RemapImages(quantize_info,image,
8693             argument_list[0].image_reference);
8694           quantize_info=DestroyQuantizeInfo(quantize_info);
8695           break;
8696         }
8697         case 42:  /* MatteFloodfill */
8698         {
8699           DrawInfo
8700             *draw_info;
8701
8702           MagickBooleanType
8703             invert;
8704
8705           PixelInfo
8706             target;
8707
8708           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8709             (DrawInfo *) NULL);
8710           if (attribute_flag[0] != 0)
8711             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8712               &geometry,exception);
8713           if (attribute_flag[1] != 0)
8714             geometry.x=argument_list[1].integer_reference;
8715           if (attribute_flag[2] != 0)
8716             geometry.y=argument_list[2].integer_reference;
8717           if (image->matte == MagickFalse)
8718             (void) SetImageOpacity(image,OpaqueAlpha);
8719           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
8720             exception);
8721           if (attribute_flag[4] != 0)
8722             QueryMagickColor(argument_list[4].string_reference,&target,
8723               exception);
8724           if (attribute_flag[3] != 0)
8725             target.alpha=SiPrefixToDouble(argument_list[3].string_reference,
8726               QuantumRange);
8727           if (attribute_flag[5] != 0)
8728             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
8729               QuantumRange);
8730           invert=MagickFalse;
8731           if (attribute_flag[6] != 0)
8732             invert=(MagickBooleanType) argument_list[6].integer_reference;
8733           channel_mask=SetPixelChannelMask(image,AlphaChannel);
8734           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8735             geometry.y,invert,exception);
8736           (void) SetPixelChannelMask(image,channel_mask);
8737           draw_info=DestroyDrawInfo(draw_info);
8738           break;
8739         }
8740         case 43:  /* Modulate */
8741         {
8742           char
8743             modulate[MaxTextExtent];
8744
8745           geometry_info.rho=100.0;
8746           geometry_info.sigma=100.0;
8747           geometry_info.xi=100.0;
8748           if (attribute_flag[0] != 0)
8749             (void)ParseGeometry(argument_list[0].string_reference,
8750               &geometry_info);
8751           if (attribute_flag[1] != 0)
8752             geometry_info.xi=argument_list[1].real_reference;
8753           if (attribute_flag[2] != 0)
8754             geometry_info.sigma=argument_list[2].real_reference;
8755           if (attribute_flag[3] != 0)
8756             {
8757               geometry_info.sigma=argument_list[3].real_reference;
8758               SetImageArtifact(image,"modulate:colorspace","HWB");
8759             }
8760           if (attribute_flag[4] != 0)
8761             {
8762               geometry_info.rho=argument_list[4].real_reference;
8763               SetImageArtifact(image,"modulate:colorspace","HSB");
8764             }
8765           if (attribute_flag[5] != 0)
8766             {
8767               geometry_info.sigma=argument_list[5].real_reference;
8768               SetImageArtifact(image,"modulate:colorspace","HSL");
8769             }
8770           if (attribute_flag[6] != 0)
8771             {
8772               geometry_info.rho=argument_list[6].real_reference;
8773               SetImageArtifact(image,"modulate:colorspace","HWB");
8774             }
8775           (void) FormatLocaleString(modulate,MaxTextExtent,"%.15g,%.15g,%.15g",
8776             geometry_info.rho,geometry_info.sigma,geometry_info.xi);
8777           (void) ModulateImage(image,modulate,exception);
8778           break;
8779         }
8780         case 44:  /* Negate */
8781         {
8782           if (attribute_flag[0] == 0)
8783             argument_list[0].integer_reference=0;
8784           if (attribute_flag[1] != 0)
8785             channel=(ChannelType) argument_list[1].integer_reference;
8786           channel_mask=SetPixelChannelMask(image,channel);
8787           (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
8788             MagickTrue : MagickFalse,exception);
8789           (void) SetPixelChannelMask(image,channel_mask);
8790           break;
8791         }
8792         case 45:  /* Normalize */
8793         {
8794           if (attribute_flag[0] != 0)
8795             channel=(ChannelType) argument_list[0].integer_reference;
8796           channel_mask=SetPixelChannelMask(image,channel);
8797           NormalizeImage(image,exception);
8798           (void) SetPixelChannelMask(image,channel_mask);
8799           break;
8800         }
8801         case 46:  /* NumberColors */
8802           break;
8803         case 47:  /* Opaque */
8804         {
8805           MagickBooleanType
8806             invert;
8807
8808           PixelInfo
8809             fill_color,
8810             target;
8811
8812           (void) QueryMagickColor("none",&target,exception);
8813           (void) QueryMagickColor("none",&fill_color,exception);
8814           if (attribute_flag[0] != 0)
8815             (void) QueryMagickColor(argument_list[0].string_reference,
8816               &target,exception);
8817           if (attribute_flag[1] != 0)
8818             (void) QueryMagickColor(argument_list[1].string_reference,
8819               &fill_color,exception);
8820           if (attribute_flag[2] != 0)
8821             image->fuzz=SiPrefixToDouble(argument_list[2].string_reference,
8822               QuantumRange);
8823           if (attribute_flag[3] != 0)
8824             channel=(ChannelType) argument_list[3].integer_reference;
8825           invert=MagickFalse;
8826           if (attribute_flag[4] != 0)
8827             invert=(MagickBooleanType) argument_list[4].integer_reference;
8828           channel_mask=SetPixelChannelMask(image,channel);
8829           (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
8830           (void) SetPixelChannelMask(image,channel_mask);
8831           break;
8832         }
8833         case 48:  /* Quantize */
8834         {
8835           QuantizeInfo
8836             *quantize_info;
8837
8838           quantize_info=AcquireQuantizeInfo(info->image_info);
8839           if (attribute_flag[0] != 0)
8840             quantize_info->number_colors=(size_t)
8841               argument_list[0].integer_reference;
8842           if (attribute_flag[1] != 0)
8843             quantize_info->tree_depth=(size_t)
8844               argument_list[1].integer_reference;
8845           if (attribute_flag[2] != 0)
8846             quantize_info->colorspace=(ColorspaceType)
8847               argument_list[2].integer_reference;
8848           if (attribute_flag[3] != 0)
8849             quantize_info->dither=argument_list[3].integer_reference != 0 ?
8850               MagickTrue : MagickFalse;
8851           if (attribute_flag[4] != 0)
8852             quantize_info->measure_error=
8853               argument_list[4].integer_reference != 0 ? MagickTrue : MagickFalse;
8854           if (attribute_flag[5] != 0)
8855             (void) QueryColorDatabase(argument_list[5].string_reference,
8856               &image->transparent_color,exception);
8857           if (attribute_flag[5] && argument_list[5].integer_reference)
8858             {
8859               (void) QuantizeImages(quantize_info,image);
8860               goto PerlException;
8861             }
8862           if (attribute_flag[6] != 0)
8863             quantize_info->dither_method=(DitherMethod)
8864               argument_list[6].integer_reference;
8865           if ((image->storage_class == DirectClass) ||
8866               (image->colors > quantize_info->number_colors) ||
8867               (quantize_info->colorspace == GRAYColorspace))
8868             (void) QuantizeImage(quantize_info,image);
8869           else
8870             CompressImageColormap(image);
8871           quantize_info=DestroyQuantizeInfo(quantize_info);
8872           break;
8873         }
8874         case 49:  /* Raise */
8875         {
8876           if (attribute_flag[0] != 0)
8877             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8878               &geometry,exception);
8879           if (attribute_flag[1] != 0)
8880             geometry.width=argument_list[1].integer_reference;
8881           if (attribute_flag[2] != 0)
8882             geometry.height=argument_list[2].integer_reference;
8883           if (attribute_flag[3] == 0)
8884             argument_list[3].integer_reference=1;
8885           (void) RaiseImage(image,&geometry,
8886             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8887             exception);
8888           break;
8889         }
8890         case 50:  /* Segment */
8891         {
8892           ColorspaceType
8893             colorspace;
8894
8895           double
8896             cluster_threshold,
8897             smoothing_threshold;
8898
8899           MagickBooleanType
8900             verbose;
8901
8902           cluster_threshold=1.0;
8903           smoothing_threshold=1.5;
8904           colorspace=RGBColorspace;
8905           verbose=MagickFalse;
8906           if (attribute_flag[0] != 0)
8907             {
8908               flags=ParseGeometry(argument_list[0].string_reference,
8909                 &geometry_info);
8910               cluster_threshold=geometry_info.rho;
8911               if (flags & SigmaValue)
8912                 smoothing_threshold=geometry_info.sigma;
8913             }
8914           if (attribute_flag[1] != 0)
8915             cluster_threshold=argument_list[1].real_reference;
8916           if (attribute_flag[2] != 0)
8917             smoothing_threshold=argument_list[2].real_reference;
8918           if (attribute_flag[3] != 0)
8919             colorspace=(ColorspaceType) argument_list[3].integer_reference;
8920           if (attribute_flag[4] != 0)
8921             verbose=argument_list[4].integer_reference != 0 ?
8922               MagickTrue : MagickFalse;
8923           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
8924             smoothing_threshold);
8925           break;
8926         }
8927         case 51:  /* Signature */
8928         {
8929           (void) SignatureImage(image);
8930           break;
8931         }
8932         case 52:  /* Solarize */
8933         {
8934           geometry_info.rho=QuantumRange/2.0;
8935           if (attribute_flag[0] != 0)
8936             flags=ParseGeometry(argument_list[0].string_reference,
8937               &geometry_info);
8938           if (attribute_flag[1] != 0)
8939             geometry_info.rho=SiPrefixToDouble(argument_list[1].string_reference,
8940              QuantumRange);
8941           (void) SolarizeImage(image,geometry_info.rho);
8942           break;
8943         }
8944         case 53:  /* Sync */
8945         {
8946           (void) SyncImage(image);
8947           break;
8948         }
8949         case 54:  /* Texture */
8950         {
8951           if (attribute_flag[0] == 0)
8952             break;
8953           TextureImage(image,argument_list[0].image_reference);
8954           break;
8955         }
8956         case 55:  /* Evalute */
8957         {
8958           MagickEvaluateOperator
8959             op;
8960
8961           op=SetEvaluateOperator;
8962           if (attribute_flag[0] == MagickFalse)
8963             argument_list[0].real_reference=0.0;
8964           if (attribute_flag[1] != MagickFalse)
8965             op=(MagickEvaluateOperator) argument_list[1].integer_reference;
8966           if (attribute_flag[2] != MagickFalse)
8967             channel=(ChannelType) argument_list[2].integer_reference;
8968           channel_mask=SetPixelChannelMask(image,channel);
8969           (void) EvaluateImage(image,op,argument_list[0].real_reference,
8970             exception);
8971           (void) SetPixelChannelMask(image,channel_mask);
8972           break;
8973         }
8974         case 56:  /* Transparent */
8975         {
8976           double
8977             opacity;
8978
8979           MagickBooleanType
8980             invert;
8981
8982           PixelInfo
8983             target;
8984
8985           (void) QueryMagickColor("none",&target,exception);
8986           if (attribute_flag[0] != 0)
8987             (void) QueryMagickColor(argument_list[0].string_reference,&target,
8988               exception);
8989           opacity=TransparentAlpha;
8990           if (attribute_flag[1] != 0)
8991             opacity=SiPrefixToDouble(argument_list[1].string_reference,
8992               QuantumRange);
8993           if (attribute_flag[2] != 0)
8994             image->fuzz=SiPrefixToDouble(argument_list[2].string_reference,
8995               QuantumRange);
8996           if (attribute_flag[3] == 0)
8997             argument_list[3].integer_reference=0;
8998           invert=MagickFalse;
8999           if (attribute_flag[3] != 0)
9000             invert=(MagickBooleanType) argument_list[3].integer_reference;
9001           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9002             invert,exception);
9003           break;
9004         }
9005         case 57:  /* Threshold */
9006         {
9007           double
9008             threshold;
9009
9010           if (attribute_flag[0] == 0)
9011             argument_list[0].string_reference="50%";
9012           if (attribute_flag[1] != 0)
9013             channel=(ChannelType) argument_list[1].integer_reference;
9014           threshold=SiPrefixToDouble(argument_list[0].string_reference,
9015             QuantumRange);
9016           channel_mask=SetPixelChannelMask(image,channel);
9017           (void) BilevelImage(image,threshold);
9018           (void) SetPixelChannelMask(image,channel_mask);
9019           break;
9020         }
9021         case 58:  /* Charcoal */
9022         {
9023           if (attribute_flag[0] != 0)
9024             {
9025               flags=ParseGeometry(argument_list[0].string_reference,
9026                 &geometry_info);
9027               if ((flags & SigmaValue) == 0)
9028                 geometry_info.sigma=1.0;
9029             }
9030           if (attribute_flag[1] != 0)
9031             geometry_info.rho=argument_list[1].real_reference;
9032           if (attribute_flag[2] != 0)
9033             geometry_info.sigma=argument_list[2].real_reference;
9034           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9035             exception);
9036           break;
9037         }
9038         case 59:  /* Trim */
9039         {
9040           if (attribute_flag[0] != 0)
9041             image->fuzz=SiPrefixToDouble(argument_list[0].string_reference,
9042               QuantumRange);
9043           image=TrimImage(image,exception);
9044           break;
9045         }
9046         case 60:  /* Wave */
9047         {
9048           if (attribute_flag[0] != 0)
9049             {
9050               flags=ParseGeometry(argument_list[0].string_reference,
9051                 &geometry_info);
9052               if ((flags & SigmaValue) == 0)
9053                 geometry_info.sigma=1.0;
9054             }
9055           if (attribute_flag[1] != 0)
9056             geometry_info.rho=argument_list[1].real_reference;
9057           if (attribute_flag[2] != 0)
9058             geometry_info.sigma=argument_list[2].real_reference;
9059           if (attribute_flag[3] != 0)
9060             image->interpolate=(InterpolatePixelMethod)
9061               argument_list[3].integer_reference;
9062           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9063             exception);
9064           break;
9065         }
9066         case 61:  /* Separate */
9067         {
9068           if (attribute_flag[0] != 0)
9069             channel=(ChannelType) argument_list[0].integer_reference;
9070           channel_mask=SetPixelChannelMask(image,channel);
9071           (void) SeparateImage(image);
9072           (void) SetPixelChannelMask(image,channel_mask);
9073           break;
9074         }
9075         case 63:  /* Stereo */
9076         {
9077           if (attribute_flag[0] == 0)
9078             {
9079               ThrowPerlException(exception,OptionError,"StereoImageRequired",
9080                 PackageName);
9081               goto PerlException;
9082             }
9083           if (attribute_flag[1] != 0)
9084             geometry.x=argument_list[1].integer_reference;
9085           if (attribute_flag[2] != 0)
9086             geometry.y=argument_list[2].integer_reference;
9087           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9088             geometry.x,geometry.y,exception);
9089           break;
9090         }
9091         case 64:  /* Stegano */
9092         {
9093           if (attribute_flag[0] == 0)
9094             {
9095               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9096                 PackageName);
9097               goto PerlException;
9098             }
9099           if (attribute_flag[1] == 0)
9100             argument_list[1].integer_reference=0;
9101           image->offset=argument_list[1].integer_reference;
9102           image=SteganoImage(image,argument_list[0].image_reference,exception);
9103           break;
9104         }
9105         case 65:  /* Deconstruct */
9106         {
9107           image=CompareImagesLayers(image,CompareAnyLayer,exception);
9108           break;
9109         }
9110         case 66:  /* GaussianBlur */
9111         {
9112           if (attribute_flag[0] != 0)
9113             {
9114               flags=ParseGeometry(argument_list[0].string_reference,
9115                 &geometry_info);
9116               if ((flags & SigmaValue) == 0)
9117                 geometry_info.sigma=1.0;
9118             }
9119           if (attribute_flag[1] != 0)
9120             geometry_info.rho=argument_list[1].real_reference;
9121           if (attribute_flag[2] != 0)
9122             geometry_info.sigma=argument_list[2].real_reference;
9123           if (attribute_flag[3] != 0)
9124             channel=(ChannelType) argument_list[3].integer_reference;
9125           channel_mask=SetPixelChannelMask(image,channel);
9126           image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9127             exception);
9128           if (image != (Image *) NULL)
9129             (void) SetPixelChannelMask(image,channel_mask);
9130           break;
9131         }
9132         case 67:  /* Convolve */
9133         {
9134           KernelInfo
9135             *kernel;
9136
9137           kernel=(KernelInfo *) NULL;
9138           if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9139             break;
9140           if (attribute_flag[0] != 0)
9141             {
9142               AV
9143                 *av;
9144
9145               size_t
9146                 order;
9147
9148               kernel=AcquireKernelInfo((const char *) NULL);
9149               if (kernel == (KernelInfo *) NULL)
9150                 break;
9151               av=(AV *) argument_list[0].array_reference;
9152               order=(size_t) sqrt(av_len(av)+1);
9153               kernel->width=order;
9154               kernel->height=order;
9155               kernel->values=(double *) AcquireQuantumMemory(order,order*
9156                 sizeof(*kernel->values));
9157               if (kernel->values == (double *) NULL)
9158                 {
9159                   kernel=DestroyKernelInfo(kernel);
9160                   ThrowPerlException(exception,ResourceLimitFatalError,
9161                     "MemoryAllocationFailed",PackageName);
9162                   goto PerlException;
9163                 }
9164               for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9165                 kernel->values[j]=(double) SvNV(*(av_fetch(av,j,0)));
9166               for ( ; j < (ssize_t) (order*order); j++)
9167                 kernel->values[j]=0.0;
9168             }
9169           if (attribute_flag[1] != 0)
9170             channel=(ChannelType) argument_list[1].integer_reference;
9171           if (attribute_flag[2] != 0)
9172             image->bias=SiPrefixToDouble(argument_list[2].string_reference,
9173               QuantumRange);
9174           if (attribute_flag[3] != 0)
9175             {
9176               kernel=AcquireKernelInfo(argument_list[3].string_reference);
9177               if (kernel == (KernelInfo *) NULL)
9178                 break;
9179             }
9180           channel_mask=SetPixelChannelMask(image,channel);
9181           kernel->bias=image->bias;
9182           image=ConvolveImage(image,kernel,exception);
9183           if (image != (Image *) NULL)
9184             (void) SetPixelChannelMask(image,channel_mask);
9185           kernel=DestroyKernelInfo(kernel);
9186           break;
9187         }
9188         case 68:  /* Profile */
9189         {
9190           const char
9191             *name;
9192
9193           Image
9194             *profile_image;
9195
9196           ImageInfo
9197             *profile_info;
9198
9199           StringInfo
9200             *profile;
9201
9202           name="*";
9203           if (attribute_flag[0] != 0)
9204             name=argument_list[0].string_reference;
9205           if (attribute_flag[2] != 0)
9206             image->rendering_intent=(RenderingIntent)
9207               argument_list[2].integer_reference;
9208           if (attribute_flag[3] != 0)
9209             image->black_point_compensation=
9210               argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9211           if (attribute_flag[1] != 0)
9212             {
9213               if (argument_list[1].length == 0)
9214                 {
9215                   /*
9216                     Remove a profile from the image.
9217                   */
9218                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9219                     MagickTrue);
9220                   break;
9221                 }
9222               /*
9223                 Associate user supplied profile with the image.
9224               */
9225               profile=AcquireStringInfo(argument_list[1].length);
9226               SetStringInfoDatum(profile,(const unsigned char *)
9227                 argument_list[1].string_reference);
9228               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9229                 (size_t) GetStringInfoLength(profile),MagickFalse);
9230               profile=DestroyStringInfo(profile);
9231               break;
9232             }
9233           /*
9234             Associate a profile with the image.
9235           */
9236           profile_info=
9237             CloneImageInfo(info ? info->image_info : (ImageInfo *) NULL);
9238           (void) CopyMagickString(profile_info->filename,name,MaxTextExtent);
9239           profile_image=ReadImages(profile_info,&image->exception);
9240           if (profile_image == (Image *) NULL)
9241             break;
9242           ResetImageProfileIterator(profile_image);
9243           name=GetNextImageProfile(profile_image);
9244           while (name != (const char *) NULL)
9245           {
9246             const StringInfo
9247               *profile;
9248
9249             profile=GetImageProfile(profile_image,name);
9250             if (profile != (const StringInfo *) NULL)
9251               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9252                 (size_t) GetStringInfoLength(profile),MagickFalse);
9253             name=GetNextImageProfile(profile_image);
9254           }
9255           profile_image=DestroyImage(profile_image);
9256           profile_info=DestroyImageInfo(profile_info);
9257           break;
9258         }
9259         case 69:  /* UnsharpMask */
9260         {
9261           if (attribute_flag[0] != 0)
9262             {
9263               flags=ParseGeometry(argument_list[0].string_reference,
9264                 &geometry_info);
9265               if ((flags & SigmaValue) == 0)
9266                 geometry_info.sigma=1.0;
9267               if ((flags & XiValue) == 0)
9268                 geometry_info.xi=1.0;
9269               if ((flags & PsiValue) == 0)
9270                 geometry_info.psi=0.5;
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             geometry_info.psi=argument_list[4].real_reference;
9280           if (attribute_flag[5] != 0)
9281             channel=(ChannelType) argument_list[5].integer_reference;
9282           channel_mask=SetPixelChannelMask(image,channel);
9283           image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9284             geometry_info.xi,geometry_info.psi,exception);
9285           if (image != (Image *) NULL)
9286             (void) SetPixelChannelMask(image,channel_mask);
9287           break;
9288         }
9289         case 70:  /* MotionBlur */
9290         {
9291           if (attribute_flag[0] != 0)
9292             {
9293               flags=ParseGeometry(argument_list[0].string_reference,
9294                 &geometry_info);
9295               if ((flags & SigmaValue) == 0)
9296                 geometry_info.sigma=1.0;
9297               if ((flags & XiValue) == 0)
9298                 geometry_info.xi=1.0;
9299             }
9300           if (attribute_flag[1] != 0)
9301             geometry_info.rho=argument_list[1].real_reference;
9302           if (attribute_flag[2] != 0)
9303             geometry_info.sigma=argument_list[2].real_reference;
9304           if (attribute_flag[3] != 0)
9305             geometry_info.xi=argument_list[3].real_reference;
9306           if (attribute_flag[4] != 0)
9307             channel=(ChannelType) argument_list[4].integer_reference;
9308           channel_mask=SetPixelChannelMask(image,channel);
9309           image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9310             geometry_info.xi,exception);
9311           if (image != (Image *) NULL)
9312             (void) SetPixelChannelMask(image,channel_mask);
9313           break;
9314         }
9315         case 71:  /* OrderedDither */
9316         {
9317           if (attribute_flag[0] == 0)
9318             argument_list[0].string_reference="o8x8";
9319           if (attribute_flag[1] != 0)
9320             channel=(ChannelType) argument_list[1].integer_reference;
9321           channel_mask=SetPixelChannelMask(image,channel);
9322           (void) OrderedPosterizeImage(image,argument_list[0].string_reference,
9323             exception);
9324           (void) SetPixelChannelMask(image,channel_mask);
9325           break;
9326         }
9327         case 72:  /* Shave */
9328         {
9329           if (attribute_flag[0] != 0)
9330             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9331               &geometry,exception);
9332           if (attribute_flag[1] != 0)
9333             geometry.width=argument_list[1].integer_reference;
9334           if (attribute_flag[2] != 0)
9335             geometry.height=argument_list[2].integer_reference;
9336           image=ShaveImage(image,&geometry,exception);
9337           break;
9338         }
9339         case 73:  /* Level */
9340         {
9341           double
9342             black_point,
9343             gamma,
9344             white_point;
9345
9346           black_point=0.0;
9347           white_point=(MagickRealType) image->columns*image->rows;
9348           gamma=1.0;
9349           if (attribute_flag[0] != 0)
9350             {
9351               flags=ParseGeometry(argument_list[0].string_reference,
9352                 &geometry_info);
9353               black_point=geometry_info.rho;
9354               if ((flags & SigmaValue) != 0)
9355                 white_point=geometry_info.sigma;
9356               if ((flags & XiValue) != 0)
9357                 gamma=geometry_info.xi;
9358               if ((flags & PercentValue) != 0)
9359                 {
9360                   black_point*=(double) (QuantumRange/100.0);
9361                   white_point*=(double) (QuantumRange/100.0);
9362                 }
9363               if ((flags & SigmaValue) == 0)
9364                 white_point=(double) QuantumRange-black_point;
9365             }
9366           if (attribute_flag[1] != 0)
9367             black_point=argument_list[1].real_reference;
9368           if (attribute_flag[2] != 0)
9369             white_point=argument_list[2].real_reference;
9370           if (attribute_flag[3] != 0)
9371             gamma=argument_list[3].real_reference;
9372           if (attribute_flag[4] != 0)
9373             channel=(ChannelType) argument_list[4].integer_reference;
9374           if (attribute_flag[5] != 0)
9375             {
9376               argument_list[0].real_reference=argument_list[5].real_reference;
9377               attribute_flag[0]=attribute_flag[5];
9378             }
9379           channel_mask=SetPixelChannelMask(image,channel);
9380           (void) LevelImage(image,black_point,white_point,gamma,exception);
9381           (void) SetPixelChannelMask(image,channel_mask);
9382           break;
9383         }
9384         case 74:  /* Clip */
9385         {
9386           if (attribute_flag[0] == 0)
9387             argument_list[0].string_reference="#1";
9388           if (attribute_flag[1] == 0)
9389             argument_list[1].integer_reference=MagickTrue;
9390           (void) ClipImagePath(image,argument_list[0].string_reference,
9391             argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse);
9392           break;
9393         }
9394         case 75:  /* AffineTransform */
9395         {
9396           DrawInfo
9397             *draw_info;
9398
9399           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9400             (DrawInfo *) NULL);
9401           if (attribute_flag[0] != 0)
9402             {
9403               AV
9404                 *av;
9405
9406               av=(AV *) argument_list[0].array_reference;
9407               if ((av_len(av) != 3) && (av_len(av) != 5))
9408                 {
9409                   ThrowPerlException(exception,OptionError,
9410                     "affine matrix must have 4 or 6 elements",PackageName);
9411                   goto PerlException;
9412                 }
9413               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9414               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9415               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9416               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9417               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9418                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9419                 {
9420                   ThrowPerlException(exception,OptionError,
9421                     "affine matrix is singular",PackageName);
9422                    goto PerlException;
9423                 }
9424               if (av_len(av) == 5)
9425                 {
9426                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9427                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9428                 }
9429             }
9430           for (j=1; j < 6; j++)
9431           {
9432             if (attribute_flag[j] == 0)
9433               continue;
9434             value=argument_list[j].string_reference;
9435             angle=argument_list[j].real_reference;
9436             current=draw_info->affine;
9437             GetAffineMatrix(&affine);
9438             switch (j)
9439             {
9440               case 1:
9441               {
9442                 /*
9443                   Translate.
9444                 */
9445                 flags=ParseGeometry(value,&geometry_info);
9446                 affine.tx=geometry_info.xi;
9447                 affine.ty=geometry_info.psi;
9448                 if ((flags & PsiValue) == 0)
9449                   affine.ty=affine.tx;
9450                 break;
9451               }
9452               case 2:
9453               {
9454                 /*
9455                   Scale.
9456                 */
9457                 flags=ParseGeometry(value,&geometry_info);
9458                 affine.sx=geometry_info.rho;
9459                 affine.sy=geometry_info.sigma;
9460                 if ((flags & SigmaValue) == 0)
9461                   affine.sy=affine.sx;
9462                 break;
9463               }
9464               case 3:
9465               {
9466                 /*
9467                   Rotate.
9468                 */
9469                 if (angle == 0.0)
9470                   break;
9471                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9472                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9473                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9474                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9475                 break;
9476               }
9477               case 4:
9478               {
9479                 /*
9480                   SkewX.
9481                 */
9482                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9483                 break;
9484               }
9485               case 5:
9486               {
9487                 /*
9488                   SkewY.
9489                 */
9490                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9491                 break;
9492               }
9493             }
9494             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9495             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9496             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9497             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9498             draw_info->affine.tx=
9499               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9500             draw_info->affine.ty=
9501               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9502           }
9503           if (attribute_flag[6] != 0)
9504             image->interpolate=(InterpolatePixelMethod)
9505               argument_list[6].integer_reference;
9506           if (attribute_flag[7] != 0)
9507             QueryColorDatabase(argument_list[7].string_reference,
9508               &image->background_color,exception);
9509           image=AffineTransformImage(image,&draw_info->affine,exception);
9510           draw_info=DestroyDrawInfo(draw_info);
9511           break;
9512         }
9513         case 76:  /* Difference */
9514         {
9515           if (attribute_flag[0] == 0)
9516             {
9517               ThrowPerlException(exception,OptionError,
9518                 "ReferenceImageRequired",PackageName);
9519               goto PerlException;
9520             }
9521           if (attribute_flag[1] != 0)
9522             image->fuzz=SiPrefixToDouble(argument_list[1].string_reference,
9523               QuantumRange);
9524           (void) IsImagesEqual(image,argument_list[0].image_reference);
9525           break;
9526         }
9527         case 77:  /* AdaptiveThreshold */
9528         {
9529           if (attribute_flag[0] != 0)
9530             {
9531               flags=ParseGeometry(argument_list[0].string_reference,
9532                 &geometry_info);
9533               if ((flags & PercentValue) != 0)
9534                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9535             }
9536           if (attribute_flag[1] != 0)
9537             geometry_info.rho=argument_list[1].integer_reference;
9538           if (attribute_flag[2] != 0)
9539             geometry_info.sigma=argument_list[2].integer_reference;
9540           if (attribute_flag[3] != 0)
9541             geometry_info.xi=argument_list[3].integer_reference;;
9542           image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
9543             (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
9544           break;
9545         }
9546         case 78:  /* Resample */
9547         {
9548           size_t
9549             height,
9550             width;
9551
9552           if (attribute_flag[0] != 0)
9553             {
9554               flags=ParseGeometry(argument_list[0].string_reference,
9555                 &geometry_info);
9556               if ((flags & SigmaValue) == 0)
9557                 geometry_info.sigma=geometry_info.rho;
9558             }
9559           if (attribute_flag[1] != 0)
9560             geometry_info.rho=argument_list[1].real_reference;
9561           if (attribute_flag[2] != 0)
9562             geometry_info.sigma=argument_list[2].real_reference;
9563           if (attribute_flag[3] == 0)
9564             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
9565           if (attribute_flag[4] == 0)
9566             SetImageArtifact(image,"filter:support",
9567               argument_list[4].string_reference);
9568           if (attribute_flag[5] != 0)
9569             argument_list[5].real_reference=1.0;
9570           width=(size_t) (geometry_info.rho*image->columns/
9571             (image->x_resolution == 0.0 ? 72.0 : image->x_resolution)+0.5);
9572           height=(size_t) (geometry_info.sigma*image->rows/
9573             (image->y_resolution == 0.0 ? 72.0 : image->y_resolution)+0.5);
9574           image=ResizeImage(image,width,height,(FilterTypes)
9575             argument_list[3].integer_reference,argument_list[5].real_reference,
9576             exception);
9577           if (image != (Image *) NULL)
9578             {
9579               image->x_resolution=geometry_info.rho;
9580               image->y_resolution=geometry_info.sigma;
9581             }
9582           break;
9583         }
9584         case 79:  /* Describe */
9585         {
9586           if (attribute_flag[0] == 0)
9587             argument_list[0].file_reference=(FILE *) NULL;
9588           if (attribute_flag[1] != 0)
9589             (void) SetImageArtifact(image,"identify:features",
9590               argument_list[1].string_reference);
9591           (void) IdentifyImage(image,argument_list[0].file_reference,
9592             MagickTrue,exception);
9593           break;
9594         }
9595         case 80:  /* BlackThreshold */
9596         {
9597           if (attribute_flag[0] == 0)
9598             argument_list[0].string_reference="50%";
9599           if (attribute_flag[2] != 0)
9600             channel=(ChannelType) argument_list[2].integer_reference;
9601           channel_mask=SetPixelChannelMask(image,channel);
9602           BlackThresholdImage(image,argument_list[0].string_reference,
9603             exception);
9604           (void) SetPixelChannelMask(image,channel_mask);
9605           break;
9606         }
9607         case 81:  /* WhiteThreshold */
9608         {
9609           if (attribute_flag[0] == 0)
9610             argument_list[0].string_reference="50%";
9611           if (attribute_flag[2] != 0)
9612             channel=(ChannelType) argument_list[2].integer_reference;
9613           channel_mask=SetPixelChannelMask(image,channel);
9614           WhiteThresholdImage(image,argument_list[0].string_reference,
9615             exception);
9616           (void) SetPixelChannelMask(image,channel_mask);
9617           break;
9618         }
9619         case 82:  /* RadialBlur */
9620         {
9621           if (attribute_flag[0] != 0)
9622             {
9623               flags=ParseGeometry(argument_list[0].string_reference,
9624                 &geometry_info);
9625               if ((flags & SigmaValue) == 0)
9626                 geometry_info.sigma=1.0;
9627             }
9628           if (attribute_flag[1] != 0)
9629             geometry_info.rho=argument_list[1].real_reference;
9630           if (attribute_flag[2] != 0)
9631             channel=(ChannelType) argument_list[2].integer_reference;
9632           channel_mask=SetPixelChannelMask(image,channel);
9633           image=RadialBlurImage(image,geometry_info.rho,exception);
9634           if (image != (Image *) NULL)
9635             (void) SetPixelChannelMask(image,channel_mask);
9636           break;
9637         }
9638         case 83:  /* Thumbnail */
9639         {
9640           if (attribute_flag[0] != 0)
9641             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
9642               &geometry,exception);
9643           if (attribute_flag[1] != 0)
9644             geometry.width=argument_list[1].integer_reference;
9645           if (attribute_flag[2] != 0)
9646             geometry.height=argument_list[2].integer_reference;
9647           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
9648           break;
9649         }
9650         case 84:  /* Strip */
9651         {
9652           (void) StripImage(image);
9653           break;
9654         }
9655         case 85:  /* Tint */
9656         {
9657           PixelPacket
9658             target;
9659
9660           (void) GetOneVirtualPixel(image,0,0,&target,exception);
9661           if (attribute_flag[0] != 0)
9662             (void) QueryColorDatabase(argument_list[0].string_reference,&target,
9663               exception);
9664           if (attribute_flag[1] == 0)
9665             argument_list[1].string_reference="100";
9666           image=TintImage(image,argument_list[1].string_reference,target,
9667             exception);
9668           break;
9669         }
9670         case 86:  /* Channel */
9671         {
9672           if (attribute_flag[0] != 0)
9673             channel=(ChannelType) argument_list[0].integer_reference;
9674           channel_mask=SetPixelChannelMask(image,channel);
9675           (void) SeparateImage(image);
9676           (void) SetPixelChannelMask(image,channel_mask);
9677           break;
9678         }
9679         case 87:  /* Splice */
9680         {
9681           if (attribute_flag[0] != 0)
9682             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
9683               &geometry,exception);
9684           if (attribute_flag[1] != 0)
9685             geometry.width=argument_list[1].integer_reference;
9686           if (attribute_flag[2] != 0)
9687             geometry.height=argument_list[2].integer_reference;
9688           if (attribute_flag[3] != 0)
9689             geometry.x=argument_list[3].integer_reference;
9690           if (attribute_flag[4] != 0)
9691             geometry.y=argument_list[4].integer_reference;
9692           if (attribute_flag[5] != 0)
9693             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
9694               QuantumRange);
9695           if (attribute_flag[6] != 0)
9696             (void) QueryColorDatabase(argument_list[6].string_reference,
9697               &image->background_color,exception);
9698           if (attribute_flag[7] != 0)
9699             image->gravity=(GravityType) argument_list[7].integer_reference;
9700           image=SpliceImage(image,&geometry,exception);
9701           break;
9702         }
9703         case 88:  /* Posterize */
9704         {
9705           if (attribute_flag[0] == 0)
9706             argument_list[0].integer_reference=3;
9707           if (attribute_flag[1] == 0)
9708             argument_list[1].integer_reference=0;
9709           (void) PosterizeImage(image,argument_list[0].integer_reference,
9710             argument_list[1].integer_reference ? MagickTrue : MagickFalse);
9711           break;
9712         }
9713         case 89:  /* Shadow */
9714         {
9715           if (attribute_flag[0] != 0)
9716             {
9717               flags=ParseGeometry(argument_list[0].string_reference,
9718                 &geometry_info);
9719               if ((flags & SigmaValue) == 0)
9720                 geometry_info.sigma=1.0;
9721               if ((flags & XiValue) == 0)
9722                 geometry_info.xi=4.0;
9723               if ((flags & PsiValue) == 0)
9724                 geometry_info.psi=4.0;
9725             }
9726           if (attribute_flag[1] != 0)
9727             geometry_info.rho=argument_list[1].real_reference;
9728           if (attribute_flag[2] != 0)
9729             geometry_info.sigma=argument_list[2].real_reference;
9730           if (attribute_flag[3] != 0)
9731             geometry_info.xi=argument_list[3].integer_reference;
9732           if (attribute_flag[4] != 0)
9733             geometry_info.psi=argument_list[4].integer_reference;
9734           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
9735             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-
9736             0.5),exception);
9737           break;
9738         }
9739         case 90:  /* Identify */
9740         {
9741           if (attribute_flag[0] == 0)
9742             argument_list[0].file_reference=(FILE *) NULL;
9743           if (attribute_flag[1] != 0)
9744             (void) SetImageArtifact(image,"identify:features",
9745               argument_list[1].string_reference);
9746           if ((attribute_flag[2] != 0) &&
9747               (argument_list[2].integer_reference != 0))
9748             (void) SetImageArtifact(image,"identify:unique","true");
9749           (void) IdentifyImage(image,argument_list[0].file_reference,
9750             MagickTrue,exception);
9751           break;
9752         }
9753         case 91:  /* SepiaTone */
9754         {
9755           if (attribute_flag[0] == 0)
9756             argument_list[0].real_reference=80.0*QuantumRange/100.0;
9757           image=SepiaToneImage(image,argument_list[0].real_reference,
9758             exception);
9759           break;
9760         }
9761         case 92:  /* SigmoidalContrast */
9762         {
9763           MagickBooleanType
9764             sharpen;
9765
9766           if (attribute_flag[0] != 0)
9767             {
9768               flags=ParseGeometry(argument_list[0].string_reference,
9769                 &geometry_info);
9770               if ((flags & SigmaValue) == 0)
9771                 geometry_info.sigma=QuantumRange/2.0;
9772               if ((flags & PercentValue) != 0)
9773                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
9774             }
9775           if (attribute_flag[1] != 0)
9776             geometry_info.rho=argument_list[1].real_reference;
9777           if (attribute_flag[2] != 0)
9778             geometry_info.sigma=argument_list[2].real_reference;
9779           if (attribute_flag[3] != 0)
9780             channel=(ChannelType) argument_list[3].integer_reference;
9781           sharpen=MagickTrue;
9782           if (attribute_flag[4] != 0)
9783             sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
9784               MagickFalse;
9785           channel_mask=SetPixelChannelMask(image,channel);
9786           (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
9787             geometry_info.sigma,exception);
9788           (void) SetPixelChannelMask(image,channel_mask);
9789           break;
9790         }
9791         case 93:  /* Extent */
9792         {
9793           if (attribute_flag[7] != 0)
9794             image->gravity=(GravityType) argument_list[7].integer_reference;
9795           if (attribute_flag[0] != 0)
9796             {
9797               int
9798                 flags;
9799
9800               flags=ParseGravityGeometry(image,
9801                 argument_list[0].string_reference,&geometry,exception);
9802               (void) flags;
9803               if (geometry.width == 0)
9804                 geometry.width=image->columns;
9805               if (geometry.height == 0)
9806                 geometry.height=image->rows;
9807             }
9808           if (attribute_flag[1] != 0)
9809             geometry.width=argument_list[1].integer_reference;
9810           if (attribute_flag[2] != 0)
9811             geometry.height=argument_list[2].integer_reference;
9812           if (attribute_flag[3] != 0)
9813             geometry.x=argument_list[3].integer_reference;
9814           if (attribute_flag[4] != 0)
9815             geometry.y=argument_list[4].integer_reference;
9816           if (attribute_flag[5] != 0)
9817             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
9818               QuantumRange);
9819           if (attribute_flag[6] != 0)
9820             (void) QueryColorDatabase(argument_list[6].string_reference,
9821               &image->background_color,exception);
9822           image=ExtentImage(image,&geometry,exception);
9823           break;
9824         }
9825         case 94:  /* Vignette */
9826         {
9827           if (attribute_flag[0] != 0)
9828             {
9829               flags=ParseGeometry(argument_list[0].string_reference,
9830                 &geometry_info);
9831               if ((flags & SigmaValue) == 0)
9832                 geometry_info.sigma=1.0;
9833               if ((flags & XiValue) == 0)
9834                 geometry_info.xi=0.1*image->columns;
9835               if ((flags & PsiValue) == 0)
9836                 geometry_info.psi=0.1*image->rows;
9837             }
9838           if (attribute_flag[1] != 0)
9839             geometry_info.rho=argument_list[1].real_reference;
9840           if (attribute_flag[2] != 0)
9841             geometry_info.sigma=argument_list[2].real_reference;
9842           if (attribute_flag[3] != 0)
9843             geometry_info.xi=argument_list[3].integer_reference;
9844           if (attribute_flag[4] != 0)
9845             geometry_info.psi=argument_list[4].integer_reference;
9846           if (attribute_flag[5] != 0)
9847             (void) QueryColorDatabase(argument_list[5].string_reference,
9848               &image->background_color,exception);
9849           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
9850             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-
9851             0.5),exception);
9852           break;
9853         }
9854         case 95:  /* ContrastStretch */
9855         {
9856           double
9857             black_point,
9858             white_point;
9859
9860           black_point=0.0;
9861           white_point=(MagickRealType) image->columns*image->rows;
9862           if (attribute_flag[0] != 0)
9863             {
9864               flags=ParseGeometry(argument_list[0].string_reference,
9865                 &geometry_info);
9866               black_point=geometry_info.rho;
9867               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
9868                 black_point;
9869               if ((flags & PercentValue) != 0)
9870                 {
9871                   black_point*=(double) image->columns*image->rows/100.0;
9872                   white_point*=(double) image->columns*image->rows/100.0;
9873                 }
9874               white_point=(MagickRealType) image->columns*image->rows-
9875                 white_point;
9876             }
9877           if (attribute_flag[1] != 0)
9878             black_point=argument_list[1].real_reference;
9879           if (attribute_flag[2] != 0)
9880             white_point=argument_list[2].real_reference;
9881           if (attribute_flag[4] != 0)
9882             channel=(ChannelType) argument_list[4].integer_reference;
9883           channel_mask=SetPixelChannelMask(image,channel);
9884           (void) ContrastStretchImage(image,black_point,white_point,exception);
9885           (void) SetPixelChannelMask(image,channel_mask);
9886           break;
9887         }
9888         case 96:  /* Sans0 */
9889         {
9890           break;
9891         }
9892         case 97:  /* Sans1 */
9893         {
9894           break;
9895         }
9896         case 98:  /* AdaptiveSharpen */
9897         {
9898           if (attribute_flag[0] != 0)
9899             {
9900               flags=ParseGeometry(argument_list[0].string_reference,
9901                 &geometry_info);
9902               if ((flags & SigmaValue) == 0)
9903                 geometry_info.sigma=1.0;
9904             }
9905           if (attribute_flag[1] != 0)
9906             geometry_info.rho=argument_list[1].real_reference;
9907           if (attribute_flag[2] != 0)
9908             geometry_info.sigma=argument_list[2].real_reference;
9909           if (attribute_flag[3] != 0)
9910             channel=(ChannelType) argument_list[3].integer_reference;
9911           channel_mask=SetPixelChannelMask(image,channel);
9912           image=AdaptiveSharpenImage(image,geometry_info.rho,
9913             geometry_info.sigma,exception);
9914           if (image != (Image *) NULL)
9915             (void) SetPixelChannelMask(image,channel_mask);
9916           break;
9917         }
9918         case 99:  /* Transpose */
9919         {
9920           image=TransposeImage(image,exception);
9921           break;
9922         }
9923         case 100:  /* Tranverse */
9924         {
9925           image=TransverseImage(image,exception);
9926           break;
9927         }
9928         case 101:  /* AutoOrient */
9929         {
9930           switch (image->orientation)
9931           {
9932             case TopRightOrientation:
9933             {
9934               image=FlopImage(image,exception);
9935               break;
9936             }
9937             case BottomRightOrientation:
9938             {
9939               image=RotateImage(image,180.0,exception);
9940               break;
9941             }
9942             case BottomLeftOrientation:
9943             {
9944               image=FlipImage(image,exception);
9945               break;
9946             }
9947             case LeftTopOrientation:
9948             {
9949               image=TransposeImage(image,exception);
9950               break;
9951             }
9952             case RightTopOrientation:
9953             {
9954               image=RotateImage(image,90.0,exception);
9955               break;
9956             }
9957             case RightBottomOrientation:
9958             {
9959               image=TransverseImage(image,exception);
9960               break;
9961             }
9962             case LeftBottomOrientation:
9963             {
9964               image=RotateImage(image,270.0,exception);
9965               break;
9966             }
9967             default:
9968               break;
9969           }
9970           break;
9971         }
9972         case 102:  /* AdaptiveBlur */
9973         {
9974           if (attribute_flag[0] != 0)
9975             {
9976               flags=ParseGeometry(argument_list[0].string_reference,
9977                 &geometry_info);
9978               if ((flags & SigmaValue) == 0)
9979                 geometry_info.sigma=1.0;
9980             }
9981           if (attribute_flag[1] != 0)
9982             geometry_info.rho=argument_list[1].real_reference;
9983           if (attribute_flag[2] != 0)
9984             geometry_info.sigma=argument_list[2].real_reference;
9985           if (attribute_flag[3] != 0)
9986             channel=(ChannelType) argument_list[3].integer_reference;
9987           channel_mask=SetPixelChannelMask(image,channel);
9988           image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
9989             exception);
9990           if (image != (Image *) NULL)
9991             (void) SetPixelChannelMask(image,channel_mask);
9992           break;
9993         }
9994         case 103:  /* Sketch */
9995         {
9996           if (attribute_flag[0] != 0)
9997             {
9998               flags=ParseGeometry(argument_list[0].string_reference,
9999                 &geometry_info);
10000               if ((flags & SigmaValue) == 0)
10001                 geometry_info.sigma=1.0;
10002               if ((flags & XiValue) == 0)
10003                 geometry_info.xi=1.0;
10004             }
10005           if (attribute_flag[1] != 0)
10006             geometry_info.rho=argument_list[1].real_reference;
10007           if (attribute_flag[2] != 0)
10008             geometry_info.sigma=argument_list[2].real_reference;
10009           if (attribute_flag[3] != 0)
10010             geometry_info.xi=argument_list[3].real_reference;
10011           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10012             geometry_info.xi,exception);
10013           break;
10014         }
10015         case 104:  /* UniqueColors */
10016         {
10017           image=UniqueImageColors(image,exception);
10018           break;
10019         }
10020         case 105:  /* AdaptiveResize */
10021         {
10022           if (attribute_flag[0] != 0)
10023             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10024               &geometry,exception);
10025           if (attribute_flag[1] != 0)
10026             geometry.width=argument_list[1].integer_reference;
10027           if (attribute_flag[2] != 0)
10028             geometry.height=argument_list[2].integer_reference;
10029           if (attribute_flag[3] != 0)
10030             image->filter=(FilterTypes) argument_list[4].integer_reference;
10031           if (attribute_flag[4] != 0)
10032             SetImageArtifact(image,"filter:support",
10033               argument_list[4].string_reference);
10034           if (attribute_flag[5] != 0)
10035             image->blur=argument_list[5].real_reference;
10036           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10037             exception);
10038           break;
10039         }
10040         case 106:  /* ClipMask */
10041         {
10042           if (attribute_flag[0] == 0)
10043             {
10044               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10045                 PackageName);
10046               goto PerlException;
10047             }
10048           image->clip_mask=CloneImage(argument_list[0].image_reference,0,0,
10049             MagickTrue,exception);
10050           (void) NegateImage(image->clip_mask,MagickFalse,exception);
10051           break;
10052         }
10053         case 107:  /* LinearStretch */
10054         {
10055            double
10056              black_point,
10057              white_point;
10058
10059            black_point=0.0;
10060            white_point=(MagickRealType) image->columns*image->rows;
10061            if (attribute_flag[0] != 0)
10062              {
10063                flags=ParseGeometry(argument_list[0].string_reference,
10064                  &geometry_info);
10065                if ((flags & SigmaValue) != 0)
10066                   white_point=geometry_info.sigma;
10067                if ((flags & PercentValue) != 0)
10068                  {
10069                    black_point*=(double) image->columns*image->rows/100.0;
10070                    white_point*=(double) image->columns*image->rows/100.0;
10071                  }
10072                if ((flags & SigmaValue) == 0)
10073                  white_point=(double) image->columns*image->rows-black_point;
10074              }
10075           if (attribute_flag[1] != 0)
10076             black_point=argument_list[1].real_reference;
10077           if (attribute_flag[2] != 0)
10078             white_point=argument_list[2].real_reference;
10079           (void) LinearStretchImage(image,black_point,white_point,exception);
10080           break;
10081         }
10082         case 109:  /* Mask */
10083         {
10084           if (attribute_flag[0] == 0)
10085             {
10086               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10087                 PackageName);
10088               goto PerlException;
10089             }
10090           image->mask=CloneImage(argument_list[0].image_reference,0,0,
10091             MagickTrue,exception);
10092           (void) NegateImage(image->mask,MagickFalse,exception);
10093           break;
10094         }
10095         case 110:  /* Polaroid */
10096         {
10097           DrawInfo
10098             *draw_info;
10099
10100           double
10101             angle;
10102
10103           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10104             (DrawInfo *) NULL);
10105           if (attribute_flag[0] != 0)
10106             (void) SetImageProperty(image,"caption",InterpretImageProperties(
10107               info ? info->image_info : (ImageInfo *) NULL,image,
10108               argument_list[0].string_reference));
10109           angle=0.0;
10110           if (attribute_flag[1] != 0)
10111             angle=argument_list[1].real_reference;
10112           if (attribute_flag[2] != 0)
10113             (void) CloneString(&draw_info->font,
10114               argument_list[2].string_reference);
10115           if (attribute_flag[3] != 0)
10116             (void) QueryColorDatabase(argument_list[3].string_reference,
10117               &draw_info->stroke,exception);
10118           if (attribute_flag[4] != 0)
10119             (void) QueryColorDatabase(argument_list[4].string_reference,
10120               &draw_info->fill,exception);
10121           if (attribute_flag[5] != 0)
10122             draw_info->stroke_width=argument_list[5].real_reference;
10123           if (attribute_flag[6] != 0)
10124             draw_info->pointsize=argument_list[6].real_reference;
10125           if (attribute_flag[7] != 0)
10126             draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10127           if (attribute_flag[8] != 0)
10128             (void) QueryColorDatabase(argument_list[8].string_reference,
10129               &image->background_color,exception);
10130           image=PolaroidImage(image,draw_info,angle,exception);
10131           draw_info=DestroyDrawInfo(draw_info);
10132           break;
10133         }
10134         case 111:  /* FloodfillPaint */
10135         {
10136           DrawInfo
10137             *draw_info;
10138
10139           MagickBooleanType
10140             invert;
10141
10142           PixelInfo
10143             target;
10144
10145           draw_info=CloneDrawInfo(info ? info->image_info :
10146             (ImageInfo *) NULL,(DrawInfo *) NULL);
10147           if (attribute_flag[0] != 0)
10148             flags=ParsePageGeometry(image,argument_list[0].string_reference,
10149               &geometry,exception);
10150           if (attribute_flag[1] != 0)
10151             geometry.x=argument_list[1].integer_reference;
10152           if (attribute_flag[2] != 0)
10153             geometry.y=argument_list[2].integer_reference;
10154           if (attribute_flag[3] != 0)
10155             (void) QueryColorDatabase(argument_list[3].string_reference,
10156               &draw_info->fill,exception);
10157           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
10158             exception);
10159           if (attribute_flag[4] != 0)
10160             QueryMagickColor(argument_list[4].string_reference,&target,
10161               exception);
10162           if (attribute_flag[5] != 0)
10163             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
10164               QuantumRange);
10165           if (attribute_flag[6] != 0)
10166             channel=(ChannelType) argument_list[6].integer_reference;
10167           invert=MagickFalse;
10168           if (attribute_flag[7] != 0)
10169             invert=(MagickBooleanType) argument_list[7].integer_reference;
10170           channel_mask=SetPixelChannelMask(image,channel);
10171           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10172             geometry.y,invert,exception);
10173           (void) SetPixelChannelMask(image,channel_mask);
10174           draw_info=DestroyDrawInfo(draw_info);
10175           break;
10176         }
10177         case 112:  /* Distort */
10178         {
10179           AV
10180             *av;
10181
10182           double
10183             *coordinates;
10184
10185           DistortImageMethod
10186             method;
10187
10188           size_t
10189             number_coordinates;
10190
10191           VirtualPixelMethod
10192             virtual_pixel;
10193
10194           if (attribute_flag[0] == 0)
10195             break;
10196           method=UndefinedDistortion;
10197           if (attribute_flag[1] != 0)
10198             method=(DistortImageMethod) argument_list[1].integer_reference;
10199           av=(AV *) argument_list[0].array_reference;
10200           number_coordinates=(size_t) av_len(av)+1;
10201           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10202             sizeof(*coordinates));
10203           if (coordinates == (double *) NULL)
10204             {
10205               ThrowPerlException(exception,ResourceLimitFatalError,
10206                 "MemoryAllocationFailed",PackageName);
10207               goto PerlException;
10208             }
10209           for (j=0; j < (ssize_t) number_coordinates; j++)
10210             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10211           virtual_pixel=UndefinedVirtualPixelMethod;
10212           if (attribute_flag[2] != 0)
10213             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10214               argument_list[2].integer_reference);
10215           image=DistortImage(image,method,number_coordinates,coordinates,
10216             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10217             exception);
10218           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10219             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10220           coordinates=(double *) RelinquishMagickMemory(coordinates);
10221           break;
10222         }
10223         case 113:  /* Clut */
10224         {
10225           if (attribute_flag[0] == 0)
10226             {
10227               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10228                 PackageName);
10229               goto PerlException;
10230             }
10231           if (attribute_flag[1] != 0)
10232             channel=(ChannelType) argument_list[1].integer_reference;
10233           channel_mask=SetPixelChannelMask(image,channel);
10234           (void) ClutImage(image,argument_list[0].image_reference,exception);
10235           (void) SetPixelChannelMask(image,channel_mask);
10236           break;
10237         }
10238         case 114:  /* LiquidRescale */
10239         {
10240           if (attribute_flag[0] != 0)
10241             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10242               &geometry,exception);
10243           if (attribute_flag[1] != 0)
10244             geometry.width=argument_list[1].integer_reference;
10245           if (attribute_flag[2] != 0)
10246             geometry.height=argument_list[2].integer_reference;
10247           if (attribute_flag[3] == 0)
10248             argument_list[3].real_reference=1.0;
10249           if (attribute_flag[4] == 0)
10250             argument_list[4].real_reference=0.0;
10251           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10252             argument_list[3].real_reference,argument_list[4].real_reference,
10253             exception);
10254           break;
10255         }
10256         case 115:  /* EncipherImage */
10257         {
10258           (void) EncipherImage(image,argument_list[0].string_reference,
10259             exception);
10260           break;
10261         }
10262         case 116:  /* DecipherImage */
10263         {
10264           (void) DecipherImage(image,argument_list[0].string_reference,
10265             exception);
10266           break;
10267         }
10268         case 117:  /* Deskew */
10269         {
10270           geometry_info.rho=QuantumRange/2.0;
10271           if (attribute_flag[0] != 0)
10272             flags=ParseGeometry(argument_list[0].string_reference,
10273               &geometry_info);
10274           if (attribute_flag[1] != 0)
10275             geometry_info.rho=SiPrefixToDouble(
10276               argument_list[1].string_reference,QuantumRange);
10277           image=DeskewImage(image,geometry_info.rho,exception);
10278           break;
10279         }
10280         case 118:  /* Remap */
10281         {
10282           QuantizeInfo
10283             *quantize_info;
10284
10285           if (attribute_flag[0] == 0)
10286             {
10287               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10288                 PackageName);
10289               goto PerlException;
10290             }
10291           quantize_info=AcquireQuantizeInfo(info->image_info);
10292           if (attribute_flag[1] != 0)
10293             quantize_info->dither=(MagickBooleanType)
10294               argument_list[1].integer_reference;
10295           if (attribute_flag[2] != 0)
10296             quantize_info->dither_method=(DitherMethod)
10297               argument_list[2].integer_reference;
10298           (void) RemapImages(quantize_info,image,
10299             argument_list[0].image_reference);
10300           quantize_info=DestroyQuantizeInfo(quantize_info);
10301           break;
10302         }
10303         case 119:  /* SparseColor */
10304         {
10305           AV
10306             *av;
10307
10308           double
10309             *coordinates;
10310
10311           SparseColorMethod
10312             method;
10313
10314           size_t
10315             number_coordinates;
10316
10317           VirtualPixelMethod
10318             virtual_pixel;
10319
10320           if (attribute_flag[0] == 0)
10321             break;
10322           method=UndefinedColorInterpolate;
10323           if (attribute_flag[1] != 0)
10324             method=(SparseColorMethod) argument_list[1].integer_reference;
10325           av=(AV *) argument_list[0].array_reference;
10326           number_coordinates=(size_t) av_len(av)+1;
10327           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10328             sizeof(*coordinates));
10329           if (coordinates == (double *) NULL)
10330             {
10331               ThrowPerlException(exception,ResourceLimitFatalError,
10332                 "MemoryAllocationFailed",PackageName);
10333               goto PerlException;
10334             }
10335           for (j=0; j < (ssize_t) number_coordinates; j++)
10336             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10337           virtual_pixel=UndefinedVirtualPixelMethod;
10338           if (attribute_flag[2] != 0)
10339             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10340               argument_list[2].integer_reference);
10341           if (attribute_flag[3] != 0)
10342             channel=(ChannelType) argument_list[3].integer_reference;
10343           channel_mask=SetPixelChannelMask(image,channel);
10344           image=SparseColorImage(image,method,number_coordinates,coordinates,
10345             exception);
10346           if (image != (Image *) NULL)
10347             (void) SetPixelChannelMask(image,channel_mask);
10348           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10349             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10350           coordinates=(double *) RelinquishMagickMemory(coordinates);
10351           break;
10352         }
10353         case 120:  /* Function */
10354         {
10355           AV
10356             *av;
10357
10358           double
10359             *parameters;
10360
10361           MagickFunction
10362             function;
10363
10364           size_t
10365             number_parameters;
10366
10367           VirtualPixelMethod
10368             virtual_pixel;
10369
10370           if (attribute_flag[0] == 0)
10371             break;
10372           function=UndefinedFunction;
10373           if (attribute_flag[1] != 0)
10374             function=(MagickFunction) argument_list[1].integer_reference;
10375           av=(AV *) argument_list[0].array_reference;
10376           number_parameters=(size_t) av_len(av)+1;
10377           parameters=(double *) AcquireQuantumMemory(number_parameters,
10378             sizeof(*parameters));
10379           if (parameters == (double *) NULL)
10380             {
10381               ThrowPerlException(exception,ResourceLimitFatalError,
10382                 "MemoryAllocationFailed",PackageName);
10383               goto PerlException;
10384             }
10385           for (j=0; j < (ssize_t) number_parameters; j++)
10386             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10387           virtual_pixel=UndefinedVirtualPixelMethod;
10388           if (attribute_flag[2] != 0)
10389             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10390               argument_list[2].integer_reference);
10391           (void) FunctionImage(image,function,number_parameters,parameters,
10392             exception);
10393           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10394             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10395           parameters=(double *) RelinquishMagickMemory(parameters);
10396           break;
10397         }
10398         case 121:  /* SelectiveBlur */
10399         {
10400           if (attribute_flag[0] != 0)
10401             {
10402               flags=ParseGeometry(argument_list[0].string_reference,
10403                 &geometry_info);
10404               if ((flags & SigmaValue) == 0)
10405                 geometry_info.sigma=1.0;
10406               if ((flags & PercentValue) != 0)
10407                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10408             }
10409           if (attribute_flag[1] != 0)
10410             geometry_info.rho=argument_list[1].real_reference;
10411           if (attribute_flag[2] != 0)
10412             geometry_info.sigma=argument_list[2].real_reference;
10413           if (attribute_flag[3] != 0)
10414             geometry_info.xi=argument_list[3].integer_reference;;
10415           if (attribute_flag[4] != 0)
10416             channel=(ChannelType) argument_list[4].integer_reference;
10417           channel_mask=SetPixelChannelMask(image,channel);
10418           image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10419             geometry_info.xi,exception);
10420           if (image != (Image *) NULL)
10421             (void) SetPixelChannelMask(image,channel_mask);
10422           break;
10423         }
10424         case 122:  /* HaldClut */
10425         {
10426           if (attribute_flag[0] == 0)
10427             {
10428               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10429                 PackageName);
10430               goto PerlException;
10431             }
10432           if (attribute_flag[1] != 0)
10433             channel=(ChannelType) argument_list[1].integer_reference;
10434           channel_mask=SetPixelChannelMask(image,channel);
10435           (void) HaldClutImage(image,argument_list[0].image_reference,
10436             exception);
10437           (void) SetPixelChannelMask(image,channel_mask);
10438           break;
10439         }
10440         case 123:  /* BlueShift */
10441         {
10442           if (attribute_flag[0] != 0)
10443             (void) ParseGeometry(argument_list[0].string_reference,
10444               &geometry_info);
10445           image=BlueShiftImage(image,geometry_info.rho,exception);
10446           break;
10447         }
10448         case 124:  /* ForwardFourierTransformImage */
10449         {
10450           image=ForwardFourierTransformImage(image,
10451             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10452             exception);
10453           break;
10454         }
10455         case 125:  /* InverseFourierTransformImage */
10456         {
10457           image=InverseFourierTransformImage(image,image->next,
10458             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10459             exception);
10460           break;
10461         }
10462         case 126:  /* ColorDecisionList */
10463         {
10464           if (attribute_flag[0] == 0)
10465             argument_list[0].string_reference=(char *) NULL;
10466           (void) ColorDecisionListImage(image,
10467             argument_list[0].string_reference,exception);
10468           break;
10469         }
10470         case 127:  /* AutoGamma */
10471         {
10472           if (attribute_flag[0] != 0)
10473             channel=(ChannelType) argument_list[0].integer_reference;
10474           channel_mask=SetPixelChannelMask(image,channel);
10475           (void) AutoGammaImage(image,exception);
10476           (void) SetPixelChannelMask(image,channel_mask);
10477           break;
10478         }
10479         case 128:  /* AutoLevel */
10480         {
10481           if (attribute_flag[0] != 0)
10482             channel=(ChannelType) argument_list[0].integer_reference;
10483           channel_mask=SetPixelChannelMask(image,channel);
10484           (void) AutoLevelImage(image,exception);
10485           (void) SetPixelChannelMask(image,channel_mask);
10486           break;
10487         }
10488         case 129:  /* LevelColors */
10489         {
10490           PixelInfo
10491             black_point,
10492             white_point;
10493
10494           (void) QueryMagickColor("#000000",&black_point,exception);
10495           (void) QueryMagickColor("#ffffff",&white_point,exception);
10496           if (attribute_flag[1] != 0)
10497              (void) QueryMagickColor(argument_list[1].string_reference,
10498                &black_point,exception);
10499           if (attribute_flag[2] != 0)
10500              (void) QueryMagickColor(argument_list[2].string_reference,
10501                &white_point,exception);
10502           if (attribute_flag[3] != 0)
10503             channel=(ChannelType) argument_list[3].integer_reference;
10504           channel_mask=SetPixelChannelMask(image,channel);
10505           (void) LevelImageColors(image,&black_point,&white_point,
10506             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10507             exception);
10508           (void) SetPixelChannelMask(image,channel_mask);
10509           break;
10510         }
10511         case 130:  /* Clamp */
10512         {
10513           if (attribute_flag[0] != 0)
10514             channel=(ChannelType) argument_list[0].integer_reference;
10515           channel_mask=SetPixelChannelMask(image,channel);
10516           (void) ClampImage(image);
10517           (void) SetPixelChannelMask(image,channel_mask);
10518           break;
10519         }
10520         case 132:  /* BrightnessContrast */
10521         {
10522           double
10523             brightness,
10524             contrast;
10525
10526           brightness=0.0;
10527           contrast=0.0;
10528           if (attribute_flag[0] != 0)
10529             {
10530               flags=ParseGeometry(argument_list[0].string_reference,
10531                 &geometry_info);
10532               brightness=geometry_info.rho;
10533               if ((flags & SigmaValue) == 0)
10534                 contrast=geometry_info.sigma;
10535             }
10536           if (attribute_flag[1] != 0)
10537             brightness=argument_list[1].real_reference;
10538           if (attribute_flag[2] != 0)
10539             contrast=argument_list[2].real_reference;
10540           if (attribute_flag[4] != 0)
10541             channel=(ChannelType) argument_list[4].integer_reference;
10542           channel_mask=SetPixelChannelMask(image,channel);
10543           (void) BrightnessContrastImage(image,brightness,contrast,exception);
10544           (void) SetPixelChannelMask(image,channel_mask);
10545           break;
10546         }
10547         case 133:  /* Morphology */
10548         {
10549           KernelInfo
10550             *kernel;
10551
10552           MorphologyMethod
10553             method;
10554
10555           ssize_t
10556             iterations;
10557
10558           if (attribute_flag[0] == 0)
10559             break;
10560           kernel=AcquireKernelInfo(argument_list[0].string_reference);
10561           if (kernel == (KernelInfo *) NULL)
10562             break;
10563           if (attribute_flag[1] != 0)
10564             channel=(ChannelType) argument_list[1].integer_reference;
10565           method=UndefinedMorphology;
10566           if (attribute_flag[2] != 0)
10567             method=argument_list[2].integer_reference;
10568           iterations=1;
10569           if (attribute_flag[3] != 0)
10570             iterations=argument_list[4].integer_reference;
10571           channel_mask=SetPixelChannelMask(image,channel);
10572           image=MorphologyImage(image,method,iterations,kernel,exception);
10573           if (image != (Image *) NULL)
10574             (void) SetPixelChannelMask(image,channel_mask);
10575           kernel=DestroyKernelInfo(kernel);
10576           break;
10577         }
10578         case 108:  /* Recolor */
10579         case 134:  /* ColorMatrix */
10580         {
10581           AV
10582             *av;
10583
10584           double
10585             *color_matrix;
10586
10587           KernelInfo
10588             *kernel_info;
10589
10590           size_t
10591             order;
10592
10593           if (attribute_flag[0] == 0)
10594             break;
10595           av=(AV *) argument_list[0].array_reference;
10596           if (av == (AV *) NULL)
10597             break;
10598           order=(size_t) sqrt(av_len(av)+1);
10599           color_matrix=(double *) AcquireQuantumMemory(order,order*
10600             sizeof(*color_matrix));
10601           if (color_matrix == (double *) NULL)
10602             {
10603               ThrowPerlException(exception,ResourceLimitFatalError,
10604                 "MemoryAllocationFailed",PackageName);
10605               goto PerlException;
10606            }
10607           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10608             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10609           for ( ; j < (ssize_t) (order*order); j++)
10610             color_matrix[j]=0.0;
10611           kernel_info=AcquireKernelInfo((const char *) NULL);
10612           if (kernel_info == (KernelInfo *) NULL)
10613             break;
10614           kernel_info->width=order;
10615           kernel_info->height=order;
10616           kernel_info->values=color_matrix;
10617           image=ColorMatrixImage(image,kernel_info,exception);
10618           kernel_info->values=(double *) NULL;
10619           kernel_info=DestroyKernelInfo(kernel_info);
10620           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10621           break;
10622         }
10623         case 135:  /* Color */
10624         {
10625           PixelInfo
10626             color;
10627
10628           (void) QueryMagickColor("none",&color,exception);
10629           if (attribute_flag[0] != 0)
10630             (void) QueryMagickColor(argument_list[0].string_reference,
10631               &color,exception);
10632           (void) SetImageColor(image,&color);
10633           break;
10634         }
10635         case 136:  /* Mode */
10636         {
10637           if (attribute_flag[0] != 0)
10638             {
10639               flags=ParseGeometry(argument_list[0].string_reference,
10640                 &geometry_info);
10641               if ((flags & SigmaValue) == 0)
10642                 geometry_info.sigma=1.0;
10643             }
10644           if (attribute_flag[1] != 0)
10645             geometry_info.rho=argument_list[1].real_reference;
10646           if (attribute_flag[2] != 0)
10647             geometry_info.sigma=argument_list[2].real_reference;
10648           if (attribute_flag[3] != 0)
10649             channel=(ChannelType) argument_list[3].integer_reference;
10650           channel_mask=SetPixelChannelMask(image,channel);
10651           image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
10652             (size_t) geometry_info.sigma,exception);
10653           if (image != (Image *) NULL)
10654             (void) SetPixelChannelMask(image,channel_mask);
10655           break;
10656         }
10657         case 137:  /* Statistic */
10658         {
10659           StatisticType
10660             statistic;
10661
10662           statistic=UndefinedStatistic;
10663           if (attribute_flag[0] != 0)
10664             {
10665               flags=ParseGeometry(argument_list[0].string_reference,
10666                 &geometry_info);
10667               if ((flags & SigmaValue) == 0)
10668                 geometry_info.sigma=1.0;
10669             }
10670           if (attribute_flag[1] != 0)
10671             geometry_info.rho=argument_list[1].real_reference;
10672           if (attribute_flag[2] != 0)
10673             geometry_info.sigma=argument_list[2].real_reference;
10674           if (attribute_flag[3] != 0)
10675             channel=(ChannelType) argument_list[3].integer_reference;
10676           if (attribute_flag[4] != 0)
10677             statistic=(StatisticType) argument_list[4].integer_reference;
10678           channel_mask=SetPixelChannelMask(image,channel);
10679           image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
10680             (size_t) geometry_info.sigma,exception);
10681           if (image != (Image *) NULL)
10682             (void) SetPixelChannelMask(image,channel_mask);
10683           break;
10684         }
10685       }
10686       if (next != (Image *) NULL)
10687         (void) CatchImageException(next);
10688       if (region_image != (Image *) NULL)
10689         {
10690           /*
10691             Composite region.
10692           */ 
10693           status=CompositeImage(region_image,CopyCompositeOp,image,
10694             region_info.x,region_info.y);
10695           (void) status;
10696           (void) CatchImageException(region_image);
10697           image=DestroyImage(image);
10698           image=region_image;
10699         }
10700       if (image != (Image *) NULL)
10701         {
10702           number_images++;
10703           if (next && (next != image))
10704             {
10705               image->next=next->next;
10706               if (image->next != (Image *) NULL)
10707                 image->next->previous=image;
10708               DeleteImageFromRegistry(*pv,next);
10709             }
10710           sv_setiv(*pv,(IV) image);
10711           next=image;
10712         }
10713       if (*pv)
10714         pv++;
10715     }
10716
10717   PerlException:
10718     if (reference_vector)
10719       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
10720     InheritPerlException(exception,perl_exception);
10721     exception=DestroyExceptionInfo(exception);
10722     sv_setiv(perl_exception,(IV) number_images);
10723     SvPOK_on(perl_exception);
10724     ST(0)=sv_2mortal(perl_exception);
10725     XSRETURN(1);
10726   }
10727 \f
10728 #
10729 ###############################################################################
10730 #                                                                             #
10731 #                                                                             #
10732 #                                                                             #
10733 #   M o n t a g e                                                             #
10734 #                                                                             #
10735 #                                                                             #
10736 #                                                                             #
10737 ###############################################################################
10738 #
10739 #
10740 void
10741 Montage(ref,...)
10742   Image::Magick ref=NO_INIT
10743   ALIAS:
10744     MontageImage  = 1
10745     montage       = 2
10746     montageimage  = 3
10747   PPCODE:
10748   {
10749     AV
10750       *av;
10751
10752     char
10753       *attribute;
10754
10755     ExceptionInfo
10756       *exception;
10757
10758     HV
10759       *hv;
10760
10761     Image
10762       *image,
10763       *next;
10764
10765     PixelInfo
10766       transparent_color;
10767
10768     MontageInfo
10769       *montage_info;
10770
10771     register ssize_t
10772       i;
10773
10774     ssize_t
10775       sp;
10776
10777     struct PackageInfo
10778       *info;
10779
10780     SV
10781       *av_reference,
10782       *perl_exception,
10783       *reference,
10784       *rv,
10785       *sv;
10786
10787     PERL_UNUSED_VAR(ref);
10788     PERL_UNUSED_VAR(ix);
10789     exception=AcquireExceptionInfo();
10790     perl_exception=newSVpv("",0);
10791     sv=NULL;
10792     attribute=NULL;
10793     if (sv_isobject(ST(0)) == 0)
10794       {
10795         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
10796           PackageName);
10797         goto PerlException;
10798       }
10799     reference=SvRV(ST(0));
10800     hv=SvSTASH(reference);
10801     av=newAV();
10802     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
10803     SvREFCNT_dec(av);
10804     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
10805     if (image == (Image *) NULL)
10806       {
10807         ThrowPerlException(exception,OptionError,"NoImagesDefined",
10808           PackageName);
10809         goto PerlException;
10810       }
10811     /*
10812       Get options.
10813     */
10814     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
10815     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
10816     (void) QueryMagickColor("none",&transparent_color,exception);
10817     for (i=2; i < items; i+=2)
10818     {
10819       attribute=(char *) SvPV(ST(i-1),na);
10820       switch (*attribute)
10821       {
10822         case 'B':
10823         case 'b':
10824         {
10825           if (LocaleCompare(attribute,"background") == 0)
10826             {
10827               (void) QueryColorDatabase(SvPV(ST(i),na),
10828                 &montage_info->background_color,exception);
10829               for (next=image; next; next=next->next)
10830                 next->background_color=montage_info->background_color;
10831               break;
10832             }
10833           if (LocaleCompare(attribute,"border") == 0)
10834             {
10835               montage_info->border_width=SvIV(ST(i));
10836               break;
10837             }
10838           if (LocaleCompare(attribute,"bordercolor") == 0)
10839             {
10840               (void) QueryColorDatabase(SvPV(ST(i),na),
10841                 &montage_info->border_color,exception);
10842               for (next=image; next; next=next->next)
10843                 next->border_color=montage_info->border_color;
10844               break;
10845             }
10846           if (LocaleCompare(attribute,"borderwidth") == 0)
10847             {
10848               montage_info->border_width=SvIV(ST(i));
10849               break;
10850             }
10851           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10852             attribute);
10853           break;
10854         }
10855         case 'C':
10856         case 'c':
10857         {
10858           if (LocaleCompare(attribute,"compose") == 0)
10859             {
10860               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
10861                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
10862               if (sp < 0)
10863                 {
10864                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
10865                     SvPV(ST(i),na));
10866                   break;
10867                 }
10868               for (next=image; next; next=next->next)
10869                 next->compose=(CompositeOperator) sp;
10870               break;
10871             }
10872           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10873             attribute);
10874           break;
10875         }
10876         case 'F':
10877         case 'f':
10878         {
10879           if (LocaleCompare(attribute,"fill") == 0)
10880             {
10881               (void) QueryColorDatabase(SvPV(ST(i),na),&montage_info->fill,
10882                 exception);
10883               break;
10884             }
10885           if (LocaleCompare(attribute,"font") == 0)
10886             {
10887               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
10888               break;
10889             }
10890           if (LocaleCompare(attribute,"frame") == 0)
10891             {
10892               char
10893                 *p;
10894
10895               p=SvPV(ST(i),na);
10896               if (IsGeometry(p) == MagickFalse)
10897                 {
10898                   ThrowPerlException(exception,OptionError,"MissingGeometry",
10899                     p);
10900                   break;
10901                 }
10902               (void) CloneString(&montage_info->frame,p);
10903               if (*p == '\0')
10904                 montage_info->frame=(char *) NULL;
10905               break;
10906             }
10907           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10908             attribute);
10909           break;
10910         }
10911         case 'G':
10912         case 'g':
10913         {
10914           if (LocaleCompare(attribute,"geometry") == 0)
10915             {
10916               char
10917                 *p;
10918
10919               p=SvPV(ST(i),na);
10920               if (IsGeometry(p) == MagickFalse)
10921                 {
10922                   ThrowPerlException(exception,OptionError,"MissingGeometry",
10923                     p);
10924                   break;
10925                 }
10926              (void) CloneString(&montage_info->geometry,p);
10927              if (*p == '\0')
10928                montage_info->geometry=(char *) NULL;
10929              break;
10930            }
10931          if (LocaleCompare(attribute,"gravity") == 0)
10932            {
10933              ssize_t
10934                in;
10935
10936              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
10937                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
10938              if (in < 0)
10939                {
10940                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
10941                    SvPV(ST(i),na));
10942                  return;
10943                }
10944              montage_info->gravity=(GravityType) in;
10945              for (next=image; next; next=next->next)
10946                next->gravity=(GravityType) in;
10947              break;
10948            }
10949           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10950             attribute);
10951           break;
10952         }
10953         case 'L':
10954         case 'l':
10955         {
10956           if (LocaleCompare(attribute,"label") == 0)
10957             {
10958               for (next=image; next; next=next->next)
10959                 (void) SetImageProperty(next,"label",InterpretImageProperties(
10960                   info ? info->image_info : (ImageInfo *) NULL,next,
10961                   SvPV(ST(i),na)));
10962               break;
10963             }
10964           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10965             attribute);
10966           break;
10967         }
10968         case 'M':
10969         case 'm':
10970         {
10971           if (LocaleCompare(attribute,"mattecolor") == 0)
10972             {
10973               (void) QueryColorDatabase(SvPV(ST(i),na),
10974                 &montage_info->matte_color,exception);
10975               for (next=image; next; next=next->next)
10976                 next->matte_color=montage_info->matte_color;
10977               break;
10978             }
10979           if (LocaleCompare(attribute,"mode") == 0)
10980             {
10981               ssize_t
10982                 in;
10983
10984               in=!SvPOK(ST(i)) ? SvIV(ST(i)) :
10985                 ParseCommandOption(MagickModeOptions,MagickFalse,SvPV(ST(i),na));
10986               switch (in)
10987               {
10988                 default:
10989                 {
10990                   ThrowPerlException(exception,OptionError,
10991                     "UnrecognizedModeType",SvPV(ST(i),na));
10992                   break;
10993                 }
10994                 case FrameMode:
10995                 {
10996                   (void) CloneString(&montage_info->frame,"15x15+3+3");
10997                   montage_info->shadow=MagickTrue;
10998                   break;
10999                 }
11000                 case UnframeMode:
11001                 {
11002                   montage_info->frame=(char *) NULL;
11003                   montage_info->shadow=MagickFalse;
11004                   montage_info->border_width=0;
11005                   break;
11006                 }
11007                 case ConcatenateMode:
11008                 {
11009                   montage_info->frame=(char *) NULL;
11010                   montage_info->shadow=MagickFalse;
11011                   (void) CloneString(&montage_info->geometry,"+0+0");
11012                   montage_info->border_width=0;
11013                 }
11014               }
11015               break;
11016             }
11017           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11018             attribute);
11019           break;
11020         }
11021         case 'P':
11022         case 'p':
11023         {
11024           if (LocaleCompare(attribute,"pointsize") == 0)
11025             {
11026               montage_info->pointsize=SvIV(ST(i));
11027               break;
11028             }
11029           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11030             attribute);
11031           break;
11032         }
11033         case 'S':
11034         case 's':
11035         {
11036           if (LocaleCompare(attribute,"shadow") == 0)
11037             {
11038               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11039                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11040               if (sp < 0)
11041                 {
11042                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11043                     SvPV(ST(i),na));
11044                   break;
11045                 }
11046              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11047              break;
11048             }
11049           if (LocaleCompare(attribute,"stroke") == 0)
11050             {
11051               (void) QueryColorDatabase(SvPV(ST(i),na),&montage_info->stroke,
11052                 exception);
11053               break;
11054             }
11055           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11056             attribute);
11057           break;
11058         }
11059         case 'T':
11060         case 't':
11061         {
11062           if (LocaleCompare(attribute,"texture") == 0)
11063             {
11064               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11065               break;
11066             }
11067           if (LocaleCompare(attribute,"tile") == 0)
11068             {
11069               char *p=SvPV(ST(i),na);
11070               if (IsGeometry(p) == MagickFalse)
11071                 {
11072                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11073                     p);
11074                   break;
11075                 }
11076               (void) CloneString(&montage_info->tile,p);
11077               if (*p == '\0')
11078                 montage_info->tile=(char *) NULL;
11079               break;
11080             }
11081           if (LocaleCompare(attribute,"title") == 0)
11082             {
11083               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11084               break;
11085             }
11086           if (LocaleCompare(attribute,"transparent") == 0)
11087             {
11088               PixelInfo
11089                 transparent_color;
11090
11091               QueryMagickColor(SvPV(ST(i),na),&transparent_color,exception);
11092               for (next=image; next; next=next->next)
11093                 (void) TransparentPaintImage(next,&transparent_color,
11094                   TransparentAlpha,MagickFalse,exception);
11095               break;
11096             }
11097           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11098             attribute);
11099           break;
11100         }
11101         default:
11102         {
11103           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11104             attribute);
11105           break;
11106         }
11107       }
11108     }
11109     image=MontageImageList(info->image_info,montage_info,image,exception);
11110     montage_info=DestroyMontageInfo(montage_info);
11111     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11112       goto PerlException;
11113     if (transparent_color.alpha != TransparentAlpha)
11114       for (next=image; next; next=next->next)
11115         (void) TransparentPaintImage(next,&transparent_color,
11116           TransparentAlpha,MagickFalse,exception);
11117     for (  ; image; image=image->next)
11118     {
11119       AddImageToRegistry(sv,image);
11120       rv=newRV(sv);
11121       av_push(av,sv_bless(rv,hv));
11122       SvREFCNT_dec(sv);
11123     }
11124     exception=DestroyExceptionInfo(exception);
11125     ST(0)=av_reference;
11126     SvREFCNT_dec(perl_exception);
11127     XSRETURN(1);
11128
11129   PerlException:
11130     InheritPerlException(exception,perl_exception);
11131     exception=DestroyExceptionInfo(exception);
11132     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11133     SvPOK_on(perl_exception);
11134     ST(0)=sv_2mortal(perl_exception);
11135     XSRETURN(1);
11136   }
11137 \f
11138 #
11139 ###############################################################################
11140 #                                                                             #
11141 #                                                                             #
11142 #                                                                             #
11143 #   M o r p h                                                                 #
11144 #                                                                             #
11145 #                                                                             #
11146 #                                                                             #
11147 ###############################################################################
11148 #
11149 #
11150 void
11151 Morph(ref,...)
11152   Image::Magick ref=NO_INIT
11153   ALIAS:
11154     MorphImage  = 1
11155     morph       = 2
11156     morphimage  = 3
11157   PPCODE:
11158   {
11159     AV
11160       *av;
11161
11162     char
11163       *attribute;
11164
11165     ExceptionInfo
11166       *exception;
11167
11168     HV
11169       *hv;
11170
11171     Image
11172       *image;
11173
11174     register ssize_t
11175       i;
11176
11177     ssize_t
11178       number_frames;
11179
11180     struct PackageInfo
11181       *info;
11182
11183     SV
11184       *av_reference,
11185       *perl_exception,
11186       *reference,
11187       *rv,
11188       *sv;
11189
11190     PERL_UNUSED_VAR(ref);
11191     PERL_UNUSED_VAR(ix);
11192     exception=AcquireExceptionInfo();
11193     perl_exception=newSVpv("",0);
11194     sv=NULL;
11195     av=NULL;
11196     attribute=NULL;
11197     if (sv_isobject(ST(0)) == 0)
11198       {
11199         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11200           PackageName);
11201         goto PerlException;
11202       }
11203     reference=SvRV(ST(0));
11204     hv=SvSTASH(reference);
11205     av=newAV();
11206     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11207     SvREFCNT_dec(av);
11208     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11209     if (image == (Image *) NULL)
11210       {
11211         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11212           PackageName);
11213         goto PerlException;
11214       }
11215     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11216     /*
11217       Get attribute.
11218     */
11219     number_frames=30;
11220     for (i=2; i < items; i+=2)
11221     {
11222       attribute=(char *) SvPV(ST(i-1),na);
11223       switch (*attribute)
11224       {
11225         case 'F':
11226         case 'f':
11227         {
11228           if (LocaleCompare(attribute,"frames") == 0)
11229             {
11230               number_frames=SvIV(ST(i));
11231               break;
11232             }
11233           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11234             attribute);
11235           break;
11236         }
11237         default:
11238         {
11239           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11240             attribute);
11241           break;
11242         }
11243       }
11244     }
11245     image=MorphImages(image,number_frames,exception);
11246     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11247       goto PerlException;
11248     for ( ; image; image=image->next)
11249     {
11250       AddImageToRegistry(sv,image);
11251       rv=newRV(sv);
11252       av_push(av,sv_bless(rv,hv));
11253       SvREFCNT_dec(sv);
11254     }
11255     exception=DestroyExceptionInfo(exception);
11256     ST(0)=av_reference;
11257     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11258     XSRETURN(1);
11259
11260   PerlException:
11261     InheritPerlException(exception,perl_exception);
11262     exception=DestroyExceptionInfo(exception);
11263     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11264     SvPOK_on(perl_exception);
11265     ST(0)=sv_2mortal(perl_exception);
11266     XSRETURN(1);
11267   }
11268 \f
11269 #
11270 ###############################################################################
11271 #                                                                             #
11272 #                                                                             #
11273 #                                                                             #
11274 #   M o s a i c                                                               #
11275 #                                                                             #
11276 #                                                                             #
11277 #                                                                             #
11278 ###############################################################################
11279 #
11280 #
11281 void
11282 Mosaic(ref)
11283   Image::Magick ref=NO_INIT
11284   ALIAS:
11285     MosaicImage   = 1
11286     mosaic        = 2
11287     mosaicimage   = 3
11288   PPCODE:
11289   {
11290     AV
11291       *av;
11292
11293     ExceptionInfo
11294       *exception;
11295
11296     HV
11297       *hv;
11298
11299     Image
11300       *image;
11301
11302     struct PackageInfo
11303       *info;
11304
11305     SV
11306       *perl_exception,
11307       *reference,
11308       *rv,
11309       *sv;
11310
11311     PERL_UNUSED_VAR(ref);
11312     PERL_UNUSED_VAR(ix);
11313     exception=AcquireExceptionInfo();
11314     perl_exception=newSVpv("",0);
11315     sv=NULL;
11316     if (sv_isobject(ST(0)) == 0)
11317       {
11318         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11319           PackageName);
11320         goto PerlException;
11321       }
11322     reference=SvRV(ST(0));
11323     hv=SvSTASH(reference);
11324     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11325     if (image == (Image *) NULL)
11326       {
11327         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11328           PackageName);
11329         goto PerlException;
11330       }
11331     image=MergeImageLayers(image,MosaicLayer,exception);
11332     /*
11333       Create blessed Perl array for the returned image.
11334     */
11335     av=newAV();
11336     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11337     SvREFCNT_dec(av);
11338     AddImageToRegistry(sv,image);
11339     rv=newRV(sv);
11340     av_push(av,sv_bless(rv,hv));
11341     SvREFCNT_dec(sv);
11342     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11343     (void) CopyMagickString(image->filename,info->image_info->filename,
11344       MaxTextExtent);
11345     SetImageInfo(info->image_info,0,&image->exception);
11346     exception=DestroyExceptionInfo(exception);
11347     SvREFCNT_dec(perl_exception);
11348     XSRETURN(1);
11349
11350   PerlException:
11351     InheritPerlException(exception,perl_exception);
11352     exception=DestroyExceptionInfo(exception);
11353     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11354     SvPOK_on(perl_exception);  /* return messages in string context */
11355     ST(0)=sv_2mortal(perl_exception);
11356     XSRETURN(1);
11357   }
11358 \f
11359 #
11360 ###############################################################################
11361 #                                                                             #
11362 #                                                                             #
11363 #                                                                             #
11364 #   P i n g                                                                   #
11365 #                                                                             #
11366 #                                                                             #
11367 #                                                                             #
11368 ###############################################################################
11369 #
11370 #
11371 void
11372 Ping(ref,...)
11373   Image::Magick ref=NO_INIT
11374   ALIAS:
11375     PingImage  = 1
11376     ping       = 2
11377     pingimage  = 3
11378   PPCODE:
11379   {
11380     AV
11381       *av;
11382
11383     char
11384       **keep,
11385       **list;
11386
11387     ExceptionInfo
11388       *exception;
11389
11390     Image
11391       *image,
11392       *next;
11393
11394     int
11395       n;
11396
11397     MagickBooleanType
11398       status;
11399
11400     register char
11401       **p;
11402
11403     register ssize_t
11404       i;
11405
11406     ssize_t
11407       ac;
11408
11409     STRLEN
11410       *length;
11411
11412     struct PackageInfo
11413       *info,
11414       *package_info;
11415
11416     SV
11417       *perl_exception,
11418       *reference;
11419
11420     size_t
11421       count;
11422
11423     PERL_UNUSED_VAR(ref);
11424     PERL_UNUSED_VAR(ix);
11425     exception=AcquireExceptionInfo();
11426     perl_exception=newSVpv("",0);
11427     package_info=(struct PackageInfo *) NULL;
11428     ac=(items < 2) ? 1 : items-1;
11429     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
11430     keep=list;
11431     length=(STRLEN *) NULL;
11432     if (list == (char **) NULL)
11433       {
11434         ThrowPerlException(exception,ResourceLimitError,
11435           "MemoryAllocationFailed",PackageName);
11436         goto PerlException;
11437       }
11438     keep=list;
11439     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
11440     if (length == (STRLEN *) NULL)
11441       {
11442         ThrowPerlException(exception,ResourceLimitError,
11443           "MemoryAllocationFailed",PackageName);
11444         goto PerlException;
11445       }
11446     if (sv_isobject(ST(0)) == 0)
11447       {
11448         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11449           PackageName);
11450         goto PerlException;
11451       }
11452     reference=SvRV(ST(0));
11453     if (SvTYPE(reference) != SVt_PVAV)
11454       {
11455         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11456           PackageName);
11457         goto PerlException;
11458       }
11459     av=(AV *) reference;
11460     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11461       exception);
11462     package_info=ClonePackageInfo(info,exception);
11463     n=1;
11464     if (items <= 1)
11465       *list=(char *) (*package_info->image_info->filename ?
11466         package_info->image_info->filename : "XC:black");
11467     else
11468       for (n=0, i=0; i < ac; i++)
11469       {
11470         list[n]=(char *) SvPV(ST(i+1),length[n]);
11471         if ((items >= 3) && strEQcase(list[n],"blob"))
11472           {
11473             void
11474               *blob;
11475
11476             i++;
11477             blob=(void *) (SvPV(ST(i+1),length[n]));
11478             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
11479           }
11480         if ((items >= 3) && strEQcase(list[n],"filename"))
11481           continue;
11482         if ((items >= 3) && strEQcase(list[n],"file"))
11483           {
11484             FILE
11485               *file;
11486
11487             PerlIO
11488               *io_info;
11489
11490             i++;
11491             io_info=IoIFP(sv_2io(ST(i+1)));
11492             if (io_info == (PerlIO *) NULL)
11493               {
11494                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11495                   PackageName);
11496                 continue;
11497               }
11498             file=PerlIO_findFILE(io_info);
11499             if (file == (FILE *) NULL)
11500               {
11501                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11502                   PackageName);
11503                 continue;
11504               }
11505             SetImageInfoFile(package_info->image_info,file);
11506           }
11507         if ((items >= 3) && strEQcase(list[n],"magick"))
11508           continue;
11509         n++;
11510       }
11511     list[n]=(char *) NULL;
11512     keep=list;
11513     status=ExpandFilenames(&n,&list);
11514     if (status == MagickFalse)
11515       {
11516         ThrowPerlException(exception,ResourceLimitError,
11517           "MemoryAllocationFailed",PackageName);
11518         goto PerlException;
11519       }
11520     count=0;
11521     for (i=0; i < n; i++)
11522     {
11523       (void) CopyMagickString(package_info->image_info->filename,list[i],
11524         MaxTextExtent);
11525       image=PingImage(package_info->image_info,exception);
11526       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11527         break;
11528       if ((package_info->image_info->file != (FILE *) NULL) ||
11529           (package_info->image_info->blob != (void *) NULL))
11530         DisassociateImageStream(image);
11531       count+=GetImageListLength(image);
11532       EXTEND(sp,4*count);
11533       for (next=image; next; next=next->next)
11534       {
11535         PUSHs(sv_2mortal(newSViv(next->columns)));
11536         PUSHs(sv_2mortal(newSViv(next->rows)));
11537         PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
11538         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
11539       }
11540       image=DestroyImageList(image);
11541     }
11542     /*
11543       Free resources.
11544     */
11545     for (i=0; i < n; i++)
11546       if (list[i] != (char *) NULL)
11547         for (p=keep; list[i] != *p++; )
11548           if (*p == NULL)
11549             {
11550               list[i]=(char *) RelinquishMagickMemory(list[i]);
11551               break;
11552             }
11553
11554   PerlException:
11555     if (package_info != (struct PackageInfo *) NULL)
11556       DestroyPackageInfo(package_info);
11557     if (list && (list != keep))
11558       list=(char **) RelinquishMagickMemory(list);
11559     if (keep)
11560       keep=(char **) RelinquishMagickMemory(keep);
11561     if (length)
11562       length=(STRLEN *) RelinquishMagickMemory(length);
11563     InheritPerlException(exception,perl_exception);
11564     exception=DestroyExceptionInfo(exception);
11565     SvREFCNT_dec(perl_exception);  /* throw away all errors */
11566   }
11567 \f
11568 #
11569 ###############################################################################
11570 #                                                                             #
11571 #                                                                             #
11572 #                                                                             #
11573 #   P r e v i e w                                                             #
11574 #                                                                             #
11575 #                                                                             #
11576 #                                                                             #
11577 ###############################################################################
11578 #
11579 #
11580 void
11581 Preview(ref,...)
11582   Image::Magick ref=NO_INIT
11583   ALIAS:
11584     PreviewImage = 1
11585     preview      = 2
11586     previewimage = 3
11587   PPCODE:
11588   {
11589     AV
11590       *av;
11591
11592     ExceptionInfo
11593       *exception;
11594
11595     HV
11596       *hv;
11597
11598     Image
11599       *image,
11600       *preview_image;
11601
11602     PreviewType
11603       preview_type;
11604
11605     struct PackageInfo
11606       *info;
11607
11608     SV
11609       *av_reference,
11610       *perl_exception,
11611       *reference,
11612       *rv,
11613       *sv;
11614
11615     PERL_UNUSED_VAR(ref);
11616     PERL_UNUSED_VAR(ix);
11617     exception=AcquireExceptionInfo();
11618     perl_exception=newSVpv("",0);
11619     sv=NULL;
11620     av=NULL;
11621     if (sv_isobject(ST(0)) == 0)
11622       {
11623         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11624           PackageName);
11625         goto PerlException;
11626       }
11627     reference=SvRV(ST(0));
11628     hv=SvSTASH(reference);
11629     av=newAV();
11630     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11631     SvREFCNT_dec(av);
11632     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11633     if (image == (Image *) NULL)
11634       {
11635         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11636           PackageName);
11637         goto PerlException;
11638       }
11639     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11640     preview_type=GammaPreview;
11641     if (items > 1)
11642       preview_type=(PreviewType)
11643         ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
11644     for ( ; image; image=image->next)
11645     {
11646       preview_image=PreviewImage(image,preview_type,exception);
11647       if (preview_image == (Image *) NULL)
11648         goto PerlException;
11649       AddImageToRegistry(sv,preview_image);
11650       rv=newRV(sv);
11651       av_push(av,sv_bless(rv,hv));
11652       SvREFCNT_dec(sv);
11653     }
11654     exception=DestroyExceptionInfo(exception);
11655     ST(0)=av_reference;
11656     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11657     XSRETURN(1);
11658
11659   PerlException:
11660     InheritPerlException(exception,perl_exception);
11661     exception=DestroyExceptionInfo(exception);
11662     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11663     SvPOK_on(perl_exception);
11664     ST(0)=sv_2mortal(perl_exception);
11665     XSRETURN(1);
11666   }
11667 \f
11668 #
11669 ###############################################################################
11670 #                                                                             #
11671 #                                                                             #
11672 #                                                                             #
11673 #   Q u e r y C o l o r                                                       #
11674 #                                                                             #
11675 #                                                                             #
11676 #                                                                             #
11677 ###############################################################################
11678 #
11679 #
11680 void
11681 QueryColor(ref,...)
11682   Image::Magick ref=NO_INIT
11683   ALIAS:
11684     querycolor = 1
11685   PPCODE:
11686   {
11687     char
11688       *name;
11689
11690     ExceptionInfo
11691       *exception;
11692
11693     PixelInfo
11694       color;
11695
11696     register ssize_t
11697       i;
11698
11699     SV
11700       *perl_exception;
11701
11702     PERL_UNUSED_VAR(ref);
11703     PERL_UNUSED_VAR(ix);
11704     exception=AcquireExceptionInfo();
11705     perl_exception=newSVpv("",0);
11706     if (items == 1)
11707       {
11708         const ColorInfo
11709           **colorlist;
11710
11711         size_t
11712           colors;
11713
11714         colorlist=GetColorInfoList("*",&colors,exception);
11715         EXTEND(sp,colors);
11716         for (i=0; i < (ssize_t) colors; i++)
11717         {
11718           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
11719         }
11720         colorlist=(const ColorInfo **)
11721           RelinquishMagickMemory((ColorInfo **) colorlist);
11722         goto PerlException;
11723       }
11724     EXTEND(sp,5*items);
11725     for (i=1; i < items; i++)
11726     {
11727       name=(char *) SvPV(ST(i),na);
11728       if (QueryMagickColor(name,&color,exception) == MagickFalse)
11729         {
11730           PUSHs(&sv_undef);
11731           continue;
11732         }
11733       PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
11734       PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
11735       PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
11736       if (color.colorspace == CMYKColorspace)
11737         PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
11738       if (color.matte != MagickFalse)
11739         PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
11740     }
11741
11742   PerlException:
11743     InheritPerlException(exception,perl_exception);
11744     exception=DestroyExceptionInfo(exception);
11745     SvREFCNT_dec(perl_exception);
11746   }
11747 \f
11748 #
11749 ###############################################################################
11750 #                                                                             #
11751 #                                                                             #
11752 #                                                                             #
11753 #   Q u e r y C o l o r N a m e                                               #
11754 #                                                                             #
11755 #                                                                             #
11756 #                                                                             #
11757 ###############################################################################
11758 #
11759 #
11760 void
11761 QueryColorname(ref,...)
11762   Image::Magick ref=NO_INIT
11763   ALIAS:
11764     querycolorname = 1
11765   PPCODE:
11766   {
11767     AV
11768       *av;
11769
11770     char
11771       message[MaxTextExtent];
11772
11773     ExceptionInfo
11774       *exception;
11775
11776     Image
11777       *image;
11778
11779     PixelPacket
11780       target_color;
11781
11782     register ssize_t
11783       i;
11784
11785     struct PackageInfo
11786       *info;
11787
11788     SV
11789       *perl_exception,
11790       *reference;  /* reference is the SV* of ref=SvIV(reference) */
11791
11792     PERL_UNUSED_VAR(ref);
11793     PERL_UNUSED_VAR(ix);
11794     exception=AcquireExceptionInfo();
11795     perl_exception=newSVpv("",0);
11796     reference=SvRV(ST(0));
11797     av=(AV *) reference;
11798     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11799       exception);
11800     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11801     if (image == (Image *) NULL)
11802       {
11803         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11804           PackageName);
11805         goto PerlException;
11806       }
11807     EXTEND(sp,items);
11808     for (i=1; i < items; i++)
11809     {
11810       (void) QueryColorDatabase(SvPV(ST(i),na),&target_color,exception);
11811       (void) QueryColorname(image,&target_color,SVGCompliance,message,
11812         exception);
11813       PUSHs(sv_2mortal(newSVpv(message,0)));
11814     }
11815
11816   PerlException:
11817     InheritPerlException(exception,perl_exception);
11818     exception=DestroyExceptionInfo(exception);
11819     SvREFCNT_dec(perl_exception);
11820   }
11821 \f
11822 #
11823 ###############################################################################
11824 #                                                                             #
11825 #                                                                             #
11826 #                                                                             #
11827 #   Q u e r y F o n t                                                         #
11828 #                                                                             #
11829 #                                                                             #
11830 #                                                                             #
11831 ###############################################################################
11832 #
11833 #
11834 void
11835 QueryFont(ref,...)
11836   Image::Magick ref=NO_INIT
11837   ALIAS:
11838     queryfont = 1
11839   PPCODE:
11840   {
11841     char
11842       *name,
11843       message[MaxTextExtent];
11844
11845     ExceptionInfo
11846       *exception;
11847
11848     register ssize_t
11849       i;
11850
11851     SV
11852       *perl_exception;
11853
11854     volatile const TypeInfo
11855       *type_info;
11856
11857     PERL_UNUSED_VAR(ref);
11858     PERL_UNUSED_VAR(ix);
11859     exception=AcquireExceptionInfo();
11860     perl_exception=newSVpv("",0);
11861     if (items == 1)
11862       {
11863         const TypeInfo
11864           **typelist;
11865
11866         size_t
11867           types;
11868
11869         typelist=GetTypeInfoList("*",&types,exception);
11870         EXTEND(sp,types);
11871         for (i=0; i < (ssize_t) types; i++)
11872         {
11873           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
11874         }
11875         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
11876           typelist);
11877         goto PerlException;
11878       }
11879     EXTEND(sp,10*items);
11880     for (i=1; i < items; i++)
11881     {
11882       name=(char *) SvPV(ST(i),na);
11883       type_info=GetTypeInfo(name,exception);
11884       if (type_info == (TypeInfo *) NULL)
11885         {
11886           PUSHs(&sv_undef);
11887           continue;
11888         }
11889       if (type_info->name == (char *) NULL)
11890         PUSHs(&sv_undef);
11891       else
11892         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
11893       if (type_info->description == (char *) NULL)
11894         PUSHs(&sv_undef);
11895       else
11896         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
11897       if (type_info->family == (char *) NULL)
11898         PUSHs(&sv_undef);
11899       else
11900         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
11901       if (type_info->style == UndefinedStyle)
11902         PUSHs(&sv_undef);
11903       else
11904         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
11905           type_info->style),0)));
11906       if (type_info->stretch == UndefinedStretch)
11907         PUSHs(&sv_undef);
11908       else
11909         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
11910           type_info->stretch),0)));
11911       (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
11912         type_info->weight);
11913       PUSHs(sv_2mortal(newSVpv(message,0)));
11914       if (type_info->encoding == (char *) NULL)
11915         PUSHs(&sv_undef);
11916       else
11917         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
11918       if (type_info->foundry == (char *) NULL)
11919         PUSHs(&sv_undef);
11920       else
11921         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
11922       if (type_info->format == (char *) NULL)
11923         PUSHs(&sv_undef);
11924       else
11925         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
11926       if (type_info->metrics == (char *) NULL)
11927         PUSHs(&sv_undef);
11928       else
11929         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
11930       if (type_info->glyphs == (char *) NULL)
11931         PUSHs(&sv_undef);
11932       else
11933         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
11934     }
11935
11936   PerlException:
11937     InheritPerlException(exception,perl_exception);
11938     exception=DestroyExceptionInfo(exception);
11939     SvREFCNT_dec(perl_exception);
11940   }
11941 \f
11942 #
11943 ###############################################################################
11944 #                                                                             #
11945 #                                                                             #
11946 #                                                                             #
11947 #   Q u e r y F o n t M e t r i c s                                           #
11948 #                                                                             #
11949 #                                                                             #
11950 #                                                                             #
11951 ###############################################################################
11952 #
11953 #
11954 void
11955 QueryFontMetrics(ref,...)
11956   Image::Magick ref=NO_INIT
11957   ALIAS:
11958     queryfontmetrics = 1
11959   PPCODE:
11960   {
11961     AffineMatrix
11962       affine,
11963       current;
11964
11965     AV
11966       *av;
11967
11968     char
11969       *attribute;
11970
11971     double
11972       x,
11973       y;
11974
11975     DrawInfo
11976       *draw_info;
11977
11978     ExceptionInfo
11979       *exception;
11980
11981     GeometryInfo
11982       geometry_info;
11983
11984     Image
11985       *image;
11986
11987     MagickBooleanType
11988       status;
11989
11990     MagickStatusType
11991       flags;
11992
11993     register ssize_t
11994       i;
11995
11996     ssize_t
11997       type;
11998
11999     struct PackageInfo
12000       *info,
12001       *package_info;
12002
12003     SV
12004       *perl_exception,
12005       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12006
12007     TypeMetric
12008       metrics;
12009
12010     PERL_UNUSED_VAR(ref);
12011     PERL_UNUSED_VAR(ix);
12012     exception=AcquireExceptionInfo();
12013     package_info=(struct PackageInfo *) NULL;
12014     perl_exception=newSVpv("",0);
12015     reference=SvRV(ST(0));
12016     av=(AV *) reference;
12017     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12018       exception);
12019     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12020     if (image == (Image *) NULL)
12021       {
12022         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12023           PackageName);
12024         goto PerlException;
12025       }
12026     package_info=ClonePackageInfo(info,exception);
12027     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12028     CloneString(&draw_info->text,"");
12029     current=draw_info->affine;
12030     GetAffineMatrix(&affine);
12031     x=0.0;
12032     y=0.0;
12033     EXTEND(sp,7*items);
12034     for (i=2; i < items; i+=2)
12035     {
12036       attribute=(char *) SvPV(ST(i-1),na);
12037       switch (*attribute)
12038       {
12039         case 'A':
12040         case 'a':
12041         {
12042           if (LocaleCompare(attribute,"antialias") == 0)
12043             {
12044               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12045                 SvPV(ST(i),na));
12046               if (type < 0)
12047                 {
12048                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12049                     SvPV(ST(i),na));
12050                   break;
12051                 }
12052               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12053               break;
12054             }
12055           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12056             attribute);
12057           break;
12058         }
12059         case 'd':
12060         case 'D':
12061         {
12062           if (LocaleCompare(attribute,"density") == 0)
12063             {
12064               CloneString(&draw_info->density,SvPV(ST(i),na));
12065               break;
12066             }
12067           if (LocaleCompare(attribute,"direction") == 0)
12068             {
12069               draw_info->direction=(DirectionType) ParseCommandOption(
12070                 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12071               break;
12072             }
12073           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12074             attribute);
12075           break;
12076         }
12077         case 'e':
12078         case 'E':
12079         {
12080           if (LocaleCompare(attribute,"encoding") == 0)
12081             {
12082               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12083               break;
12084             }
12085           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12086             attribute);
12087           break;
12088         }
12089         case 'f':
12090         case 'F':
12091         {
12092           if (LocaleCompare(attribute,"family") == 0)
12093             {
12094               CloneString(&draw_info->family,SvPV(ST(i),na));
12095               break;
12096             }
12097           if (LocaleCompare(attribute,"fill") == 0)
12098             {
12099               if (info)
12100                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->fill,
12101                   &image->exception);
12102               break;
12103             }
12104           if (LocaleCompare(attribute,"font") == 0)
12105             {
12106               CloneString(&draw_info->font,SvPV(ST(i),na));
12107               break;
12108             }
12109           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12110             attribute);
12111           break;
12112         }
12113         case 'g':
12114         case 'G':
12115         {
12116           if (LocaleCompare(attribute,"geometry") == 0)
12117             {
12118               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12119               break;
12120             }
12121           if (LocaleCompare(attribute,"gravity") == 0)
12122             {
12123               draw_info->gravity=(GravityType) ParseCommandOption(
12124                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12125               break;
12126             }
12127           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12128             attribute);
12129           break;
12130         }
12131         case 'i':
12132         case 'I':
12133         {
12134           if (LocaleCompare(attribute,"interline-spacing") == 0)
12135             {
12136               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12137               draw_info->interline_spacing=geometry_info.rho;
12138               break;
12139             }
12140           if (LocaleCompare(attribute,"interword-spacing") == 0)
12141             {
12142               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12143               draw_info->interword_spacing=geometry_info.rho;
12144               break;
12145             }
12146           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12147             attribute);
12148           break;
12149         }
12150         case 'k':
12151         case 'K':
12152         {
12153           if (LocaleCompare(attribute,"kerning") == 0)
12154             {
12155               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12156               draw_info->kerning=geometry_info.rho;
12157               break;
12158             }
12159           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12160             attribute);
12161           break;
12162         }
12163         case 'p':
12164         case 'P':
12165         {
12166           if (LocaleCompare(attribute,"pointsize") == 0)
12167             {
12168               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12169               draw_info->pointsize=geometry_info.rho;
12170               break;
12171             }
12172           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12173             attribute);
12174           break;
12175         }
12176         case 'r':
12177         case 'R':
12178         {
12179           if (LocaleCompare(attribute,"rotate") == 0)
12180             {
12181               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12182               affine.rx=geometry_info.rho;
12183               affine.ry=geometry_info.sigma;
12184               if ((flags & SigmaValue) == 0)
12185                 affine.ry=affine.rx;
12186               break;
12187             }
12188           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12189             attribute);
12190           break;
12191         }
12192         case 's':
12193         case 'S':
12194         {
12195           if (LocaleCompare(attribute,"scale") == 0)
12196             {
12197               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12198               affine.sx=geometry_info.rho;
12199               affine.sy=geometry_info.sigma;
12200               if ((flags & SigmaValue) == 0)
12201                 affine.sy=affine.sx;
12202               break;
12203             }
12204           if (LocaleCompare(attribute,"skew") == 0)
12205             {
12206               double
12207                 x_angle,
12208                 y_angle;
12209
12210               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12211               x_angle=geometry_info.rho;
12212               y_angle=geometry_info.sigma;
12213               if ((flags & SigmaValue) == 0)
12214                 y_angle=x_angle;
12215               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12216               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12217               break;
12218             }
12219           if (LocaleCompare(attribute,"stroke") == 0)
12220             {
12221               if (info)
12222                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->stroke,
12223                   &image->exception);
12224               break;
12225             }
12226           if (LocaleCompare(attribute,"style") == 0)
12227             {
12228               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12229                 SvPV(ST(i),na));
12230               if (type < 0)
12231                 {
12232                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12233                     SvPV(ST(i),na));
12234                   break;
12235                 }
12236               draw_info->style=(StyleType) type;
12237               break;
12238             }
12239           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12240             attribute);
12241           break;
12242         }
12243         case 't':
12244         case 'T':
12245         {
12246           if (LocaleCompare(attribute,"text") == 0)
12247             {
12248               CloneString(&draw_info->text,SvPV(ST(i),na));
12249               break;
12250             }
12251           if (LocaleCompare(attribute,"translate") == 0)
12252             {
12253               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12254               affine.tx=geometry_info.rho;
12255               affine.ty=geometry_info.sigma;
12256               if ((flags & SigmaValue) == 0)
12257                 affine.ty=affine.tx;
12258               break;
12259             }
12260           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12261             attribute);
12262           break;
12263         }
12264         case 'w':
12265         case 'W':
12266         {
12267           if (LocaleCompare(attribute,"weight") == 0)
12268             {
12269               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12270               draw_info->weight=(size_t) geometry_info.rho;
12271               break;
12272             }
12273           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12274             attribute);
12275           break;
12276         }
12277         case 'x':
12278         case 'X':
12279         {
12280           if (LocaleCompare(attribute,"x") == 0)
12281             {
12282               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12283               x=geometry_info.rho;
12284               break;
12285             }
12286           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12287             attribute);
12288           break;
12289         }
12290         case 'y':
12291         case 'Y':
12292         {
12293           if (LocaleCompare(attribute,"y") == 0)
12294             {
12295               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12296               y=geometry_info.rho;
12297               break;
12298             }
12299           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12300             attribute);
12301           break;
12302         }
12303         default:
12304         {
12305           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12306             attribute);
12307           break;
12308         }
12309       }
12310     }
12311     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12312     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12313     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12314     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12315     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12316     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12317     if (draw_info->geometry == (char *) NULL)
12318       {
12319         draw_info->geometry=AcquireString((char *) NULL);
12320         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12321           "%.15g,%.15g",x,y);
12322       }
12323     status=GetTypeMetrics(image,draw_info,&metrics);
12324     (void) CatchImageException(image);
12325     if (status == MagickFalse)
12326       PUSHs(&sv_undef);
12327     else
12328       {
12329         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12330         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12331         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12332         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12333         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12334         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12335         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12336         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12337         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12338         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12339         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12340         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12341         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12342       }
12343     draw_info=DestroyDrawInfo(draw_info);
12344
12345   PerlException:
12346     if (package_info != (struct PackageInfo *) NULL)
12347       DestroyPackageInfo(package_info);
12348     InheritPerlException(exception,perl_exception);
12349     exception=DestroyExceptionInfo(exception);
12350     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12351   }
12352 \f
12353 #
12354 ###############################################################################
12355 #                                                                             #
12356 #                                                                             #
12357 #                                                                             #
12358 #   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                         #
12359 #                                                                             #
12360 #                                                                             #
12361 #                                                                             #
12362 ###############################################################################
12363 #
12364 #
12365 void
12366 QueryMultilineFontMetrics(ref,...)
12367   Image::Magick ref=NO_INIT
12368   ALIAS:
12369     querymultilinefontmetrics = 1
12370   PPCODE:
12371   {
12372     AffineMatrix
12373       affine,
12374       current;
12375
12376     AV
12377       *av;
12378
12379     char
12380       *attribute;
12381
12382     double
12383       x,
12384       y;
12385
12386     DrawInfo
12387       *draw_info;
12388
12389     ExceptionInfo
12390       *exception;
12391
12392     GeometryInfo
12393       geometry_info;
12394
12395     Image
12396       *image;
12397
12398     MagickBooleanType
12399       status;
12400
12401     MagickStatusType
12402       flags;
12403
12404     register ssize_t
12405       i;
12406
12407     ssize_t
12408       type;
12409
12410     struct PackageInfo
12411       *info,
12412       *package_info;
12413
12414     SV
12415       *perl_exception,
12416       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12417
12418     TypeMetric
12419       metrics;
12420
12421     PERL_UNUSED_VAR(ref);
12422     PERL_UNUSED_VAR(ix);
12423     exception=AcquireExceptionInfo();
12424     package_info=(struct PackageInfo *) NULL;
12425     perl_exception=newSVpv("",0);
12426     reference=SvRV(ST(0));
12427     av=(AV *) reference;
12428     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12429       exception);
12430     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12431     if (image == (Image *) NULL)
12432       {
12433         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12434           PackageName);
12435         goto PerlException;
12436       }
12437     package_info=ClonePackageInfo(info,exception);
12438     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12439     CloneString(&draw_info->text,"");
12440     current=draw_info->affine;
12441     GetAffineMatrix(&affine);
12442     x=0.0;
12443     y=0.0;
12444     EXTEND(sp,7*items);
12445     for (i=2; i < items; i+=2)
12446     {
12447       attribute=(char *) SvPV(ST(i-1),na);
12448       switch (*attribute)
12449       {
12450         case 'A':
12451         case 'a':
12452         {
12453           if (LocaleCompare(attribute,"antialias") == 0)
12454             {
12455               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12456                 SvPV(ST(i),na));
12457               if (type < 0)
12458                 {
12459                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12460                     SvPV(ST(i),na));
12461                   break;
12462                 }
12463               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12464               break;
12465             }
12466           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12467             attribute);
12468           break;
12469         }
12470         case 'd':
12471         case 'D':
12472         {
12473           if (LocaleCompare(attribute,"density") == 0)
12474             {
12475               CloneString(&draw_info->density,SvPV(ST(i),na));
12476               break;
12477             }
12478           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12479             attribute);
12480           break;
12481         }
12482         case 'e':
12483         case 'E':
12484         {
12485           if (LocaleCompare(attribute,"encoding") == 0)
12486             {
12487               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12488               break;
12489             }
12490           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12491             attribute);
12492           break;
12493         }
12494         case 'f':
12495         case 'F':
12496         {
12497           if (LocaleCompare(attribute,"family") == 0)
12498             {
12499               CloneString(&draw_info->family,SvPV(ST(i),na));
12500               break;
12501             }
12502           if (LocaleCompare(attribute,"fill") == 0)
12503             {
12504               if (info)
12505                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->fill,
12506                   &image->exception);
12507               break;
12508             }
12509           if (LocaleCompare(attribute,"font") == 0)
12510             {
12511               CloneString(&draw_info->font,SvPV(ST(i),na));
12512               break;
12513             }
12514           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12515             attribute);
12516           break;
12517         }
12518         case 'g':
12519         case 'G':
12520         {
12521           if (LocaleCompare(attribute,"geometry") == 0)
12522             {
12523               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12524               break;
12525             }
12526           if (LocaleCompare(attribute,"gravity") == 0)
12527             {
12528               draw_info->gravity=(GravityType) ParseCommandOption(
12529                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12530               break;
12531             }
12532           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12533             attribute);
12534           break;
12535         }
12536         case 'p':
12537         case 'P':
12538         {
12539           if (LocaleCompare(attribute,"pointsize") == 0)
12540             {
12541               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12542               draw_info->pointsize=geometry_info.rho;
12543               break;
12544             }
12545           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12546             attribute);
12547           break;
12548         }
12549         case 'r':
12550         case 'R':
12551         {
12552           if (LocaleCompare(attribute,"rotate") == 0)
12553             {
12554               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12555               affine.rx=geometry_info.rho;
12556               affine.ry=geometry_info.sigma;
12557               if ((flags & SigmaValue) == 0)
12558                 affine.ry=affine.rx;
12559               break;
12560             }
12561           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12562             attribute);
12563           break;
12564         }
12565         case 's':
12566         case 'S':
12567         {
12568           if (LocaleCompare(attribute,"scale") == 0)
12569             {
12570               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12571               affine.sx=geometry_info.rho;
12572               affine.sy=geometry_info.sigma;
12573               if ((flags & SigmaValue) == 0)
12574                 affine.sy=affine.sx;
12575               break;
12576             }
12577           if (LocaleCompare(attribute,"skew") == 0)
12578             {
12579               double
12580                 x_angle,
12581                 y_angle;
12582
12583               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12584               x_angle=geometry_info.rho;
12585               y_angle=geometry_info.sigma;
12586               if ((flags & SigmaValue) == 0)
12587                 y_angle=x_angle;
12588               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12589               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12590               break;
12591             }
12592           if (LocaleCompare(attribute,"stroke") == 0)
12593             {
12594               if (info)
12595                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->stroke,
12596                   &image->exception);
12597               break;
12598             }
12599           if (LocaleCompare(attribute,"style") == 0)
12600             {
12601               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12602                 SvPV(ST(i),na));
12603               if (type < 0)
12604                 {
12605                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12606                     SvPV(ST(i),na));
12607                   break;
12608                 }
12609               draw_info->style=(StyleType) type;
12610               break;
12611             }
12612           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12613             attribute);
12614           break;
12615         }
12616         case 't':
12617         case 'T':
12618         {
12619           if (LocaleCompare(attribute,"text") == 0)
12620             {
12621               CloneString(&draw_info->text,SvPV(ST(i),na));
12622               break;
12623             }
12624           if (LocaleCompare(attribute,"translate") == 0)
12625             {
12626               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12627               affine.tx=geometry_info.rho;
12628               affine.ty=geometry_info.sigma;
12629               if ((flags & SigmaValue) == 0)
12630                 affine.ty=affine.tx;
12631               break;
12632             }
12633           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12634             attribute);
12635           break;
12636         }
12637         case 'w':
12638         case 'W':
12639         {
12640           if (LocaleCompare(attribute,"weight") == 0)
12641             {
12642               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12643               draw_info->weight=(size_t) geometry_info.rho;
12644               break;
12645             }
12646           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12647             attribute);
12648           break;
12649         }
12650         case 'x':
12651         case 'X':
12652         {
12653           if (LocaleCompare(attribute,"x") == 0)
12654             {
12655               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12656               x=geometry_info.rho;
12657               break;
12658             }
12659           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12660             attribute);
12661           break;
12662         }
12663         case 'y':
12664         case 'Y':
12665         {
12666           if (LocaleCompare(attribute,"y") == 0)
12667             {
12668               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12669               y=geometry_info.rho;
12670               break;
12671             }
12672           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12673             attribute);
12674           break;
12675         }
12676         default:
12677         {
12678           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12679             attribute);
12680           break;
12681         }
12682       }
12683     }
12684     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12685     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12686     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12687     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12688     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12689     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12690     if (draw_info->geometry == (char *) NULL)
12691       {
12692         draw_info->geometry=AcquireString((char *) NULL);
12693         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12694           "%.15g,%.15g",x,y);
12695       }
12696     status=GetMultilineTypeMetrics(image,draw_info,&metrics);
12697     (void) CatchImageException(image);
12698     if (status == MagickFalse)
12699       PUSHs(&sv_undef);
12700     else
12701       {
12702         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12703         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12704         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12705         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12706         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12707         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12708         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12709         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12710         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12711         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12712         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12713         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12714         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12715       }
12716     draw_info=DestroyDrawInfo(draw_info);
12717
12718   PerlException:
12719     if (package_info != (struct PackageInfo *) NULL)
12720       DestroyPackageInfo(package_info);
12721     InheritPerlException(exception,perl_exception);
12722     exception=DestroyExceptionInfo(exception);
12723     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12724   }
12725 \f
12726 #
12727 ###############################################################################
12728 #                                                                             #
12729 #                                                                             #
12730 #                                                                             #
12731 #   Q u e r y F o r m a t                                                     #
12732 #                                                                             #
12733 #                                                                             #
12734 #                                                                             #
12735 ###############################################################################
12736 #
12737 #
12738 void
12739 QueryFormat(ref,...)
12740   Image::Magick ref=NO_INIT
12741   ALIAS:
12742     queryformat = 1
12743   PPCODE:
12744   {
12745     char
12746       *name;
12747
12748     ExceptionInfo
12749       *exception;
12750
12751     register ssize_t
12752       i;
12753
12754     SV
12755       *perl_exception;
12756
12757     volatile const MagickInfo
12758       *magick_info;
12759
12760     PERL_UNUSED_VAR(ref);
12761     PERL_UNUSED_VAR(ix);
12762     exception=AcquireExceptionInfo();
12763     perl_exception=newSVpv("",0);
12764     if (items == 1)
12765       {
12766         char
12767           format[MaxTextExtent];
12768
12769         const MagickInfo
12770           **format_list;
12771
12772         size_t
12773           types;
12774
12775         format_list=GetMagickInfoList("*",&types,exception);
12776         EXTEND(sp,types);
12777         for (i=0; i < (ssize_t) types; i++)
12778         {
12779           (void) CopyMagickString(format,format_list[i]->name,MaxTextExtent);
12780           LocaleLower(format);
12781           PUSHs(sv_2mortal(newSVpv(format,0)));
12782         }
12783         format_list=(const MagickInfo **)
12784           RelinquishMagickMemory((MagickInfo *) format_list);
12785         goto PerlException;
12786       }
12787     EXTEND(sp,8*items);
12788     for (i=1; i < items; i++)
12789     {
12790       name=(char *) SvPV(ST(i),na);
12791       magick_info=GetMagickInfo(name,exception);
12792       if (magick_info == (const MagickInfo *) NULL)
12793         {
12794           PUSHs(&sv_undef);
12795           continue;
12796         }
12797       PUSHs(sv_2mortal(newSViv(magick_info->adjoin)));
12798       PUSHs(sv_2mortal(newSViv(magick_info->blob_support)));
12799       PUSHs(sv_2mortal(newSViv(magick_info->raw)));
12800       PUSHs(sv_2mortal(newSViv((long) magick_info->decoder)));
12801       PUSHs(sv_2mortal(newSViv((long) magick_info->encoder)));
12802       if (magick_info->description == (char *) NULL)
12803         PUSHs(&sv_undef);
12804       else
12805         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
12806       if (magick_info->module == (char *) NULL)
12807         PUSHs(&sv_undef);
12808       else
12809         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
12810     }
12811
12812   PerlException:
12813     InheritPerlException(exception,perl_exception);
12814     exception=DestroyExceptionInfo(exception);
12815     SvREFCNT_dec(perl_exception);
12816   }
12817 \f
12818 #
12819 ###############################################################################
12820 #                                                                             #
12821 #                                                                             #
12822 #                                                                             #
12823 #   Q u e r y O p t i o n                                                     #
12824 #                                                                             #
12825 #                                                                             #
12826 #                                                                             #
12827 ###############################################################################
12828 #
12829 #
12830 void
12831 QueryOption(ref,...)
12832   Image::Magick ref=NO_INIT
12833   ALIAS:
12834     queryoption = 1
12835   PPCODE:
12836   {
12837     char
12838       **options;
12839
12840     ExceptionInfo
12841       *exception;
12842
12843     register ssize_t
12844       i;
12845
12846     ssize_t
12847       j,
12848       option;
12849
12850     SV
12851       *perl_exception;
12852
12853     PERL_UNUSED_VAR(ref);
12854     PERL_UNUSED_VAR(ix);
12855     exception=AcquireExceptionInfo();
12856     perl_exception=newSVpv("",0);
12857     EXTEND(sp,8*items);
12858     for (i=1; i < items; i++)
12859     {
12860       option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
12861         SvPV(ST(i),na));
12862       options=GetCommandOptions((CommandOption) option);
12863       if (options == (char **) NULL)
12864         PUSHs(&sv_undef);
12865       else
12866         {
12867           for (j=0; options[j] != (char *) NULL; j++)
12868             PUSHs(sv_2mortal(newSVpv(options[j],0)));
12869           options=DestroyStringList(options);
12870         }
12871     }
12872
12873     InheritPerlException(exception,perl_exception);
12874     exception=DestroyExceptionInfo(exception);
12875     SvREFCNT_dec(perl_exception);
12876   }
12877 \f
12878 #
12879 ###############################################################################
12880 #                                                                             #
12881 #                                                                             #
12882 #                                                                             #
12883 #   R e a d                                                                   #
12884 #                                                                             #
12885 #                                                                             #
12886 #                                                                             #
12887 ###############################################################################
12888 #
12889 #
12890 void
12891 Read(ref,...)
12892   Image::Magick ref=NO_INIT
12893   ALIAS:
12894     ReadImage  = 1
12895     read       = 2
12896     readimage  = 3
12897   PPCODE:
12898   {
12899     AV
12900       *av;
12901
12902     char
12903       **keep,
12904       **list;
12905
12906     ExceptionInfo
12907       *exception;
12908
12909     HV
12910       *hv;
12911
12912     Image
12913       *image;
12914
12915     int
12916       n;
12917
12918     MagickBooleanType
12919       status;
12920
12921     register char
12922       **p;
12923
12924     register ssize_t
12925       i;
12926
12927     ssize_t
12928       ac,
12929       number_images;
12930
12931     STRLEN
12932       *length;
12933
12934     struct PackageInfo
12935       *info,
12936       *package_info;
12937
12938     SV
12939       *perl_exception,  /* Perl variable for storing messages */
12940       *reference,
12941       *rv,
12942       *sv;
12943
12944     PERL_UNUSED_VAR(ref);
12945     PERL_UNUSED_VAR(ix);
12946     exception=AcquireExceptionInfo();
12947     perl_exception=newSVpv("",0);
12948     sv=NULL;
12949     package_info=(struct PackageInfo *) NULL;
12950     number_images=0;
12951     ac=(items < 2) ? 1 : items-1;
12952     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
12953     keep=list;
12954     length=(STRLEN *) NULL;
12955     if (list == (char **) NULL)
12956       {
12957         ThrowPerlException(exception,ResourceLimitError,
12958           "MemoryAllocationFailed",PackageName);
12959         goto PerlException;
12960       }
12961     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
12962     if (length == (STRLEN *) NULL)
12963       {
12964         ThrowPerlException(exception,ResourceLimitError,
12965           "MemoryAllocationFailed",PackageName);
12966         goto PerlException;
12967       }
12968     if (sv_isobject(ST(0)) == 0)
12969       {
12970         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12971           PackageName);
12972         goto PerlException;
12973       }
12974     reference=SvRV(ST(0));
12975     hv=SvSTASH(reference);
12976     if (SvTYPE(reference) != SVt_PVAV)
12977       {
12978         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12979           PackageName);
12980         goto PerlException;
12981       }
12982     av=(AV *) reference;
12983     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12984       exception);
12985     package_info=ClonePackageInfo(info,exception);
12986     n=1;
12987     if (items <= 1)
12988       *list=(char *) (*package_info->image_info->filename ?
12989         package_info->image_info->filename : "XC:black");
12990     else
12991       for (n=0, i=0; i < ac; i++)
12992       {
12993         list[n]=(char *) SvPV(ST(i+1),length[n]);
12994         if ((items >= 3) && strEQcase(list[n],"blob"))
12995           {
12996             void
12997               *blob;
12998
12999             i++;
13000             blob=(void *) (SvPV(ST(i+1),length[n]));
13001             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13002           }
13003         if ((items >= 3) && strEQcase(list[n],"filename"))
13004           continue;
13005         if ((items >= 3) && strEQcase(list[n],"file"))
13006           {
13007             FILE
13008               *file;
13009
13010             PerlIO
13011               *io_info;
13012
13013             i++;
13014             io_info=IoIFP(sv_2io(ST(i+1)));
13015             if (io_info == (PerlIO *) NULL)
13016               {
13017                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13018                   PackageName);
13019                 continue;
13020               }
13021             file=PerlIO_findFILE(io_info);
13022             if (file == (FILE *) NULL)
13023               {
13024                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13025                   PackageName);
13026                 continue;
13027               }
13028             SetImageInfoFile(package_info->image_info,file);
13029           }
13030         if ((items >= 3) && strEQcase(list[n],"magick"))
13031           continue;
13032         n++;
13033       }
13034     list[n]=(char *) NULL;
13035     keep=list;
13036     status=ExpandFilenames(&n,&list);
13037     if (status == MagickFalse)
13038       {
13039         ThrowPerlException(exception,ResourceLimitError,
13040           "MemoryAllocationFailed",PackageName);
13041         goto PerlException;
13042       }
13043     number_images=0;
13044     for (i=0; i < n; i++)
13045     {
13046       if ((package_info->image_info->file != (FILE *) NULL) ||
13047           (package_info->image_info->blob != (void *) NULL))
13048         {
13049           image=ReadImages(package_info->image_info,exception);
13050           if (image != (Image *) NULL)
13051             DisassociateImageStream(image);
13052         }
13053       else
13054         {
13055           (void) CopyMagickString(package_info->image_info->filename,list[i],
13056             MaxTextExtent);
13057           image=ReadImages(package_info->image_info,exception);
13058         }
13059       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
13060         break;
13061       for ( ; image; image=image->next)
13062       {
13063         AddImageToRegistry(sv,image);
13064         rv=newRV(sv);
13065         av_push(av,sv_bless(rv,hv));
13066         SvREFCNT_dec(sv);
13067         number_images++;
13068       }
13069     }
13070     /*
13071       Free resources.
13072     */
13073     for (i=0; i < n; i++)
13074       if (list[i] != (char *) NULL)
13075         for (p=keep; list[i] != *p++; )
13076           if (*p == (char *) NULL)
13077             {
13078               list[i]=(char *) RelinquishMagickMemory(list[i]);
13079               break;
13080             }
13081
13082   PerlException:
13083     if (package_info != (struct PackageInfo *) NULL)
13084       DestroyPackageInfo(package_info);
13085     if (list && (list != keep))
13086       list=(char **) RelinquishMagickMemory(list);
13087     if (keep)
13088       keep=(char **) RelinquishMagickMemory(keep);
13089     if (length)
13090       length=(STRLEN *) RelinquishMagickMemory(length);
13091     InheritPerlException(exception,perl_exception);
13092     exception=DestroyExceptionInfo(exception);
13093     sv_setiv(perl_exception,(IV) number_images);
13094     SvPOK_on(perl_exception);
13095     ST(0)=sv_2mortal(perl_exception);
13096     XSRETURN(1);
13097   }
13098 \f
13099 #
13100 ###############################################################################
13101 #                                                                             #
13102 #                                                                             #
13103 #                                                                             #
13104 #   R e m o t e                                                               #
13105 #                                                                             #
13106 #                                                                             #
13107 #                                                                             #
13108 ###############################################################################
13109 #
13110 #
13111 void
13112 Remote(ref,...)
13113   Image::Magick ref=NO_INIT
13114   ALIAS:
13115     RemoteCommand  = 1
13116     remote         = 2
13117     remoteCommand  = 3
13118   PPCODE:
13119   {
13120     AV
13121       *av;
13122
13123     ExceptionInfo
13124       *exception;
13125
13126     register ssize_t
13127       i;
13128
13129     SV
13130       *perl_exception,
13131       *reference;
13132
13133     struct PackageInfo
13134       *info;
13135
13136     PERL_UNUSED_VAR(ref);
13137     PERL_UNUSED_VAR(ix);
13138     exception=AcquireExceptionInfo();
13139     perl_exception=newSVpv("",0);
13140     reference=SvRV(ST(0));
13141     av=(AV *) reference;
13142     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13143       exception);
13144     for (i=1; i < items; i++)
13145       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13146         SvPV(ST(i),na),exception);
13147     InheritPerlException(exception,perl_exception);
13148     exception=DestroyExceptionInfo(exception);
13149     SvREFCNT_dec(perl_exception);    /* throw away all errors */
13150   }
13151 \f
13152 #
13153 ###############################################################################
13154 #                                                                             #
13155 #                                                                             #
13156 #                                                                             #
13157 #   S e t                                                                     #
13158 #                                                                             #
13159 #                                                                             #
13160 #                                                                             #
13161 ###############################################################################
13162 #
13163 #
13164 void
13165 Set(ref,...)
13166   Image::Magick ref=NO_INIT
13167   ALIAS:
13168     SetAttributes  = 1
13169     SetAttribute   = 2
13170     set            = 3
13171     setattributes  = 4
13172     setattribute   = 5
13173   PPCODE:
13174   {
13175     ExceptionInfo
13176       *exception;
13177
13178     Image
13179       *image;
13180
13181     register ssize_t
13182       i;
13183
13184     struct PackageInfo
13185       *info;
13186
13187     SV
13188       *perl_exception,
13189       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13190
13191     PERL_UNUSED_VAR(ref);
13192     PERL_UNUSED_VAR(ix);
13193     exception=AcquireExceptionInfo();
13194     perl_exception=newSVpv("",0);
13195     if (sv_isobject(ST(0)) == 0)
13196       {
13197         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13198           PackageName);
13199         goto PerlException;
13200       }
13201     reference=SvRV(ST(0));
13202     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13203     if (items == 2)
13204       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13205     else
13206       for (i=2; i < items; i+=2)
13207         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13208
13209   PerlException:
13210     InheritPerlException(exception,perl_exception);
13211     exception=DestroyExceptionInfo(exception);
13212     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13213     SvPOK_on(perl_exception);
13214     ST(0)=sv_2mortal(perl_exception);
13215     XSRETURN(1);
13216   }
13217 \f
13218 #
13219 ###############################################################################
13220 #                                                                             #
13221 #                                                                             #
13222 #                                                                             #
13223 #   S e t P i x e l                                                           #
13224 #                                                                             #
13225 #                                                                             #
13226 #                                                                             #
13227 ###############################################################################
13228 #
13229 #
13230 void
13231 SetPixel(ref,...)
13232   Image::Magick ref=NO_INIT
13233   ALIAS:
13234     setpixel = 1
13235     setPixel = 2
13236   PPCODE:
13237   {
13238     AV
13239       *av;
13240
13241     char
13242       *attribute;
13243
13244     ChannelType
13245       channel,
13246       channel_mask;
13247
13248     ExceptionInfo
13249       *exception;
13250
13251     Image
13252       *image;
13253
13254     MagickBooleanType
13255       normalize;
13256
13257     RectangleInfo
13258       region;
13259
13260     register ssize_t
13261       i;
13262
13263     register Quantum
13264       *q;
13265
13266     ssize_t
13267       option;
13268
13269     struct PackageInfo
13270       *info;
13271
13272     SV
13273       *perl_exception,
13274       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13275
13276     PERL_UNUSED_VAR(ref);
13277     PERL_UNUSED_VAR(ix);
13278     exception=AcquireExceptionInfo();
13279     perl_exception=newSVpv("",0);
13280     reference=SvRV(ST(0));
13281     av=(AV *) reference;
13282     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13283       exception);
13284     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13285     if (image == (Image *) NULL)
13286       {
13287         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13288           PackageName);
13289         goto PerlException;
13290       }
13291     av=(AV *) NULL;
13292     normalize=MagickTrue;
13293     region.x=0;
13294     region.y=0;
13295     region.width=image->columns;
13296     region.height=1;
13297     if (items == 1)
13298       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13299     channel=DefaultChannels;
13300     for (i=2; i < items; i+=2)
13301     {
13302       attribute=(char *) SvPV(ST(i-1),na);
13303       switch (*attribute)
13304       {
13305         case 'C':
13306         case 'c':
13307         {
13308           if (LocaleCompare(attribute,"channel") == 0)
13309             {
13310               ssize_t
13311                 option;
13312
13313               option=ParseChannelOption(SvPV(ST(i),na));
13314               if (option < 0)
13315                 {
13316                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13317                     SvPV(ST(i),na));
13318                   return;
13319                 }
13320               channel=(ChannelType) option;
13321               break;
13322             }
13323           if (LocaleCompare(attribute,"color") == 0)
13324             {
13325               if (SvTYPE(ST(i)) != SVt_RV)
13326                 {
13327                   char
13328                     message[MaxTextExtent];
13329
13330                   (void) FormatLocaleString(message,MaxTextExtent,
13331                     "invalid %.60s value",attribute);
13332                   ThrowPerlException(exception,OptionError,message,
13333                     SvPV(ST(i),na));
13334                 }
13335               av=(AV *) SvRV(ST(i));
13336               break;
13337             }
13338           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13339             attribute);
13340           break;
13341         }
13342         case 'g':
13343         case 'G':
13344         {
13345           if (LocaleCompare(attribute,"geometry") == 0)
13346             {
13347               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
13348               break;
13349             }
13350           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13351             attribute);
13352           break;
13353         }
13354         case 'N':
13355         case 'n':
13356         {
13357           if (LocaleCompare(attribute,"normalize") == 0)
13358             {
13359               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13360                 SvPV(ST(i),na));
13361               if (option < 0)
13362                 {
13363                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13364                     SvPV(ST(i),na));
13365                   break;
13366                 }
13367              normalize=option != 0 ? MagickTrue : MagickFalse;
13368              break;
13369             }
13370           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13371             attribute);
13372           break;
13373         }
13374         case 'x':
13375         case 'X':
13376         {
13377           if (LocaleCompare(attribute,"x") == 0)
13378             {
13379               region.x=SvIV(ST(i));
13380               break;
13381             }
13382           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13383             attribute);
13384           break;
13385         }
13386         case 'y':
13387         case 'Y':
13388         {
13389           if (LocaleCompare(attribute,"y") == 0)
13390             {
13391               region.y=SvIV(ST(i));
13392               break;
13393             }
13394           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13395             attribute);
13396           break;
13397         }
13398         default:
13399         {
13400           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13401             attribute);
13402           break;
13403         }
13404       }
13405     }
13406     (void) SetImageStorageClass(image,DirectClass,exception);
13407     channel_mask=SetPixelChannelMask(image,channel);
13408     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
13409     if ((q == (const Quantum *) NULL) || (av == (AV *) NULL) ||
13410         (SvTYPE(av) != SVt_PVAV))
13411       PUSHs(&sv_undef);
13412     else
13413       {
13414         double
13415           scale;
13416
13417         register ssize_t
13418           i;
13419
13420         i=0;
13421         scale=1.0;
13422         if (normalize != MagickFalse)
13423           scale=QuantumRange;
13424         if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
13425             (i <= av_len(av)))
13426           {
13427             SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
13428               av_fetch(av,i,0)))),q);
13429             i++;
13430           }
13431         if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
13432             (i <= av_len(av)))
13433           {
13434             SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
13435               av_fetch(av,i,0)))),q);
13436             i++;
13437           }
13438         if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
13439             (i <= av_len(av)))
13440           {
13441             SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
13442               av_fetch(av,i,0)))),q);
13443             i++;
13444           }
13445         if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
13446             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
13447           {
13448             SetPixelBlack(image,ClampToQuantum(scale*
13449               SvNV(*(av_fetch(av,i,0)))),q);
13450             i++;
13451           }
13452         if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
13453             (i <= av_len(av)))
13454           {
13455             SetPixelAlpha(image,ClampToQuantum(scale*
13456               SvNV(*(av_fetch(av,i,0)))),q);
13457             i++;
13458           }
13459         (void) SyncAuthenticPixels(image,exception);
13460       }
13461     (void) SetPixelChannelMask(image,channel_mask);
13462
13463   PerlException:
13464     InheritPerlException(exception,perl_exception);
13465     exception=DestroyExceptionInfo(exception);
13466     SvREFCNT_dec(perl_exception);
13467   }
13468 \f
13469 #
13470 ###############################################################################
13471 #                                                                             #
13472 #                                                                             #
13473 #                                                                             #
13474 #   S m u s h                                                                 #
13475 #                                                                             #
13476 #                                                                             #
13477 #                                                                             #
13478 ###############################################################################
13479 #
13480 #
13481 void
13482 Smush(ref,...)
13483   Image::Magick ref=NO_INIT
13484   ALIAS:
13485     SmushImage  = 1
13486     smush       = 2
13487     smushimage  = 3
13488   PPCODE:
13489   {
13490     AV
13491       *av;
13492
13493     char
13494       *attribute;
13495
13496     ExceptionInfo
13497       *exception;
13498
13499     HV
13500       *hv;
13501
13502     Image
13503       *image;
13504
13505     register ssize_t
13506       i;
13507
13508     ssize_t
13509       offset,
13510       stack;
13511
13512     struct PackageInfo
13513       *info;
13514
13515     SV
13516       *av_reference,
13517       *perl_exception,
13518       *reference,
13519       *rv,
13520       *sv;
13521
13522     PERL_UNUSED_VAR(ref);
13523     PERL_UNUSED_VAR(ix);
13524     exception=AcquireExceptionInfo();
13525     perl_exception=newSVpv("",0);
13526     sv=NULL;
13527     attribute=NULL;
13528     av=NULL;
13529     if (sv_isobject(ST(0)) == 0)
13530       {
13531         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13532           PackageName);
13533         goto PerlException;
13534       }
13535     reference=SvRV(ST(0));
13536     hv=SvSTASH(reference);
13537     av=newAV();
13538     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13539     SvREFCNT_dec(av);
13540     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13541     if (image == (Image *) NULL)
13542       {
13543         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13544           PackageName);
13545         goto PerlException;
13546       }
13547     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13548     /*
13549       Get options.
13550     */
13551     offset=0;
13552     stack=MagickTrue;
13553     for (i=2; i < items; i+=2)
13554     {
13555       attribute=(char *) SvPV(ST(i-1),na);
13556       switch (*attribute)
13557       {
13558         case 'O':
13559         case 'o':
13560         {
13561           if (LocaleCompare(attribute,"offset") == 0)
13562             {
13563               offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
13564               break;
13565             }
13566           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13567             attribute);
13568           break;
13569         }
13570         case 'S':
13571         case 's':
13572         {
13573           if (LocaleCompare(attribute,"stack") == 0)
13574             {
13575               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13576                 SvPV(ST(i),na));
13577               if (stack < 0)
13578                 {
13579                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13580                     SvPV(ST(i),na));
13581                   return;
13582                 }
13583               break;
13584             }
13585           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13586             attribute);
13587           break;
13588         }
13589         default:
13590         {
13591           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13592             attribute);
13593           break;
13594         }
13595       }
13596     }
13597     image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
13598       exception);
13599     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
13600       goto PerlException;
13601     for ( ; image; image=image->next)
13602     {
13603       AddImageToRegistry(sv,image);
13604       rv=newRV(sv);
13605       av_push(av,sv_bless(rv,hv));
13606       SvREFCNT_dec(sv);
13607     }
13608     exception=DestroyExceptionInfo(exception);
13609     ST(0)=av_reference;
13610     SvREFCNT_dec(perl_exception);
13611     XSRETURN(1);
13612
13613   PerlException:
13614     InheritPerlException(exception,perl_exception);
13615     exception=DestroyExceptionInfo(exception);
13616     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
13617     SvPOK_on(perl_exception);
13618     ST(0)=sv_2mortal(perl_exception);
13619     XSRETURN(1);
13620   }
13621 \f
13622 #
13623 ###############################################################################
13624 #                                                                             #
13625 #                                                                             #
13626 #                                                                             #
13627 #   S t a t i s t i c s                                                       #
13628 #                                                                             #
13629 #                                                                             #
13630 #                                                                             #
13631 ###############################################################################
13632 #
13633 #
13634 void
13635 Statistics(ref,...)
13636   Image::Magick ref=NO_INIT
13637   ALIAS:
13638     StatisticsImage = 1
13639     statistics      = 2
13640     statisticsimage = 3
13641   PPCODE:
13642   {
13643 #define ChannelStatistics(channel) \
13644 { \
13645   (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
13646     (double) channel_statistics[channel].depth); \
13647   PUSHs(sv_2mortal(newSVpv(message,0))); \
13648   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13649     channel_statistics[channel].minima/scale); \
13650   PUSHs(sv_2mortal(newSVpv(message,0))); \
13651   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13652     channel_statistics[channel].maxima/scale); \
13653   PUSHs(sv_2mortal(newSVpv(message,0))); \
13654   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13655     channel_statistics[channel].mean/scale); \
13656   PUSHs(sv_2mortal(newSVpv(message,0))); \
13657   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13658     channel_statistics[channel].standard_deviation/scale); \
13659   PUSHs(sv_2mortal(newSVpv(message,0))); \
13660   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13661     channel_statistics[channel].kurtosis); \
13662   PUSHs(sv_2mortal(newSVpv(message,0))); \
13663   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13664     channel_statistics[channel].skewness); \
13665   PUSHs(sv_2mortal(newSVpv(message,0))); \
13666 }
13667
13668     AV
13669       *av;
13670
13671     char
13672       message[MaxTextExtent];
13673
13674     ChannelStatistics
13675       *channel_statistics;
13676
13677     double
13678       scale;
13679
13680     ExceptionInfo
13681       *exception;
13682
13683     Image
13684       *image;
13685
13686     ssize_t
13687       count;
13688
13689     struct PackageInfo
13690       *info;
13691
13692     SV
13693       *perl_exception,
13694       *reference;
13695
13696     PERL_UNUSED_VAR(ref);
13697     PERL_UNUSED_VAR(ix);
13698     exception=AcquireExceptionInfo();
13699     perl_exception=newSVpv("",0);
13700     av=NULL;
13701     if (sv_isobject(ST(0)) == 0)
13702       {
13703         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13704           PackageName);
13705         goto PerlException;
13706       }
13707     reference=SvRV(ST(0));
13708     av=newAV();
13709     SvREFCNT_dec(av);
13710     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13711     if (image == (Image *) NULL)
13712       {
13713         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13714           PackageName);
13715         goto PerlException;
13716       }
13717     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13718     count=0;
13719     for ( ; image; image=image->next)
13720     {
13721       channel_statistics=GetImageStatistics(image,&image->exception);
13722       if (channel_statistics == (ChannelStatistics *) NULL)
13723         continue;
13724       count++;
13725       EXTEND(sp,35*count);
13726       scale=(double) QuantumRange;
13727       ChannelStatistics(RedChannel);
13728       ChannelStatistics(GreenChannel);
13729       ChannelStatistics(BlueChannel);
13730       if (image->colorspace == CMYKColorspace)
13731         ChannelStatistics(BlackChannel);
13732       if (image->matte != MagickFalse)
13733         ChannelStatistics(AlphaChannel);
13734       channel_statistics=(ChannelStatistics *)
13735         RelinquishMagickMemory(channel_statistics);
13736     }
13737
13738   PerlException:
13739     InheritPerlException(exception,perl_exception);
13740     exception=DestroyExceptionInfo(exception);
13741     SvREFCNT_dec(perl_exception);
13742   }
13743 \f
13744 #
13745 ###############################################################################
13746 #                                                                             #
13747 #                                                                             #
13748 #                                                                             #
13749 #   S y n c A u t h e n t i c P i x e l s                                     #
13750 #                                                                             #
13751 #                                                                             #
13752 #                                                                             #
13753 ###############################################################################
13754 #
13755 #
13756 void
13757 SyncAuthenticPixels(ref,...)
13758   Image::Magick ref = NO_INIT
13759   ALIAS:
13760     Syncauthenticpixels = 1
13761     SyncImagePixels = 2
13762     syncimagepixels = 3
13763   CODE:
13764   {
13765     ExceptionInfo
13766       *exception;
13767
13768     Image
13769       *image;
13770
13771     MagickBooleanType
13772       status;
13773
13774     struct PackageInfo
13775       *info;
13776
13777     SV
13778       *perl_exception,
13779       *reference;
13780
13781     PERL_UNUSED_VAR(ref);
13782     PERL_UNUSED_VAR(ix);
13783     exception=AcquireExceptionInfo();
13784     perl_exception=newSVpv("",0);
13785     if (sv_isobject(ST(0)) == 0)
13786       {
13787         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13788           PackageName);
13789         goto PerlException;
13790       }
13791
13792     reference=SvRV(ST(0));
13793     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13794     if (image == (Image *) NULL)
13795       {
13796         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13797           PackageName);
13798         goto PerlException;
13799       }
13800
13801     status=SyncAuthenticPixels(image,exception);
13802     if (status != MagickFalse)
13803       return;
13804     InheritException(exception,&image->exception);
13805
13806   PerlException:
13807     InheritPerlException(exception,perl_exception);
13808     exception=DestroyExceptionInfo(exception);
13809     SvREFCNT_dec(perl_exception);  /* throw away all errors */
13810   }
13811 \f
13812 #
13813 ###############################################################################
13814 #                                                                             #
13815 #                                                                             #
13816 #                                                                             #
13817 #   T r a n s f o r m                                                         #
13818 #                                                                             #
13819 #                                                                             #
13820 #                                                                             #
13821 ###############################################################################
13822 #
13823 #
13824 void
13825 Transform(ref,...)
13826   Image::Magick ref=NO_INIT
13827   ALIAS:
13828     TransformImage = 1
13829     transform      = 2
13830     transformimage = 3
13831   PPCODE:
13832   {
13833     AV
13834       *av;
13835
13836     char
13837       *attribute,
13838       *crop_geometry,
13839       *geometry;
13840
13841     ExceptionInfo
13842       *exception;
13843
13844     HV
13845       *hv;
13846
13847     Image
13848       *clone,
13849       *image;
13850
13851     register ssize_t
13852       i;
13853
13854     struct PackageInfo
13855       *info;
13856
13857     SV
13858       *av_reference,
13859       *perl_exception,
13860       *reference,
13861       *rv,
13862       *sv;
13863
13864     PERL_UNUSED_VAR(ref);
13865     PERL_UNUSED_VAR(ix);
13866     exception=AcquireExceptionInfo();
13867     perl_exception=newSVpv("",0);
13868     sv=NULL;
13869     av=NULL;
13870     attribute=NULL;
13871     if (sv_isobject(ST(0)) == 0)
13872       {
13873         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13874           PackageName);
13875         goto PerlException;
13876       }
13877     reference=SvRV(ST(0));
13878     hv=SvSTASH(reference);
13879     av=newAV();
13880     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13881     SvREFCNT_dec(av);
13882     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13883     if (image == (Image *) NULL)
13884       {
13885         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13886           PackageName);
13887         goto PerlException;
13888       }
13889     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13890     /*
13891       Get attribute.
13892     */
13893     crop_geometry=(char *) NULL;
13894     geometry=(char *) NULL;
13895     for (i=2; i < items; i+=2)
13896     {
13897       attribute=(char *) SvPV(ST(i-1),na);
13898       switch (*attribute)
13899       {
13900         case 'c':
13901         case 'C':
13902         {
13903           if (LocaleCompare(attribute,"crop") == 0)
13904             {
13905               crop_geometry=SvPV(ST(i),na);
13906               break;
13907             }
13908           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13909             attribute);
13910           break;
13911         }
13912         case 'g':
13913         case 'G':
13914         {
13915           if (LocaleCompare(attribute,"geometry") == 0)
13916             {
13917               geometry=SvPV(ST(i),na);
13918               break;
13919             }
13920          if (LocaleCompare(attribute,"gravity") == 0)
13921            {
13922              Image
13923                *next;
13924
13925              ssize_t
13926                in;
13927
13928              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
13929                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13930              if (in < 0)
13931                {
13932                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
13933                    SvPV(ST(i),na));
13934                  return;
13935                }
13936              for (next=image; next; next=next->next)
13937                next->gravity=(GravityType) in;
13938              break;
13939            }
13940           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13941             attribute);
13942           break;
13943         }
13944         default:
13945         {
13946           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13947             attribute);
13948           break;
13949         }
13950       }
13951     }
13952     for ( ; image; image=image->next)
13953     {
13954       clone=CloneImage(image,0,0,MagickTrue,exception);
13955       if ((clone == (Image *) NULL) || (exception->severity >= ErrorException))
13956         goto PerlException;
13957       TransformImage(&clone,crop_geometry,geometry);
13958       for ( ; clone; clone=clone->next)
13959       {
13960         AddImageToRegistry(sv,clone);
13961         rv=newRV(sv);
13962         av_push(av,sv_bless(rv,hv));
13963         SvREFCNT_dec(sv);
13964       }
13965     }
13966     exception=DestroyExceptionInfo(exception);
13967     ST(0)=av_reference;
13968     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13969     XSRETURN(1);
13970
13971   PerlException:
13972     InheritPerlException(exception,perl_exception);
13973     exception=DestroyExceptionInfo(exception);
13974     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
13975     SvPOK_on(perl_exception);
13976     ST(0)=sv_2mortal(perl_exception);
13977     XSRETURN(1);
13978   }
13979 \f
13980 #
13981 ###############################################################################
13982 #                                                                             #
13983 #                                                                             #
13984 #                                                                             #
13985 #   W r i t e                                                                 #
13986 #                                                                             #
13987 #                                                                             #
13988 #                                                                             #
13989 ###############################################################################
13990 #
13991 #
13992 void
13993 Write(ref,...)
13994   Image::Magick ref=NO_INIT
13995   ALIAS:
13996     WriteImage    = 1
13997     write         = 2
13998     writeimage    = 3
13999   PPCODE:
14000   {
14001     char
14002       filename[MaxTextExtent];
14003
14004     ExceptionInfo
14005       *exception;
14006
14007     Image
14008       *image,
14009       *next;
14010
14011     register ssize_t
14012       i;
14013
14014     ssize_t
14015       number_images,
14016       scene;
14017
14018     struct PackageInfo
14019       *info,
14020       *package_info;
14021
14022     SV
14023       *perl_exception,
14024       *reference;
14025
14026     PERL_UNUSED_VAR(ref);
14027     PERL_UNUSED_VAR(ix);
14028     exception=AcquireExceptionInfo();
14029     perl_exception=newSVpv("",0);
14030     number_images=0;
14031     package_info=(struct PackageInfo *) NULL;
14032     if (sv_isobject(ST(0)) == 0)
14033       {
14034         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14035           PackageName);
14036         goto PerlException;
14037       }
14038     reference=SvRV(ST(0));
14039     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14040     if (image == (Image *) NULL)
14041       {
14042         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14043           PackageName);
14044         goto PerlException;
14045       }
14046     package_info=ClonePackageInfo(info,exception);
14047     if (items == 2)
14048       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14049     else
14050       if (items > 2)
14051         for (i=2; i < items; i+=2)
14052           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14053             exception);
14054     (void) CopyMagickString(filename,package_info->image_info->filename,
14055       MaxTextExtent);
14056     scene=0;
14057     for (next=image; next; next=next->next)
14058     {
14059       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
14060       next->scene=scene++;
14061     }
14062     SetImageInfo(package_info->image_info,(unsigned int)
14063       GetImageListLength(image),&image->exception);
14064     for (next=image; next; next=next->next)
14065     {
14066       (void) WriteImage(package_info->image_info,next,exception);
14067       number_images++;
14068       if (package_info->image_info->adjoin)
14069         break;
14070     }
14071
14072   PerlException:
14073     if (package_info != (struct PackageInfo *) NULL)
14074       DestroyPackageInfo(package_info);
14075     InheritPerlException(exception,perl_exception);
14076     exception=DestroyExceptionInfo(exception);
14077     sv_setiv(perl_exception,(IV) number_images);
14078     SvPOK_on(perl_exception);
14079     ST(0)=sv_2mortal(perl_exception);
14080     XSRETURN(1);
14081   }