]> granicus.if.org Git - imagemagick/blob - PerlMagick/Magick.xs
e4eb6df61d1358c02072b3cb1f40b5a686d1c684
[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 %                                 Cristy                                      %
23 %                             February 1997                                   %
24 %                                                                             %
25 %                                                                             %
26 %  Copyright 1999-2014 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(__cplusplus) || defined(c_plusplus)
52 extern "C" {
53 #endif
54
55 #define PERL_NO_GET_CONTEXT
56 #include "EXTERN.h"
57 #include "perl.h"
58 #include "XSUB.h"
59 #include <math.h>
60 #include <MagickCore/MagickCore.h>
61 #undef tainted
62
63 #if defined(__cplusplus) || defined(c_plusplus)
64 }
65 #endif
66 \f
67 /*
68   Define declarations.
69 */
70 #ifndef aTHX_
71 #define aTHX_
72 #define pTHX_
73 #define dTHX
74 #endif
75 #define DegreesToRadians(x)  (MagickPI*(x)/180.0)
76 #define EndOf(array)  (&array[NumberOf(array)])
77 #define MagickPI  3.14159265358979323846264338327950288419716939937510
78 #define MaxArguments  33
79 #ifndef na
80 #define na  PL_na
81 #endif
82 #define NumberOf(array)  (sizeof(array)/sizeof(*array))
83 #define PackageName   "Image::Magick"
84 #if PERL_VERSION <= 6
85 #define PerlIO  FILE
86 #define PerlIO_importFILE(f, fl)  (f)
87 #define PerlIO_findFILE(f)  NULL
88 #endif
89 #ifndef sv_undef
90 #define sv_undef  PL_sv_undef
91 #endif
92
93 #define AddImageToRegistry(sv,image) \
94 { \
95   if (magick_registry != (SplayTreeInfo *) NULL) \
96     { \
97       (void) AddValueToSplayTree(magick_registry,image,image); \
98       (sv)=newSViv(PTR2IV(image)); \
99     } \
100 }
101
102 #define DeleteImageFromRegistry(reference,image) \
103 { \
104   if (magick_registry != (SplayTreeInfo *) NULL) \
105     { \
106       if (GetImageReferenceCount(image) == 1) \
107        (void) DeleteNodeByValueFromSplayTree(magick_registry,image); \
108       image=DestroyImage(image); \
109       sv_setiv(reference,0); \
110     } \
111 }
112
113 #define InheritPerlException(exception,perl_exception) \
114 { \
115   char \
116     message[MaxTextExtent]; \
117  \
118   if ((exception)->severity != UndefinedException) \
119     { \
120       (void) FormatLocaleString(message,MaxTextExtent,"Exception %d: %s%s%s%s",\
121         (exception)->severity, (exception)->reason ? \
122         GetLocaleExceptionMessage((exception)->severity,(exception)->reason) : \
123         "Unknown", (exception)->description ? " (" : "", \
124         (exception)->description ? GetLocaleExceptionMessage( \
125         (exception)->severity,(exception)->description) : "", \
126         (exception)->description ? ")" : ""); \
127       if ((perl_exception) != (SV *) NULL) \
128         { \
129           if (SvCUR(perl_exception)) \
130             sv_catpv(perl_exception,"\n"); \
131           sv_catpv(perl_exception,message); \
132         } \
133     } \
134 }
135
136 #define ThrowPerlException(exception,severity,tag,reason) \
137   (void) ThrowMagickException(exception,GetMagickModule(),severity, \
138     tag,"`%s'",reason); \
139 \f
140 /*
141   Typedef and structure declarations.
142 */
143 typedef enum
144 {
145   ArrayReference = (~0),
146   RealReference = (~0)-1,
147   FileReference = (~0)-2,
148   ImageReference = (~0)-3,
149   IntegerReference = (~0)-4,
150   StringReference = (~0)-5
151 } MagickReference;
152
153 typedef struct _Arguments
154 {
155   const char
156     *method;
157
158   ssize_t
159     type;
160 } Arguments;
161
162 struct ArgumentList
163 {
164   ssize_t
165     integer_reference;
166
167   double
168     real_reference;
169
170   const char
171     *string_reference;
172
173   Image
174     *image_reference;
175
176   SV
177     *array_reference;
178
179   FILE
180     *file_reference;
181
182   size_t
183     length;
184 };
185
186 struct PackageInfo
187 {
188   ImageInfo
189     *image_info;
190 };
191
192 typedef void
193   *Image__Magick;  /* data type for the Image::Magick package */
194 \f
195 /*
196   Static declarations.
197 */
198 static struct
199   Methods
200   {
201     const char
202       *name;
203
204     Arguments
205       arguments[MaxArguments];
206   } Methods[] =
207   {
208     { "Comment", { {"comment", StringReference} } },
209     { "Label", { {"label", StringReference} } },
210     { "AddNoise", { {"noise", MagickNoiseOptions}, {"attenuate", RealReference},
211       {"channel", MagickChannelOptions} } },
212     { "Colorize", { {"fill", StringReference}, {"blend", StringReference} } },
213     { "Border", { {"geometry", StringReference}, {"width", IntegerReference},
214       {"height", IntegerReference}, {"fill", StringReference},
215       {"bordercolor", StringReference}, {"color", StringReference},
216       {"compose", MagickComposeOptions} } },
217     { "Blur", { {"geometry", StringReference}, {"radius", RealReference},
218       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
219     { "Chop", { {"geometry", StringReference}, {"width", IntegerReference},
220       {"height", IntegerReference}, {"x", IntegerReference},
221       {"y", IntegerReference} } },
222     { "Crop", { {"geometry", StringReference}, {"width", IntegerReference},
223       {"height", IntegerReference}, {"x", IntegerReference},
224       {"y", IntegerReference}, {"fuzz", StringReference},
225       {"gravity", MagickGravityOptions} } },
226     { "Despeckle", },
227     { "Edge", { {"radius", RealReference} } },
228     { "Emboss", { {"geometry", StringReference}, {"radius", RealReference},
229       {"sigma", RealReference} } },
230     { "Enhance", },
231     { "Flip", },
232     { "Flop", },
233     { "Frame", { {"geometry", StringReference}, {"width", IntegerReference},
234       {"height", IntegerReference}, {"inner", IntegerReference},
235       {"outer", IntegerReference}, {"fill", StringReference},
236       {"color", StringReference}, {"compose", MagickComposeOptions} } },
237     { "Implode", { {"amount", RealReference},
238       {"interpolate", MagickInterpolateOptions} } },
239     { "Magnify", },
240     { "MedianFilter", { {"geometry", StringReference},
241       {"width", IntegerReference}, {"height", IntegerReference},
242       {"channel", MagickChannelOptions} } },
243     { "Minify", },
244     { "OilPaint", { {"radius", RealReference}, {"sigma", RealReference} } },
245     { "ReduceNoise", { {"geometry", StringReference},
246       {"width", IntegerReference},{"height", IntegerReference},
247       {"channel", MagickChannelOptions} } },
248     { "Roll", { {"geometry", StringReference}, {"x", IntegerReference},
249       {"y", IntegerReference} } },
250     { "Rotate", { {"degrees", RealReference},
251       {"background", StringReference} } },
252     { "Sample", { {"geometry", StringReference}, {"width", IntegerReference},
253       {"height", IntegerReference} } },
254     { "Scale", { {"geometry", StringReference}, {"width", IntegerReference},
255       {"height", IntegerReference} } },
256     { "Shade", { {"geometry", StringReference}, {"azimuth", RealReference},
257       {"elevation", RealReference}, {"gray", MagickBooleanOptions} } },
258     { "Sharpen", { {"geometry", StringReference}, {"radius", RealReference},
259       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
260     { "Shear", { {"geometry", StringReference}, {"x", RealReference},
261       {"y", RealReference}, { "fill", StringReference},
262       {"color", StringReference} } },
263     { "Spread", { {"radius", RealReference},
264       {"interpolate", MagickInterpolateOptions} } },
265     { "Swirl", { {"degrees", RealReference},
266       {"interpolate", MagickInterpolateOptions} } },
267     { "Resize", { {"geometry", StringReference}, {"width", IntegerReference},
268       {"height", IntegerReference}, {"filter", MagickFilterOptions},
269       {"support", StringReference } } },
270     { "Zoom", { {"geometry", StringReference}, {"width", IntegerReference},
271       {"height", IntegerReference}, {"filter", MagickFilterOptions},
272       {"support", RealReference } } },
273     { "Annotate", { {"text", StringReference}, {"font", StringReference},
274       {"pointsize", RealReference}, {"density", StringReference},
275       {"undercolor", StringReference}, {"stroke", StringReference},
276       {"fill", StringReference}, {"geometry", StringReference},
277       {"sans", StringReference}, {"x", RealReference},
278       {"y", RealReference}, {"gravity", MagickGravityOptions},
279       {"translate", StringReference}, {"scale", StringReference},
280       {"rotate", RealReference}, {"skewX", RealReference},
281       {"skewY", RealReference}, {"strokewidth", RealReference},
282       {"antialias", MagickBooleanOptions}, {"family", StringReference},
283       {"style", MagickStyleOptions}, {"stretch", MagickStretchOptions},
284       {"weight", IntegerReference}, {"align", MagickAlignOptions},
285       {"encoding", StringReference}, {"affine", ArrayReference},
286       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
287       {"tile", ImageReference}, {"kerning", RealReference},
288       {"interline-spacing", RealReference},
289       {"interword-spacing", RealReference},
290       {"direction", MagickDirectionOptions} } },
291     { "ColorFloodfill", { {"geometry", StringReference},
292       {"x", IntegerReference}, {"y", IntegerReference},
293       {"fill", StringReference}, {"bordercolor", StringReference},
294       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
295     { "Composite", { {"image", ImageReference},
296       {"compose", MagickComposeOptions}, {"geometry", StringReference},
297       {"x", IntegerReference}, {"y", IntegerReference},
298       {"gravity", MagickGravityOptions}, {"opacity", StringReference},
299       {"tile", MagickBooleanOptions}, {"rotate", RealReference},
300       {"color", StringReference}, {"mask", ImageReference},
301       {"channel", MagickChannelOptions},
302       {"interpolate", MagickInterpolateOptions}, {"args", StringReference},
303       {"blend", StringReference}, {"crop-to-self", MagickBooleanOptions} } },
304     { "Contrast", { {"sharpen", MagickBooleanOptions} } },
305     { "CycleColormap", { {"display", IntegerReference} } },
306     { "Draw", { {"primitive", MagickPrimitiveOptions},
307       {"points", StringReference}, {"method", MagickMethodOptions},
308       {"stroke", StringReference}, {"fill", StringReference},
309       {"strokewidth", RealReference}, {"font", StringReference},
310       {"bordercolor", StringReference}, {"x", RealReference},
311       {"y", RealReference}, {"translate", StringReference},
312       {"scale", StringReference}, {"rotate", RealReference},
313       {"skewX", RealReference}, {"skewY", RealReference},
314       {"tile", ImageReference}, {"pointsize", RealReference},
315       {"antialias", MagickBooleanOptions}, {"density", StringReference},
316       {"linewidth", RealReference}, {"affine", ArrayReference},
317       {"stroke-dashoffset", RealReference},
318       {"stroke-dasharray", ArrayReference},
319       {"interpolate", MagickInterpolateOptions},
320       {"origin", StringReference}, {"text", StringReference},
321       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
322       {"vector-graphics", StringReference}, {"kerning", RealReference},
323       {"interline-spacing", RealReference},
324       {"interword-spacing", RealReference},
325       {"direction", MagickDirectionOptions} } },
326     { "Equalize", { {"channel", MagickChannelOptions} } },
327     { "Gamma", { {"gamma", StringReference}, {"channel", MagickChannelOptions},
328       {"red", RealReference}, {"green", RealReference},
329       {"blue", RealReference} } },
330     { "Map", { {"image", ImageReference},
331       {"dither-method", MagickDitherOptions} } },
332     { "MatteFloodfill", { {"geometry", StringReference},
333       {"x", IntegerReference}, {"y", IntegerReference},
334       {"opacity", StringReference}, {"bordercolor", StringReference},
335       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
336     { "Modulate", { {"factor", StringReference}, {"hue", RealReference},
337       {"saturation", RealReference}, {"whiteness", RealReference},
338       {"brightness", RealReference}, {"lightness", RealReference},
339       {"blackness", RealReference} } },
340     { "Negate", { {"gray", MagickBooleanOptions},
341       {"channel", MagickChannelOptions} } },
342     { "Normalize", { {"channel", MagickChannelOptions} } },
343     { "NumberColors", },
344     { "Opaque", { {"color", StringReference}, {"fill", StringReference},
345       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
346       {"invert", MagickBooleanOptions} } },
347     { "Quantize", { {"colors", IntegerReference},
348       {"treedepth", IntegerReference}, {"colorspace", MagickColorspaceOptions},
349       {"dither", MagickDitherOptions}, {"measure", MagickBooleanOptions},
350       {"global", MagickBooleanOptions}, {"transparent-color", StringReference},
351       {"dither-method", MagickDitherOptions} } },
352     { "Raise", { {"geometry", StringReference}, {"width", IntegerReference},
353       {"height", IntegerReference}, {"raise", MagickBooleanOptions} } },
354     { "Segment", { {"geometry", StringReference},
355       {"cluster-threshold", RealReference},
356       {"smoothing-threshold", RealReference},
357       {"colorspace", MagickColorspaceOptions},
358       {"verbose", MagickBooleanOptions} } },
359     { "Signature", },
360     { "Solarize", { {"geometry", StringReference},
361       {"threshold", StringReference} } },
362     { "Sync", },
363     { "Texture", { {"texture", ImageReference} } },
364     { "Evaluate", { {"value", RealReference},
365       {"operator", MagickEvaluateOptions},
366       {"channel", MagickChannelOptions} } },
367     { "Transparent", { {"color", StringReference}, {"opacity", StringReference},
368       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
369     { "Threshold", { {"threshold", StringReference},
370       {"channel", MagickChannelOptions} } },
371     { "Charcoal", { {"geometry", StringReference}, {"radius", RealReference},
372       {"sigma", RealReference} } },
373     { "Trim", { {"fuzz", StringReference} } },
374     { "Wave", { {"geometry", StringReference}, {"amplitude", RealReference},
375       {"wavelength", RealReference},
376       {"interpolate", MagickInterpolateOptions} } },
377     { "Separate", { {"channel", MagickChannelOptions} } },
378     { "Condense", },
379     { "Stereo", { {"image", ImageReference}, {"x", IntegerReference},
380       {"y", IntegerReference} } },
381     { "Stegano", { {"image", ImageReference}, {"offset", IntegerReference} } },
382     { "Deconstruct", },
383     { "GaussianBlur", { {"geometry", StringReference},
384       {"radius", RealReference}, {"sigma", RealReference},
385       {"channel", MagickChannelOptions} } },
386     { "Convolve", { {"coefficients", ArrayReference},
387       {"channel", MagickChannelOptions}, {"bias", StringReference},
388       {"kernel", StringReference} } },
389     { "Profile", { {"name", StringReference}, {"profile", StringReference},
390       { "rendering-intent", MagickIntentOptions},
391       { "black-point-compensation", MagickBooleanOptions} } },
392     { "UnsharpMask", { {"geometry", StringReference},
393       {"radius", RealReference}, {"sigma", RealReference},
394       {"gain", RealReference}, {"threshold", RealReference},
395       {"channel", MagickChannelOptions} } },
396     { "MotionBlur", { {"geometry", StringReference},
397       {"radius", RealReference}, {"sigma", RealReference},
398       {"angle", RealReference}, {"channel", MagickChannelOptions} } },
399     { "OrderedDither", { {"threshold", StringReference},
400       {"channel", MagickChannelOptions} } },
401     { "Shave", { {"geometry", StringReference}, {"width", IntegerReference},
402       {"height", IntegerReference} } },
403     { "Level", { {"levels", StringReference}, {"black-point", RealReference},
404       {"white-point", RealReference}, {"gamma", RealReference},
405       {"channel", MagickChannelOptions}, {"level", StringReference} } },
406     { "Clip", { {"id", StringReference}, {"inside", MagickBooleanOptions} } },
407     { "AffineTransform", { {"affine", ArrayReference},
408       {"translate", StringReference}, {"scale", StringReference},
409       {"rotate", RealReference}, {"skewX", RealReference},
410       {"skewY", RealReference}, {"interpolate", MagickInterpolateOptions},
411       {"background", StringReference} } },
412     { "Difference", { {"image", ImageReference}, {"fuzz", StringReference} } },
413     { "AdaptiveThreshold", { {"geometry", StringReference},
414       {"width", IntegerReference}, {"height", IntegerReference} } },
415     { "Resample", { {"density", StringReference}, {"x", RealReference},
416       {"y", RealReference}, {"filter", MagickFilterOptions},
417       {"support", RealReference } } },
418     { "Describe", { {"file", FileReference} } },
419     { "BlackThreshold", { {"threshold", StringReference},
420       {"channel", MagickChannelOptions} } },
421     { "WhiteThreshold", { {"threshold", StringReference},
422       {"channel", MagickChannelOptions} } },
423     { "RotationalBlur", { {"geometry", StringReference},
424       {"angle", RealReference}, {"channel", MagickChannelOptions} } },
425     { "Thumbnail", { {"geometry", StringReference}, {"width", IntegerReference},
426       {"height", IntegerReference} } },
427     { "Strip", },
428     { "Tint", { {"fill", StringReference}, {"blend", StringReference} } },
429     { "Channel", { {"channel", MagickChannelOptions} } },
430     { "Splice", { {"geometry", StringReference}, {"width", IntegerReference},
431       {"height", IntegerReference}, {"x", IntegerReference},
432       {"y", IntegerReference}, {"fuzz", StringReference},
433       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
434     { "Posterize", { {"levels", IntegerReference},
435       {"dither", MagickBooleanOptions} } },
436     { "Shadow", { {"geometry", StringReference}, {"alpha", RealReference},
437       {"sigma", RealReference}, {"x", IntegerReference},
438       {"y", IntegerReference} } },
439     { "Identify", { {"file", FileReference}, {"features", StringReference},
440       {"unique", MagickBooleanOptions} } },
441     { "SepiaTone", { {"threshold", RealReference} } },
442     { "SigmoidalContrast", { {"geometry", StringReference},
443       {"contrast", RealReference}, {"mid-point", RealReference},
444       {"channel", MagickChannelOptions}, {"sharpen", MagickBooleanOptions} } },
445     { "Extent", { {"geometry", StringReference}, {"width", IntegerReference},
446       {"height", IntegerReference}, {"x", IntegerReference},
447       {"y", IntegerReference}, {"fuzz", StringReference},
448       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
449     { "Vignette", { {"geometry", StringReference}, {"radius", RealReference},
450       {"sigma", RealReference}, {"x", IntegerReference},
451       {"y", IntegerReference}, {"background", StringReference} } },
452     { "ContrastStretch", { {"levels", StringReference},
453       {"black-point", RealReference},{"white-point", RealReference},
454       {"channel", MagickChannelOptions} } },
455     { "Sans0", },
456     { "Sans1", },
457     { "AdaptiveSharpen", { {"geometry", StringReference},
458       {"radius", RealReference}, {"sigma", RealReference},
459       {"bias", RealReference}, {"channel", MagickChannelOptions} } },
460     { "Transpose", },
461     { "Transverse", },
462     { "AutoOrient", },
463     { "AdaptiveBlur", { {"geometry", StringReference},
464       {"radius", RealReference}, {"sigma", RealReference},
465       {"channel", MagickChannelOptions} } },
466     { "Sketch", { {"geometry", StringReference},
467       {"radius", RealReference}, {"sigma", RealReference},
468       {"angle", RealReference} } },
469     { "UniqueColors", },
470     { "AdaptiveResize", { {"geometry", StringReference},
471       {"width", IntegerReference}, {"height", IntegerReference},
472       {"filter", MagickFilterOptions}, {"support", StringReference },
473       {"blur", RealReference } } },
474     { "ClipMask", { {"mask", ImageReference} } },
475     { "LinearStretch", { {"levels", StringReference},
476       {"black-point", RealReference},{"white-point", RealReference} } },
477     { "ColorMatrix", { {"matrix", ArrayReference} } },
478     { "Mask", { {"mask", ImageReference} } },
479     { "Polaroid", { {"caption", StringReference}, {"angle", RealReference},
480       {"font", StringReference}, {"stroke", StringReference},
481       {"fill", StringReference}, {"strokewidth", RealReference},
482       {"pointsize", RealReference}, {"gravity", MagickGravityOptions},
483       {"background", StringReference},
484       {"interpolate", MagickInterpolateOptions} } },
485     { "FloodfillPaint", { {"geometry", StringReference},
486       {"x", IntegerReference}, {"y", IntegerReference},
487       {"fill", StringReference}, {"bordercolor", StringReference},
488       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
489       {"invert", MagickBooleanOptions} } },
490     { "Distort", { {"points", ArrayReference}, {"method", MagickDistortOptions},
491       {"virtual-pixel", MagickVirtualPixelOptions},
492       {"best-fit", MagickBooleanOptions} } },
493     { "Clut", { {"image", ImageReference},
494       {"interpolate", MagickInterpolateOptions},
495       {"channel", MagickChannelOptions} } },
496     { "LiquidRescale", { {"geometry", StringReference},
497       {"width", IntegerReference}, {"height", IntegerReference},
498       {"delta-x", RealReference}, {"rigidity", RealReference } } },
499     { "Encipher", { {"passphrase", StringReference} } },
500     { "Decipher", { {"passphrase", StringReference} } },
501     { "Deskew", { {"geometry", StringReference},
502       {"threshold", StringReference} } },
503     { "Remap", { {"image", ImageReference},
504       {"dither-method", MagickDitherOptions} } },
505     { "SparseColor", { {"points", ArrayReference},
506       {"method", MagickSparseColorOptions},
507       {"virtual-pixel", MagickVirtualPixelOptions},
508       {"channel", MagickChannelOptions} } },
509     { "Function", { {"parameters", ArrayReference},
510       {"function", MagickFunctionOptions},
511       {"virtual-pixel", MagickVirtualPixelOptions} } },
512     { "SelectiveBlur", { {"geometry", StringReference},
513       {"radius", RealReference}, {"sigma", RealReference},
514       {"threshold", RealReference}, {"channel", MagickChannelOptions} } },
515     { "HaldClut", { {"image", ImageReference},
516       {"channel", MagickChannelOptions} } },
517     { "BlueShift", { {"factor", StringReference} } },
518     { "ForwardFourierTransform", { {"magnitude", MagickBooleanOptions} } },
519     { "InverseFourierTransform", { {"magnitude", MagickBooleanOptions} } },
520     { "ColorDecisionList", {
521       {"color-correction-collection", StringReference} } },
522     { "AutoGamma", { {"channel", MagickChannelOptions} } },
523     { "AutoLevel", { {"channel", MagickChannelOptions} } },
524     { "LevelColors", { {"invert", MagickBooleanOptions},
525       {"black-point", StringReference}, {"white-point", StringReference},
526       {"channel", MagickChannelOptions}, {"invert", MagickBooleanOptions} } },
527     { "Clamp", { {"channel", MagickChannelOptions} } },
528     { "BrightnessContrast", { {"levels", StringReference},
529       {"brightness", RealReference},{"contrast", RealReference},
530       {"channel", MagickChannelOptions} } },
531     { "Morphology", { {"kernel", StringReference},
532       {"channel", MagickChannelOptions}, {"method", MagickMorphologyOptions},
533       {"iterations", IntegerReference} } },
534     { "Sans", { {"matrix", ArrayReference} } },
535     { "Color", { {"color", StringReference} } },
536     { "Mode", { {"geometry", StringReference},
537       {"width", IntegerReference},{"height", IntegerReference},
538       {"channel", MagickChannelOptions} } },
539     { "Statistic", { {"geometry", StringReference},
540       {"width", IntegerReference},{"height", IntegerReference},
541       {"channel", MagickChannelOptions}, {"type", MagickStatisticOptions} } },
542     { "Perceptible", { {"epsilon", RealReference},
543       {"channel", MagickChannelOptions} } },
544     { "Poly", { {"terms", ArrayReference},
545       {"channel", MagickChannelOptions} } },
546     { "Grayscale", { {"method", MagickNoiseOptions} } },
547     { "CannyEdge", { {"geometry", StringReference},
548       {"radius", RealReference}, {"sigma", RealReference},
549       {"lower-percent", RealReference}, {"upper-percent", RealReference} } },
550   };
551
552 static SplayTreeInfo
553   *magick_registry = (SplayTreeInfo *) NULL;
554 \f
555 /*
556   Forward declarations.
557 */
558 static Image
559   *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
560
561 static ssize_t
562   strEQcase(const char *,const char *);
563 \f
564 /*
565 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
566 %                                                                             %
567 %                                                                             %
568 %                                                                             %
569 %   C l o n e P a c k a g e I n f o                                           %
570 %                                                                             %
571 %                                                                             %
572 %                                                                             %
573 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
574 %
575 %  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
576 %  a new one.
577 %
578 %  The format of the ClonePackageInfo routine is:
579 %
580 %      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
581 %        exception)
582 %
583 %  A description of each parameter follows:
584 %
585 %    o info: a structure of type info.
586 %
587 %    o exception: Return any errors or warnings in this structure.
588 %
589 */
590 static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
591   ExceptionInfo *exception)
592 {
593   struct PackageInfo
594     *clone_info;
595
596   clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
597   if (clone_info == (struct PackageInfo *) NULL)
598     {
599       ThrowPerlException(exception,ResourceLimitError,
600         "UnableToClonePackageInfo",PackageName);
601       return((struct PackageInfo *) NULL);
602     }
603   if (info == (struct PackageInfo *) NULL)
604     {
605       clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
606       return(clone_info);
607     }
608   *clone_info=(*info);
609   clone_info->image_info=CloneImageInfo(info->image_info);
610   return(clone_info);
611 }
612 \f
613 /*
614 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
615 %                                                                             %
616 %                                                                             %
617 %                                                                             %
618 %   c o n s t a n t                                                           %
619 %                                                                             %
620 %                                                                             %
621 %                                                                             %
622 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
623 %
624 %  constant() returns a double value for the specified name.
625 %
626 %  The format of the constant routine is:
627 %
628 %      double constant(char *name,ssize_t sans)
629 %
630 %  A description of each parameter follows:
631 %
632 %    o value: Method constant returns a double value for the specified name.
633 %
634 %    o name: The name of the constant.
635 %
636 %    o sans: This integer value is not used.
637 %
638 */
639 static double constant(char *name,ssize_t sans)
640 {
641   (void) sans;
642   errno=0;
643   switch (*name)
644   {
645     case 'B':
646     {
647       if (strEQ(name,"BlobError"))
648         return(BlobError);
649       if (strEQ(name,"BlobWarning"))
650         return(BlobWarning);
651       break;
652     }
653     case 'C':
654     {
655       if (strEQ(name,"CacheError"))
656         return(CacheError);
657       if (strEQ(name,"CacheWarning"))
658         return(CacheWarning);
659       if (strEQ(name,"CoderError"))
660         return(CoderError);
661       if (strEQ(name,"CoderWarning"))
662         return(CoderWarning);
663       if (strEQ(name,"ConfigureError"))
664         return(ConfigureError);
665       if (strEQ(name,"ConfigureWarning"))
666         return(ConfigureWarning);
667       if (strEQ(name,"CorruptImageError"))
668         return(CorruptImageError);
669       if (strEQ(name,"CorruptImageWarning"))
670         return(CorruptImageWarning);
671       break;
672     }
673     case 'D':
674     {
675       if (strEQ(name,"DelegateError"))
676         return(DelegateError);
677       if (strEQ(name,"DelegateWarning"))
678         return(DelegateWarning);
679       if (strEQ(name,"DrawError"))
680         return(DrawError);
681       if (strEQ(name,"DrawWarning"))
682         return(DrawWarning);
683       break;
684     }
685     case 'E':
686     {
687       if (strEQ(name,"ErrorException"))
688         return(ErrorException);
689       if (strEQ(name,"ExceptionError"))
690         return(CoderError);
691       if (strEQ(name,"ExceptionWarning"))
692         return(CoderWarning);
693       break;
694     }
695     case 'F':
696     {
697       if (strEQ(name,"FatalErrorException"))
698         return(FatalErrorException);
699       if (strEQ(name,"FileOpenError"))
700         return(FileOpenError);
701       if (strEQ(name,"FileOpenWarning"))
702         return(FileOpenWarning);
703       break;
704     }
705     case 'I':
706     {
707       if (strEQ(name,"ImageError"))
708         return(ImageError);
709       if (strEQ(name,"ImageWarning"))
710         return(ImageWarning);
711       break;
712     }
713     case 'M':
714     {
715       if (strEQ(name,"MaxRGB"))
716         return(QuantumRange);
717       if (strEQ(name,"MissingDelegateError"))
718         return(MissingDelegateError);
719       if (strEQ(name,"MissingDelegateWarning"))
720         return(MissingDelegateWarning);
721       if (strEQ(name,"ModuleError"))
722         return(ModuleError);
723       if (strEQ(name,"ModuleWarning"))
724         return(ModuleWarning);
725       break;
726     }
727     case 'O':
728     {
729       if (strEQ(name,"Opaque"))
730         return(OpaqueAlpha);
731       if (strEQ(name,"OptionError"))
732         return(OptionError);
733       if (strEQ(name,"OptionWarning"))
734         return(OptionWarning);
735       break;
736     }
737     case 'Q':
738     {
739       if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
740         return(MAGICKCORE_QUANTUM_DEPTH);
741       if (strEQ(name,"QuantumDepth"))
742         return(MAGICKCORE_QUANTUM_DEPTH);
743       if (strEQ(name,"QuantumRange"))
744         return(QuantumRange);
745       break;
746     }
747     case 'R':
748     {
749       if (strEQ(name,"ResourceLimitError"))
750         return(ResourceLimitError);
751       if (strEQ(name,"ResourceLimitWarning"))
752         return(ResourceLimitWarning);
753       if (strEQ(name,"RegistryError"))
754         return(RegistryError);
755       if (strEQ(name,"RegistryWarning"))
756         return(RegistryWarning);
757       break;
758     }
759     case 'S':
760     {
761       if (strEQ(name,"StreamError"))
762         return(StreamError);
763       if (strEQ(name,"StreamWarning"))
764         return(StreamWarning);
765       if (strEQ(name,"Success"))
766         return(0);
767       break;
768     }
769     case 'T':
770     {
771       if (strEQ(name,"Transparent"))
772         return(TransparentAlpha);
773       if (strEQ(name,"TypeError"))
774         return(TypeError);
775       if (strEQ(name,"TypeWarning"))
776         return(TypeWarning);
777       break;
778     }
779     case 'W':
780     {
781       if (strEQ(name,"WarningException"))
782         return(WarningException);
783       break;
784     }
785     case 'X':
786     {
787       if (strEQ(name,"XServerError"))
788         return(XServerError);
789       if (strEQ(name,"XServerWarning"))
790         return(XServerWarning);
791       break;
792     }
793   }
794   errno=EINVAL;
795   return(0);
796 }
797 \f
798 /*
799 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
800 %                                                                             %
801 %                                                                             %
802 %                                                                             %
803 %   D e s t r o y P a c k a g e I n f o                                       %
804 %                                                                             %
805 %                                                                             %
806 %                                                                             %
807 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
808 %
809 %  Method DestroyPackageInfo frees a previously created info structure.
810 %
811 %  The format of the DestroyPackageInfo routine is:
812 %
813 %      DestroyPackageInfo(struct PackageInfo *info)
814 %
815 %  A description of each parameter follows:
816 %
817 %    o info: a structure of type info.
818 %
819 */
820 static void DestroyPackageInfo(struct PackageInfo *info)
821 {
822   info->image_info=DestroyImageInfo(info->image_info);
823   info=(struct PackageInfo *) RelinquishMagickMemory(info);
824 }
825 \f
826 /*
827 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
828 %                                                                             %
829 %                                                                             %
830 %                                                                             %
831 %   G e t L i s t                                                             %
832 %                                                                             %
833 %                                                                             %
834 %                                                                             %
835 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
836 %
837 %  Method GetList is recursively called by SetupList to traverse the
838 %  Image__Magick reference.  If building an reference_vector (see SetupList),
839 %  *current is the current position in *reference_vector and *last is the final
840 %  entry in *reference_vector.
841 %
842 %  The format of the GetList routine is:
843 %
844 %      GetList(info)
845 %
846 %  A description of each parameter follows:
847 %
848 %    o info: a structure of type info.
849 %
850 */
851 static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
852   ssize_t *current,ssize_t *last,ExceptionInfo *exception)
853 {
854   Image
855     *image;
856
857   if (reference == (SV *) NULL)
858     return(NULL);
859   switch (SvTYPE(reference))
860   {
861     case SVt_PVAV:
862     {
863       AV
864         *av;
865
866       Image
867         *head,
868         *previous;
869
870       register ssize_t
871         i;
872
873       ssize_t
874         n;
875
876       /*
877         Array of images.
878       */
879       previous=(Image *) NULL;
880       head=(Image *) NULL;
881       av=(AV *) reference;
882       n=av_len(av);
883       for (i=0; i <= n; i++)
884       {
885         SV
886           **rv;
887
888         rv=av_fetch(av,i,0);
889         if (rv && *rv && sv_isobject(*rv))
890           {
891             image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
892               exception);
893             if (image == (Image *) NULL)
894               continue;
895             if (image == previous)
896               {
897                 image=CloneImage(image,0,0,MagickTrue,exception);
898                 if (image == (Image *) NULL)
899                   return(NULL);
900               }
901             image->previous=previous;
902             *(previous ? &previous->next : &head)=image;
903             for (previous=image; previous->next; previous=previous->next) ;
904           }
905       }
906       return(head);
907     }
908     case SVt_PVMG:
909     {
910       /*
911         Blessed scalar, one image.
912       */
913       image=INT2PTR(Image *,SvIV(reference));
914       if (image == (Image *) NULL)
915         return(NULL);
916       image->previous=(Image *) NULL;
917       image->next=(Image *) NULL;
918       if (reference_vector)
919         {
920           if (*current == *last)
921             {
922               *last+=256;
923               if (*reference_vector == (SV **) NULL)
924                 *reference_vector=(SV **) AcquireQuantumMemory(*last,
925                   sizeof(*reference_vector));
926               else
927                 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
928                   *last,sizeof(*reference_vector));
929             }
930           if (*reference_vector == (SV **) NULL)
931             {
932               ThrowPerlException(exception,ResourceLimitError,
933                 "MemoryAllocationFailed",PackageName);
934               return((Image *) NULL);
935             }
936           (*reference_vector)[*current]=reference;
937           (*reference_vector)[++(*current)]=NULL;
938         }
939       return(image);
940     }
941     default:
942       break;
943   }
944   (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
945     (double) SvTYPE(reference));
946   return((Image *) NULL);
947 }
948 \f
949 /*
950 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
951 %                                                                             %
952 %                                                                             %
953 %                                                                             %
954 %   G e t P a c k a g e I n f o                                               %
955 %                                                                             %
956 %                                                                             %
957 %                                                                             %
958 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
959 %
960 %  Method GetPackageInfo looks up or creates an info structure for the given
961 %  Image__Magick reference.  If it does create a new one, the information in
962 %  package_info is used to initialize it.
963 %
964 %  The format of the GetPackageInfo routine is:
965 %
966 %      struct PackageInfo *GetPackageInfo(void *reference,
967 %        struct PackageInfo *package_info,ExceptionInfo *exception)
968 %
969 %  A description of each parameter follows:
970 %
971 %    o info: a structure of type info.
972 %
973 %    o exception: Return any errors or warnings in this structure.
974 %
975 */
976 static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
977   struct PackageInfo *package_info,ExceptionInfo *exception)
978 {
979   char
980     message[MaxTextExtent];
981
982   struct PackageInfo
983     *clone_info;
984
985   SV
986     *sv;
987
988   (void) FormatLocaleString(message,MaxTextExtent,"%s::package%s%p",
989     PackageName,XS_VERSION,reference);
990   sv=perl_get_sv(message,(TRUE | 0x02));
991   if (sv == (SV *) NULL)
992     {
993       ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
994         message);
995       return(package_info);
996     }
997   if (SvREFCNT(sv) == 0)
998     (void) SvREFCNT_inc(sv);
999   if (SvIOKp(sv) && (clone_info=INT2PTR(struct PackageInfo *,SvIV(sv))))
1000     return(clone_info);
1001   clone_info=ClonePackageInfo(package_info,exception);
1002   sv_setiv(sv,PTR2IV(clone_info));
1003   return(clone_info);
1004 }
1005 \f
1006 /*
1007 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1008 %                                                                             %
1009 %                                                                             %
1010 %                                                                             %
1011 %   S e t A t t r i b u t e                                                   %
1012 %                                                                             %
1013 %                                                                             %
1014 %                                                                             %
1015 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1016 %
1017 %  SetAttribute() sets the attribute to the value in sval.  This can change
1018 %  either or both of image or info.
1019 %
1020 %  The format of the SetAttribute routine is:
1021 %
1022 %      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1023 %        SV *sval,ExceptionInfo *exception)
1024 %
1025 %  A description of each parameter follows:
1026 %
1027 %    o list: a list of strings.
1028 %
1029 %    o string: a character string.
1030 %
1031 */
1032
1033 static double SiPrefixToDoubleInterval(const char *string,const double interval)
1034 {
1035   char
1036     *q;
1037
1038   double
1039     value;
1040
1041   value=InterpretSiPrefixValue(string,&q);
1042   if (*q == '%')
1043     value*=interval/100.0;
1044   return(value);
1045 }
1046
1047 static inline double StringToDouble(const char *string,char **sentinal)
1048 {
1049   return(InterpretLocaleValue(string,sentinal));
1050 }
1051
1052 static double StringToDoubleInterval(const char *string,const double interval)
1053 {
1054   char
1055     *q;
1056
1057   double
1058     value;
1059
1060   value=InterpretLocaleValue(string,&q);
1061   if (*q == '%')
1062     value*=interval/100.0;
1063   return(value);
1064 }
1065
1066 static inline ssize_t StringToLong(const char *value)
1067 {
1068   return(strtol(value,(char **) NULL,10));
1069 }
1070
1071 static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1072   const char *attribute,SV *sval,ExceptionInfo *exception)
1073 {
1074   GeometryInfo
1075     geometry_info;
1076
1077   long
1078     x,
1079     y;
1080
1081   PixelInfo
1082     pixel;
1083
1084   MagickStatusType
1085     flags;
1086
1087   PixelInfo
1088     *color,
1089     target_color;
1090
1091   ssize_t
1092     sp;
1093
1094   switch (*attribute)
1095   {
1096     case 'A':
1097     case 'a':
1098     {
1099       if (LocaleCompare(attribute,"adjoin") == 0)
1100         {
1101           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1102             SvPV(sval,na)) : SvIV(sval);
1103           if (sp < 0)
1104             {
1105               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1106                 SvPV(sval,na));
1107               break;
1108             }
1109           if (info)
1110             info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1111           break;
1112         }
1113       if (LocaleCompare(attribute,"alpha") == 0)
1114         {
1115           sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaChannelOptions,
1116             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1117           if (sp < 0)
1118             {
1119               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1120                 SvPV(sval,na));
1121               break;
1122             }
1123           for ( ; image; image=image->next)
1124             (void) SetImageAlphaChannel(image,(AlphaChannelOption) sp,
1125               exception);
1126           break;
1127         }
1128       if (LocaleCompare(attribute,"antialias") == 0)
1129         {
1130           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1131             SvPV(sval,na)) : SvIV(sval);
1132           if (sp < 0)
1133             {
1134               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1135                 SvPV(sval,na));
1136               break;
1137             }
1138           if (info)
1139             info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1140           break;
1141         }
1142       if (LocaleCompare(attribute,"area-limit") == 0)
1143         {
1144           MagickSizeType
1145             limit;
1146
1147           limit=MagickResourceInfinity;
1148           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1149             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1150               100.0);
1151           (void) SetMagickResourceLimit(AreaResource,limit);
1152           break;
1153         }
1154       if (LocaleCompare(attribute,"attenuate") == 0)
1155         {
1156           if (info)
1157             (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1158           break;
1159         }
1160       if (LocaleCompare(attribute,"authenticate") == 0)
1161         {
1162           if (info)
1163             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1164           break;
1165         }
1166       if (info)
1167         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1168       for ( ; image; image=image->next)
1169         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1170       break;
1171     }
1172     case 'B':
1173     case 'b':
1174     {
1175       if (LocaleCompare(attribute,"background") == 0)
1176         {
1177           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1178             exception);
1179           if (info)
1180             info->image_info->background_color=target_color;
1181           for ( ; image; image=image->next)
1182             image->background_color=target_color;
1183           break;
1184         }
1185       if (LocaleCompare(attribute,"blue-primary") == 0)
1186         {
1187           for ( ; image; image=image->next)
1188           {
1189             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1190             image->chromaticity.blue_primary.x=geometry_info.rho;
1191             image->chromaticity.blue_primary.y=geometry_info.sigma;
1192             if ((flags & SigmaValue) == 0)
1193               image->chromaticity.blue_primary.y=
1194                 image->chromaticity.blue_primary.x;
1195           }
1196           break;
1197         }
1198       if (LocaleCompare(attribute,"bordercolor") == 0)
1199         {
1200           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1201             exception);
1202           if (info)
1203             info->image_info->border_color=target_color;
1204           for ( ; image; image=image->next)
1205             image->border_color=target_color;
1206           break;
1207         }
1208       if (info)
1209         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1210       for ( ; image; image=image->next)
1211         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1212       break;
1213     }
1214     case 'C':
1215     case 'c':
1216     {
1217       if (LocaleCompare(attribute,"cache-threshold") == 0)
1218         {
1219           (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1220             SiPrefixToDoubleInterval(SvPV(sval,na),100.0));
1221           (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1222             (2.0*SiPrefixToDoubleInterval(SvPV(sval,na),100.0)));
1223           break;
1224         }
1225       if (LocaleCompare(attribute,"clip-mask") == 0)
1226         {
1227           Image
1228             *clip_mask;
1229
1230           clip_mask=(Image *) NULL;
1231           if (SvPOK(sval))
1232             clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1233           for ( ; image; image=image->next)
1234             SetImageMask(image,clip_mask,exception);
1235           break;
1236         }
1237       if (LocaleNCompare(attribute,"colormap",8) == 0)
1238         {
1239           for ( ; image; image=image->next)
1240           {
1241             int
1242               items;
1243
1244             long
1245               i;
1246
1247             if (image->storage_class == DirectClass)
1248               continue;
1249             i=0;
1250             items=sscanf(attribute,"%*[^[][%ld",&i);
1251             (void) items;
1252             if (i > (ssize_t) image->colors)
1253               i%=image->colors;
1254             if ((strchr(SvPV(sval,na),',') == 0) ||
1255                 (strchr(SvPV(sval,na),')') != 0))
1256               QueryColorCompliance(SvPV(sval,na),AllCompliance,
1257                 image->colormap+i,exception);
1258             else
1259               {
1260                 color=image->colormap+i;
1261                 pixel.red=color->red;
1262                 pixel.green=color->green;
1263                 pixel.blue=color->blue;
1264                 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1265                 pixel.red=geometry_info.rho;
1266                 pixel.green=geometry_info.sigma;
1267                 pixel.blue=geometry_info.xi;
1268                 color->red=ClampToQuantum(pixel.red);
1269                 color->green=ClampToQuantum(pixel.green);
1270                 color->blue=ClampToQuantum(pixel.blue);
1271               }
1272           }
1273           break;
1274         }
1275       if (LocaleCompare(attribute,"colorspace") == 0)
1276         {
1277           sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1278             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1279           if (sp < 0)
1280             {
1281               ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1282                 SvPV(sval,na));
1283               break;
1284             }
1285           for ( ; image; image=image->next)
1286             (void) TransformImageColorspace(image,(ColorspaceType) sp,
1287               exception);
1288           break;
1289         }
1290       if (LocaleCompare(attribute,"comment") == 0)
1291         {
1292           for ( ; image; image=image->next)
1293             (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1294               info ? info->image_info : (ImageInfo *) NULL,image,
1295               SvPV(sval,na),exception),exception);
1296           break;
1297         }
1298       if (LocaleCompare(attribute,"compression") == 0)
1299         {
1300           sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1301             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1302           if (sp < 0)
1303             {
1304               ThrowPerlException(exception,OptionError,
1305                 "UnrecognizedImageCompression",SvPV(sval,na));
1306               break;
1307             }
1308           if (info)
1309             info->image_info->compression=(CompressionType) sp;
1310           for ( ; image; image=image->next)
1311             image->compression=(CompressionType) sp;
1312           break;
1313         }
1314       if (info)
1315         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1316       for ( ; image; image=image->next)
1317         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1318       break;
1319     }
1320     case 'D':
1321     case 'd':
1322     {
1323       if (LocaleCompare(attribute,"debug") == 0)
1324         {
1325           SetLogEventMask(SvPV(sval,na));
1326           break;
1327         }
1328       if (LocaleCompare(attribute,"delay") == 0)
1329         {
1330           flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1331           for ( ; image; image=image->next)
1332           {
1333             image->delay=(size_t) floor(geometry_info.rho+0.5);
1334             if ((flags & SigmaValue) != 0)
1335               image->ticks_per_second=(ssize_t)
1336                 floor(geometry_info.sigma+0.5);
1337           }
1338           break;
1339         }
1340       if (LocaleCompare(attribute,"disk-limit") == 0)
1341         {
1342           MagickSizeType
1343             limit;
1344
1345           limit=MagickResourceInfinity;
1346           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1347             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1348               100.0);
1349           (void) SetMagickResourceLimit(DiskResource,limit);
1350           break;
1351         }
1352       if (LocaleCompare(attribute,"density") == 0)
1353         {
1354           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1355             {
1356               ThrowPerlException(exception,OptionError,"MissingGeometry",
1357                 SvPV(sval,na));
1358               break;
1359             }
1360           if (info)
1361             (void) CloneString(&info->image_info->density,SvPV(sval,na));
1362           for ( ; image; image=image->next)
1363           {
1364             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1365             image->resolution.x=geometry_info.rho;
1366             image->resolution.y=geometry_info.sigma;
1367             if ((flags & SigmaValue) == 0)
1368               image->resolution.y=image->resolution.x;
1369           }
1370           break;
1371         }
1372       if (LocaleCompare(attribute,"depth") == 0)
1373         {
1374           if (info)
1375             info->image_info->depth=SvIV(sval);
1376           for ( ; image; image=image->next)
1377             (void) SetImageDepth(image,SvIV(sval),exception);
1378           break;
1379         }
1380       if (LocaleCompare(attribute,"dispose") == 0)
1381         {
1382           sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1383             SvPV(sval,na)) : SvIV(sval);
1384           if (sp < 0)
1385             {
1386               ThrowPerlException(exception,OptionError,
1387                 "UnrecognizedDisposeMethod",SvPV(sval,na));
1388               break;
1389             }
1390           for ( ; image; image=image->next)
1391             image->dispose=(DisposeType) sp;
1392           break;
1393         }
1394       if (LocaleCompare(attribute,"dither") == 0)
1395         {
1396           if (info)
1397             {
1398               sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1399                 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1400               if (sp < 0)
1401                 {
1402                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
1403                     SvPV(sval,na));
1404                   break;
1405                 }
1406               info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1407             }
1408           break;
1409         }
1410       if (LocaleCompare(attribute,"display") == 0)
1411         {
1412           display:
1413           if (info)
1414             (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1415           break;
1416         }
1417       if (info)
1418         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1419       for ( ; image; image=image->next)
1420         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1421       break;
1422     }
1423     case 'E':
1424     case 'e':
1425     {
1426       if (LocaleCompare(attribute,"endian") == 0)
1427         {
1428           sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1429             SvPV(sval,na)) : SvIV(sval);
1430           if (sp < 0)
1431             {
1432               ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1433                 SvPV(sval,na));
1434               break;
1435             }
1436           if (info)
1437             info->image_info->endian=(EndianType) sp;
1438           for ( ; image; image=image->next)
1439             image->endian=(EndianType) sp;
1440           break;
1441         }
1442       if (LocaleCompare(attribute,"extract") == 0)
1443         {
1444           /*
1445             Set image extract geometry.
1446           */
1447           (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1448           break;
1449         }
1450       if (info)
1451         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1452       for ( ; image; image=image->next)
1453         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1454       break;
1455     }
1456     case 'F':
1457     case 'f':
1458     {
1459       if (LocaleCompare(attribute,"filename") == 0)
1460         {
1461           if (info)
1462             (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1463               MaxTextExtent);
1464           for ( ; image; image=image->next)
1465             (void) CopyMagickString(image->filename,SvPV(sval,na),
1466               MaxTextExtent);
1467           break;
1468         }
1469       if (LocaleCompare(attribute,"file") == 0)
1470         {
1471           FILE
1472             *file;
1473
1474           PerlIO
1475             *io_info;
1476
1477           if (info == (struct PackageInfo *) NULL)
1478             break;
1479           io_info=IoIFP(sv_2io(sval));
1480           if (io_info == (PerlIO *) NULL)
1481             {
1482               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1483                 PackageName);
1484               break;
1485             }
1486           file=PerlIO_findFILE(io_info);
1487           if (file == (FILE *) NULL)
1488             {
1489               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1490                 PackageName);
1491               break;
1492             }
1493           SetImageInfoFile(info->image_info,file);
1494           break;
1495         }
1496       if (LocaleCompare(attribute,"fill") == 0)
1497         {
1498           if (info)
1499             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1500           break;
1501         }
1502       if (LocaleCompare(attribute,"font") == 0)
1503         {
1504           if (info)
1505             (void) CloneString(&info->image_info->font,SvPV(sval,na));
1506           break;
1507         }
1508       if (LocaleCompare(attribute,"foreground") == 0)
1509         break;
1510       if (LocaleCompare(attribute,"fuzz") == 0)
1511         {
1512           if (info)
1513             info->image_info->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1514               QuantumRange+1.0);
1515           for ( ; image; image=image->next)
1516             image->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1517               QuantumRange+1.0);
1518           break;
1519         }
1520       if (info)
1521         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1522       for ( ; image; image=image->next)
1523         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1524       break;
1525     }
1526     case 'G':
1527     case 'g':
1528     {
1529       if (LocaleCompare(attribute,"gamma") == 0)
1530         {
1531           for ( ; image; image=image->next)
1532             image->gamma=SvNV(sval);
1533           break;
1534         }
1535       if (LocaleCompare(attribute,"gravity") == 0)
1536         {
1537           sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1538             SvPV(sval,na)) : SvIV(sval);
1539           if (sp < 0)
1540             {
1541               ThrowPerlException(exception,OptionError,
1542                 "UnrecognizedGravityType",SvPV(sval,na));
1543               break;
1544             }
1545           if (info)
1546             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1547           for ( ; image; image=image->next)
1548             image->gravity=(GravityType) sp;
1549           break;
1550         }
1551       if (LocaleCompare(attribute,"green-primary") == 0)
1552         {
1553           for ( ; image; image=image->next)
1554           {
1555             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1556             image->chromaticity.green_primary.x=geometry_info.rho;
1557             image->chromaticity.green_primary.y=geometry_info.sigma;
1558             if ((flags & SigmaValue) == 0)
1559               image->chromaticity.green_primary.y=
1560                 image->chromaticity.green_primary.x;
1561           }
1562           break;
1563         }
1564       if (info)
1565         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1566       for ( ; image; image=image->next)
1567         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1568       break;
1569     }
1570     case 'I':
1571     case 'i':
1572     {
1573       if (LocaleNCompare(attribute,"index",5) == 0)
1574         {
1575           int
1576             items;
1577
1578           long
1579             index;
1580
1581           register Quantum
1582             *q;
1583
1584           CacheView
1585             *image_view;
1586
1587           for ( ; image; image=image->next)
1588           {
1589             if (image->storage_class != PseudoClass)
1590               continue;
1591             x=0;
1592             y=0;
1593             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1594             (void) items;
1595             image_view=AcquireAuthenticCacheView(image,exception);
1596             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1597             if (q != (Quantum *) NULL)
1598               {
1599                 items=sscanf(SvPV(sval,na),"%ld",&index);
1600                 if ((index >= 0) && (index < (ssize_t) image->colors))
1601                   SetPixelIndex(image,index,q);
1602                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1603               }
1604             image_view=DestroyCacheView(image_view);
1605           }
1606           break;
1607         }
1608       if (LocaleCompare(attribute,"iterations") == 0)
1609         {
1610   iterations:
1611           for ( ; image; image=image->next)
1612             image->iterations=SvIV(sval);
1613           break;
1614         }
1615       if (LocaleCompare(attribute,"interlace") == 0)
1616         {
1617           sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1618             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1619           if (sp < 0)
1620             {
1621               ThrowPerlException(exception,OptionError,
1622                 "UnrecognizedInterlaceType",SvPV(sval,na));
1623               break;
1624             }
1625           if (info)
1626             info->image_info->interlace=(InterlaceType) sp;
1627           for ( ; image; image=image->next)
1628             image->interlace=(InterlaceType) sp;
1629           break;
1630         }
1631       if (info)
1632         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1633       for ( ; image; image=image->next)
1634         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1635       break;
1636     }
1637     case 'L':
1638     case 'l':
1639     {
1640       if (LocaleCompare(attribute,"label") == 0)
1641         {
1642           for ( ; image; image=image->next)
1643             (void) SetImageProperty(image,"label",InterpretImageProperties(
1644               info ? info->image_info : (ImageInfo *) NULL,image,
1645               SvPV(sval,na),exception),exception);
1646           break;
1647         }
1648       if (LocaleCompare(attribute,"loop") == 0)
1649         goto iterations;
1650       if (info)
1651         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1652       for ( ; image; image=image->next)
1653         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1654       break;
1655     }
1656     case 'M':
1657     case 'm':
1658     {
1659       if (LocaleCompare(attribute,"magick") == 0)
1660         {
1661           if (info)
1662             (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
1663               "%s:",SvPV(sval,na));
1664           for ( ; image; image=image->next)
1665             (void) CopyMagickString(image->magick,SvPV(sval,na),MaxTextExtent);
1666           break;
1667         }
1668       if (LocaleCompare(attribute,"map-limit") == 0)
1669         {
1670           MagickSizeType
1671             limit;
1672
1673           limit=MagickResourceInfinity;
1674           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1675             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1676               100.0);
1677           (void) SetMagickResourceLimit(MapResource,limit);
1678           break;
1679         }
1680       if (LocaleCompare(attribute,"mask") == 0)
1681         {
1682           Image
1683             *mask;
1684
1685           mask=(Image *) NULL;
1686           if (SvPOK(sval))
1687             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1688           for ( ; image; image=image->next)
1689             SetImageMask(image,mask,exception);
1690           break;
1691         }
1692       if (LocaleCompare(attribute,"mattecolor") == 0)
1693         {
1694           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1695             exception);
1696           if (info)
1697             info->image_info->matte_color=target_color;
1698           for ( ; image; image=image->next)
1699             image->matte_color=target_color;
1700           break;
1701         }
1702       if (LocaleCompare(attribute,"matte") == 0)
1703         {
1704           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1705             SvPV(sval,na)) : SvIV(sval);
1706           if (sp < 0)
1707             {
1708               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1709                 SvPV(sval,na));
1710               break;
1711             }
1712           for ( ; image; image=image->next)
1713             image->alpha_trait=sp != 0 ? BlendPixelTrait : UndefinedPixelTrait;
1714           break;
1715         }
1716       if (LocaleCompare(attribute,"memory-limit") == 0)
1717         {
1718           MagickSizeType
1719             limit;
1720
1721           limit=MagickResourceInfinity;
1722           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1723             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1724               100.0);
1725           (void) SetMagickResourceLimit(MemoryResource,limit);
1726           break;
1727         }
1728       if (LocaleCompare(attribute,"monochrome") == 0)
1729         {
1730           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1731             SvPV(sval,na)) : SvIV(sval);
1732           if (sp < 0)
1733             {
1734               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1735                 SvPV(sval,na));
1736               break;
1737             }
1738           if (info)
1739             info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1740           for ( ; image; image=image->next)
1741             (void) SetImageType(image,BilevelType,exception);
1742           break;
1743         }
1744       if (info)
1745         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1746       for ( ; image; image=image->next)
1747         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1748       break;
1749     }
1750     case 'O':
1751     case 'o':
1752     {
1753       if (LocaleCompare(attribute,"option") == 0)
1754         {
1755           if (info)
1756             DefineImageOption(info->image_info,SvPV(sval,na));
1757           break;
1758         }
1759       if (LocaleCompare(attribute,"orientation") == 0)
1760         {
1761           sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1762             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1763           if (sp < 0)
1764             {
1765               ThrowPerlException(exception,OptionError,
1766                 "UnrecognizedOrientationType",SvPV(sval,na));
1767               break;
1768             }
1769           if (info)
1770             info->image_info->orientation=(OrientationType) sp;
1771           for ( ; image; image=image->next)
1772             image->orientation=(OrientationType) sp;
1773           break;
1774         }
1775       if (info)
1776         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1777       for ( ; image; image=image->next)
1778         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1779       break;
1780     }
1781     case 'P':
1782     case 'p':
1783     {
1784       if (LocaleCompare(attribute,"page") == 0)
1785         {
1786           char
1787             *geometry;
1788
1789           geometry=GetPageGeometry(SvPV(sval,na));
1790           if (info)
1791             (void) CloneString(&info->image_info->page,geometry);
1792           for ( ; image; image=image->next)
1793             (void) ParsePageGeometry(image,geometry,&image->page,exception);
1794           geometry=(char *) RelinquishMagickMemory(geometry);
1795           break;
1796         }
1797       if (LocaleNCompare(attribute,"pixel",5) == 0)
1798         {
1799           int
1800             items;
1801
1802           PixelInfo
1803             pixel;
1804
1805           register Quantum
1806             *q;
1807
1808           CacheView
1809             *image_view;
1810
1811           for ( ; image; image=image->next)
1812           {
1813             if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1814               break;
1815             x=0;
1816             y=0;
1817             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1818             (void) items;
1819             image_view=AcquireVirtualCacheView(image,exception);
1820             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1821             if (q != (Quantum *) NULL)
1822               {
1823                 if ((strchr(SvPV(sval,na),',') == 0) ||
1824                     (strchr(SvPV(sval,na),')') != 0))
1825                   QueryColorCompliance(SvPV(sval,na),AllCompliance,
1826                     &pixel,exception);
1827                 else
1828                   {
1829                     GetPixelInfo(image,&pixel);
1830                     flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1831                     pixel.red=geometry_info.rho;
1832                     if ((flags & SigmaValue) != 0)
1833                       pixel.green=geometry_info.sigma;
1834                     if ((flags & XiValue) != 0)
1835                       pixel.blue=geometry_info.xi;
1836                     if ((flags & PsiValue) != 0)
1837                       pixel.alpha=geometry_info.psi;
1838                     if ((flags & ChiValue) != 0)
1839                       pixel.black=geometry_info.chi;
1840                   }
1841                 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1842                 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1843                 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1844                 if (image->colorspace == CMYKColorspace)
1845                   SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1846                 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1847                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1848               }
1849             image_view=DestroyCacheView(image_view);
1850           }
1851           break;
1852         }
1853       if (LocaleCompare(attribute,"pointsize") == 0)
1854         {
1855           if (info)
1856             {
1857               (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1858               info->image_info->pointsize=geometry_info.rho;
1859             }
1860           break;
1861         }
1862       if (LocaleCompare(attribute,"preview") == 0)
1863         {
1864           sp=SvPOK(sval) ? ParseCommandOption(MagickPreviewOptions,MagickFalse,
1865             SvPV(sval,na)) : SvIV(sval);
1866           if (sp < 0)
1867             {
1868               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1869                 SvPV(sval,na));
1870               break;
1871             }
1872           if (info)
1873             info->image_info->preview_type=(PreviewType) sp;
1874           break;
1875         }
1876       if (info)
1877         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1878       for ( ; image; image=image->next)
1879         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1880       break;
1881     }
1882     case 'Q':
1883     case 'q':
1884     {
1885       if (LocaleCompare(attribute,"quality") == 0)
1886         {
1887           if (info)
1888             info->image_info->quality=SvIV(sval);
1889           for ( ; image; image=image->next)
1890             image->quality=SvIV(sval);
1891           break;
1892         }
1893       if (info)
1894         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1895       for ( ; image; image=image->next)
1896         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1897       break;
1898     }
1899     case 'R':
1900     case 'r':
1901     {
1902       if (LocaleCompare(attribute,"red-primary") == 0)
1903         {
1904           for ( ; image; image=image->next)
1905           {
1906             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1907             image->chromaticity.red_primary.x=geometry_info.rho;
1908             image->chromaticity.red_primary.y=geometry_info.sigma;
1909             if ((flags & SigmaValue) == 0)
1910               image->chromaticity.red_primary.y=
1911                 image->chromaticity.red_primary.x;
1912           }
1913           break;
1914         }
1915       if (LocaleCompare(attribute,"render") == 0)
1916         {
1917           sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1918             SvPV(sval,na)) : SvIV(sval);
1919           if (sp < 0)
1920             {
1921               ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1922                 SvPV(sval,na));
1923               break;
1924             }
1925          for ( ; image; image=image->next)
1926            image->rendering_intent=(RenderingIntent) sp;
1927          break;
1928        }
1929       if (LocaleCompare(attribute,"repage") == 0)
1930         {
1931           RectangleInfo
1932             geometry;
1933
1934           for ( ; image; image=image->next)
1935           {
1936             flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
1937             if ((flags & WidthValue) != 0)
1938               {
1939                 if ((flags & HeightValue) == 0)
1940                   geometry.height=geometry.width;
1941                 image->page.width=geometry.width;
1942                 image->page.height=geometry.height;
1943               }
1944             if ((flags & AspectValue) != 0)
1945               {
1946                 if ((flags & XValue) != 0)
1947                   image->page.x+=geometry.x;
1948                 if ((flags & YValue) != 0)
1949                   image->page.y+=geometry.y;
1950               }
1951             else
1952               {
1953                 if ((flags & XValue) != 0)
1954                   {
1955                     image->page.x=geometry.x;
1956                     if (((flags & WidthValue) != 0) && (geometry.x > 0))
1957                       image->page.width=image->columns+geometry.x;
1958                   }
1959                 if ((flags & YValue) != 0)
1960                   {
1961                     image->page.y=geometry.y;
1962                     if (((flags & HeightValue) != 0) && (geometry.y > 0))
1963                       image->page.height=image->rows+geometry.y;
1964                   }
1965               }
1966           }
1967           break;
1968         }
1969       if (info)
1970         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1971       for ( ; image; image=image->next)
1972         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1973       break;
1974     }
1975     case 'S':
1976     case 's':
1977     {
1978       if (LocaleCompare(attribute,"sampling-factor") == 0)
1979         {
1980           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1981             {
1982               ThrowPerlException(exception,OptionError,"MissingGeometry",
1983                 SvPV(sval,na));
1984               break;
1985             }
1986           if (info)
1987             (void) CloneString(&info->image_info->sampling_factor,
1988               SvPV(sval,na));
1989           break;
1990         }
1991       if (LocaleCompare(attribute,"scene") == 0)
1992         {
1993           for ( ; image; image=image->next)
1994             image->scene=SvIV(sval);
1995           break;
1996         }
1997       if (LocaleCompare(attribute,"server") == 0)
1998         goto display;
1999       if (LocaleCompare(attribute,"size") == 0)
2000         {
2001           if (info)
2002             {
2003               if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2004                 {
2005                   ThrowPerlException(exception,OptionError,"MissingGeometry",
2006                     SvPV(sval,na));
2007                   break;
2008                 }
2009               (void) CloneString(&info->image_info->size,SvPV(sval,na));
2010             }
2011           break;
2012         }
2013       if (LocaleCompare(attribute,"stroke") == 0)
2014         {
2015           if (info)
2016             (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2017           break;
2018         }
2019       if (info)
2020         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2021       for ( ; image; image=image->next)
2022         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2023       break;
2024     }
2025     case 'T':
2026     case 't':
2027     {
2028       if (LocaleCompare(attribute,"texture") == 0)
2029         {
2030           if (info)
2031             (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2032           break;
2033         }
2034       if (LocaleCompare(attribute,"thread-limit") == 0)
2035         {
2036           MagickSizeType
2037             limit;
2038
2039           limit=MagickResourceInfinity;
2040           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2041             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2042               100.0);
2043           (void) SetMagickResourceLimit(ThreadResource,limit);
2044           break;
2045         }
2046       if (LocaleCompare(attribute,"tile-offset") == 0)
2047         {
2048           char
2049             *geometry;
2050
2051           geometry=GetPageGeometry(SvPV(sval,na));
2052           if (info)
2053             (void) CloneString(&info->image_info->page,geometry);
2054           for ( ; image; image=image->next)
2055             (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2056               exception);
2057           geometry=(char *) RelinquishMagickMemory(geometry);
2058           break;
2059         }
2060       if (LocaleCompare(attribute,"time-limit") == 0)
2061         {
2062           MagickSizeType
2063             limit;
2064
2065           limit=MagickResourceInfinity;
2066           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2067             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2068               100.0);
2069           (void) SetMagickResourceLimit(TimeResource,limit);
2070           break;
2071         }
2072       if (LocaleCompare(attribute,"transparent-color") == 0)
2073         {
2074           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
2075             exception);
2076           if (info)
2077             info->image_info->transparent_color=target_color;
2078           for ( ; image; image=image->next)
2079             image->transparent_color=target_color;
2080           break;
2081         }
2082       if (LocaleCompare(attribute,"type") == 0)
2083         {
2084           sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2085             SvPV(sval,na)) : SvIV(sval);
2086           if (sp < 0)
2087             {
2088               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2089                 SvPV(sval,na));
2090               break;
2091             }
2092           if (info)
2093             info->image_info->type=(ImageType) sp;
2094           for ( ; image; image=image->next)
2095             SetImageType(image,(ImageType) sp,exception);
2096           break;
2097         }
2098       if (info)
2099         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2100       for ( ; image; image=image->next)
2101         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2102       break;
2103     }
2104     case 'U':
2105     case 'u':
2106     {
2107       if (LocaleCompare(attribute,"units") == 0)
2108         {
2109           sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2110             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2111           if (sp < 0)
2112             {
2113               ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2114                 SvPV(sval,na));
2115               break;
2116             }
2117           if (info)
2118             info->image_info->units=(ResolutionType) sp;
2119           for ( ; image; image=image->next)
2120           {
2121             ResolutionType
2122               units;
2123
2124             units=(ResolutionType) sp;
2125             if (image->units != units)
2126               switch (image->units)
2127               {
2128                 case UndefinedResolution:
2129                 case PixelsPerInchResolution:
2130                 {
2131                   if (units == PixelsPerCentimeterResolution)
2132                     {
2133                       image->resolution.x*=2.54;
2134                       image->resolution.y*=2.54;
2135                     }
2136                   break;
2137                 }
2138                 case PixelsPerCentimeterResolution:
2139                 {
2140                   if (units == PixelsPerInchResolution)
2141                     {
2142                       image->resolution.x/=2.54;
2143                       image->resolution.y/=2.54;
2144                     }
2145                   break;
2146                 }
2147               }
2148             image->units=units;
2149           }
2150           break;
2151         }
2152       if (info)
2153         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2154       for ( ; image; image=image->next)
2155         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2156       break;
2157     }
2158     case 'V':
2159     case 'v':
2160     {
2161       if (LocaleCompare(attribute,"verbose") == 0)
2162         {
2163           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2164             SvPV(sval,na)) : SvIV(sval);
2165           if (sp < 0)
2166             {
2167               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2168                 SvPV(sval,na));
2169               break;
2170             }
2171           if (info)
2172             info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2173           break;
2174         }
2175       if (LocaleCompare(attribute,"view") == 0)
2176         {
2177           if (info)
2178             (void) CloneString(&info->image_info->view,SvPV(sval,na));
2179           break;
2180         }
2181       if (LocaleCompare(attribute,"virtual-pixel") == 0)
2182         {
2183           sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2184             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2185           if (sp < 0)
2186             {
2187               ThrowPerlException(exception,OptionError,
2188                 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2189               break;
2190             }
2191           for ( ; image; image=image->next)
2192             SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp,exception);
2193           break;
2194         }
2195       if (info)
2196         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2197       for ( ; image; image=image->next)
2198         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2199       break;
2200     }
2201     case 'W':
2202     case 'w':
2203     {
2204       if (LocaleCompare(attribute,"white-point") == 0)
2205         {
2206           for ( ; image; image=image->next)
2207           {
2208             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2209             image->chromaticity.white_point.x=geometry_info.rho;
2210             image->chromaticity.white_point.y=geometry_info.sigma;
2211             if ((flags & SigmaValue) == 0)
2212               image->chromaticity.white_point.y=
2213                 image->chromaticity.white_point.x;
2214           }
2215           break;
2216         }
2217       if (info)
2218         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2219       for ( ; image; image=image->next)
2220         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2221       break;
2222     }
2223     default:
2224     {
2225       if (info)
2226         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2227       for ( ; image; image=image->next)
2228         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2229       break;
2230     }
2231   }
2232 }
2233 \f
2234 /*
2235 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2236 %                                                                             %
2237 %                                                                             %
2238 %                                                                             %
2239 %   S e t u p L i s t                                                         %
2240 %                                                                             %
2241 %                                                                             %
2242 %                                                                             %
2243 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2244 %
2245 %  Method SetupList returns the list of all the images linked by their
2246 %  image->next and image->previous link lists for use with ImageMagick.  If
2247 %  info is non-NULL, an info structure is returned in *info.  If
2248 %  reference_vector is non-NULL,an array of SV* are returned in
2249 %  *reference_vector.  Reference_vector is used when the images are going to be
2250 %  replaced with new Image*'s.
2251 %
2252 %  The format of the SetupList routine is:
2253 %
2254 %      Image *SetupList(SV *reference,struct PackageInfo **info,
2255 %        SV ***reference_vector,ExceptionInfo *exception)
2256 %
2257 %  A description of each parameter follows:
2258 %
2259 %    o list: a list of strings.
2260 %
2261 %    o string: a character string.
2262 %
2263 %    o exception: Return any errors or warnings in this structure.
2264 %
2265 */
2266 static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2267   SV ***reference_vector,ExceptionInfo *exception)
2268 {
2269   Image
2270     *image;
2271
2272   ssize_t
2273     current,
2274     last;
2275
2276   if (reference_vector)
2277     *reference_vector=NULL;
2278   if (info)
2279     *info=NULL;
2280   current=0;
2281   last=0;
2282   image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2283   if (info && (SvTYPE(reference) == SVt_PVAV))
2284     *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2285       exception);
2286   return(image);
2287 }
2288 \f
2289 /*
2290 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2291 %                                                                             %
2292 %                                                                             %
2293 %                                                                             %
2294 %   s t r E Q c a s e                                                         %
2295 %                                                                             %
2296 %                                                                             %
2297 %                                                                             %
2298 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2299 %
2300 %  strEQcase() compares two strings and returns 0 if they are the
2301 %  same or if the second string runs out first.  The comparison is case
2302 %  insensitive.
2303 %
2304 %  The format of the strEQcase routine is:
2305 %
2306 %      ssize_t strEQcase(const char *p,const char *q)
2307 %
2308 %  A description of each parameter follows:
2309 %
2310 %    o p: a character string.
2311 %
2312 %    o q: a character string.
2313 %
2314 %
2315 */
2316 static ssize_t strEQcase(const char *p,const char *q)
2317 {
2318   char
2319     c;
2320
2321   register ssize_t
2322     i;
2323
2324   for (i=0 ; (c=(*q)) != 0; i++)
2325   {
2326     if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2327         (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2328       return(0);
2329     p++;
2330     q++;
2331   }
2332   return(((*q == 0) && (*p == 0)) ? i : 0);
2333 }
2334 \f
2335 /*
2336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2337 %                                                                             %
2338 %                                                                             %
2339 %                                                                             %
2340 %   I m a g e : : M a g i c k                                                 %
2341 %                                                                             %
2342 %                                                                             %
2343 %                                                                             %
2344 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2345 %
2346 %
2347 */
2348 MODULE = Image::Magick PACKAGE = Image::Magick
2349
2350 PROTOTYPES: ENABLE
2351
2352 BOOT:
2353   MagickCoreGenesis("PerlMagick",MagickFalse);
2354   SetWarningHandler(NULL);
2355   SetErrorHandler(NULL);
2356   magick_registry=NewSplayTree((int (*)(const void *,const void *))
2357     NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2358
2359 void
2360 UNLOAD()
2361   PPCODE:
2362   {
2363     if (magick_registry != (SplayTreeInfo *) NULL)
2364       magick_registry=DestroySplayTree(magick_registry);
2365     MagickCoreTerminus();
2366   }
2367
2368 double
2369 constant(name,argument)
2370   char *name
2371   ssize_t argument
2372 \f
2373 #
2374 ###############################################################################
2375 #                                                                             #
2376 #                                                                             #
2377 #                                                                             #
2378 #   A n i m a t e                                                             #
2379 #                                                                             #
2380 #                                                                             #
2381 #                                                                             #
2382 ###############################################################################
2383 #
2384 #
2385 void
2386 Animate(ref,...)
2387   Image::Magick ref=NO_INIT
2388   ALIAS:
2389     AnimateImage  = 1
2390     animate       = 2
2391     animateimage  = 3
2392   PPCODE:
2393   {
2394     ExceptionInfo
2395       *exception;
2396
2397     Image
2398       *image;
2399
2400     register ssize_t
2401       i;
2402
2403     struct PackageInfo
2404       *info,
2405       *package_info;
2406
2407     SV
2408       *perl_exception,
2409       *reference;
2410
2411     PERL_UNUSED_VAR(ref);
2412     PERL_UNUSED_VAR(ix);
2413     exception=AcquireExceptionInfo();
2414     perl_exception=newSVpv("",0);
2415     package_info=(struct PackageInfo *) NULL;
2416     if (sv_isobject(ST(0)) == 0)
2417       {
2418         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2419           PackageName);
2420         goto PerlException;
2421       }
2422     reference=SvRV(ST(0));
2423     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2424     if (image == (Image *) NULL)
2425       {
2426         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2427           PackageName);
2428         goto PerlException;
2429       }
2430     package_info=ClonePackageInfo(info,exception);
2431     if (items == 2)
2432       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2433     else
2434       if (items > 2)
2435         for (i=2; i < items; i+=2)
2436           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2437             exception);
2438     (void) AnimateImages(package_info->image_info,image,exception);
2439     (void) CatchImageException(image);
2440
2441   PerlException:
2442     if (package_info != (struct PackageInfo *) NULL)
2443       DestroyPackageInfo(package_info);
2444     InheritPerlException(exception,perl_exception);
2445     exception=DestroyExceptionInfo(exception);
2446     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2447     SvPOK_on(perl_exception);
2448     ST(0)=sv_2mortal(perl_exception);
2449     XSRETURN(1);
2450   }
2451 \f
2452 #
2453 ###############################################################################
2454 #                                                                             #
2455 #                                                                             #
2456 #                                                                             #
2457 #   A p p e n d                                                               #
2458 #                                                                             #
2459 #                                                                             #
2460 #                                                                             #
2461 ###############################################################################
2462 #
2463 #
2464 void
2465 Append(ref,...)
2466   Image::Magick ref=NO_INIT
2467   ALIAS:
2468     AppendImage  = 1
2469     append       = 2
2470     appendimage  = 3
2471   PPCODE:
2472   {
2473     AV
2474       *av;
2475
2476     char
2477       *attribute;
2478
2479     ExceptionInfo
2480       *exception;
2481
2482     HV
2483       *hv;
2484
2485     Image
2486       *image;
2487
2488     register ssize_t
2489       i;
2490
2491     ssize_t
2492       stack;
2493
2494     struct PackageInfo
2495       *info;
2496
2497     SV
2498       *av_reference,
2499       *perl_exception,
2500       *reference,
2501       *rv,
2502       *sv;
2503
2504     PERL_UNUSED_VAR(ref);
2505     PERL_UNUSED_VAR(ix);
2506     exception=AcquireExceptionInfo();
2507     perl_exception=newSVpv("",0);
2508     sv=NULL;
2509     attribute=NULL;
2510     av=NULL;
2511     if (sv_isobject(ST(0)) == 0)
2512       {
2513         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2514           PackageName);
2515         goto PerlException;
2516       }
2517     reference=SvRV(ST(0));
2518     hv=SvSTASH(reference);
2519     av=newAV();
2520     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2521     SvREFCNT_dec(av);
2522     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2523     if (image == (Image *) NULL)
2524       {
2525         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2526           PackageName);
2527         goto PerlException;
2528       }
2529     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2530     /*
2531       Get options.
2532     */
2533     stack=MagickTrue;
2534     for (i=2; i < items; i+=2)
2535     {
2536       attribute=(char *) SvPV(ST(i-1),na);
2537       switch (*attribute)
2538       {
2539         case 'S':
2540         case 's':
2541         {
2542           if (LocaleCompare(attribute,"stack") == 0)
2543             {
2544               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2545                 SvPV(ST(i),na));
2546               if (stack < 0)
2547                 {
2548                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
2549                     SvPV(ST(i),na));
2550                   return;
2551                 }
2552               break;
2553             }
2554           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2555             attribute);
2556           break;
2557         }
2558         default:
2559         {
2560           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2561             attribute);
2562           break;
2563         }
2564       }
2565     }
2566     image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2567     if (image == (Image *) NULL)
2568       goto PerlException;
2569     for ( ; image; image=image->next)
2570     {
2571       AddImageToRegistry(sv,image);
2572       rv=newRV(sv);
2573       av_push(av,sv_bless(rv,hv));
2574       SvREFCNT_dec(sv);
2575     }
2576     exception=DestroyExceptionInfo(exception);
2577     ST(0)=av_reference;
2578     SvREFCNT_dec(perl_exception);
2579     XSRETURN(1);
2580
2581   PerlException:
2582     InheritPerlException(exception,perl_exception);
2583     exception=DestroyExceptionInfo(exception);
2584     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2585     SvPOK_on(perl_exception);
2586     ST(0)=sv_2mortal(perl_exception);
2587     XSRETURN(1);
2588   }
2589 \f
2590 #
2591 ###############################################################################
2592 #                                                                             #
2593 #                                                                             #
2594 #                                                                             #
2595 #   A v e r a g e                                                             #
2596 #                                                                             #
2597 #                                                                             #
2598 #                                                                             #
2599 ###############################################################################
2600 #
2601 #
2602 void
2603 Average(ref)
2604   Image::Magick ref=NO_INIT
2605   ALIAS:
2606     AverageImage   = 1
2607     average        = 2
2608     averageimage   = 3
2609   PPCODE:
2610   {
2611     AV
2612       *av;
2613
2614     char
2615       *p;
2616
2617     ExceptionInfo
2618       *exception;
2619
2620     HV
2621       *hv;
2622
2623     Image
2624       *image;
2625
2626     struct PackageInfo
2627       *info;
2628
2629     SV
2630       *perl_exception,
2631       *reference,
2632       *rv,
2633       *sv;
2634
2635     PERL_UNUSED_VAR(ref);
2636     PERL_UNUSED_VAR(ix);
2637     exception=AcquireExceptionInfo();
2638     perl_exception=newSVpv("",0);
2639     sv=NULL;
2640     if (sv_isobject(ST(0)) == 0)
2641       {
2642         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2643           PackageName);
2644         goto PerlException;
2645       }
2646     reference=SvRV(ST(0));
2647     hv=SvSTASH(reference);
2648     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2649     if (image == (Image *) NULL)
2650       {
2651         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2652           PackageName);
2653         goto PerlException;
2654       }
2655     image=EvaluateImages(image,MeanEvaluateOperator,exception);
2656     if (image == (Image *) NULL)
2657       goto PerlException;
2658     /*
2659       Create blessed Perl array for the returned image.
2660     */
2661     av=newAV();
2662     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2663     SvREFCNT_dec(av);
2664     AddImageToRegistry(sv,image);
2665     rv=newRV(sv);
2666     av_push(av,sv_bless(rv,hv));
2667     SvREFCNT_dec(sv);
2668     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2669     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
2670       "average-%.*s",(int) (MaxTextExtent-9),
2671       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2672     (void) CopyMagickString(image->filename,info->image_info->filename,
2673       MaxTextExtent);
2674     SetImageInfo(info->image_info,0,exception);
2675     exception=DestroyExceptionInfo(exception);
2676     SvREFCNT_dec(perl_exception);
2677     XSRETURN(1);
2678
2679   PerlException:
2680     InheritPerlException(exception,perl_exception);
2681     exception=DestroyExceptionInfo(exception);
2682     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2683     SvPOK_on(perl_exception);
2684     ST(0)=sv_2mortal(perl_exception);
2685     XSRETURN(1);
2686   }
2687 \f
2688 #
2689 ###############################################################################
2690 #                                                                             #
2691 #                                                                             #
2692 #                                                                             #
2693 #   B l o b T o I m a g e                                                     #
2694 #                                                                             #
2695 #                                                                             #
2696 #                                                                             #
2697 ###############################################################################
2698 #
2699 #
2700 void
2701 BlobToImage(ref,...)
2702   Image::Magick ref=NO_INIT
2703   ALIAS:
2704     BlobToImage  = 1
2705     blobtoimage  = 2
2706     blobto       = 3
2707   PPCODE:
2708   {
2709     AV
2710       *av;
2711
2712     char
2713       **keep,
2714       **list;
2715
2716     ExceptionInfo
2717       *exception;
2718
2719     HV
2720       *hv;
2721
2722     Image
2723       *image;
2724
2725     register char
2726       **p;
2727
2728     register ssize_t
2729       i;
2730
2731     ssize_t
2732       ac,
2733       n,
2734       number_images;
2735
2736     STRLEN
2737       *length;
2738
2739     struct PackageInfo
2740       *info;
2741
2742     SV
2743       *perl_exception,
2744       *reference,
2745       *rv,
2746       *sv;
2747
2748     PERL_UNUSED_VAR(ref);
2749     PERL_UNUSED_VAR(ix);
2750     exception=AcquireExceptionInfo();
2751     perl_exception=newSVpv("",0);
2752     sv=NULL;
2753     number_images=0;
2754     ac=(items < 2) ? 1 : items-1;
2755     length=(STRLEN *) NULL;
2756     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2757     if (list == (char **) NULL)
2758       {
2759         ThrowPerlException(exception,ResourceLimitError,
2760           "MemoryAllocationFailed",PackageName);
2761         goto PerlException;
2762       }
2763     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2764     if (length == (STRLEN *) NULL)
2765       {
2766         ThrowPerlException(exception,ResourceLimitError,
2767           "MemoryAllocationFailed",PackageName);
2768         goto PerlException;
2769       }
2770     if (sv_isobject(ST(0)) == 0)
2771       {
2772         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2773           PackageName);
2774         goto PerlException;
2775       }
2776     reference=SvRV(ST(0));
2777     hv=SvSTASH(reference);
2778     if (SvTYPE(reference) != SVt_PVAV)
2779       {
2780         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2781           PackageName);
2782         goto PerlException;
2783       }
2784     av=(AV *) reference;
2785     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2786       exception);
2787     n=1;
2788     if (items <= 1)
2789       {
2790         ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2791         goto PerlException;
2792       }
2793     for (n=0, i=0; i < ac; i++)
2794     {
2795       list[n]=(char *) (SvPV(ST(i+1),length[n]));
2796       if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2797         {
2798           list[n]=(char *) (SvPV(ST(i+2),length[n]));
2799           continue;
2800         }
2801       n++;
2802     }
2803     list[n]=(char *) NULL;
2804     keep=list;
2805     for (i=number_images=0; i < n; i++)
2806     {
2807       image=BlobToImage(info->image_info,list[i],length[i],exception);
2808       if (image == (Image *) NULL)
2809         break;
2810       for ( ; image; image=image->next)
2811       {
2812         AddImageToRegistry(sv,image);
2813         rv=newRV(sv);
2814         av_push(av,sv_bless(rv,hv));
2815         SvREFCNT_dec(sv);
2816         number_images++;
2817       }
2818     }
2819     /*
2820       Free resources.
2821     */
2822     for (i=0; i < n; i++)
2823       if (list[i] != (char *) NULL)
2824         for (p=keep; list[i] != *p++; )
2825           if (*p == (char *) NULL)
2826             {
2827               list[i]=(char *) RelinquishMagickMemory(list[i]);
2828               break;
2829             }
2830
2831   PerlException:
2832     if (list)
2833       list=(char **) RelinquishMagickMemory(list);
2834     if (length)
2835       length=(STRLEN *) RelinquishMagickMemory(length);
2836     InheritPerlException(exception,perl_exception);
2837     exception=DestroyExceptionInfo(exception);
2838     sv_setiv(perl_exception,(IV) number_images);
2839     SvPOK_on(perl_exception);
2840     ST(0)=sv_2mortal(perl_exception);
2841     XSRETURN(1);
2842   }
2843 \f
2844 #
2845 ###############################################################################
2846 #                                                                             #
2847 #                                                                             #
2848 #                                                                             #
2849 #   C h a n n e l F x                                                         #
2850 #                                                                             #
2851 #                                                                             #
2852 #                                                                             #
2853 ###############################################################################
2854 #
2855 #
2856 void
2857 ChannelFx(ref,...)
2858   Image::Magick ref=NO_INIT
2859   ALIAS:
2860     ChannelFxImage  = 1
2861     channelfx       = 2
2862     channelfximage  = 3
2863   PPCODE:
2864   {
2865     AV
2866       *av;
2867
2868     char
2869       *attribute,
2870       expression[MaxTextExtent];
2871
2872     ChannelType
2873       channel,
2874       channel_mask;
2875
2876     ExceptionInfo
2877       *exception;
2878
2879     HV
2880       *hv;
2881
2882     Image
2883       *image;
2884
2885     register ssize_t
2886       i;
2887
2888     struct PackageInfo
2889       *info;
2890
2891     SV
2892       *av_reference,
2893       *perl_exception,
2894       *reference,
2895       *rv,
2896       *sv;
2897
2898     PERL_UNUSED_VAR(ref);
2899     PERL_UNUSED_VAR(ix);
2900     exception=AcquireExceptionInfo();
2901     perl_exception=newSVpv("",0);
2902     sv=NULL;
2903     attribute=NULL;
2904     av=NULL;
2905     if (sv_isobject(ST(0)) == 0)
2906       {
2907         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2908           PackageName);
2909         goto PerlException;
2910       }
2911     reference=SvRV(ST(0));
2912     hv=SvSTASH(reference);
2913     av=newAV();
2914     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2915     SvREFCNT_dec(av);
2916     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2917     if (image == (Image *) NULL)
2918       {
2919         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2920           PackageName);
2921         goto PerlException;
2922       }
2923     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2924     /*
2925       Get options.
2926     */
2927     channel=DefaultChannels;
2928     (void) CopyMagickString(expression,"u",MaxTextExtent);
2929     if (items == 2)
2930       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MaxTextExtent);
2931     else
2932       for (i=2; i < items; i+=2)
2933       {
2934         attribute=(char *) SvPV(ST(i-1),na);
2935         switch (*attribute)
2936         {
2937           case 'C':
2938           case 'c':
2939           {
2940             if (LocaleCompare(attribute,"channel") == 0)
2941               {
2942                 ssize_t
2943                   option;
2944
2945                 option=ParseChannelOption(SvPV(ST(i),na));
2946                 if (option < 0)
2947                   {
2948                     ThrowPerlException(exception,OptionError,
2949                       "UnrecognizedType",SvPV(ST(i),na));
2950                     return;
2951                   }
2952                 channel=(ChannelType) option;
2953                 break;
2954               }
2955             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2956               attribute);
2957             break;
2958           }
2959           case 'E':
2960           case 'e':
2961           {
2962             if (LocaleCompare(attribute,"expression") == 0)
2963               {
2964                 (void) CopyMagickString(expression,SvPV(ST(i),na),
2965                   MaxTextExtent);
2966                 break;
2967               }
2968             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2969               attribute);
2970             break;
2971           }
2972           default:
2973           {
2974             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2975               attribute);
2976             break;
2977           }
2978         }
2979       }
2980     channel_mask=SetImageChannelMask(image,channel);
2981     image=ChannelFxImage(image,expression,exception);
2982     if (image != (Image *) NULL)
2983       (void) SetImageChannelMask(image,channel_mask);
2984     if (image == (Image *) NULL)
2985       goto PerlException;
2986     for ( ; image; image=image->next)
2987     {
2988       AddImageToRegistry(sv,image);
2989       rv=newRV(sv);
2990       av_push(av,sv_bless(rv,hv));
2991       SvREFCNT_dec(sv);
2992     }
2993     exception=DestroyExceptionInfo(exception);
2994     ST(0)=av_reference;
2995     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
2996     XSRETURN(1);
2997
2998   PerlException:
2999     InheritPerlException(exception,perl_exception);
3000     exception=DestroyExceptionInfo(exception);
3001     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3002     SvPOK_on(perl_exception);
3003     ST(0)=sv_2mortal(perl_exception);
3004     XSRETURN(1);
3005   }
3006 \f
3007 #
3008 ###############################################################################
3009 #                                                                             #
3010 #                                                                             #
3011 #                                                                             #
3012 #   C l o n e                                                                 #
3013 #                                                                             #
3014 #                                                                             #
3015 #                                                                             #
3016 ###############################################################################
3017 #
3018 #
3019 void
3020 Clone(ref)
3021   Image::Magick ref=NO_INIT
3022   ALIAS:
3023     CopyImage   = 1
3024     copy        = 2
3025     copyimage   = 3
3026     CloneImage  = 4
3027     clone       = 5
3028     cloneimage  = 6
3029     Clone       = 7
3030   PPCODE:
3031   {
3032     AV
3033       *av;
3034
3035     ExceptionInfo
3036       *exception;
3037
3038     HV
3039       *hv;
3040
3041     Image
3042       *clone,
3043       *image;
3044
3045     struct PackageInfo
3046       *info;
3047
3048     SV
3049       *perl_exception,
3050       *reference,
3051       *rv,
3052       *sv;
3053
3054     PERL_UNUSED_VAR(ref);
3055     PERL_UNUSED_VAR(ix);
3056     exception=AcquireExceptionInfo();
3057     perl_exception=newSVpv("",0);
3058     sv=NULL;
3059     if (sv_isobject(ST(0)) == 0)
3060       {
3061         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3062           PackageName);
3063         goto PerlException;
3064       }
3065     reference=SvRV(ST(0));
3066     hv=SvSTASH(reference);
3067     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3068     if (image == (Image *) NULL)
3069       {
3070         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3071           PackageName);
3072         goto PerlException;
3073       }
3074     /*
3075       Create blessed Perl array for the returned image.
3076     */
3077     av=newAV();
3078     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3079     SvREFCNT_dec(av);
3080     for ( ; image; image=image->next)
3081     {
3082       clone=CloneImage(image,0,0,MagickTrue,exception);
3083       if (clone == (Image *) NULL)
3084         break;
3085       AddImageToRegistry(sv,clone);
3086       rv=newRV(sv);
3087       av_push(av,sv_bless(rv,hv));
3088       SvREFCNT_dec(sv);
3089     }
3090     exception=DestroyExceptionInfo(exception);
3091     SvREFCNT_dec(perl_exception);
3092     XSRETURN(1);
3093
3094   PerlException:
3095     InheritPerlException(exception,perl_exception);
3096     exception=DestroyExceptionInfo(exception);
3097     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3098     SvPOK_on(perl_exception);
3099     ST(0)=sv_2mortal(perl_exception);
3100     XSRETURN(1);
3101   }
3102 \f
3103 #
3104 ###############################################################################
3105 #                                                                             #
3106 #                                                                             #
3107 #                                                                             #
3108 #   C L O N E                                                                 #
3109 #                                                                             #
3110 #                                                                             #
3111 #                                                                             #
3112 ###############################################################################
3113 #
3114 #
3115 void
3116 CLONE(ref,...)
3117   SV *ref;
3118   CODE:
3119   {
3120     PERL_UNUSED_VAR(ref);
3121     if (magick_registry != (SplayTreeInfo *) NULL)
3122       {
3123         register Image
3124           *p;
3125
3126         ResetSplayTreeIterator(magick_registry);
3127         p=(Image *) GetNextKeyInSplayTree(magick_registry);
3128         while (p != (Image *) NULL)
3129         {
3130           ReferenceImage(p);
3131           p=(Image *) GetNextKeyInSplayTree(magick_registry);
3132         }
3133       }
3134   }
3135 \f
3136 #
3137 ###############################################################################
3138 #                                                                             #
3139 #                                                                             #
3140 #                                                                             #
3141 #   C o a l e s c e                                                           #
3142 #                                                                             #
3143 #                                                                             #
3144 #                                                                             #
3145 ###############################################################################
3146 #
3147 #
3148 void
3149 Coalesce(ref)
3150   Image::Magick ref=NO_INIT
3151   ALIAS:
3152     CoalesceImage   = 1
3153     coalesce        = 2
3154     coalesceimage   = 3
3155   PPCODE:
3156   {
3157     AV
3158       *av;
3159
3160     ExceptionInfo
3161       *exception;
3162
3163     HV
3164       *hv;
3165
3166     Image
3167       *image;
3168
3169     struct PackageInfo
3170       *info;
3171
3172     SV
3173       *av_reference,
3174       *perl_exception,
3175       *reference,
3176       *rv,
3177       *sv;
3178
3179     PERL_UNUSED_VAR(ref);
3180     PERL_UNUSED_VAR(ix);
3181     exception=AcquireExceptionInfo();
3182     perl_exception=newSVpv("",0);
3183     sv=NULL;
3184     if (sv_isobject(ST(0)) == 0)
3185       {
3186         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3187           PackageName);
3188         goto PerlException;
3189       }
3190     reference=SvRV(ST(0));
3191     hv=SvSTASH(reference);
3192     av=newAV();
3193     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3194     SvREFCNT_dec(av);
3195     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3196     if (image == (Image *) NULL)
3197       {
3198         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3199           PackageName);
3200         goto PerlException;
3201       }
3202     image=CoalesceImages(image,exception);
3203     if (image == (Image *) NULL)
3204       goto PerlException;
3205     for ( ; image; image=image->next)
3206     {
3207       AddImageToRegistry(sv,image);
3208       rv=newRV(sv);
3209       av_push(av,sv_bless(rv,hv));
3210       SvREFCNT_dec(sv);
3211     }
3212     exception=DestroyExceptionInfo(exception);
3213     ST(0)=av_reference;
3214     SvREFCNT_dec(perl_exception);
3215     XSRETURN(1);
3216
3217   PerlException:
3218     InheritPerlException(exception,perl_exception);
3219     exception=DestroyExceptionInfo(exception);
3220     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3221     SvPOK_on(perl_exception);
3222     ST(0)=sv_2mortal(perl_exception);
3223     XSRETURN(1);
3224   }
3225 \f
3226 #
3227 ###############################################################################
3228 #                                                                             #
3229 #                                                                             #
3230 #                                                                             #
3231 #   C o m p a r e                                                             #
3232 #                                                                             #
3233 #                                                                             #
3234 #                                                                             #
3235 ###############################################################################
3236 #
3237 #
3238 void
3239 Compare(ref,...)
3240   Image::Magick ref=NO_INIT
3241   ALIAS:
3242     CompareImages = 1
3243     compare      = 2
3244     compareimage = 3
3245   PPCODE:
3246   {
3247     AV
3248       *av;
3249
3250     char
3251       *attribute;
3252
3253     double
3254       distortion;
3255
3256     ExceptionInfo
3257       *exception;
3258
3259     HV
3260       *hv;
3261
3262     Image
3263       *difference_image,
3264       *image,
3265       *reconstruct_image;
3266
3267     MetricType
3268       metric;
3269
3270     register ssize_t
3271       i;
3272
3273     ssize_t
3274       option;
3275
3276     struct PackageInfo
3277       *info;
3278
3279     SV
3280       *av_reference,
3281       *perl_exception,
3282       *reference,
3283       *rv,
3284       *sv;
3285
3286     PERL_UNUSED_VAR(ref);
3287     PERL_UNUSED_VAR(ix);
3288     exception=AcquireExceptionInfo();
3289     perl_exception=newSVpv("",0);
3290     sv=NULL;
3291     av=NULL;
3292     attribute=NULL;
3293     if (sv_isobject(ST(0)) == 0)
3294       {
3295         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3296           PackageName);
3297         goto PerlException;
3298       }
3299     reference=SvRV(ST(0));
3300     hv=SvSTASH(reference);
3301     av=newAV();
3302     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3303     SvREFCNT_dec(av);
3304     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3305     if (image == (Image *) NULL)
3306       {
3307         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3308           PackageName);
3309         goto PerlException;
3310       }
3311     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3312     /*
3313       Get attribute.
3314     */
3315     reconstruct_image=image;
3316     metric=RootMeanSquaredErrorMetric;
3317     for (i=2; i < items; i+=2)
3318     {
3319       attribute=(char *) SvPV(ST(i-1),na);
3320       switch (*attribute)
3321       {
3322         case 'C':
3323         case 'c':
3324         {
3325           if (LocaleCompare(attribute,"channel") == 0)
3326             {
3327               ssize_t
3328                 option;
3329
3330               option=ParseChannelOption(SvPV(ST(i),na));
3331               if (option < 0)
3332                 {
3333                   ThrowPerlException(exception,OptionError,
3334                     "UnrecognizedType",SvPV(ST(i),na));
3335                   return;
3336                 }
3337               SetPixelChannelMask(image,(ChannelType) option);
3338               break;
3339             }
3340           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3341             attribute);
3342           break;
3343         }
3344         case 'F':
3345         case 'f':
3346         {
3347           if (LocaleCompare(attribute,"fuzz") == 0)
3348             {
3349               image->fuzz=StringToDoubleInterval(SvPV(ST(i),na),100.0);
3350               break;
3351             }
3352           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3353             attribute);
3354           break;
3355         }
3356         case 'I':
3357         case 'i':
3358         {
3359           if (LocaleCompare(attribute,"image") == 0)
3360             {
3361               reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3362                 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3363               break;
3364             }
3365           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3366             attribute);
3367           break;
3368         }
3369         case 'M':
3370         case 'm':
3371         {
3372           if (LocaleCompare(attribute,"metric") == 0)
3373             {
3374               option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3375                 SvPV(ST(i),na));
3376               if (option < 0)
3377                 {
3378                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3379                     SvPV(ST(i),na));
3380                   break;
3381                 }
3382               metric=(MetricType) option;
3383               break;
3384             }
3385           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3386             attribute);
3387           break;
3388         }
3389         default:
3390         {
3391           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3392             attribute);
3393           break;
3394         }
3395       }
3396     }
3397     difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3398       exception);
3399     if (difference_image != (Image *) NULL)
3400       {
3401         difference_image->error.mean_error_per_pixel=distortion;
3402         AddImageToRegistry(sv,difference_image);
3403         rv=newRV(sv);
3404         av_push(av,sv_bless(rv,hv));
3405         SvREFCNT_dec(sv);
3406       }
3407     exception=DestroyExceptionInfo(exception);
3408     ST(0)=av_reference;
3409     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3410     XSRETURN(1);
3411
3412   PerlException:
3413     InheritPerlException(exception,perl_exception);
3414     exception=DestroyExceptionInfo(exception);
3415     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3416     SvPOK_on(perl_exception);
3417     ST(0)=sv_2mortal(perl_exception);
3418     XSRETURN(1);
3419   }
3420 \f
3421 #
3422 ###############################################################################
3423 #                                                                             #
3424 #                                                                             #
3425 #                                                                             #
3426 #   C o m p l e x I m a g e s                                                 #
3427 #                                                                             #
3428 #                                                                             #
3429 #                                                                             #
3430 ###############################################################################
3431 #
3432 #
3433 void
3434 ComplexImages(ref)
3435   Image::Magick ref=NO_INIT
3436   ALIAS:
3437     ComplexImages   = 1
3438     compleximages   = 2
3439   PPCODE:
3440   {
3441     AV
3442       *av;
3443
3444     char
3445       *attribute,
3446       *p;
3447
3448     ComplexOperator
3449       op;
3450
3451     ExceptionInfo
3452       *exception;
3453
3454     HV
3455       *hv;
3456
3457     Image
3458       *image;
3459
3460     register ssize_t
3461       i;
3462
3463     struct PackageInfo
3464       *info;
3465
3466     SV
3467       *perl_exception,
3468       *reference,
3469       *rv,
3470       *sv;
3471
3472     PERL_UNUSED_VAR(ref);
3473     PERL_UNUSED_VAR(ix);
3474     exception=AcquireExceptionInfo();
3475     perl_exception=newSVpv("",0);
3476     sv=NULL;
3477     if (sv_isobject(ST(0)) == 0)
3478       {
3479         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3480           PackageName);
3481         goto PerlException;
3482       }
3483     reference=SvRV(ST(0));
3484     hv=SvSTASH(reference);
3485     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3486     if (image == (Image *) NULL)
3487       {
3488         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3489           PackageName);
3490         goto PerlException;
3491       }
3492     op=UndefinedComplexOperator;
3493     if (items == 2)
3494       {
3495         ssize_t
3496           in;
3497
3498         in=ParseCommandOption(MagickComplexOptions,MagickFalse,(char *)
3499           SvPV(ST(1),na));
3500         if (in < 0)
3501           {
3502             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3503               SvPV(ST(1),na));
3504             return;
3505           }
3506         op=(ComplexOperator) in;
3507       }
3508     else
3509       for (i=2; i < items; i+=2)
3510       {
3511         attribute=(char *) SvPV(ST(i-1),na);
3512         switch (*attribute)
3513         {
3514           case 'O':
3515           case 'o':
3516           {
3517             if (LocaleCompare(attribute,"operator") == 0)
3518               {
3519                 ssize_t
3520                   in;
3521
3522                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3523                   MagickComplexOptions,MagickFalse,SvPV(ST(i),na));
3524                 if (in < 0)
3525                   {
3526                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3527                       SvPV(ST(i),na));
3528                     return;
3529                   }
3530                 op=(ComplexOperator) in;
3531                 break;
3532               }
3533             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3534               attribute);
3535             break;
3536           }
3537           default:
3538           {
3539             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3540               attribute);
3541             break;
3542           }
3543         }
3544       }
3545     image=ComplexImages(image,op,exception);
3546     if (image == (Image *) NULL)
3547       goto PerlException;
3548     /*
3549       Create blessed Perl array for the returned image.
3550     */
3551     av=newAV();
3552     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3553     SvREFCNT_dec(av);
3554     AddImageToRegistry(sv,image);
3555     rv=newRV(sv);
3556     av_push(av,sv_bless(rv,hv));
3557     SvREFCNT_dec(sv);
3558     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3559     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
3560       "complex-%.*s",(int) (MaxTextExtent-9),
3561       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3562     (void) CopyMagickString(image->filename,info->image_info->filename,
3563       MaxTextExtent);
3564     SetImageInfo(info->image_info,0,exception);
3565     exception=DestroyExceptionInfo(exception);
3566     SvREFCNT_dec(perl_exception);
3567     XSRETURN(1);
3568
3569   PerlException:
3570     InheritPerlException(exception,perl_exception);
3571     exception=DestroyExceptionInfo(exception);
3572     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3573     SvPOK_on(perl_exception);
3574     ST(0)=sv_2mortal(perl_exception);
3575     XSRETURN(1);
3576   }
3577 \f
3578 #
3579 ###############################################################################
3580 #                                                                             #
3581 #                                                                             #
3582 #                                                                             #
3583 #   C o m p a r e L a y e r s                                                 #
3584 #                                                                             #
3585 #                                                                             #
3586 #                                                                             #
3587 ###############################################################################
3588 #
3589 #
3590 void
3591 CompareLayers(ref)
3592   Image::Magick ref=NO_INIT
3593   ALIAS:
3594     CompareImagesLayers   = 1
3595     comparelayers        = 2
3596     compareimagelayers   = 3
3597   PPCODE:
3598   {
3599     AV
3600       *av;
3601
3602     char
3603       *attribute;
3604
3605     ExceptionInfo
3606       *exception;
3607
3608     HV
3609       *hv;
3610
3611     Image
3612       *image;
3613
3614     LayerMethod
3615       method;
3616
3617     register ssize_t
3618       i;
3619
3620     ssize_t
3621       option;
3622
3623     struct PackageInfo
3624       *info;
3625
3626     SV
3627       *av_reference,
3628       *perl_exception,
3629       *reference,
3630       *rv,
3631       *sv;
3632
3633     PERL_UNUSED_VAR(ref);
3634     PERL_UNUSED_VAR(ix);
3635     exception=AcquireExceptionInfo();
3636     perl_exception=newSVpv("",0);
3637     sv=NULL;
3638     if (sv_isobject(ST(0)) == 0)
3639       {
3640         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3641           PackageName);
3642         goto PerlException;
3643       }
3644     reference=SvRV(ST(0));
3645     hv=SvSTASH(reference);
3646     av=newAV();
3647     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3648     SvREFCNT_dec(av);
3649     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3650     if (image == (Image *) NULL)
3651       {
3652         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3653           PackageName);
3654         goto PerlException;
3655       }
3656     method=CompareAnyLayer;
3657     for (i=2; i < items; i+=2)
3658     {
3659       attribute=(char *) SvPV(ST(i-1),na);
3660       switch (*attribute)
3661       {
3662         case 'M':
3663         case 'm':
3664         {
3665           if (LocaleCompare(attribute,"method") == 0)
3666             {
3667               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3668                 SvPV(ST(i),na));
3669               if (option < 0)
3670                 {
3671                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3672                     SvPV(ST(i),na));
3673                   break;
3674                 }
3675                method=(LayerMethod) option;
3676               break;
3677             }
3678           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3679             attribute);
3680           break;
3681         }
3682         default:
3683         {
3684           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3685             attribute);
3686           break;
3687         }
3688       }
3689     }
3690     image=CompareImagesLayers(image,method,exception);
3691     if (image == (Image *) NULL)
3692       goto PerlException;
3693     for ( ; image; image=image->next)
3694     {
3695       AddImageToRegistry(sv,image);
3696       rv=newRV(sv);
3697       av_push(av,sv_bless(rv,hv));
3698       SvREFCNT_dec(sv);
3699     }
3700     exception=DestroyExceptionInfo(exception);
3701     ST(0)=av_reference;
3702     SvREFCNT_dec(perl_exception);
3703     XSRETURN(1);
3704
3705   PerlException:
3706     InheritPerlException(exception,perl_exception);
3707     exception=DestroyExceptionInfo(exception);
3708     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3709     SvPOK_on(perl_exception);
3710     ST(0)=sv_2mortal(perl_exception);
3711     XSRETURN(1);
3712   }
3713 \f
3714 #
3715 ###############################################################################
3716 #                                                                             #
3717 #                                                                             #
3718 #                                                                             #
3719 #   D e s t r o y                                                             #
3720 #                                                                             #
3721 #                                                                             #
3722 #                                                                             #
3723 ###############################################################################
3724 #
3725 #
3726 void
3727 DESTROY(ref)
3728   Image::Magick ref=NO_INIT
3729   PPCODE:
3730   {
3731     SV
3732       *reference;
3733
3734     PERL_UNUSED_VAR(ref);
3735     if (sv_isobject(ST(0)) == 0)
3736       croak("ReferenceIsNotMyType");
3737     reference=SvRV(ST(0));
3738     switch (SvTYPE(reference))
3739     {
3740       case SVt_PVAV:
3741       {
3742         char
3743           message[MaxTextExtent];
3744
3745         const SV
3746           *key;
3747
3748         HV
3749           *hv;
3750
3751         GV
3752           **gvp;
3753
3754         struct PackageInfo
3755           *info;
3756
3757         SV
3758           *sv;
3759
3760         /*
3761           Array (AV *) reference
3762         */
3763         (void) FormatLocaleString(message,MaxTextExtent,"package%s%p",
3764           XS_VERSION,reference);
3765         hv=gv_stashpv(PackageName, FALSE);
3766         if (!hv)
3767           break;
3768         gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3769         if (!gvp)
3770           break;
3771         sv=GvSV(*gvp);
3772         if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3773           {
3774             info=INT2PTR(struct PackageInfo *,SvIV(sv));
3775             DestroyPackageInfo(info);
3776           }
3777         key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3778         (void) key;
3779         break;
3780       }
3781       case SVt_PVMG:
3782       {
3783         Image
3784           *image;
3785
3786         /*
3787           Blessed scalar = (Image *) SvIV(reference)
3788         */
3789         image=INT2PTR(Image *,SvIV(reference));
3790         if (image != (Image *) NULL)
3791           DeleteImageFromRegistry(reference,image);
3792         break;
3793       }
3794       default:
3795         break;
3796     }
3797   }
3798 \f
3799 #
3800 ###############################################################################
3801 #                                                                             #
3802 #                                                                             #
3803 #                                                                             #
3804 #   D i s p l a y                                                             #
3805 #                                                                             #
3806 #                                                                             #
3807 #                                                                             #
3808 ###############################################################################
3809 #
3810 #
3811 void
3812 Display(ref,...)
3813   Image::Magick ref=NO_INIT
3814   ALIAS:
3815     DisplayImage  = 1
3816     display       = 2
3817     displayimage  = 3
3818   PPCODE:
3819   {
3820     ExceptionInfo
3821       *exception;
3822
3823     Image
3824       *image;
3825
3826     register ssize_t
3827       i;
3828
3829     struct PackageInfo
3830       *info,
3831       *package_info;
3832
3833     SV
3834       *perl_exception,
3835       *reference;
3836
3837     PERL_UNUSED_VAR(ref);
3838     PERL_UNUSED_VAR(ix);
3839     exception=AcquireExceptionInfo();
3840     perl_exception=newSVpv("",0);
3841     package_info=(struct PackageInfo *) NULL;
3842     if (sv_isobject(ST(0)) == 0)
3843       {
3844         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3845           PackageName);
3846         goto PerlException;
3847       }
3848     reference=SvRV(ST(0));
3849     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3850     if (image == (Image *) NULL)
3851       {
3852         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3853           PackageName);
3854         goto PerlException;
3855       }
3856     package_info=ClonePackageInfo(info,exception);
3857     if (items == 2)
3858       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3859     else
3860       if (items > 2)
3861         for (i=2; i < items; i+=2)
3862           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3863             exception);
3864     (void) DisplayImages(package_info->image_info,image,exception);
3865     (void) CatchImageException(image);
3866
3867   PerlException:
3868     if (package_info != (struct PackageInfo *) NULL)
3869       DestroyPackageInfo(package_info);
3870     InheritPerlException(exception,perl_exception);
3871     exception=DestroyExceptionInfo(exception);
3872     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3873     SvPOK_on(perl_exception);
3874     ST(0)=sv_2mortal(perl_exception);
3875     XSRETURN(1);
3876   }
3877 \f
3878 #
3879 ###############################################################################
3880 #                                                                             #
3881 #                                                                             #
3882 #                                                                             #
3883 #   E v a l u a t e I m a g e s                                               #
3884 #                                                                             #
3885 #                                                                             #
3886 #                                                                             #
3887 ###############################################################################
3888 #
3889 #
3890 void
3891 EvaluateImages(ref)
3892   Image::Magick ref=NO_INIT
3893   ALIAS:
3894     EvaluateImages   = 1
3895     evaluateimages   = 2
3896   PPCODE:
3897   {
3898     AV
3899       *av;
3900
3901     char
3902       *attribute,
3903       *p;
3904
3905     ExceptionInfo
3906       *exception;
3907
3908     HV
3909       *hv;
3910
3911     Image
3912       *image;
3913
3914     MagickEvaluateOperator
3915       op;
3916
3917     register ssize_t
3918       i;
3919
3920     struct PackageInfo
3921       *info;
3922
3923     SV
3924       *perl_exception,
3925       *reference,
3926       *rv,
3927       *sv;
3928
3929     PERL_UNUSED_VAR(ref);
3930     PERL_UNUSED_VAR(ix);
3931     exception=AcquireExceptionInfo();
3932     perl_exception=newSVpv("",0);
3933     sv=NULL;
3934     if (sv_isobject(ST(0)) == 0)
3935       {
3936         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3937           PackageName);
3938         goto PerlException;
3939       }
3940     reference=SvRV(ST(0));
3941     hv=SvSTASH(reference);
3942     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3943     if (image == (Image *) NULL)
3944       {
3945         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3946           PackageName);
3947         goto PerlException;
3948       }
3949     op=MeanEvaluateOperator;
3950     if (items == 2)
3951       {
3952         ssize_t
3953           in;
3954
3955         in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
3956           SvPV(ST(1),na));
3957         if (in < 0)
3958           {
3959             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3960               SvPV(ST(1),na));
3961             return;
3962           }
3963         op=(MagickEvaluateOperator) in;
3964       }
3965     else
3966       for (i=2; i < items; i+=2)
3967       {
3968         attribute=(char *) SvPV(ST(i-1),na);
3969         switch (*attribute)
3970         {
3971           case 'O':
3972           case 'o':
3973           {
3974             if (LocaleCompare(attribute,"operator") == 0)
3975               {
3976                 ssize_t
3977                   in;
3978
3979                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3980                   MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
3981                 if (in < 0)
3982                   {
3983                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3984                       SvPV(ST(i),na));
3985                     return;
3986                   }
3987                 op=(MagickEvaluateOperator) in;
3988                 break;
3989               }
3990             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3991               attribute);
3992             break;
3993           }
3994           default:
3995           {
3996             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3997               attribute);
3998             break;
3999           }
4000         }
4001       }
4002     image=EvaluateImages(image,op,exception);
4003     if (image == (Image *) NULL)
4004       goto PerlException;
4005     /*
4006       Create blessed Perl array for the returned image.
4007     */
4008     av=newAV();
4009     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4010     SvREFCNT_dec(av);
4011     AddImageToRegistry(sv,image);
4012     rv=newRV(sv);
4013     av_push(av,sv_bless(rv,hv));
4014     SvREFCNT_dec(sv);
4015     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4016     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
4017       "evaluate-%.*s",(int) (MaxTextExtent-9),
4018       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4019     (void) CopyMagickString(image->filename,info->image_info->filename,
4020       MaxTextExtent);
4021     SetImageInfo(info->image_info,0,exception);
4022     exception=DestroyExceptionInfo(exception);
4023     SvREFCNT_dec(perl_exception);
4024     XSRETURN(1);
4025
4026   PerlException:
4027     InheritPerlException(exception,perl_exception);
4028     exception=DestroyExceptionInfo(exception);
4029     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4030     SvPOK_on(perl_exception);
4031     ST(0)=sv_2mortal(perl_exception);
4032     XSRETURN(1);
4033   }
4034 \f
4035 #
4036 ###############################################################################
4037 #                                                                             #
4038 #                                                                             #
4039 #                                                                             #
4040 #   F e a t u r e s                                                           #
4041 #                                                                             #
4042 #                                                                             #
4043 #                                                                             #
4044 ###############################################################################
4045 #
4046 #
4047 void
4048 Features(ref,...)
4049   Image::Magick ref=NO_INIT
4050   ALIAS:
4051     FeaturesImage = 1
4052     features      = 2
4053     featuresimage = 3
4054   PPCODE:
4055   {
4056 #define ChannelFeatures(channel,direction) \
4057 { \
4058   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4059     channel_features[channel].angular_second_moment[direction]); \
4060   PUSHs(sv_2mortal(newSVpv(message,0))); \
4061   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4062     channel_features[channel].contrast[direction]); \
4063   PUSHs(sv_2mortal(newSVpv(message,0))); \
4064   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4065     channel_features[channel].contrast[direction]); \
4066   PUSHs(sv_2mortal(newSVpv(message,0))); \
4067   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4068     channel_features[channel].variance_sum_of_squares[direction]); \
4069   PUSHs(sv_2mortal(newSVpv(message,0))); \
4070   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4071     channel_features[channel].inverse_difference_moment[direction]); \
4072   PUSHs(sv_2mortal(newSVpv(message,0))); \
4073   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4074     channel_features[channel].sum_average[direction]); \
4075   PUSHs(sv_2mortal(newSVpv(message,0))); \
4076   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4077     channel_features[channel].sum_variance[direction]); \
4078   PUSHs(sv_2mortal(newSVpv(message,0))); \
4079   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4080     channel_features[channel].sum_entropy[direction]); \
4081   PUSHs(sv_2mortal(newSVpv(message,0))); \
4082   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4083     channel_features[channel].entropy[direction]); \
4084   PUSHs(sv_2mortal(newSVpv(message,0))); \
4085   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4086     channel_features[channel].difference_variance[direction]); \
4087   PUSHs(sv_2mortal(newSVpv(message,0))); \
4088   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4089     channel_features[channel].difference_entropy[direction]); \
4090   PUSHs(sv_2mortal(newSVpv(message,0))); \
4091   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4092     channel_features[channel].measure_of_correlation_1[direction]); \
4093   PUSHs(sv_2mortal(newSVpv(message,0))); \
4094   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4095     channel_features[channel].measure_of_correlation_2[direction]); \
4096   PUSHs(sv_2mortal(newSVpv(message,0))); \
4097   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4098     channel_features[channel].maximum_correlation_coefficient[direction]); \
4099   PUSHs(sv_2mortal(newSVpv(message,0))); \
4100 }
4101
4102     AV
4103       *av;
4104
4105     char
4106       *attribute,
4107       message[MaxTextExtent];
4108
4109     ChannelFeatures
4110       *channel_features;
4111
4112     double
4113       distance;
4114
4115     ExceptionInfo
4116       *exception;
4117
4118     Image
4119       *image;
4120
4121     register ssize_t
4122       i;
4123
4124     ssize_t
4125       count;
4126
4127     struct PackageInfo
4128       *info;
4129
4130     SV
4131       *perl_exception,
4132       *reference;
4133
4134     PERL_UNUSED_VAR(ref);
4135     PERL_UNUSED_VAR(ix);
4136     exception=AcquireExceptionInfo();
4137     perl_exception=newSVpv("",0);
4138     av=NULL;
4139     if (sv_isobject(ST(0)) == 0)
4140       {
4141         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4142           PackageName);
4143         goto PerlException;
4144       }
4145     reference=SvRV(ST(0));
4146     av=newAV();
4147     SvREFCNT_dec(av);
4148     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4149     if (image == (Image *) NULL)
4150       {
4151         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4152           PackageName);
4153         goto PerlException;
4154       }
4155     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4156     distance=1;
4157     for (i=2; i < items; i+=2)
4158     {
4159       attribute=(char *) SvPV(ST(i-1),na);
4160       switch (*attribute)
4161       {
4162         case 'D':
4163         case 'd':
4164         {
4165           if (LocaleCompare(attribute,"distance") == 0)
4166             {
4167               distance=StringToLong((char *) SvPV(ST(1),na));
4168               break;
4169             }
4170           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4171             attribute);
4172           break;
4173         }
4174         default:
4175         {
4176           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4177             attribute);
4178           break;
4179         }
4180       }
4181     }
4182     count=0;
4183     for ( ; image; image=image->next)
4184     {
4185       channel_features=GetImageFeatures(image,distance,exception);
4186       if (channel_features == (ChannelFeatures *) NULL)
4187         continue;
4188       count++;
4189       EXTEND(sp,75*count);
4190       for (i=0; i < 4; i++)
4191       {
4192         ChannelFeatures(RedChannel,i);
4193         ChannelFeatures(GreenChannel,i);
4194         ChannelFeatures(BlueChannel,i);
4195         if (image->colorspace == CMYKColorspace)
4196           ChannelFeatures(BlackChannel,i);
4197         if (image->alpha_trait == BlendPixelTrait)
4198           ChannelFeatures(AlphaChannel,i);
4199       }
4200       channel_features=(ChannelFeatures *)
4201         RelinquishMagickMemory(channel_features);
4202     }
4203
4204   PerlException:
4205     InheritPerlException(exception,perl_exception);
4206     exception=DestroyExceptionInfo(exception);
4207     SvREFCNT_dec(perl_exception);
4208   }
4209 \f
4210 #
4211 ###############################################################################
4212 #                                                                             #
4213 #                                                                             #
4214 #                                                                             #
4215 #   F l a t t e n                                                             #
4216 #                                                                             #
4217 #                                                                             #
4218 #                                                                             #
4219 ###############################################################################
4220 #
4221 #
4222 void
4223 Flatten(ref)
4224   Image::Magick ref=NO_INIT
4225   ALIAS:
4226     FlattenImage   = 1
4227     flatten        = 2
4228     flattenimage   = 3
4229   PPCODE:
4230   {
4231     AV
4232       *av;
4233
4234     char
4235       *attribute,
4236       *p;
4237
4238     ExceptionInfo
4239       *exception;
4240
4241     HV
4242       *hv;
4243
4244     Image
4245       *image;
4246
4247     PixelInfo
4248       background_color;
4249
4250     register ssize_t
4251       i;
4252
4253     struct PackageInfo
4254       *info;
4255
4256     SV
4257       *perl_exception,
4258       *reference,
4259       *rv,
4260       *sv;
4261
4262     PERL_UNUSED_VAR(ref);
4263     PERL_UNUSED_VAR(ix);
4264     exception=AcquireExceptionInfo();
4265     perl_exception=newSVpv("",0);
4266     sv=NULL;
4267     if (sv_isobject(ST(0)) == 0)
4268       {
4269         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4270           PackageName);
4271         goto PerlException;
4272       }
4273     reference=SvRV(ST(0));
4274     hv=SvSTASH(reference);
4275     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4276     if (image == (Image *) NULL)
4277       {
4278         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4279           PackageName);
4280         goto PerlException;
4281       }
4282     background_color=image->background_color;
4283     if (items == 2)
4284       (void) QueryColorCompliance((char *) SvPV(ST(1),na),AllCompliance,
4285         &background_color,exception);
4286     else
4287       for (i=2; i < items; i+=2)
4288       {
4289         attribute=(char *) SvPV(ST(i-1),na);
4290         switch (*attribute)
4291         {
4292           case 'B':
4293           case 'b':
4294           {
4295             if (LocaleCompare(attribute,"background") == 0)
4296               {
4297                 (void) QueryColorCompliance((char *) SvPV(ST(1),na),
4298                   AllCompliance,&background_color,exception);
4299                 break;
4300               }
4301             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4302               attribute);
4303             break;
4304           }
4305           default:
4306           {
4307             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4308               attribute);
4309             break;
4310           }
4311         }
4312       }
4313     image->background_color=background_color;
4314     image=MergeImageLayers(image,FlattenLayer,exception);
4315     if (image == (Image *) NULL)
4316       goto PerlException;
4317     /*
4318       Create blessed Perl array for the returned image.
4319     */
4320     av=newAV();
4321     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4322     SvREFCNT_dec(av);
4323     AddImageToRegistry(sv,image);
4324     rv=newRV(sv);
4325     av_push(av,sv_bless(rv,hv));
4326     SvREFCNT_dec(sv);
4327     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4328     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
4329       "flatten-%.*s",(int) (MaxTextExtent-9),
4330       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4331     (void) CopyMagickString(image->filename,info->image_info->filename,
4332       MaxTextExtent);
4333     SetImageInfo(info->image_info,0,exception);
4334     exception=DestroyExceptionInfo(exception);
4335     SvREFCNT_dec(perl_exception);
4336     XSRETURN(1);
4337
4338   PerlException:
4339     InheritPerlException(exception,perl_exception);
4340     exception=DestroyExceptionInfo(exception);
4341     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4342     SvPOK_on(perl_exception);  /* return messages in string context */
4343     ST(0)=sv_2mortal(perl_exception);
4344     XSRETURN(1);
4345   }
4346 \f
4347 #
4348 ###############################################################################
4349 #                                                                             #
4350 #                                                                             #
4351 #                                                                             #
4352 #   F x                                                                       #
4353 #                                                                             #
4354 #                                                                             #
4355 #                                                                             #
4356 ###############################################################################
4357 #
4358 #
4359 void
4360 Fx(ref,...)
4361   Image::Magick ref=NO_INIT
4362   ALIAS:
4363     FxImage  = 1
4364     fx       = 2
4365     fximage  = 3
4366   PPCODE:
4367   {
4368     AV
4369       *av;
4370
4371     char
4372       *attribute,
4373       expression[MaxTextExtent];
4374
4375     ChannelType
4376       channel,
4377       channel_mask;
4378
4379     ExceptionInfo
4380       *exception;
4381
4382     HV
4383       *hv;
4384
4385     Image
4386       *image;
4387
4388     register ssize_t
4389       i;
4390
4391     struct PackageInfo
4392       *info;
4393
4394     SV
4395       *av_reference,
4396       *perl_exception,
4397       *reference,
4398       *rv,
4399       *sv;
4400
4401     PERL_UNUSED_VAR(ref);
4402     PERL_UNUSED_VAR(ix);
4403     exception=AcquireExceptionInfo();
4404     perl_exception=newSVpv("",0);
4405     sv=NULL;
4406     attribute=NULL;
4407     av=NULL;
4408     if (sv_isobject(ST(0)) == 0)
4409       {
4410         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4411           PackageName);
4412         goto PerlException;
4413       }
4414     reference=SvRV(ST(0));
4415     hv=SvSTASH(reference);
4416     av=newAV();
4417     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4418     SvREFCNT_dec(av);
4419     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4420     if (image == (Image *) NULL)
4421       {
4422         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4423           PackageName);
4424         goto PerlException;
4425       }
4426     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4427     /*
4428       Get options.
4429     */
4430     channel=DefaultChannels;
4431     (void) CopyMagickString(expression,"u",MaxTextExtent);
4432     if (items == 2)
4433       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MaxTextExtent);
4434     else
4435       for (i=2; i < items; i+=2)
4436       {
4437         attribute=(char *) SvPV(ST(i-1),na);
4438         switch (*attribute)
4439         {
4440           case 'C':
4441           case 'c':
4442           {
4443             if (LocaleCompare(attribute,"channel") == 0)
4444               {
4445                 ssize_t
4446                   option;
4447
4448                 option=ParseChannelOption(SvPV(ST(i),na));
4449                 if (option < 0)
4450                   {
4451                     ThrowPerlException(exception,OptionError,
4452                       "UnrecognizedType",SvPV(ST(i),na));
4453                     return;
4454                   }
4455                 channel=(ChannelType) option;
4456                 break;
4457               }
4458             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4459               attribute);
4460             break;
4461           }
4462           case 'E':
4463           case 'e':
4464           {
4465             if (LocaleCompare(attribute,"expression") == 0)
4466               {
4467                 (void) CopyMagickString(expression,SvPV(ST(i),na),
4468                   MaxTextExtent);
4469                 break;
4470               }
4471             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4472               attribute);
4473             break;
4474           }
4475           default:
4476           {
4477             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4478               attribute);
4479             break;
4480           }
4481         }
4482       }
4483     channel_mask=SetImageChannelMask(image,channel);
4484     image=FxImage(image,expression,exception);
4485     if (image != (Image *) NULL)
4486       (void) SetImageChannelMask(image,channel_mask);
4487     if (image == (Image *) NULL)
4488       goto PerlException;
4489     for ( ; image; image=image->next)
4490     {
4491       AddImageToRegistry(sv,image);
4492       rv=newRV(sv);
4493       av_push(av,sv_bless(rv,hv));
4494       SvREFCNT_dec(sv);
4495     }
4496     exception=DestroyExceptionInfo(exception);
4497     ST(0)=av_reference;
4498     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4499     XSRETURN(1);
4500
4501   PerlException:
4502     InheritPerlException(exception,perl_exception);
4503     exception=DestroyExceptionInfo(exception);
4504     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4505     SvPOK_on(perl_exception);
4506     ST(0)=sv_2mortal(perl_exception);
4507     XSRETURN(1);
4508   }
4509 \f
4510 #
4511 ###############################################################################
4512 #                                                                             #
4513 #                                                                             #
4514 #                                                                             #
4515 #   G e t                                                                     #
4516 #                                                                             #
4517 #                                                                             #
4518 #                                                                             #
4519 ###############################################################################
4520 #
4521 #
4522 void
4523 Get(ref,...)
4524   Image::Magick ref=NO_INIT
4525   ALIAS:
4526     GetAttributes = 1
4527     GetAttribute  = 2
4528     get           = 3
4529     getattributes = 4
4530     getattribute  = 5
4531   PPCODE:
4532   {
4533     char
4534       *attribute,
4535       color[MaxTextExtent];
4536
4537     const char
4538       *value;
4539
4540     ExceptionInfo
4541       *exception;
4542
4543     Image
4544       *image;
4545
4546     long
4547       j;
4548
4549     register ssize_t
4550       i;
4551
4552     struct PackageInfo
4553       *info;
4554
4555     SV
4556       *perl_exception,
4557       *reference,
4558       *s;
4559
4560     PERL_UNUSED_VAR(ref);
4561     PERL_UNUSED_VAR(ix);
4562     exception=AcquireExceptionInfo();
4563     perl_exception=newSVpv("",0);
4564     if (sv_isobject(ST(0)) == 0)
4565       {
4566         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4567           PackageName);
4568         XSRETURN_EMPTY;
4569       }
4570     reference=SvRV(ST(0));
4571     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4572     if (image == (Image *) NULL && !info)
4573       XSRETURN_EMPTY;
4574     EXTEND(sp,items);
4575     for (i=1; i < items; i++)
4576     {
4577       attribute=(char *) SvPV(ST(i),na);
4578       s=NULL;
4579       switch (*attribute)
4580       {
4581         case 'A':
4582         case 'a':
4583         {
4584           if (LocaleCompare(attribute,"adjoin") == 0)
4585             {
4586               if (info)
4587                 s=newSViv((ssize_t) info->image_info->adjoin);
4588               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4589               continue;
4590             }
4591           if (LocaleCompare(attribute,"antialias") == 0)
4592             {
4593               if (info)
4594                 s=newSViv((ssize_t) info->image_info->antialias);
4595               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4596               continue;
4597             }
4598           if (LocaleCompare(attribute,"area") == 0)
4599             {
4600               s=newSViv(GetMagickResource(AreaResource));
4601               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4602               continue;
4603             }
4604           if (LocaleCompare(attribute,"attenuate") == 0)
4605             {
4606               const char
4607                 *value;
4608
4609               value=GetImageProperty(image,attribute,exception);
4610               if (value != (const char *) NULL)
4611                 s=newSVpv(value,0);
4612               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4613               continue;
4614             }
4615           if (LocaleCompare(attribute,"authenticate") == 0)
4616             {
4617               if (info)
4618                 {
4619                   const char
4620                     *option;
4621
4622                   option=GetImageOption(info->image_info,attribute);
4623                   if (option != (const char *) NULL)
4624                     s=newSVpv(option,0);
4625                 }
4626               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4627               continue;
4628             }
4629           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4630             attribute);
4631           break;
4632         }
4633         case 'B':
4634         case 'b':
4635         {
4636           if (LocaleCompare(attribute,"background") == 0)
4637             {
4638               if (image == (Image *) NULL)
4639                 break;
4640               (void) FormatLocaleString(color,MaxTextExtent,
4641                 "%.20g,%.20g,%.20g,%.20g",image->background_color.red,
4642                 image->background_color.green,image->background_color.blue,
4643                 image->background_color.alpha);
4644               s=newSVpv(color,0);
4645               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4646               continue;
4647             }
4648           if (LocaleCompare(attribute,"base-columns") == 0)
4649             {
4650               if (image != (Image *) NULL)
4651                 s=newSViv((ssize_t) image->magick_columns);
4652               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4653               continue;
4654             }
4655           if (LocaleCompare(attribute,"base-filename") == 0)
4656             {
4657               if (image != (Image *) NULL)
4658                 s=newSVpv(image->magick_filename,0);
4659               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4660               continue;
4661             }
4662           if (LocaleCompare(attribute,"base-height") == 0)
4663             {
4664               if (image != (Image *) NULL)
4665                 s=newSViv((ssize_t) image->magick_rows);
4666               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4667               continue;
4668             }
4669           if (LocaleCompare(attribute,"base-rows") == 0)
4670             {
4671               if (image != (Image *) NULL)
4672                 s=newSViv((ssize_t) image->magick_rows);
4673               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4674               continue;
4675             }
4676           if (LocaleCompare(attribute,"base-width") == 0)
4677             {
4678               if (image != (Image *) NULL)
4679                 s=newSViv((ssize_t) image->magick_columns);
4680               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4681               continue;
4682             }
4683           if (LocaleCompare(attribute,"blue-primary") == 0)
4684             {
4685               if (image == (Image *) NULL)
4686                 break;
4687               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4688                 image->chromaticity.blue_primary.x,
4689                 image->chromaticity.blue_primary.y);
4690               s=newSVpv(color,0);
4691               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4692               continue;
4693             }
4694           if (LocaleCompare(attribute,"bordercolor") == 0)
4695             {
4696               if (image == (Image *) NULL)
4697                 break;
4698               (void) FormatLocaleString(color,MaxTextExtent,
4699                 "%.20g,%.20g,%.20g,%.20g",image->border_color.red,
4700                 image->border_color.green,image->border_color.blue,
4701                 image->border_color.alpha);
4702               s=newSVpv(color,0);
4703               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4704               continue;
4705             }
4706           if (LocaleCompare(attribute,"bounding-box") == 0)
4707             {
4708               char
4709                 geometry[MaxTextExtent];
4710
4711               RectangleInfo
4712                 page;
4713
4714               if (image == (Image *) NULL)
4715                 break;
4716               page=GetImageBoundingBox(image,exception);
4717               (void) FormatLocaleString(geometry,MaxTextExtent,
4718                 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4719                 page.height,(double) page.x,(double) page.y);
4720               s=newSVpv(geometry,0);
4721               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4722               continue;
4723             }
4724           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4725             attribute);
4726           break;
4727         }
4728         case 'C':
4729         case 'c':
4730         {
4731           if (LocaleCompare(attribute,"class") == 0)
4732             {
4733               if (image == (Image *) NULL)
4734                 break;
4735               s=newSViv(image->storage_class);
4736               (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4737                 image->storage_class));
4738               SvIOK_on(s);
4739               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4740               continue;
4741             }
4742           if (LocaleCompare(attribute,"clip-mask") == 0)
4743             {
4744               if (image != (Image *) NULL)
4745                 {
4746                   Image
4747                     *mask_image;
4748
4749                   SV
4750                     *sv;
4751
4752                   sv=NULL;
4753                   if (image->read_mask == MagickFalse)
4754                     ClipImage(image,exception);
4755                   mask_image=GetImageMask(image,exception);
4756                   if (mask_image != (Image *) NULL)
4757                     {
4758                       AddImageToRegistry(sv,mask_image);
4759                       s=sv_bless(newRV(sv),SvSTASH(reference));
4760                     }
4761                 }
4762               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4763               continue;
4764             }
4765           if (LocaleCompare(attribute,"clip-path") == 0)
4766             {
4767               if (image != (Image *) NULL)
4768                 {
4769                   Image
4770                     *mask_image;
4771
4772                   SV
4773                     *sv;
4774
4775                   sv=NULL;
4776                   if (image->read_mask != MagickFalse)
4777                     ClipImage(image,exception);
4778                   mask_image=GetImageMask(image,exception);
4779                   if (mask_image != (Image *) NULL)
4780                     {
4781                       AddImageToRegistry(sv,mask_image);
4782                       s=sv_bless(newRV(sv),SvSTASH(reference));
4783                     }
4784                 }
4785               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4786               continue;
4787             }
4788           if (LocaleCompare(attribute,"compression") == 0)
4789             {
4790               j=info ? info->image_info->compression : image ?
4791                 image->compression : UndefinedCompression;
4792               if (info)
4793                 if (info->image_info->compression == UndefinedCompression)
4794                   j=image->compression;
4795               s=newSViv(j);
4796               (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4797                 j));
4798               SvIOK_on(s);
4799               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4800               continue;
4801             }
4802           if (LocaleCompare(attribute,"colorspace") == 0)
4803             {
4804               j=image ? image->colorspace : RGBColorspace;
4805               s=newSViv(j);
4806               (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4807                 j));
4808               SvIOK_on(s);
4809               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4810               continue;
4811             }
4812           if (LocaleCompare(attribute,"colors") == 0)
4813             {
4814               if (image != (Image *) NULL)
4815                 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4816                   exception));
4817               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4818               continue;
4819             }
4820           if (LocaleNCompare(attribute,"colormap",8) == 0)
4821             {
4822               int
4823                 items;
4824
4825               if (image == (Image *) NULL || !image->colormap)
4826                 break;
4827               j=0;
4828               items=sscanf(attribute,"%*[^[][%ld",&j);
4829               (void) items;
4830               if (j > (ssize_t) image->colors)
4831                 j%=image->colors;
4832               (void) FormatLocaleString(color,MaxTextExtent,
4833                 "%.20g,%.20g,%.20g,%.20g",image->colormap[j].red,
4834                 image->colormap[j].green,image->colormap[j].blue,
4835                 image->colormap[j].alpha);
4836               s=newSVpv(color,0);
4837               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4838               continue;
4839             }
4840           if (LocaleCompare(attribute,"columns") == 0)
4841             {
4842               if (image != (Image *) NULL)
4843                 s=newSViv((ssize_t) image->columns);
4844               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4845               continue;
4846             }
4847           if (LocaleCompare(attribute,"comment") == 0)
4848             {
4849               const char
4850                 *value;
4851
4852               value=GetImageProperty(image,attribute,exception);
4853               if (value != (const char *) NULL)
4854                 s=newSVpv(value,0);
4855               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4856               continue;
4857             }
4858           if (LocaleCompare(attribute,"copyright") == 0)
4859             {
4860               s=newSVpv(GetMagickCopyright(),0);
4861               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4862               continue;
4863             }
4864           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4865             attribute);
4866           break;
4867         }
4868         case 'D':
4869         case 'd':
4870         {
4871           if (LocaleCompare(attribute,"density") == 0)
4872             {
4873               char
4874                 geometry[MaxTextExtent];
4875
4876               if (image == (Image *) NULL)
4877                 break;
4878               (void) FormatLocaleString(geometry,MaxTextExtent,"%.15gx%.15g",
4879                 image->resolution.x,image->resolution.y);
4880               s=newSVpv(geometry,0);
4881               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4882               continue;
4883             }
4884           if (LocaleCompare(attribute,"delay") == 0)
4885             {
4886               if (image != (Image *) NULL)
4887                 s=newSViv((ssize_t) image->delay);
4888               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4889               continue;
4890             }
4891           if (LocaleCompare(attribute,"depth") == 0)
4892             {
4893               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4894               if (image != (Image *) NULL)
4895                 s=newSViv((ssize_t) GetImageDepth(image,exception));
4896               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4897               continue;
4898             }
4899           if (LocaleCompare(attribute,"directory") == 0)
4900             {
4901               if (image && image->directory)
4902                 s=newSVpv(image->directory,0);
4903               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4904               continue;
4905             }
4906           if (LocaleCompare(attribute,"dispose") == 0)
4907             {
4908               if (image == (Image *) NULL)
4909                 break;
4910
4911               s=newSViv(image->dispose);
4912               (void) sv_setpv(s,
4913                 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
4914               SvIOK_on(s);
4915               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4916               continue;
4917             }
4918           if (LocaleCompare(attribute,"disk") == 0)
4919             {
4920               s=newSViv(GetMagickResource(DiskResource));
4921               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4922               continue;
4923             }
4924           if (LocaleCompare(attribute,"dither") == 0)
4925             {
4926               if (info)
4927                 s=newSViv((ssize_t) info->image_info->dither);
4928               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4929               continue;
4930             }
4931           if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4932             {
4933               if (info && info->image_info->server_name)
4934                 s=newSVpv(info->image_info->server_name,0);
4935               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4936               continue;
4937             }
4938           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4939             attribute);
4940           break;
4941         }
4942         case 'E':
4943         case 'e':
4944         {
4945           if (LocaleCompare(attribute,"elapsed-time") == 0)
4946             {
4947               if (image != (Image *) NULL)
4948                 s=newSVnv(GetElapsedTime(&image->timer));
4949               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4950               continue;
4951             }
4952           if (LocaleCompare(attribute,"endian") == 0)
4953             {
4954               j=info ? info->image_info->endian : image ? image->endian :
4955                 UndefinedEndian;
4956               s=newSViv(j);
4957               (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
4958               SvIOK_on(s);
4959               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4960               continue;
4961             }
4962           if (LocaleCompare(attribute,"error") == 0)
4963             {
4964               if (image != (Image *) NULL)
4965                 s=newSVnv(image->error.mean_error_per_pixel);
4966               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4967               continue;
4968             }
4969           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4970             attribute);
4971           break;
4972         }
4973         case 'F':
4974         case 'f':
4975         {
4976           if (LocaleCompare(attribute,"filesize") == 0)
4977             {
4978               if (image != (Image *) NULL)
4979                 s=newSViv((ssize_t) GetBlobSize(image));
4980               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4981               continue;
4982             }
4983           if (LocaleCompare(attribute,"filename") == 0)
4984             {
4985               if (info && info->image_info->filename &&
4986                   *info->image_info->filename)
4987                 s=newSVpv(info->image_info->filename,0);
4988               if (image != (Image *) NULL)
4989                 s=newSVpv(image->filename,0);
4990               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4991               continue;
4992             }
4993           if (LocaleCompare(attribute,"filter") == 0)
4994             {
4995               s=image ? newSViv(image->filter) : newSViv(0);
4996               (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
4997                 image->filter));
4998               SvIOK_on(s);
4999               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5000               continue;
5001             }
5002           if (LocaleCompare(attribute,"font") == 0)
5003             {
5004               if (info && info->image_info->font)
5005                 s=newSVpv(info->image_info->font,0);
5006               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5007               continue;
5008             }
5009           if (LocaleCompare(attribute,"foreground") == 0)
5010             continue;
5011           if (LocaleCompare(attribute,"format") == 0)
5012             {
5013               const MagickInfo
5014                 *magick_info;
5015
5016               magick_info=(const MagickInfo *) NULL;
5017               if (info && (*info->image_info->magick != '\0'))
5018                 magick_info=GetMagickInfo(info->image_info->magick,exception);
5019               if (image != (Image *) NULL)
5020                 magick_info=GetMagickInfo(image->magick,exception);
5021               if ((magick_info != (const MagickInfo *) NULL) &&
5022                   (*magick_info->description != '\0'))
5023                 s=newSVpv((char *) magick_info->description,0);
5024               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5025               continue;
5026             }
5027           if (LocaleCompare(attribute,"fuzz") == 0)
5028             {
5029               if (info)
5030                 s=newSVnv(info->image_info->fuzz);
5031               if (image != (Image *) NULL)
5032                 s=newSVnv(image->fuzz);
5033               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5034               continue;
5035             }
5036           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5037             attribute);
5038           break;
5039         }
5040         case 'G':
5041         case 'g':
5042         {
5043           if (LocaleCompare(attribute,"gamma") == 0)
5044             {
5045               if (image != (Image *) NULL)
5046                 s=newSVnv(image->gamma);
5047               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5048               continue;
5049             }
5050           if (LocaleCompare(attribute,"geometry") == 0)
5051             {
5052               if (image && image->geometry)
5053                 s=newSVpv(image->geometry,0);
5054               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5055               continue;
5056             }
5057           if (LocaleCompare(attribute,"gravity") == 0)
5058             {
5059               s=image ? newSViv(image->gravity) : newSViv(0);
5060               (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
5061                 image->gravity));
5062               SvIOK_on(s);
5063               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5064               continue;
5065             }
5066           if (LocaleCompare(attribute,"green-primary") == 0)
5067             {
5068               if (image == (Image *) NULL)
5069                 break;
5070               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5071                 image->chromaticity.green_primary.x,
5072                 image->chromaticity.green_primary.y);
5073               s=newSVpv(color,0);
5074               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5075               continue;
5076             }
5077           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5078             attribute);
5079           break;
5080         }
5081         case 'H':
5082         case 'h':
5083         {
5084           if (LocaleCompare(attribute,"height") == 0)
5085             {
5086               if (image != (Image *) NULL)
5087                 s=newSViv((ssize_t) image->rows);
5088               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5089               continue;
5090             }
5091           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5092             attribute);
5093           break;
5094         }
5095         case 'I':
5096         case 'i':
5097         {
5098           if (LocaleCompare(attribute,"icc") == 0)
5099             {
5100               if (image != (Image *) NULL)
5101                 {
5102                   const StringInfo
5103                     *profile;
5104
5105                   profile=GetImageProfile(image,"icc");
5106                   if (profile != (StringInfo *) NULL)
5107                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5108                       GetStringInfoLength(profile));
5109                 }
5110               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5111               continue;
5112             }
5113           if (LocaleCompare(attribute,"icm") == 0)
5114             {
5115               if (image != (Image *) NULL)
5116                 {
5117                   const StringInfo
5118                     *profile;
5119
5120                   profile=GetImageProfile(image,"icm");
5121                   if (profile != (const StringInfo *) NULL)
5122                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5123                       GetStringInfoLength(profile));
5124                 }
5125               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5126               continue;
5127             }
5128           if (LocaleCompare(attribute,"id") == 0)
5129             {
5130               if (image != (Image *) NULL)
5131                 {
5132                   char
5133                     key[MaxTextExtent];
5134
5135                   MagickBooleanType
5136                     status;
5137
5138                   static ssize_t
5139                     id = 0;
5140
5141                   (void) FormatLocaleString(key,MaxTextExtent,"%.20g\n",(double)
5142                     id);
5143                   status=SetImageRegistry(ImageRegistryType,key,image,
5144                     exception);
5145                   (void) status;
5146                   s=newSViv(id++);
5147                 }
5148               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5149               continue;
5150             }
5151           if (LocaleNCompare(attribute,"index",5) == 0)
5152             {
5153               char
5154                 name[MaxTextExtent];
5155
5156               int
5157                 items;
5158
5159               long
5160                 x,
5161                 y;
5162
5163               register const Quantum
5164                 *p;
5165
5166               CacheView
5167                 *image_view;
5168
5169               if (image == (Image *) NULL)
5170                 break;
5171               if (image->storage_class != PseudoClass)
5172                 break;
5173               x=0;
5174               y=0;
5175               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5176               (void) items;
5177               image_view=AcquireVirtualCacheView(image,exception);
5178               p=GetCacheViewVirtualPixels(image_view,x,y,1,1,exception);
5179               if (p != (const Quantum *) NULL)
5180                 {
5181                   (void) FormatLocaleString(name,MaxTextExtent,QuantumFormat,
5182                     GetPixelIndex(image,p));
5183                   s=newSVpv(name,0);
5184                   PUSHs(s ? sv_2mortal(s) : &sv_undef);
5185                 }
5186               image_view=DestroyCacheView(image_view);
5187               continue;
5188             }
5189           if (LocaleCompare(attribute,"iptc") == 0)
5190             {
5191               if (image != (Image *) NULL)
5192                 {
5193                   const StringInfo
5194                     *profile;
5195
5196                   profile=GetImageProfile(image,"iptc");
5197                   if (profile != (const StringInfo *) NULL)
5198                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5199                       GetStringInfoLength(profile));
5200                 }
5201               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5202               continue;
5203             }
5204           if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
5205             {
5206               if (image != (Image *) NULL)
5207                 s=newSViv((ssize_t) image->iterations);
5208               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5209               continue;
5210             }
5211           if (LocaleCompare(attribute,"interlace") == 0)
5212             {
5213               j=info ? info->image_info->interlace : image ? image->interlace :
5214                 UndefinedInterlace;
5215               s=newSViv(j);
5216               (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
5217                 j));
5218               SvIOK_on(s);
5219               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5220               continue;
5221             }
5222           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5223             attribute);
5224           break;
5225         }
5226         case 'L':
5227         case 'l':
5228         {
5229           if (LocaleCompare(attribute,"label") == 0)
5230             {
5231               const char
5232                 *value;
5233
5234               if (image == (Image *) NULL)
5235                 break;
5236               value=GetImageProperty(image,"Label",exception);
5237               if (value != (const char *) NULL)
5238                 s=newSVpv(value,0);
5239               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5240               continue;
5241             }
5242           if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
5243             {
5244               if (image != (Image *) NULL)
5245                 s=newSViv((ssize_t) image->iterations);
5246               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5247               continue;
5248             }
5249           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5250             attribute);
5251           break;
5252         }
5253         case 'M':
5254         case 'm':
5255         {
5256           if (LocaleCompare(attribute,"magick") == 0)
5257             {
5258               if (info && *info->image_info->magick)
5259                 s=newSVpv(info->image_info->magick,0);
5260               if (image != (Image *) NULL)
5261                 s=newSVpv(image->magick,0);
5262               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5263               continue;
5264             }
5265           if (LocaleCompare(attribute,"map") == 0)
5266             {
5267               s=newSViv(GetMagickResource(MapResource));
5268               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5269               continue;
5270             }
5271           if (LocaleCompare(attribute,"maximum-error") == 0)
5272             {
5273               if (image != (Image *) NULL)
5274                 s=newSVnv(image->error.normalized_maximum_error);
5275               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5276               continue;
5277             }
5278           if (LocaleCompare(attribute,"memory") == 0)
5279             {
5280               s=newSViv(GetMagickResource(MemoryResource));
5281               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5282               continue;
5283             }
5284           if (LocaleCompare(attribute,"mean-error") == 0)
5285             {
5286               if (image != (Image *) NULL)
5287                 s=newSVnv(image->error.normalized_mean_error);
5288               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5289               continue;
5290             }
5291           if (LocaleCompare(attribute,"mime") == 0)
5292             {
5293               if (info && *info->image_info->magick)
5294                 s=newSVpv(MagickToMime(info->image_info->magick),0);
5295               if (image != (Image *) NULL)
5296                 s=newSVpv(MagickToMime(image->magick),0);
5297               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5298               continue;
5299             }
5300           if (LocaleCompare(attribute,"mattecolor") == 0)
5301             {
5302               if (image == (Image *) NULL)
5303                 break;
5304               (void) FormatLocaleString(color,MaxTextExtent,
5305                 "%.20g,%.20g,%.20g,%.20g",image->matte_color.red,
5306                 image->matte_color.green,image->matte_color.blue,
5307                 image->matte_color.alpha);
5308               s=newSVpv(color,0);
5309               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5310               continue;
5311             }
5312           if (LocaleCompare(attribute,"matte") == 0)
5313             {
5314               if (image != (Image *) NULL)
5315                 s=newSViv((ssize_t) image->alpha_trait == BlendPixelTrait ?
5316                   1 : 0);
5317               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5318               continue;
5319             }
5320           if (LocaleCompare(attribute,"mime") == 0)
5321             {
5322               const char
5323                 *magick;
5324
5325               magick=NULL;
5326               if (info && *info->image_info->magick)
5327                 magick=info->image_info->magick;
5328               if (image != (Image *) NULL)
5329                 magick=image->magick;
5330               if (magick)
5331                 {
5332                   char
5333                     *mime;
5334
5335                   mime=MagickToMime(magick);
5336                   s=newSVpv(mime,0);
5337                   mime=(char *) RelinquishMagickMemory(mime);
5338                 }
5339               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5340               continue;
5341             }
5342           if (LocaleCompare(attribute,"monochrome") == 0)
5343             {
5344               if (image == (Image *) NULL)
5345                 continue;
5346               j=info ? info->image_info->monochrome :
5347                 IsImageMonochrome(image,exception);
5348               s=newSViv(j);
5349               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5350               continue;
5351             }
5352           if (LocaleCompare(attribute,"montage") == 0)
5353             {
5354               if (image && image->montage)
5355                 s=newSVpv(image->montage,0);
5356               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5357               continue;
5358             }
5359           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5360             attribute);
5361           break;
5362         }
5363         case 'O':
5364         case 'o':
5365         {
5366           if (LocaleCompare(attribute,"orientation") == 0)
5367             {
5368               j=info ? info->image_info->orientation : image ?
5369                 image->orientation : UndefinedOrientation;
5370               s=newSViv(j);
5371               (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5372                 j));
5373               SvIOK_on(s);
5374               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5375               continue;
5376             }
5377           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5378             attribute);
5379           break;
5380         }
5381         case 'P':
5382         case 'p':
5383         {
5384           if (LocaleCompare(attribute,"page") == 0)
5385             {
5386               if (info && info->image_info->page)
5387                 s=newSVpv(info->image_info->page,0);
5388               if (image != (Image *) NULL)
5389                 {
5390                   char
5391                     geometry[MaxTextExtent];
5392
5393                   (void) FormatLocaleString(geometry,MaxTextExtent,
5394                     "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5395                     (double) image->page.height,(double) image->page.x,(double)
5396                     image->page.y);
5397                   s=newSVpv(geometry,0);
5398                 }
5399               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5400               continue;
5401             }
5402           if (LocaleCompare(attribute,"page.x") == 0)
5403             {
5404               if (image != (Image *) NULL)
5405                 s=newSViv((ssize_t) image->page.x);
5406               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5407               continue;
5408             }
5409           if (LocaleCompare(attribute,"page.y") == 0)
5410             {
5411               if (image != (Image *) NULL)
5412                 s=newSViv((ssize_t) image->page.y);
5413               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5414               continue;
5415             }
5416           if (LocaleNCompare(attribute,"pixel",5) == 0)
5417             {
5418               char
5419                 tuple[MaxTextExtent];
5420
5421               int
5422                 items;
5423
5424               long
5425                 x,
5426                 y;
5427
5428               register const Quantum
5429                 *p;
5430
5431               if (image == (Image *) NULL)
5432                 break;
5433               x=0;
5434               y=0;
5435               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5436               (void) items;
5437               p=GetVirtualPixels(image,x,y,1,1,exception);
5438               if (image->colorspace != CMYKColorspace)
5439                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5440                   QuantumFormat "," QuantumFormat "," QuantumFormat,
5441                   GetPixelRed(image,p),GetPixelGreen(image,p),
5442                   GetPixelBlue(image,p),GetPixelAlpha(image,p));
5443               else
5444                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5445                   QuantumFormat "," QuantumFormat "," QuantumFormat ","
5446                   QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5447                   GetPixelBlue(image,p),GetPixelBlack(image,p),
5448                   GetPixelAlpha(image,p));
5449               s=newSVpv(tuple,0);
5450               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5451               continue;
5452             }
5453           if (LocaleCompare(attribute,"pointsize") == 0)
5454             {
5455               if (info)
5456                 s=newSViv((ssize_t) info->image_info->pointsize);
5457               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5458               continue;
5459             }
5460           if (LocaleCompare(attribute,"preview") == 0)
5461             {
5462               s=newSViv(info->image_info->preview_type);
5463               (void) sv_setpv(s,CommandOptionToMnemonic(MagickPreviewOptions,
5464                 info->image_info->preview_type));
5465               SvIOK_on(s);
5466               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5467               continue;
5468             }
5469           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5470             attribute);
5471           break;
5472         }
5473         case 'Q':
5474         case 'q':
5475         {
5476           if (LocaleCompare(attribute,"quality") == 0)
5477             {
5478               if (info)
5479                 s=newSViv((ssize_t) info->image_info->quality);
5480               if (image != (Image *) NULL)
5481                 s=newSViv((ssize_t) image->quality);
5482               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5483               continue;
5484             }
5485           if (LocaleCompare(attribute,"quantum") == 0)
5486             {
5487               if (info)
5488                 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5489               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5490               continue;
5491             }
5492           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5493             attribute);
5494           break;
5495         }
5496         case 'R':
5497         case 'r':
5498         {
5499           if (LocaleCompare(attribute,"rendering-intent") == 0)
5500             {
5501               s=newSViv(image->rendering_intent);
5502               (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5503                 image->rendering_intent));
5504               SvIOK_on(s);
5505               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5506               continue;
5507             }
5508           if (LocaleCompare(attribute,"red-primary") == 0)
5509             {
5510               if (image == (Image *) NULL)
5511                 break;
5512               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5513                 image->chromaticity.red_primary.x,
5514                 image->chromaticity.red_primary.y);
5515               s=newSVpv(color,0);
5516               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5517               continue;
5518             }
5519           if (LocaleCompare(attribute,"rows") == 0)
5520             {
5521               if (image != (Image *) NULL)
5522                 s=newSViv((ssize_t) image->rows);
5523               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5524               continue;
5525             }
5526           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5527             attribute);
5528           break;
5529         }
5530         case 'S':
5531         case 's':
5532         {
5533           if (LocaleCompare(attribute,"sampling-factor") == 0)
5534             {
5535               if (info && info->image_info->sampling_factor)
5536                 s=newSVpv(info->image_info->sampling_factor,0);
5537               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5538               continue;
5539             }
5540           if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5541             {
5542               if (info && info->image_info->server_name)
5543                 s=newSVpv(info->image_info->server_name,0);
5544               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5545               continue;
5546             }
5547           if (LocaleCompare(attribute,"size") == 0)
5548             {
5549               if (info && info->image_info->size)
5550                 s=newSVpv(info->image_info->size,0);
5551               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5552               continue;
5553             }
5554           if (LocaleCompare(attribute,"scene") == 0)
5555             {
5556               if (image != (Image *) NULL)
5557                 s=newSViv((ssize_t) image->scene);
5558               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5559               continue;
5560             }
5561           if (LocaleCompare(attribute,"scenes") == 0)
5562             {
5563               if (image != (Image *) NULL)
5564                 s=newSViv((ssize_t) info->image_info->number_scenes);
5565               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5566               continue;
5567             }
5568           if (LocaleCompare(attribute,"signature") == 0)
5569             {
5570               const char
5571                 *value;
5572
5573               if (image == (Image *) NULL)
5574                 break;
5575               (void) SignatureImage(image,exception);
5576               value=GetImageProperty(image,"Signature",exception);
5577               if (value != (const char *) NULL)
5578                 s=newSVpv(value,0);
5579               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5580               continue;
5581             }
5582           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5583             attribute);
5584           break;
5585         }
5586         case 'T':
5587         case 't':
5588         {
5589           if (LocaleCompare(attribute,"taint") == 0)
5590             {
5591               if (image != (Image *) NULL)
5592                 s=newSViv((ssize_t) IsTaintImage(image));
5593               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5594               continue;
5595             }
5596           if (LocaleCompare(attribute,"texture") == 0)
5597             {
5598               if (info && info->image_info->texture)
5599                 s=newSVpv(info->image_info->texture,0);
5600               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5601               continue;
5602             }
5603           if (LocaleCompare(attribute,"total-ink-density") == 0)
5604             {
5605               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5606               if (image != (Image *) NULL)
5607                 s=newSVnv(GetImageTotalInkDensity(image,exception));
5608               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5609               continue;
5610             }
5611           if (LocaleCompare(attribute,"transparent-color") == 0)
5612             {
5613               if (image == (Image *) NULL)
5614                 break;
5615               (void) FormatLocaleString(color,MaxTextExtent,
5616                 "%.20g,%.20g,%.20g,%.20g",image->transparent_color.red,
5617                 image->transparent_color.green,image->transparent_color.blue,
5618                 image->transparent_color.alpha);
5619               s=newSVpv(color,0);
5620               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5621               continue;
5622             }
5623           if (LocaleCompare(attribute,"type") == 0)
5624             {
5625               if (image == (Image *) NULL)
5626                 break;
5627               j=(ssize_t) GetImageType(image,exception);
5628               s=newSViv(j);
5629               (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5630               SvIOK_on(s);
5631               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5632               continue;
5633             }
5634           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5635             attribute);
5636           break;
5637         }
5638         case 'U':
5639         case 'u':
5640         {
5641           if (LocaleCompare(attribute,"units") == 0)
5642             {
5643               j=info ? info->image_info->units : image ? image->units :
5644                 UndefinedResolution;
5645               if (info && (info->image_info->units == UndefinedResolution))
5646                 if (image)
5647                   j=image->units;
5648               if (j == UndefinedResolution)
5649                 s=newSVpv("undefined units",0);
5650               else
5651                 if (j == PixelsPerInchResolution)
5652                   s=newSVpv("pixels / inch",0);
5653                 else
5654                   s=newSVpv("pixels / centimeter",0);
5655               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5656               continue;
5657             }
5658           if (LocaleCompare(attribute,"user-time") == 0)
5659             {
5660               if (image != (Image *) NULL)
5661                 s=newSVnv(GetUserTime(&image->timer));
5662               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5663               continue;
5664             }
5665           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5666             attribute);
5667           break;
5668         }
5669         case 'V':
5670         case 'v':
5671         {
5672           if (LocaleCompare(attribute,"verbose") == 0)
5673             {
5674               if (info)
5675                 s=newSViv((ssize_t) info->image_info->verbose);
5676               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5677               continue;
5678             }
5679           if (LocaleCompare(attribute,"version") == 0)
5680             {
5681               s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5682               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5683               continue;
5684             }
5685           if (LocaleCompare(attribute,"view") == 0)
5686             {
5687               if (info && info->image_info->view)
5688                 s=newSVpv(info->image_info->view,0);
5689               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5690               continue;
5691             }
5692           if (LocaleCompare(attribute,"virtual-pixel") == 0)
5693             {
5694               if (image == (Image *) NULL)
5695                 break;
5696               j=(ssize_t) GetImageVirtualPixelMethod(image);
5697               s=newSViv(j);
5698               (void) sv_setpv(s,CommandOptionToMnemonic(
5699                 MagickVirtualPixelOptions,j));
5700               SvIOK_on(s);
5701               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5702               continue;
5703             }
5704           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5705             attribute);
5706           break;
5707         }
5708         case 'W':
5709         case 'w':
5710         {
5711           if (LocaleCompare(attribute,"white-point") == 0)
5712             {
5713               if (image == (Image *) NULL)
5714                 break;
5715               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5716                 image->chromaticity.white_point.x,
5717                 image->chromaticity.white_point.y);
5718               s=newSVpv(color,0);
5719               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5720               continue;
5721             }
5722           if (LocaleCompare(attribute,"width") == 0)
5723             {
5724               if (image != (Image *) NULL)
5725                 s=newSViv((ssize_t) image->columns);
5726               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5727               continue;
5728             }
5729           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5730              attribute);
5731           break;
5732         }
5733         case 'X':
5734         case 'x':
5735         {
5736           if (LocaleCompare(attribute,"x-resolution") == 0)
5737             {
5738               if (image != (Image *) NULL)
5739                 s=newSVnv(image->resolution.x);
5740               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5741               continue;
5742             }
5743           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5744             attribute);
5745           break;
5746         }
5747         case 'Y':
5748         case 'y':
5749         {
5750           if (LocaleCompare(attribute,"y-resolution") == 0)
5751             {
5752               if (image != (Image *) NULL)
5753                 s=newSVnv(image->resolution.y);
5754               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5755               continue;
5756             }
5757           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5758             attribute);
5759           break;
5760         }
5761         default:
5762           break;
5763       }
5764       if (image == (Image *) NULL)
5765         ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5766           attribute)
5767       else
5768         {
5769           value=GetImageProperty(image,attribute,exception);
5770           if (value != (const char *) NULL)
5771             {
5772               s=newSVpv(value,0);
5773               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5774             }
5775           else
5776             if (*attribute != '%')
5777               ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5778                 attribute)
5779             else
5780               {
5781                  char
5782                    *meta;
5783
5784                  meta=InterpretImageProperties(info ? info->image_info :
5785                    (ImageInfo *) NULL,image,attribute,exception);
5786                  s=newSVpv(meta,0);
5787                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5788                  meta=(char *) RelinquishMagickMemory(meta);
5789               }
5790         }
5791     }
5792     exception=DestroyExceptionInfo(exception);
5793     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5794   }
5795 \f
5796 #
5797 ###############################################################################
5798 #                                                                             #
5799 #                                                                             #
5800 #                                                                             #
5801 #   G e t A u t h e n t i c P i x e l s                                       #
5802 #                                                                             #
5803 #                                                                             #
5804 #                                                                             #
5805 ###############################################################################
5806 #
5807 #
5808 void *
5809 GetAuthenticPixels(ref,...)
5810   Image::Magick ref = NO_INIT
5811   ALIAS:
5812     getauthenticpixels = 1
5813     GetImagePixels = 2
5814     getimagepixels = 3
5815   CODE:
5816   {
5817     char
5818       *attribute;
5819
5820     ExceptionInfo
5821       *exception;
5822
5823     Image
5824       *image;
5825
5826     RectangleInfo
5827       region;
5828
5829     ssize_t
5830       i;
5831
5832     struct PackageInfo
5833       *info;
5834
5835     SV
5836       *perl_exception,
5837       *reference;
5838
5839     void
5840       *blob = NULL;
5841
5842     PERL_UNUSED_VAR(ref);
5843     PERL_UNUSED_VAR(ix);
5844     exception=AcquireExceptionInfo();
5845     perl_exception=newSVpv("",0);
5846     if (sv_isobject(ST(0)) == 0)
5847       {
5848         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5849           PackageName);
5850         goto PerlException;
5851       }
5852     reference=SvRV(ST(0));
5853
5854     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5855     if (image == (Image *) NULL)
5856       {
5857         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5858           PackageName);
5859         goto PerlException;
5860       }
5861
5862     region.x=0;
5863     region.y=0;
5864     region.width=image->columns;
5865     region.height=1;
5866     if (items == 1)
5867       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5868     for (i=2; i < items; i+=2)
5869     {
5870       attribute=(char *) SvPV(ST(i-1),na);
5871       switch (*attribute)
5872       {
5873         case 'g':
5874         case 'G':
5875         {
5876           if (LocaleCompare(attribute,"geometry") == 0)
5877             {
5878               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5879               break;
5880             }
5881           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5882             attribute);
5883           break;
5884         }
5885         case 'H':
5886         case 'h':
5887         {
5888           if (LocaleCompare(attribute,"height") == 0)
5889             {
5890               region.height=SvIV(ST(i));
5891               continue;
5892             }
5893           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5894             attribute);
5895           break;
5896         }
5897         case 'X':
5898         case 'x':
5899         {
5900           if (LocaleCompare(attribute,"x") == 0)
5901             {
5902               region.x=SvIV(ST(i));
5903               continue;
5904             }
5905           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5906             attribute);
5907           break;
5908         }
5909         case 'Y':
5910         case 'y':
5911         {
5912           if (LocaleCompare(attribute,"y") == 0)
5913             {
5914               region.y=SvIV(ST(i));
5915               continue;
5916             }
5917           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5918             attribute);
5919           break;
5920         }
5921         case 'W':
5922         case 'w':
5923         {
5924           if (LocaleCompare(attribute,"width") == 0)
5925             {
5926               region.width=SvIV(ST(i));
5927               continue;
5928             }
5929           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5930             attribute);
5931           break;
5932         }
5933       }
5934     }
5935     blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5936       region.height,exception);
5937     if (blob != (void *) NULL)
5938       goto PerlEnd;
5939
5940   PerlException:
5941     InheritPerlException(exception,perl_exception);
5942     exception=DestroyExceptionInfo(exception);
5943     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5944
5945   PerlEnd:
5946     RETVAL = blob;
5947   }
5948   OUTPUT:
5949     RETVAL
5950 \f
5951 #
5952 ###############################################################################
5953 #                                                                             #
5954 #                                                                             #
5955 #                                                                             #
5956 #   G e t V i r t u a l P i x e l s                                           #
5957 #                                                                             #
5958 #                                                                             #
5959 #                                                                             #
5960 ###############################################################################
5961 #
5962 #
5963 void *
5964 GetVirtualPixels(ref,...)
5965   Image::Magick ref = NO_INIT
5966   ALIAS:
5967     getvirtualpixels = 1
5968     AcquireImagePixels = 2
5969     acquireimagepixels = 3
5970   CODE:
5971   {
5972     char
5973       *attribute;
5974
5975     const void
5976       *blob = NULL;
5977
5978     ExceptionInfo
5979       *exception;
5980
5981     Image
5982       *image;
5983
5984     RectangleInfo
5985       region;
5986
5987     ssize_t
5988       i;
5989
5990     struct PackageInfo
5991       *info;
5992
5993     SV
5994       *perl_exception,
5995       *reference;
5996
5997     PERL_UNUSED_VAR(ref);
5998     PERL_UNUSED_VAR(ix);
5999     exception=AcquireExceptionInfo();
6000     perl_exception=newSVpv("",0);
6001     if (sv_isobject(ST(0)) == 0)
6002       {
6003         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6004           PackageName);
6005         goto PerlException;
6006       }
6007     reference=SvRV(ST(0));
6008
6009     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6010     if (image == (Image *) NULL)
6011       {
6012         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6013           PackageName);
6014         goto PerlException;
6015       }
6016
6017     region.x=0;
6018     region.y=0;
6019     region.width=image->columns;
6020     region.height=1;
6021     if (items == 1)
6022       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6023     for (i=2; i < items; i+=2)
6024     {
6025       attribute=(char *) SvPV(ST(i-1),na);
6026       switch (*attribute)
6027       {
6028         case 'g':
6029         case 'G':
6030         {
6031           if (LocaleCompare(attribute,"geometry") == 0)
6032             {
6033               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6034               break;
6035             }
6036           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6037             attribute);
6038           break;
6039         }
6040         case 'H':
6041         case 'h':
6042         {
6043           if (LocaleCompare(attribute,"height") == 0)
6044             {
6045               region.height=SvIV(ST(i));
6046               continue;
6047             }
6048           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6049             attribute);
6050           break;
6051         }
6052         case 'X':
6053         case 'x':
6054         {
6055           if (LocaleCompare(attribute,"x") == 0)
6056             {
6057               region.x=SvIV(ST(i));
6058               continue;
6059             }
6060           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6061             attribute);
6062           break;
6063         }
6064         case 'Y':
6065         case 'y':
6066         {
6067           if (LocaleCompare(attribute,"y") == 0)
6068             {
6069               region.y=SvIV(ST(i));
6070               continue;
6071             }
6072           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6073             attribute);
6074           break;
6075         }
6076         case 'W':
6077         case 'w':
6078         {
6079           if (LocaleCompare(attribute,"width") == 0)
6080             {
6081               region.width=SvIV(ST(i));
6082               continue;
6083             }
6084           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6085             attribute);
6086           break;
6087         }
6088       }
6089     }
6090     blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
6091       region.height,exception);
6092     if (blob != (void *) NULL)
6093       goto PerlEnd;
6094
6095   PerlException:
6096     InheritPerlException(exception,perl_exception);
6097     exception=DestroyExceptionInfo(exception);
6098     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6099
6100   PerlEnd:
6101     RETVAL = (void *) blob;
6102   }
6103   OUTPUT:
6104     RETVAL
6105 \f
6106 #
6107 ###############################################################################
6108 #                                                                             #
6109 #                                                                             #
6110 #                                                                             #
6111 #   G e t A u t h e n t i c M e t a c o n t e n t                             #
6112 #                                                                             #
6113 #                                                                             #
6114 #                                                                             #
6115 ###############################################################################
6116 #
6117 #
6118 void *
6119 GetAuthenticMetacontent(ref,...)
6120   Image::Magick ref = NO_INIT
6121   ALIAS:
6122     getauthenticmetacontent = 1
6123     GetMetacontent = 2
6124     getmetacontent = 3
6125   CODE:
6126   {
6127     ExceptionInfo
6128       *exception;
6129
6130     Image
6131       *image;
6132
6133     struct PackageInfo
6134       *info;
6135
6136     SV
6137       *perl_exception,
6138       *reference;
6139
6140     void
6141       *blob = NULL;
6142
6143     PERL_UNUSED_VAR(ref);
6144     PERL_UNUSED_VAR(ix);
6145     exception=AcquireExceptionInfo();
6146     perl_exception=newSVpv("",0);
6147     if (sv_isobject(ST(0)) == 0)
6148       {
6149         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6150           PackageName);
6151         goto PerlException;
6152       }
6153     reference=SvRV(ST(0));
6154
6155     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6156     if (image == (Image *) NULL)
6157       {
6158         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6159           PackageName);
6160         goto PerlException;
6161       }
6162
6163     blob=(void *) GetAuthenticMetacontent(image);
6164     if (blob != (void *) NULL)
6165       goto PerlEnd;
6166
6167   PerlException:
6168     InheritPerlException(exception,perl_exception);
6169     exception=DestroyExceptionInfo(exception);
6170     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6171
6172   PerlEnd:
6173     RETVAL = blob;
6174   }
6175   OUTPUT:
6176     RETVAL
6177 \f
6178 #
6179 ###############################################################################
6180 #                                                                             #
6181 #                                                                             #
6182 #                                                                             #
6183 #   G e t V i r t u a l M e t a c o n t e n t                                 #
6184 #                                                                             #
6185 #                                                                             #
6186 #                                                                             #
6187 ###############################################################################
6188 #
6189 #
6190 void *
6191 GetVirtualMetacontent(ref,...)
6192   Image::Magick ref = NO_INIT
6193   ALIAS:
6194     getvirtualmetacontent = 1
6195   CODE:
6196   {
6197     ExceptionInfo
6198       *exception;
6199
6200     Image
6201       *image;
6202
6203     struct PackageInfo
6204       *info;
6205
6206     SV
6207       *perl_exception,
6208       *reference;
6209
6210     void
6211       *blob = NULL;
6212
6213     PERL_UNUSED_VAR(ref);
6214     PERL_UNUSED_VAR(ix);
6215     exception=AcquireExceptionInfo();
6216     perl_exception=newSVpv("",0);
6217     if (sv_isobject(ST(0)) == 0)
6218       {
6219         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6220           PackageName);
6221         goto PerlException;
6222       }
6223     reference=SvRV(ST(0));
6224
6225     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6226     if (image == (Image *) NULL)
6227       {
6228         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6229           PackageName);
6230         goto PerlException;
6231       }
6232
6233     blob=(void *) GetVirtualMetacontent(image);
6234     if (blob != (void *) NULL)
6235       goto PerlEnd;
6236
6237   PerlException:
6238     InheritPerlException(exception,perl_exception);
6239     exception=DestroyExceptionInfo(exception);
6240     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6241
6242   PerlEnd:
6243     RETVAL = blob;
6244   }
6245   OUTPUT:
6246     RETVAL
6247 \f
6248 #
6249 ###############################################################################
6250 #                                                                             #
6251 #                                                                             #
6252 #                                                                             #
6253 #   H i s t o g r a m                                                         #
6254 #                                                                             #
6255 #                                                                             #
6256 #                                                                             #
6257 ###############################################################################
6258 #
6259 #
6260 void
6261 Histogram(ref,...)
6262   Image::Magick ref=NO_INIT
6263   ALIAS:
6264     HistogramImage = 1
6265     histogram      = 2
6266     histogramimage = 3
6267   PPCODE:
6268   {
6269     AV
6270       *av;
6271
6272     char
6273       message[MaxTextExtent];
6274
6275     PixelInfo
6276       *histogram;
6277
6278     ExceptionInfo
6279       *exception;
6280
6281     Image
6282       *image;
6283
6284     register ssize_t
6285       i;
6286
6287     ssize_t
6288       count;
6289
6290     struct PackageInfo
6291       *info;
6292
6293     SV
6294       *perl_exception,
6295       *reference;
6296
6297     size_t
6298       number_colors;
6299
6300     PERL_UNUSED_VAR(ref);
6301     PERL_UNUSED_VAR(ix);
6302     exception=AcquireExceptionInfo();
6303     perl_exception=newSVpv("",0);
6304     av=NULL;
6305     if (sv_isobject(ST(0)) == 0)
6306       {
6307         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6308           PackageName);
6309         goto PerlException;
6310       }
6311     reference=SvRV(ST(0));
6312     av=newAV();
6313     SvREFCNT_dec(av);
6314     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6315     if (image == (Image *) NULL)
6316       {
6317         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6318           PackageName);
6319         goto PerlException;
6320       }
6321     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
6322     count=0;
6323     for ( ; image; image=image->next)
6324     {
6325       histogram=GetImageHistogram(image,&number_colors,exception);
6326       if (histogram == (PixelInfo *) NULL)
6327         continue;
6328       count+=(ssize_t) number_colors;
6329       EXTEND(sp,6*count);
6330       for (i=0; i < (ssize_t) number_colors; i++)
6331       {
6332         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6333           histogram[i].red);
6334         PUSHs(sv_2mortal(newSVpv(message,0)));
6335         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6336           histogram[i].green);
6337         PUSHs(sv_2mortal(newSVpv(message,0)));
6338         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6339           histogram[i].blue);
6340         PUSHs(sv_2mortal(newSVpv(message,0)));
6341         if (image->colorspace == CMYKColorspace)
6342           {
6343             (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6344               histogram[i].black);
6345             PUSHs(sv_2mortal(newSVpv(message,0)));
6346           }
6347         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6348           histogram[i].alpha);
6349         PUSHs(sv_2mortal(newSVpv(message,0)));
6350         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
6351           histogram[i].count);
6352         PUSHs(sv_2mortal(newSVpv(message,0)));
6353       }
6354       histogram=(PixelInfo *) RelinquishMagickMemory(histogram);
6355     }
6356
6357   PerlException:
6358     InheritPerlException(exception,perl_exception);
6359     exception=DestroyExceptionInfo(exception);
6360     SvREFCNT_dec(perl_exception);
6361   }
6362 \f
6363 #
6364 ###############################################################################
6365 #                                                                             #
6366 #                                                                             #
6367 #                                                                             #
6368 #   G e t P i x e l                                                           #
6369 #                                                                             #
6370 #                                                                             #
6371 #                                                                             #
6372 ###############################################################################
6373 #
6374 #
6375 void
6376 GetPixel(ref,...)
6377   Image::Magick ref=NO_INIT
6378   ALIAS:
6379     getpixel = 1
6380     getPixel = 2
6381   PPCODE:
6382   {
6383     AV
6384       *av;
6385
6386     char
6387       *attribute;
6388
6389     ExceptionInfo
6390       *exception;
6391
6392     Image
6393       *image;
6394
6395     MagickBooleanType
6396       normalize;
6397
6398     RectangleInfo
6399       region;
6400
6401     register const Quantum
6402       *p;
6403
6404     register ssize_t
6405       i;
6406
6407     ssize_t
6408       option;
6409
6410     struct PackageInfo
6411       *info;
6412
6413     SV
6414       *perl_exception,
6415       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6416
6417     PERL_UNUSED_VAR(ref);
6418     PERL_UNUSED_VAR(ix);
6419     exception=AcquireExceptionInfo();
6420     perl_exception=newSVpv("",0);
6421     reference=SvRV(ST(0));
6422     av=(AV *) reference;
6423     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6424       exception);
6425     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6426     if (image == (Image *) NULL)
6427       {
6428         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6429           PackageName);
6430         goto PerlException;
6431       }
6432     normalize=MagickTrue;
6433     region.x=0;
6434     region.y=0;
6435     region.width=image->columns;
6436     region.height=1;
6437     if (items == 1)
6438       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6439     for (i=2; i < items; i+=2)
6440     {
6441       attribute=(char *) SvPV(ST(i-1),na);
6442       switch (*attribute)
6443       {
6444         case 'C':
6445         case 'c':
6446         {
6447           if (LocaleCompare(attribute,"channel") == 0)
6448             {
6449               ssize_t
6450                 option;
6451
6452               option=ParseChannelOption(SvPV(ST(i),na));
6453               if (option < 0)
6454                 {
6455                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6456                     SvPV(ST(i),na));
6457                   return;
6458                 }
6459               SetPixelChannelMask(image,(ChannelType) option);
6460               break;
6461             }
6462           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6463             attribute);
6464           break;
6465         }
6466         case 'g':
6467         case 'G':
6468         {
6469           if (LocaleCompare(attribute,"geometry") == 0)
6470             {
6471               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6472               break;
6473             }
6474           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6475             attribute);
6476           break;
6477         }
6478         case 'N':
6479         case 'n':
6480         {
6481           if (LocaleCompare(attribute,"normalize") == 0)
6482             {
6483               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6484                 SvPV(ST(i),na));
6485               if (option < 0)
6486                 {
6487                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6488                     SvPV(ST(i),na));
6489                   break;
6490                 }
6491              normalize=option != 0 ? MagickTrue : MagickFalse;
6492              break;
6493             }
6494           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6495             attribute);
6496           break;
6497         }
6498         case 'x':
6499         case 'X':
6500         {
6501           if (LocaleCompare(attribute,"x") == 0)
6502             {
6503               region.x=SvIV(ST(i));
6504               break;
6505             }
6506           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6507             attribute);
6508           break;
6509         }
6510         case 'y':
6511         case 'Y':
6512         {
6513           if (LocaleCompare(attribute,"y") == 0)
6514             {
6515               region.y=SvIV(ST(i));
6516               break;
6517             }
6518           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6519             attribute);
6520           break;
6521         }
6522         default:
6523         {
6524           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6525             attribute);
6526           break;
6527         }
6528       }
6529     }
6530     p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6531     if (p == (const Quantum *) NULL)
6532       PUSHs(&sv_undef);
6533     else
6534       {
6535         double
6536           scale;
6537
6538         scale=1.0;
6539         if (normalize != MagickFalse)
6540           scale=1.0/QuantumRange;
6541         if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
6542           PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6543         if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6544           PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6545         if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6546           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6547         if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6548             (image->colorspace == CMYKColorspace))
6549           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6550         if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
6551           PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6552       }
6553
6554   PerlException:
6555     InheritPerlException(exception,perl_exception);
6556     exception=DestroyExceptionInfo(exception);
6557     SvREFCNT_dec(perl_exception);
6558   }
6559 \f
6560 #
6561 ###############################################################################
6562 #                                                                             #
6563 #                                                                             #
6564 #                                                                             #
6565 #   G e t P i x e l s                                                         #
6566 #                                                                             #
6567 #                                                                             #
6568 #                                                                             #
6569 ###############################################################################
6570 #
6571 #
6572 void
6573 GetPixels(ref,...)
6574   Image::Magick ref=NO_INIT
6575   ALIAS:
6576     getpixels = 1
6577     getPixels = 2
6578   PPCODE:
6579   {
6580     AV
6581       *av;
6582
6583     char
6584       *attribute;
6585
6586     const char
6587       *map;
6588
6589     ExceptionInfo
6590       *exception;
6591
6592     Image
6593       *image;
6594
6595     MagickBooleanType
6596       normalize,
6597       status;
6598
6599     RectangleInfo
6600       region;
6601
6602     register ssize_t
6603       i;
6604
6605     ssize_t
6606       option;
6607
6608     struct PackageInfo
6609       *info;
6610
6611     SV
6612       *perl_exception,
6613       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6614
6615     PERL_UNUSED_VAR(ref);
6616     PERL_UNUSED_VAR(ix);
6617     exception=AcquireExceptionInfo();
6618     perl_exception=newSVpv("",0);
6619     reference=SvRV(ST(0));
6620     av=(AV *) reference;
6621     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6622       exception);
6623     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6624     if (image == (Image *) NULL)
6625       {
6626         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6627           PackageName);
6628         goto PerlException;
6629       }
6630     map="RGB";
6631     if (image->alpha_trait == BlendPixelTrait)
6632       map="RGBA";
6633     if (image->colorspace == CMYKColorspace)
6634       {
6635         map="CMYK";
6636         if (image->alpha_trait == BlendPixelTrait)
6637           map="CMYKA";
6638       }
6639     normalize=MagickFalse;
6640     region.x=0;
6641     region.y=0;
6642     region.width=image->columns;
6643     region.height=1;
6644     if (items == 1)
6645       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6646     for (i=2; i < items; i+=2)
6647     {
6648       attribute=(char *) SvPV(ST(i-1),na);
6649       switch (*attribute)
6650       {
6651         case 'g':
6652         case 'G':
6653         {
6654           if (LocaleCompare(attribute,"geometry") == 0)
6655             {
6656               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6657               break;
6658             }
6659           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6660             attribute);
6661           break;
6662         }
6663         case 'H':
6664         case 'h':
6665         {
6666           if (LocaleCompare(attribute,"height") == 0)
6667             {
6668               region.height=SvIV(ST(i));
6669               break;
6670             }
6671           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6672             attribute);
6673           break;
6674         }
6675         case 'M':
6676         case 'm':
6677         {
6678           if (LocaleCompare(attribute,"map") == 0)
6679             {
6680               map=SvPV(ST(i),na);
6681               break;
6682             }
6683           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6684             attribute);
6685           break;
6686         }
6687         case 'N':
6688         case 'n':
6689         {
6690           if (LocaleCompare(attribute,"normalize") == 0)
6691             {
6692               option=ParseCommandOption(MagickBooleanOptions,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              normalize=option != 0 ? MagickTrue : MagickFalse;
6701              break;
6702             }
6703           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6704             attribute);
6705           break;
6706         }
6707         case 'W':
6708         case 'w':
6709         {
6710           if (LocaleCompare(attribute,"width") == 0)
6711             {
6712               region.width=SvIV(ST(i));
6713               break;
6714             }
6715           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6716             attribute);
6717           break;
6718         }
6719         case 'x':
6720         case 'X':
6721         {
6722           if (LocaleCompare(attribute,"x") == 0)
6723             {
6724               region.x=SvIV(ST(i));
6725               break;
6726             }
6727           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6728             attribute);
6729           break;
6730         }
6731         case 'y':
6732         case 'Y':
6733         {
6734           if (LocaleCompare(attribute,"y") == 0)
6735             {
6736               region.y=SvIV(ST(i));
6737               break;
6738             }
6739           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6740             attribute);
6741           break;
6742         }
6743         default:
6744         {
6745           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6746             attribute);
6747           break;
6748         }
6749       }
6750     }
6751     if (normalize != MagickFalse)
6752       {
6753         float
6754           *pixels;
6755
6756         pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6757           region.height*sizeof(*pixels));
6758         if (pixels == (float *) NULL)
6759           {
6760             ThrowPerlException(exception,ResourceLimitError,
6761               "MemoryAllocationFailed",PackageName);
6762             goto PerlException;
6763           }
6764         status=ExportImagePixels(image,region.x,region.y,region.width,
6765           region.height,map,FloatPixel,pixels,exception);
6766         if (status == MagickFalse)
6767           PUSHs(&sv_undef);
6768         else
6769           {
6770             EXTEND(sp,strlen(map)*region.width*region.height);
6771             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6772               PUSHs(sv_2mortal(newSVnv(pixels[i])));
6773           }
6774         pixels=(float *) RelinquishMagickMemory(pixels);
6775       }
6776     else
6777       {
6778         Quantum
6779           *pixels;
6780
6781         pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6782           region.height*sizeof(*pixels));
6783         if (pixels == (Quantum *) NULL)
6784           {
6785             ThrowPerlException(exception,ResourceLimitError,
6786               "MemoryAllocationFailed",PackageName);
6787             goto PerlException;
6788           }
6789         status=ExportImagePixels(image,region.x,region.y,region.width,
6790           region.height,map,QuantumPixel,pixels,exception);
6791         if (status == MagickFalse)
6792           PUSHs(&sv_undef);
6793         else
6794           {
6795             EXTEND(sp,strlen(map)*region.width*region.height);
6796             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6797               PUSHs(sv_2mortal(newSViv(pixels[i])));
6798           }
6799         pixels=(Quantum *) RelinquishMagickMemory(pixels);
6800       }
6801
6802   PerlException:
6803     InheritPerlException(exception,perl_exception);
6804     exception=DestroyExceptionInfo(exception);
6805     SvREFCNT_dec(perl_exception);
6806   }
6807 \f
6808 #
6809 ###############################################################################
6810 #                                                                             #
6811 #                                                                             #
6812 #                                                                             #
6813 #   I m a g e T o B l o b                                                     #
6814 #                                                                             #
6815 #                                                                             #
6816 #                                                                             #
6817 ###############################################################################
6818 #
6819 #
6820 void
6821 ImageToBlob(ref,...)
6822   Image::Magick ref=NO_INIT
6823   ALIAS:
6824     ImageToBlob  = 1
6825     imagetoblob  = 2
6826     toblob       = 3
6827     blob         = 4
6828   PPCODE:
6829   {
6830     char
6831       filename[MaxTextExtent];
6832
6833     ExceptionInfo
6834       *exception;
6835
6836     Image
6837       *image,
6838       *next;
6839
6840     register ssize_t
6841       i;
6842
6843     struct PackageInfo
6844       *info,
6845       *package_info;
6846
6847     size_t
6848       length;
6849
6850     ssize_t
6851       scene;
6852
6853     SV
6854       *perl_exception,
6855       *reference;
6856
6857     void
6858       *blob;
6859
6860     PERL_UNUSED_VAR(ref);
6861     PERL_UNUSED_VAR(ix);
6862     exception=AcquireExceptionInfo();
6863     perl_exception=newSVpv("",0);
6864     package_info=(struct PackageInfo *) NULL;
6865     if (sv_isobject(ST(0)) == 0)
6866       {
6867         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6868           PackageName);
6869         goto PerlException;
6870       }
6871     reference=SvRV(ST(0));
6872     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6873     if (image == (Image *) NULL)
6874       {
6875         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6876           PackageName);
6877         goto PerlException;
6878       }
6879     package_info=ClonePackageInfo(info,exception);
6880     for (i=2; i < items; i+=2)
6881       SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6882     (void) CopyMagickString(filename,package_info->image_info->filename,
6883       MaxTextExtent);
6884     scene=0;
6885     for (next=image; next; next=next->next)
6886     {
6887       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
6888       next->scene=scene++;
6889     }
6890     SetImageInfo(package_info->image_info,(unsigned int)
6891       GetImageListLength(image),exception);
6892     EXTEND(sp,(ssize_t) GetImageListLength(image));
6893     for ( ; image; image=image->next)
6894     {
6895       length=0;
6896       blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6897       if (blob != (char *) NULL)
6898         {
6899           PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6900           blob=(unsigned char *) RelinquishMagickMemory(blob);
6901         }
6902       if (package_info->image_info->adjoin)
6903         break;
6904     }
6905
6906   PerlException:
6907     if (package_info != (struct PackageInfo *) NULL)
6908       DestroyPackageInfo(package_info);
6909     InheritPerlException(exception,perl_exception);
6910     exception=DestroyExceptionInfo(exception);
6911     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6912   }
6913 \f
6914 #
6915 ###############################################################################
6916 #                                                                             #
6917 #                                                                             #
6918 #                                                                             #
6919 #   L a y e r s                                                               #
6920 #                                                                             #
6921 #                                                                             #
6922 #                                                                             #
6923 ###############################################################################
6924 #
6925 #
6926 void
6927 Layers(ref,...)
6928   Image::Magick ref=NO_INIT
6929   ALIAS:
6930     Layers                = 1
6931     layers           = 2
6932     OptimizeImageLayers   = 3
6933     optimizelayers        = 4
6934     optimizeimagelayers   = 5
6935   PPCODE:
6936   {
6937     AV
6938       *av;
6939
6940     char
6941       *attribute;
6942
6943     CompositeOperator
6944       compose;
6945
6946     ExceptionInfo
6947       *exception;
6948
6949     HV
6950       *hv;
6951
6952     Image
6953       *image,
6954       *layers;
6955
6956     LayerMethod
6957       method;
6958
6959     register ssize_t
6960       i;
6961
6962     ssize_t
6963       option,
6964       sp;
6965
6966     struct PackageInfo
6967       *info;
6968
6969     SV
6970       *av_reference,
6971       *perl_exception,
6972       *reference,
6973       *rv,
6974       *sv;
6975
6976     PERL_UNUSED_VAR(ref);
6977     PERL_UNUSED_VAR(ix);
6978     exception=AcquireExceptionInfo();
6979     perl_exception=newSVpv("",0);
6980     sv=NULL;
6981     if (sv_isobject(ST(0)) == 0)
6982       {
6983         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6984           PackageName);
6985         goto PerlException;
6986       }
6987     reference=SvRV(ST(0));
6988     hv=SvSTASH(reference);
6989     av=newAV();
6990     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
6991     SvREFCNT_dec(av);
6992     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6993     if (image == (Image *) NULL)
6994       {
6995         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6996           PackageName);
6997         goto PerlException;
6998       }
6999     compose=image->compose;
7000     method=OptimizeLayer;
7001     for (i=2; i < items; i+=2)
7002     {
7003       attribute=(char *) SvPV(ST(i-1),na);
7004       switch (*attribute)
7005       {
7006         case 'C':
7007         case 'c':
7008         {
7009           if (LocaleCompare(attribute,"compose") == 0)
7010             {
7011               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
7012                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
7013               if (sp < 0)
7014                 {
7015                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
7016                     SvPV(ST(i),na));
7017                   break;
7018                 }
7019               compose=(CompositeOperator) sp;
7020               break;
7021             }
7022           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7023             attribute);
7024           break;
7025         }
7026         case 'M':
7027         case 'm':
7028         {
7029           if (LocaleCompare(attribute,"method") == 0)
7030             {
7031               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
7032                 SvPV(ST(i),na));
7033               if (option < 0)
7034                 {
7035                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
7036                     SvPV(ST(i),na));
7037                   break;
7038                 }
7039               method=(LayerMethod) option;
7040               break;
7041             }
7042           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7043             attribute);
7044           break;
7045         }
7046         default:
7047         {
7048           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7049             attribute);
7050           break;
7051         }
7052       }
7053     }
7054     layers=(Image *) NULL;
7055     switch (method)
7056     {
7057       case CompareAnyLayer:
7058       case CompareClearLayer:
7059       case CompareOverlayLayer:
7060       default:
7061       {
7062         layers=CompareImagesLayers(image,method,exception);
7063         break;
7064       }
7065       case MergeLayer:
7066       case FlattenLayer:
7067       case MosaicLayer:
7068       {
7069         layers=MergeImageLayers(image,method,exception);
7070         break;
7071       }
7072       case DisposeLayer:
7073       {
7074         layers=DisposeImages(image,exception);
7075         break;
7076       }
7077       case OptimizeImageLayer:
7078       {
7079         layers=OptimizeImageLayers(image,exception);
7080         break;
7081       }
7082       case OptimizePlusLayer:
7083       {
7084         layers=OptimizePlusImageLayers(image,exception);
7085         break;
7086       }
7087       case OptimizeTransLayer:
7088       {
7089         OptimizeImageTransparency(image,exception);
7090         break;
7091       }
7092       case RemoveDupsLayer:
7093       {
7094         RemoveDuplicateLayers(&image,exception);
7095         break;
7096       }
7097       case RemoveZeroLayer:
7098       {
7099         RemoveZeroDelayLayers(&image,exception);
7100         break;
7101       }
7102       case OptimizeLayer:
7103       {
7104         QuantizeInfo
7105           *quantize_info;
7106
7107         /*
7108           General Purpose, GIF Animation Optimizer.
7109         */
7110         layers=CoalesceImages(image,exception);
7111         if (layers == (Image *) NULL)
7112           break;
7113         image=layers;
7114         layers=OptimizeImageLayers(image,exception);
7115         if (layers == (Image *) NULL)
7116           break;
7117         image=DestroyImageList(image);
7118         image=layers;
7119         layers=(Image *) NULL;
7120         OptimizeImageTransparency(image,exception);
7121         quantize_info=AcquireQuantizeInfo(info->image_info);
7122         (void) RemapImages(quantize_info,image,(Image *) NULL,exception);
7123         quantize_info=DestroyQuantizeInfo(quantize_info);
7124         break;
7125       }
7126       case CompositeLayer:
7127       {
7128         Image
7129           *source;
7130
7131         RectangleInfo
7132           geometry;
7133
7134         /*
7135           Split image sequence at the first 'NULL:' image.
7136         */
7137         source=image;
7138         while (source != (Image *) NULL)
7139         {
7140           source=GetNextImageInList(source);
7141           if ((source != (Image *) NULL) &&
7142               (LocaleCompare(source->magick,"NULL") == 0))
7143             break;
7144         }
7145         if (source != (Image *) NULL)
7146           {
7147             if ((GetPreviousImageInList(source) == (Image *) NULL) ||
7148                 (GetNextImageInList(source) == (Image *) NULL))
7149               source=(Image *) NULL;
7150             else
7151               {
7152                 /*
7153                   Separate the two lists, junk the null: image.
7154                 */
7155                 source=SplitImageList(source->previous);
7156                 DeleteImageFromList(&source);
7157               }
7158           }
7159         if (source == (Image *) NULL)
7160           {
7161             (void) ThrowMagickException(exception,GetMagickModule(),
7162               OptionError,"MissingNullSeparator","layers Composite");
7163             break;
7164           }
7165         /*
7166           Adjust offset with gravity and virtual canvas.
7167         */
7168         SetGeometry(image,&geometry);
7169         (void) ParseAbsoluteGeometry(image->geometry,&geometry);
7170         geometry.width=source->page.width != 0 ? source->page.width :
7171           source->columns;
7172         geometry.height=source->page.height != 0 ? source->page.height :
7173           source->rows;
7174         GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
7175           image->columns,image->page.height != 0 ? image->page.height :
7176           image->rows,image->gravity,&geometry);
7177         CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
7178         source=DestroyImageList(source);
7179         break;
7180       }
7181     }
7182     if (layers != (Image *) NULL)
7183       image=layers;
7184     else
7185       image=CloneImage(image,0,0,MagickTrue,exception);
7186     if (image == (Image *) NULL)
7187       goto PerlException;
7188     for ( ; image; image=image->next)
7189     {
7190       AddImageToRegistry(sv,image);
7191       rv=newRV(sv);
7192       av_push(av,sv_bless(rv,hv));
7193       SvREFCNT_dec(sv);
7194     }
7195     exception=DestroyExceptionInfo(exception);
7196     ST(0)=av_reference;
7197     SvREFCNT_dec(perl_exception);
7198     XSRETURN(1);
7199
7200   PerlException:
7201     InheritPerlException(exception,perl_exception);
7202     exception=DestroyExceptionInfo(exception);
7203     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
7204     SvPOK_on(perl_exception);
7205     ST(0)=sv_2mortal(perl_exception);
7206     XSRETURN(1);
7207   }
7208 \f
7209 #
7210 ###############################################################################
7211 #                                                                             #
7212 #                                                                             #
7213 #                                                                             #
7214 #   M a g i c k T o M i m e                                                   #
7215 #                                                                             #
7216 #                                                                             #
7217 #                                                                             #
7218 ###############################################################################
7219 #
7220 #
7221 SV *
7222 MagickToMime(ref,name)
7223   Image::Magick ref=NO_INIT
7224   char *name
7225   ALIAS:
7226     magicktomime = 1
7227   CODE:
7228   {
7229     char
7230       *mime;
7231
7232     PERL_UNUSED_VAR(ref);
7233     PERL_UNUSED_VAR(ix);
7234     mime=MagickToMime(name);
7235     RETVAL=newSVpv(mime,0);
7236     mime=(char *) RelinquishMagickMemory(mime);
7237   }
7238   OUTPUT:
7239     RETVAL
7240 \f
7241 #
7242 ###############################################################################
7243 #                                                                             #
7244 #                                                                             #
7245 #                                                                             #
7246 #   M o g r i f y                                                             #
7247 #                                                                             #
7248 #                                                                             #
7249 #                                                                             #
7250 ###############################################################################
7251 #
7252 #
7253 void
7254 Mogrify(ref,...)
7255   Image::Magick ref=NO_INIT
7256   ALIAS:
7257     Comment            =   1
7258     CommentImage       =   2
7259     Label              =   3
7260     LabelImage         =   4
7261     AddNoise           =   5
7262     AddNoiseImage      =   6
7263     Colorize           =   7
7264     ColorizeImage      =   8
7265     Border             =   9
7266     BorderImage        =  10
7267     Blur               =  11
7268     BlurImage          =  12
7269     Chop               =  13
7270     ChopImage          =  14
7271     Crop               =  15
7272     CropImage          =  16
7273     Despeckle          =  17
7274     DespeckleImage     =  18
7275     Edge               =  19
7276     EdgeImage          =  20
7277     Emboss             =  21
7278     EmbossImage        =  22
7279     Enhance            =  23
7280     EnhanceImage       =  24
7281     Flip               =  25
7282     FlipImage          =  26
7283     Flop               =  27
7284     FlopImage          =  28
7285     Frame              =  29
7286     FrameImage         =  30
7287     Implode            =  31
7288     ImplodeImage       =  32
7289     Magnify            =  33
7290     MagnifyImage       =  34
7291     MedianFilter       =  35
7292     MedianConvolveImage  =  36
7293     Minify             =  37
7294     MinifyImage        =  38
7295     OilPaint           =  39
7296     OilPaintImage      =  40
7297     ReduceNoise        =  41
7298     ReduceNoiseImage   =  42
7299     Roll               =  43
7300     RollImage          =  44
7301     Rotate             =  45
7302     RotateImage        =  46
7303     Sample             =  47
7304     SampleImage        =  48
7305     Scale              =  49
7306     ScaleImage         =  50
7307     Shade              =  51
7308     ShadeImage         =  52
7309     Sharpen            =  53
7310     SharpenImage       =  54
7311     Shear              =  55
7312     ShearImage         =  56
7313     Spread             =  57
7314     SpreadImage        =  58
7315     Swirl              =  59
7316     SwirlImage         =  60
7317     Resize             =  61
7318     ResizeImage        =  62
7319     Zoom               =  63
7320     ZoomImage          =  64
7321     Annotate           =  65
7322     AnnotateImage      =  66
7323     ColorFloodfill     =  67
7324     ColorFloodfillImage=  68
7325     Composite          =  69
7326     CompositeImage     =  70
7327     Contrast           =  71
7328     ContrastImage      =  72
7329     CycleColormap      =  73
7330     CycleColormapImage =  74
7331     Draw               =  75
7332     DrawImage          =  76
7333     Equalize           =  77
7334     EqualizeImage      =  78
7335     Gamma              =  79
7336     GammaImage         =  80
7337     Map                =  81
7338     MapImage           =  82
7339     MatteFloodfill     =  83
7340     MatteFloodfillImage=  84
7341     Modulate           =  85
7342     ModulateImage      =  86
7343     Negate             =  87
7344     NegateImage        =  88
7345     Normalize          =  89
7346     NormalizeImage     =  90
7347     NumberColors       =  91
7348     NumberColorsImage  =  92
7349     Opaque             =  93
7350     OpaqueImage        =  94
7351     Quantize           =  95
7352     QuantizeImage      =  96
7353     Raise              =  97
7354     RaiseImage         =  98
7355     Segment            =  99
7356     SegmentImage       = 100
7357     Signature          = 101
7358     SignatureImage     = 102
7359     Solarize           = 103
7360     SolarizeImage      = 104
7361     Sync               = 105
7362     SyncImage          = 106
7363     Texture            = 107
7364     TextureImage       = 108
7365     Evaluate           = 109
7366     EvaluateImage      = 110
7367     Transparent        = 111
7368     TransparentImage   = 112
7369     Threshold          = 113
7370     ThresholdImage     = 114
7371     Charcoal           = 115
7372     CharcoalImage      = 116
7373     Trim               = 117
7374     TrimImage          = 118
7375     Wave               = 119
7376     WaveImage          = 120
7377     Separate           = 121
7378     SeparateImage      = 122
7379     Stereo             = 125
7380     StereoImage        = 126
7381     Stegano            = 127
7382     SteganoImage       = 128
7383     Deconstruct        = 129
7384     DeconstructImage   = 130
7385     GaussianBlur       = 131
7386     GaussianBlurImage  = 132
7387     Convolve           = 133
7388     ConvolveImage      = 134
7389     Profile            = 135
7390     ProfileImage       = 136
7391     UnsharpMask        = 137
7392     UnsharpMaskImage   = 138
7393     MotionBlur         = 139
7394     MotionBlurImage    = 140
7395     OrderedDither      = 141
7396     OrderedDitherImage = 142
7397     Shave              = 143
7398     ShaveImage         = 144
7399     Level              = 145
7400     LevelImage         = 146
7401     Clip               = 147
7402     ClipImage          = 148
7403     AffineTransform    = 149
7404     AffineTransformImage = 150
7405     Difference         = 151
7406     DifferenceImage    = 152
7407     AdaptiveThreshold  = 153
7408     AdaptiveThresholdImage = 154
7409     Resample           = 155
7410     ResampleImage      = 156
7411     Describe           = 157
7412     DescribeImage      = 158
7413     BlackThreshold     = 159
7414     BlackThresholdImage= 160
7415     WhiteThreshold     = 161
7416     WhiteThresholdImage= 162
7417     RotationalBlur     = 163
7418     RotationalBlurImage= 164
7419     Thumbnail          = 165
7420     ThumbnailImage     = 166
7421     Strip              = 167
7422     StripImage         = 168
7423     Tint               = 169
7424     TintImage          = 170
7425     Channel            = 171
7426     ChannelImage       = 172
7427     Splice             = 173
7428     SpliceImage        = 174
7429     Posterize          = 175
7430     PosterizeImage     = 176
7431     Shadow             = 177
7432     ShadowImage        = 178
7433     Identify           = 179
7434     IdentifyImage      = 180
7435     SepiaTone          = 181
7436     SepiaToneImage     = 182
7437     SigmoidalContrast  = 183
7438     SigmoidalContrastImage = 184
7439     Extent             = 185
7440     ExtentImage        = 186
7441     Vignette           = 187
7442     VignetteImage      = 188
7443     ContrastStretch    = 189
7444     ContrastStretchImage = 190
7445     Sans0              = 191
7446     Sans0Image         = 192
7447     Sans1              = 193
7448     Sans1Image         = 194
7449     AdaptiveSharpen    = 195
7450     AdaptiveSharpenImage = 196
7451     Transpose          = 197
7452     TransposeImage     = 198
7453     Transverse         = 199
7454     TransverseImage    = 200
7455     AutoOrient         = 201
7456     AutoOrientImage    = 202
7457     AdaptiveBlur       = 203
7458     AdaptiveBlurImage  = 204
7459     Sketch             = 205
7460     SketchImage        = 206
7461     UniqueColors       = 207
7462     UniqueColorsImage  = 208
7463     AdaptiveResize     = 209
7464     AdaptiveResizeImage= 210
7465     ClipMask           = 211
7466     ClipMaskImage      = 212
7467     LinearStretch      = 213
7468     LinearStretchImage = 214
7469     ColorMatrix        = 215
7470     ColorMatrixImage   = 216
7471     Mask               = 217
7472     MaskImage          = 218
7473     Polaroid           = 219
7474     PolaroidImage      = 220
7475     FloodfillPaint     = 221
7476     FloodfillPaintImage= 222
7477     Distort            = 223
7478     DistortImage       = 224
7479     Clut               = 225
7480     ClutImage          = 226
7481     LiquidRescale      = 227
7482     LiquidRescaleImage = 228
7483     Encipher           = 229
7484     EncipherImage      = 230
7485     Decipher           = 231
7486     DecipherImage      = 232
7487     Deskew             = 233
7488     DeskewImage        = 234
7489     Remap              = 235
7490     RemapImage         = 236
7491     SparseColor        = 237
7492     SparseColorImage   = 238
7493     Function           = 239
7494     FunctionImage      = 240
7495     SelectiveBlur      = 241
7496     SelectiveBlurImage = 242
7497     HaldClut           = 243
7498     HaldClutImage      = 244
7499     BlueShift          = 245
7500     BlueShiftImage     = 246
7501     ForwardFourierTransform  = 247
7502     ForwardFourierTransformImage = 248
7503     InverseFourierTransform = 249
7504     InverseFourierTransformImage = 250
7505     ColorDecisionList  = 251
7506     ColorDecisionListImage = 252
7507     AutoGamma          = 253
7508     AutoGammaImage     = 254
7509     AutoLevel          = 255
7510     AutoLevelImage     = 256
7511     LevelColors        = 257
7512     LevelImageColors   = 258
7513     Clamp              = 259
7514     ClampImage         = 260
7515     BrightnessContrast = 261
7516     BrightnessContrastImage = 262
7517     Morphology         = 263
7518     MorphologyImage    = 264
7519     Color              = 265
7520     ColorImage         = 266
7521     Mode               = 267
7522     ModeImage          = 268
7523     Statistic          = 269
7524     StatisticImage     = 270
7525     Perceptible        = 271
7526     PerceptibleImage   = 272
7527     Poly               = 273
7528     PolyImage          = 274
7529     Grayscale          = 275
7530     GrayscaleImage     = 276
7531     CannyEdge          = 278
7532     CannyEdgeImage     = 279
7533     MogrifyRegion      = 666
7534   PPCODE:
7535   {
7536     AffineMatrix
7537       affine,
7538       current;
7539
7540     char
7541       attribute_flag[MaxArguments],
7542       message[MaxTextExtent];
7543
7544     ChannelType
7545       channel,
7546       channel_mask;
7547
7548     CompositeOperator
7549       compose;
7550
7551     const char
7552       *attribute,
7553       *value;
7554
7555     double
7556       angle;
7557
7558     ExceptionInfo
7559       *exception;
7560
7561     GeometryInfo
7562       geometry_info;
7563
7564     Image
7565       *image,
7566       *next,
7567       *region_image;
7568
7569     MagickBooleanType
7570       status;
7571
7572     MagickStatusType
7573       flags;
7574
7575     PixelInfo
7576       fill_color;
7577
7578     RectangleInfo
7579       geometry,
7580       region_info;
7581
7582     register ssize_t
7583       i;
7584
7585     ssize_t
7586       base,
7587       j,
7588       number_images;
7589
7590     struct Methods
7591       *rp;
7592
7593     struct PackageInfo
7594       *info;
7595
7596     SV
7597       *perl_exception,
7598       **pv,
7599       *reference,
7600       **reference_vector;
7601
7602     struct ArgumentList
7603       argument_list[MaxArguments];
7604
7605     PERL_UNUSED_VAR(ref);
7606     PERL_UNUSED_VAR(ix);
7607     exception=AcquireExceptionInfo();
7608     perl_exception=newSVpv("",0);
7609     reference_vector=NULL;
7610     region_image=NULL;
7611     number_images=0;
7612     base=2;
7613     if (sv_isobject(ST(0)) == 0)
7614       {
7615         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7616           PackageName);
7617         goto PerlException;
7618       }
7619     reference=SvRV(ST(0));
7620     region_info.width=0;
7621     region_info.height=0;
7622     region_info.x=0;
7623     region_info.y=0;
7624     region_image=(Image *) NULL;
7625     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7626     if (ix && (ix != 666))
7627       {
7628         /*
7629           Called as Method(...)
7630         */
7631         ix=(ix+1)/2;
7632         rp=(&Methods[ix-1]);
7633         attribute=rp->name;
7634       }
7635     else
7636       {
7637         /*
7638           Called as Mogrify("Method",...)
7639         */
7640         attribute=(char *) SvPV(ST(1),na);
7641         if (ix)
7642           {
7643             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7644             attribute=(char *) SvPV(ST(2),na);
7645             base++;
7646           }
7647         for (rp=Methods; ; rp++)
7648         {
7649           if (rp >= EndOf(Methods))
7650             {
7651               ThrowPerlException(exception,OptionError,
7652                 "UnrecognizedPerlMagickMethod",attribute);
7653               goto PerlException;
7654             }
7655           if (strEQcase(attribute,rp->name))
7656             break;
7657         }
7658         ix=rp-Methods+1;
7659         base++;
7660       }
7661     if (image == (Image *) NULL)
7662       {
7663         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7664         goto PerlException;
7665       }
7666     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7667     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7668     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7669     {
7670       Arguments
7671         *pp,
7672         *qq;
7673
7674       ssize_t
7675         ssize_test;
7676
7677       struct ArgumentList
7678         *al;
7679
7680       SV
7681         *sv;
7682
7683       sv=NULL;
7684       ssize_test=0;
7685       pp=(Arguments *) NULL;
7686       qq=rp->arguments;
7687       if (i == items)
7688         {
7689           pp=rp->arguments,
7690           sv=ST(i-1);
7691         }
7692       else
7693         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7694         {
7695           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7696             break;
7697           if (strEQcase(attribute,qq->method) > ssize_test)
7698             {
7699               pp=qq;
7700               ssize_test=strEQcase(attribute,qq->method);
7701             }
7702         }
7703       if (pp == (Arguments *) NULL)
7704         {
7705           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7706             attribute);
7707           goto continue_outer_loop;
7708         }
7709       al=(&argument_list[pp-rp->arguments]);
7710       switch (pp->type)
7711       {
7712         case ArrayReference:
7713         {
7714           if (SvTYPE(sv) != SVt_RV)
7715             {
7716               (void) FormatLocaleString(message,MaxTextExtent,
7717                 "invalid %.60s value",pp->method);
7718               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7719               goto continue_outer_loop;
7720             }
7721           al->array_reference=SvRV(sv);
7722           break;
7723         }
7724         case RealReference:
7725         {
7726           al->real_reference=SvNV(sv);
7727           break;
7728         }
7729         case FileReference:
7730         {
7731           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7732           break;
7733         }
7734         case ImageReference:
7735         {
7736           if (!sv_isobject(sv) ||
7737               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7738                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7739             {
7740               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7741                 PackageName);
7742               goto PerlException;
7743             }
7744           break;
7745         }
7746         case IntegerReference:
7747         {
7748           al->integer_reference=SvIV(sv);
7749           break;
7750         }
7751         case StringReference:
7752         {
7753           al->string_reference=(char *) SvPV(sv,al->length);
7754           if (sv_isobject(sv))
7755             al->image_reference=SetupList(aTHX_ SvRV(sv),
7756               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7757           break;
7758         }
7759         default:
7760         {
7761           /*
7762             Is a string; look up name.
7763           */
7764           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7765             {
7766               al->string_reference=(char *) SvPV(sv,al->length);
7767               al->integer_reference=(-1);
7768               break;
7769             }
7770           al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7771             MagickFalse,SvPV(sv,na));
7772           if (pp->type == MagickChannelOptions)
7773             al->integer_reference=ParseChannelOption(SvPV(sv,na));
7774           if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7775             {
7776               (void) FormatLocaleString(message,MaxTextExtent,
7777                 "invalid %.60s value",pp->method);
7778               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7779               goto continue_outer_loop;
7780             }
7781           break;
7782         }
7783       }
7784       attribute_flag[pp-rp->arguments]++;
7785       continue_outer_loop: ;
7786     }
7787     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7788     pv=reference_vector;
7789     SetGeometryInfo(&geometry_info);
7790     channel=DefaultChannels;
7791     for (next=image; next; next=next->next)
7792     {
7793       image=next;
7794       SetGeometry(image,&geometry);
7795       if ((region_info.width*region_info.height) != 0)
7796         {
7797           region_image=image;
7798           image=CropImage(image,&region_info,exception);
7799         }
7800       switch (ix)
7801       {
7802         default:
7803         {
7804           (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double) ix);
7805           ThrowPerlException(exception,OptionError,
7806             "UnrecognizedPerlMagickMethod",message);
7807           goto PerlException;
7808         }
7809         case 1:  /* Comment */
7810         {
7811           if (attribute_flag[0] == 0)
7812             argument_list[0].string_reference=(char *) NULL;
7813           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7814             info ? info->image_info : (ImageInfo *) NULL,image,
7815             argument_list[0].string_reference,exception),exception);
7816           break;
7817         }
7818         case 2:  /* Label */
7819         {
7820           if (attribute_flag[0] == 0)
7821             argument_list[0].string_reference=(char *) NULL;
7822           (void) SetImageProperty(image,"label",InterpretImageProperties(
7823             info ? info->image_info : (ImageInfo *) NULL,image,
7824             argument_list[0].string_reference,exception),exception);
7825           break;
7826         }
7827         case 3:  /* AddNoise */
7828         {
7829           double
7830             attenuate;
7831
7832           if (attribute_flag[0] == 0)
7833             argument_list[0].integer_reference=UniformNoise;
7834           attenuate=1.0;
7835           if (attribute_flag[1] != 0)
7836             attenuate=argument_list[1].real_reference;
7837           if (attribute_flag[2] != 0)
7838             channel=(ChannelType) argument_list[2].integer_reference;
7839           channel_mask=SetImageChannelMask(image,channel);
7840           image=AddNoiseImage(image,(NoiseType)
7841             argument_list[0].integer_reference,attenuate,exception);
7842           if (image != (Image *) NULL)
7843             (void) SetImageChannelMask(image,channel_mask);
7844           break;
7845         }
7846         case 4:  /* Colorize */
7847         {
7848           PixelInfo
7849             target;
7850
7851           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
7852             0,0,&target,exception);
7853           if (attribute_flag[0] != 0)
7854             (void) QueryColorCompliance(argument_list[0].string_reference,
7855               AllCompliance,&target,exception);
7856           if (attribute_flag[1] == 0)
7857             argument_list[1].string_reference="100%";
7858           image=ColorizeImage(image,argument_list[1].string_reference,&target,
7859             exception);
7860           break;
7861         }
7862         case 5:  /* Border */
7863         {
7864           CompositeOperator
7865             compose;
7866
7867           geometry.width=0;
7868           geometry.height=0;
7869           if (attribute_flag[0] != 0)
7870             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7871               &geometry,exception);
7872           if (attribute_flag[1] != 0)
7873             geometry.width=argument_list[1].integer_reference;
7874           if (attribute_flag[2] != 0)
7875             geometry.height=argument_list[2].integer_reference;
7876           if (attribute_flag[3] != 0)
7877             QueryColorCompliance(argument_list[3].string_reference,
7878               AllCompliance,&image->border_color,exception);
7879           if (attribute_flag[4] != 0)
7880             QueryColorCompliance(argument_list[4].string_reference,
7881               AllCompliance,&image->border_color,exception);
7882           if (attribute_flag[5] != 0)
7883             QueryColorCompliance(argument_list[5].string_reference,
7884               AllCompliance,&image->border_color,exception);
7885           compose=image->compose;
7886           if (attribute_flag[6] != 0)
7887             compose=(CompositeOperator) argument_list[6].integer_reference;
7888           image=BorderImage(image,&geometry,compose,exception);
7889           break;
7890         }
7891         case 6:  /* Blur */
7892         {
7893           if (attribute_flag[0] != 0)
7894             {
7895               flags=ParseGeometry(argument_list[0].string_reference,
7896                 &geometry_info);
7897               if ((flags & SigmaValue) == 0)
7898                 geometry_info.sigma=1.0;
7899             }
7900           if (attribute_flag[1] != 0)
7901             geometry_info.rho=argument_list[1].real_reference;
7902           if (attribute_flag[2] != 0)
7903             geometry_info.sigma=argument_list[2].real_reference;
7904           if (attribute_flag[3] != 0)
7905             channel=(ChannelType) argument_list[3].integer_reference;
7906           channel_mask=SetImageChannelMask(image,channel);
7907           image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
7908             exception);
7909           if (image != (Image *) NULL)
7910             (void) SetImageChannelMask(image,channel_mask);
7911           break;
7912         }
7913         case 7:  /* Chop */
7914         {
7915           if (attribute_flag[0] != 0)
7916             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7917               &geometry,exception);
7918           if (attribute_flag[1] != 0)
7919             geometry.width=argument_list[1].integer_reference;
7920           if (attribute_flag[2] != 0)
7921             geometry.height=argument_list[2].integer_reference;
7922           if (attribute_flag[3] != 0)
7923             geometry.x=argument_list[3].integer_reference;
7924           if (attribute_flag[4] != 0)
7925             geometry.y=argument_list[4].integer_reference;
7926           image=ChopImage(image,&geometry,exception);
7927           break;
7928         }
7929         case 8:  /* Crop */
7930         {
7931           if (attribute_flag[6] != 0)
7932             image->gravity=(GravityType) argument_list[6].integer_reference;
7933           if (attribute_flag[0] != 0)
7934             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7935               &geometry,exception);
7936           if (attribute_flag[1] != 0)
7937             geometry.width=argument_list[1].integer_reference;
7938           if (attribute_flag[2] != 0)
7939             geometry.height=argument_list[2].integer_reference;
7940           if (attribute_flag[3] != 0)
7941             geometry.x=argument_list[3].integer_reference;
7942           if (attribute_flag[4] != 0)
7943             geometry.y=argument_list[4].integer_reference;
7944           if (attribute_flag[5] != 0)
7945             image->fuzz=StringToDoubleInterval(
7946               argument_list[5].string_reference,(double) QuantumRange+1.0);
7947           image=CropImage(image,&geometry,exception);
7948           break;
7949         }
7950         case 9:  /* Despeckle */
7951         {
7952           image=DespeckleImage(image,exception);
7953           break;
7954         }
7955         case 10:  /* Edge */
7956         {
7957           if (attribute_flag[0] != 0)
7958             geometry_info.rho=argument_list[0].real_reference;
7959           image=EdgeImage(image,geometry_info.rho,exception);
7960           break;
7961         }
7962         case 11:  /* Emboss */
7963         {
7964           if (attribute_flag[0] != 0)
7965             {
7966               flags=ParseGeometry(argument_list[0].string_reference,
7967                 &geometry_info);
7968               if ((flags & SigmaValue) == 0)
7969                 geometry_info.sigma=1.0;
7970             }
7971           if (attribute_flag[1] != 0)
7972             geometry_info.rho=argument_list[1].real_reference;
7973           if (attribute_flag[2] != 0)
7974             geometry_info.sigma=argument_list[2].real_reference;
7975           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
7976             exception);
7977           break;
7978         }
7979         case 12:  /* Enhance */
7980         {
7981           image=EnhanceImage(image,exception);
7982           break;
7983         }
7984         case 13:  /* Flip */
7985         {
7986           image=FlipImage(image,exception);
7987           break;
7988         }
7989         case 14:  /* Flop */
7990         {
7991           image=FlopImage(image,exception);
7992           break;
7993         }
7994         case 15:  /* Frame */
7995         {
7996           CompositeOperator
7997             compose;
7998
7999           FrameInfo
8000             frame_info;
8001
8002           if (attribute_flag[0] != 0)
8003             {
8004               flags=ParsePageGeometry(image,argument_list[0].string_reference,
8005                 &geometry,exception);
8006               frame_info.width=geometry.width;
8007               frame_info.height=geometry.height;
8008               frame_info.outer_bevel=geometry.x;
8009               frame_info.inner_bevel=geometry.y;
8010             }
8011           if (attribute_flag[1] != 0)
8012             frame_info.width=argument_list[1].integer_reference;
8013           if (attribute_flag[2] != 0)
8014             frame_info.height=argument_list[2].integer_reference;
8015           if (attribute_flag[3] != 0)
8016             frame_info.inner_bevel=argument_list[3].integer_reference;
8017           if (attribute_flag[4] != 0)
8018             frame_info.outer_bevel=argument_list[4].integer_reference;
8019           if (attribute_flag[5] != 0)
8020             QueryColorCompliance(argument_list[5].string_reference,
8021               AllCompliance,&fill_color,exception);
8022           if (attribute_flag[6] != 0)
8023             QueryColorCompliance(argument_list[6].string_reference,
8024               AllCompliance,&fill_color,exception);
8025           frame_info.x=(ssize_t) frame_info.width;
8026           frame_info.y=(ssize_t) frame_info.height;
8027           frame_info.width=image->columns+2*frame_info.x;
8028           frame_info.height=image->rows+2*frame_info.y;
8029           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
8030             image->matte_color=fill_color;
8031           compose=image->compose;
8032           if (attribute_flag[7] != 0)
8033             compose=(CompositeOperator) argument_list[7].integer_reference;
8034           image=FrameImage(image,&frame_info,compose,exception);
8035           break;
8036         }
8037         case 16:  /* Implode */
8038         {
8039           PixelInterpolateMethod
8040             method;
8041
8042           if (attribute_flag[0] == 0)
8043             argument_list[0].real_reference=0.5;
8044           method=UndefinedInterpolatePixel;
8045           if (attribute_flag[1] != 0)
8046             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8047           image=ImplodeImage(image,argument_list[0].real_reference,
8048             method,exception);
8049           break;
8050         }
8051         case 17:  /* Magnify */
8052         {
8053           image=MagnifyImage(image,exception);
8054           break;
8055         }
8056         case 18:  /* MedianFilter */
8057         {
8058           if (attribute_flag[0] != 0)
8059             {
8060               flags=ParseGeometry(argument_list[0].string_reference,
8061                 &geometry_info);
8062               if ((flags & SigmaValue) == 0)
8063                 geometry_info.sigma=geometry_info.rho;
8064             }
8065           if (attribute_flag[1] != 0)
8066             geometry_info.rho=argument_list[1].real_reference;
8067           if (attribute_flag[2] != 0)
8068             geometry_info.sigma=argument_list[2].real_reference;
8069           if (attribute_flag[3] != 0)
8070             channel=(ChannelType) argument_list[3].integer_reference;
8071           channel_mask=SetImageChannelMask(image,channel);
8072           image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
8073             (size_t) geometry_info.sigma,exception);
8074           if (image != (Image *) NULL)
8075             (void) SetImageChannelMask(image,channel_mask);
8076           break;
8077         }
8078         case 19:  /* Minify */
8079         {
8080           image=MinifyImage(image,exception);
8081           break;
8082         }
8083         case 20:  /* OilPaint */
8084         {
8085           if (attribute_flag[0] == 0)
8086             argument_list[0].real_reference=0.0;
8087           if (attribute_flag[1] == 0)
8088             argument_list[1].real_reference=1.0;
8089           image=OilPaintImage(image,argument_list[0].real_reference,
8090             argument_list[1].real_reference,exception);
8091           break;
8092         }
8093         case 21:  /* ReduceNoise */
8094         {
8095           if (attribute_flag[0] != 0)
8096             {
8097               flags=ParseGeometry(argument_list[0].string_reference,
8098                 &geometry_info);
8099               if ((flags & SigmaValue) == 0)
8100                 geometry_info.sigma=1.0;
8101             }
8102           if (attribute_flag[1] != 0)
8103             geometry_info.rho=argument_list[1].real_reference;
8104           if (attribute_flag[2] != 0)
8105             geometry_info.sigma=argument_list[2].real_reference;
8106           if (attribute_flag[3] != 0)
8107             channel=(ChannelType) argument_list[3].integer_reference;
8108           channel_mask=SetImageChannelMask(image,channel);
8109           image=StatisticImage(image,NonpeakStatistic,(size_t)
8110             geometry_info.rho,(size_t) geometry_info.sigma,exception);
8111           if (image != (Image *) NULL)
8112             (void) SetImageChannelMask(image,channel_mask);
8113           break;
8114         }
8115         case 22:  /* Roll */
8116         {
8117           if (attribute_flag[0] != 0)
8118             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8119               &geometry,exception);
8120           if (attribute_flag[1] != 0)
8121             geometry.x=argument_list[1].integer_reference;
8122           if (attribute_flag[2] != 0)
8123             geometry.y=argument_list[2].integer_reference;
8124           image=RollImage(image,geometry.x,geometry.y,exception);
8125           break;
8126         }
8127         case 23:  /* Rotate */
8128         {
8129           if (attribute_flag[0] == 0)
8130             argument_list[0].real_reference=90.0;
8131           if (attribute_flag[1] != 0)
8132             {
8133               QueryColorCompliance(argument_list[1].string_reference,
8134                 AllCompliance,&image->background_color,exception);
8135               if ((image->background_color.alpha_trait == BlendPixelTrait) &&
8136                   (image->alpha_trait != BlendPixelTrait))
8137                 (void) SetImageAlpha(image,OpaqueAlpha,exception);
8138             }
8139           image=RotateImage(image,argument_list[0].real_reference,exception);
8140           break;
8141         }
8142         case 24:  /* Sample */
8143         {
8144           if (attribute_flag[0] != 0)
8145             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8146               &geometry,exception);
8147           if (attribute_flag[1] != 0)
8148             geometry.width=argument_list[1].integer_reference;
8149           if (attribute_flag[2] != 0)
8150             geometry.height=argument_list[2].integer_reference;
8151           image=SampleImage(image,geometry.width,geometry.height,exception);
8152           break;
8153         }
8154         case 25:  /* Scale */
8155         {
8156           if (attribute_flag[0] != 0)
8157             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8158               &geometry,exception);
8159           if (attribute_flag[1] != 0)
8160             geometry.width=argument_list[1].integer_reference;
8161           if (attribute_flag[2] != 0)
8162             geometry.height=argument_list[2].integer_reference;
8163           image=ScaleImage(image,geometry.width,geometry.height,exception);
8164           break;
8165         }
8166         case 26:  /* Shade */
8167         {
8168           if (attribute_flag[0] != 0)
8169             {
8170               flags=ParseGeometry(argument_list[0].string_reference,
8171                 &geometry_info);
8172               if ((flags & SigmaValue) == 0)
8173                 geometry_info.sigma=0.0;
8174             }
8175           if (attribute_flag[1] != 0)
8176             geometry_info.rho=argument_list[1].real_reference;
8177           if (attribute_flag[2] != 0)
8178             geometry_info.sigma=argument_list[2].real_reference;
8179           image=ShadeImage(image,
8180             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8181             geometry_info.rho,geometry_info.sigma,exception);
8182           break;
8183         }
8184         case 27:  /* Sharpen */
8185         {
8186           if (attribute_flag[0] != 0)
8187             {
8188               flags=ParseGeometry(argument_list[0].string_reference,
8189                 &geometry_info);
8190               if ((flags & SigmaValue) == 0)
8191                 geometry_info.sigma=1.0;
8192             }
8193           if (attribute_flag[1] != 0)
8194             geometry_info.rho=argument_list[1].real_reference;
8195           if (attribute_flag[2] != 0)
8196             geometry_info.sigma=argument_list[2].real_reference;
8197           if (attribute_flag[3] != 0)
8198             channel=(ChannelType) argument_list[3].integer_reference;
8199           channel_mask=SetImageChannelMask(image,channel);
8200           image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
8201             exception);
8202           if (image != (Image *) NULL)
8203             (void) SetImageChannelMask(image,channel_mask);
8204           break;
8205         }
8206         case 28:  /* Shear */
8207         {
8208           if (attribute_flag[0] != 0)
8209             {
8210               flags=ParseGeometry(argument_list[0].string_reference,
8211                 &geometry_info);
8212               if ((flags & SigmaValue) == 0)
8213                 geometry_info.sigma=geometry_info.rho;
8214             }
8215           if (attribute_flag[1] != 0)
8216             geometry_info.rho=argument_list[1].real_reference;
8217           if (attribute_flag[2] != 0)
8218             geometry_info.sigma=argument_list[2].real_reference;
8219           if (attribute_flag[3] != 0)
8220             QueryColorCompliance(argument_list[3].string_reference,
8221               AllCompliance,&image->background_color,exception);
8222           if (attribute_flag[4] != 0)
8223             QueryColorCompliance(argument_list[4].string_reference,
8224               AllCompliance,&image->background_color,exception);
8225           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
8226             exception);
8227           break;
8228         }
8229         case 29:  /* Spread */
8230         {
8231           PixelInterpolateMethod
8232             method;
8233
8234           if (attribute_flag[0] == 0)
8235             argument_list[0].real_reference=1.0;
8236           method=UndefinedInterpolatePixel;
8237           if (attribute_flag[1] != 0)
8238             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8239           image=SpreadImage(image,argument_list[0].real_reference,method,
8240             exception);
8241           break;
8242         }
8243         case 30:  /* Swirl */
8244         {
8245           PixelInterpolateMethod
8246             method;
8247
8248           if (attribute_flag[0] == 0)
8249             argument_list[0].real_reference=50.0;
8250           method=UndefinedInterpolatePixel;
8251           if (attribute_flag[1] != 0)
8252             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8253           image=SwirlImage(image,argument_list[0].real_reference,
8254             method,exception);
8255           break;
8256         }
8257         case 31:  /* Resize */
8258         case 32:  /* Zoom */
8259         {
8260           if (attribute_flag[0] != 0)
8261             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8262               &geometry,exception);
8263           if (attribute_flag[1] != 0)
8264             geometry.width=argument_list[1].integer_reference;
8265           if (attribute_flag[2] != 0)
8266             geometry.height=argument_list[2].integer_reference;
8267           if (attribute_flag[3] == 0)
8268             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
8269           if (attribute_flag[4] != 0)
8270             SetImageArtifact(image,"filter:support",
8271               argument_list[4].string_reference);
8272           image=ResizeImage(image,geometry.width,geometry.height,
8273             (FilterTypes) argument_list[3].integer_reference,
8274             exception);
8275           break;
8276         }
8277         case 33:  /* Annotate */
8278         {
8279           DrawInfo
8280             *draw_info;
8281
8282           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8283             (DrawInfo *) NULL);
8284           if (attribute_flag[0] != 0)
8285             {
8286               char
8287                 *text;
8288
8289               text=InterpretImageProperties(info ? info->image_info :
8290                 (ImageInfo *) NULL,image,argument_list[0].string_reference,
8291                 exception);
8292               (void) CloneString(&draw_info->text,text);
8293               text=DestroyString(text);
8294             }
8295           if (attribute_flag[1] != 0)
8296             (void) CloneString(&draw_info->font,
8297               argument_list[1].string_reference);
8298           if (attribute_flag[2] != 0)
8299             draw_info->pointsize=argument_list[2].real_reference;
8300           if (attribute_flag[3] != 0)
8301             (void) CloneString(&draw_info->density,
8302               argument_list[3].string_reference);
8303           if (attribute_flag[4] != 0)
8304             (void) QueryColorCompliance(argument_list[4].string_reference,
8305               AllCompliance,&draw_info->undercolor,exception);
8306           if (attribute_flag[5] != 0)
8307             {
8308               (void) QueryColorCompliance(argument_list[5].string_reference,
8309                 AllCompliance,&draw_info->stroke,exception);
8310               if (argument_list[5].image_reference != (Image *) NULL)
8311                 draw_info->stroke_pattern=CloneImage(
8312                   argument_list[5].image_reference,0,0,MagickTrue,exception);
8313             }
8314           if (attribute_flag[6] != 0)
8315             {
8316               (void) QueryColorCompliance(argument_list[6].string_reference,
8317                 AllCompliance,&draw_info->fill,exception);
8318               if (argument_list[6].image_reference != (Image *) NULL)
8319                 draw_info->fill_pattern=CloneImage(
8320                   argument_list[6].image_reference,0,0,MagickTrue,exception);
8321             }
8322           if (attribute_flag[7] != 0)
8323             {
8324               (void) CloneString(&draw_info->geometry,
8325                 argument_list[7].string_reference);
8326               flags=ParsePageGeometry(image,argument_list[7].string_reference,
8327                 &geometry,exception);
8328               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8329                 geometry_info.sigma=geometry_info.xi;
8330             }
8331           if (attribute_flag[8] != 0)
8332             (void) QueryColorCompliance(argument_list[8].string_reference,
8333               AllCompliance,&draw_info->fill,exception);
8334           if (attribute_flag[11] != 0)
8335             draw_info->gravity=(GravityType)
8336               argument_list[11].integer_reference;
8337           if (attribute_flag[25] != 0)
8338             {
8339               AV
8340                 *av;
8341
8342               av=(AV *) argument_list[25].array_reference;
8343               if ((av_len(av) != 3) && (av_len(av) != 5))
8344                 {
8345                   ThrowPerlException(exception,OptionError,
8346                     "affine matrix must have 4 or 6 elements",PackageName);
8347                   goto PerlException;
8348                 }
8349               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8350               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8351               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8352               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8353               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8354                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8355                 {
8356                   ThrowPerlException(exception,OptionError,
8357                     "affine matrix is singular",PackageName);
8358                    goto PerlException;
8359                 }
8360               if (av_len(av) == 5)
8361                 {
8362                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8363                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8364                 }
8365             }
8366           for (j=12; j < 17; j++)
8367           {
8368             if (attribute_flag[j] == 0)
8369               continue;
8370             value=argument_list[j].string_reference;
8371             angle=argument_list[j].real_reference;
8372             current=draw_info->affine;
8373             GetAffineMatrix(&affine);
8374             switch (j)
8375             {
8376               case 12:
8377               {
8378                 /*
8379                   Translate.
8380                 */
8381                 flags=ParseGeometry(value,&geometry_info);
8382                 affine.tx=geometry_info.xi;
8383                 affine.ty=geometry_info.psi;
8384                 if ((flags & PsiValue) == 0)
8385                   affine.ty=affine.tx;
8386                 break;
8387               }
8388               case 13:
8389               {
8390                 /*
8391                   Scale.
8392                 */
8393                 flags=ParseGeometry(value,&geometry_info);
8394                 affine.sx=geometry_info.rho;
8395                 affine.sy=geometry_info.sigma;
8396                 if ((flags & SigmaValue) == 0)
8397                   affine.sy=affine.sx;
8398                 break;
8399               }
8400               case 14:
8401               {
8402                 /*
8403                   Rotate.
8404                 */
8405                 if (angle == 0.0)
8406                   break;
8407                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8408                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8409                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8410                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8411                 break;
8412               }
8413               case 15:
8414               {
8415                 /*
8416                   SkewX.
8417                 */
8418                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8419                 break;
8420               }
8421               case 16:
8422               {
8423                 /*
8424                   SkewY.
8425                 */
8426                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8427                 break;
8428               }
8429             }
8430             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8431             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8432             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8433             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8434             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8435               current.tx;
8436             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8437               current.ty;
8438           }
8439           if (attribute_flag[9] == 0)
8440             argument_list[9].real_reference=0.0;
8441           if (attribute_flag[10] == 0)
8442             argument_list[10].real_reference=0.0;
8443           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8444             {
8445               char
8446                 geometry[MaxTextExtent];
8447
8448               (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
8449                 (double) argument_list[9].real_reference+draw_info->affine.tx,
8450                 (double) argument_list[10].real_reference+draw_info->affine.ty);
8451               (void) CloneString(&draw_info->geometry,geometry);
8452             }
8453           if (attribute_flag[17] != 0)
8454             draw_info->stroke_width=argument_list[17].real_reference;
8455           if (attribute_flag[18] != 0)
8456             {
8457               draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8458                 MagickTrue : MagickFalse;
8459               draw_info->stroke_antialias=draw_info->text_antialias;
8460             }
8461           if (attribute_flag[19] != 0)
8462             (void) CloneString(&draw_info->family,
8463               argument_list[19].string_reference);
8464           if (attribute_flag[20] != 0)
8465             draw_info->style=(StyleType) argument_list[20].integer_reference;
8466           if (attribute_flag[21] != 0)
8467             draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8468           if (attribute_flag[22] != 0)
8469             draw_info->weight=argument_list[22].integer_reference;
8470           if (attribute_flag[23] != 0)
8471             draw_info->align=(AlignType) argument_list[23].integer_reference;
8472           if (attribute_flag[24] != 0)
8473             (void) CloneString(&draw_info->encoding,
8474               argument_list[24].string_reference);
8475           if (attribute_flag[25] != 0)
8476             draw_info->fill_pattern=CloneImage(
8477               argument_list[25].image_reference,0,0,MagickTrue,exception);
8478           if (attribute_flag[26] != 0)
8479             draw_info->fill_pattern=CloneImage(
8480               argument_list[26].image_reference,0,0,MagickTrue,exception);
8481           if (attribute_flag[27] != 0)
8482             draw_info->stroke_pattern=CloneImage(
8483               argument_list[27].image_reference,0,0,MagickTrue,exception);
8484           if (attribute_flag[29] != 0)
8485             draw_info->kerning=argument_list[29].real_reference;
8486           if (attribute_flag[30] != 0)
8487             draw_info->interline_spacing=argument_list[30].real_reference;
8488           if (attribute_flag[31] != 0)
8489             draw_info->interword_spacing=argument_list[31].real_reference;
8490           if (attribute_flag[32] != 0)
8491             draw_info->direction=(DirectionType)
8492               argument_list[32].integer_reference;
8493           (void) AnnotateImage(image,draw_info,exception);
8494           draw_info=DestroyDrawInfo(draw_info);
8495           break;
8496         }
8497         case 34:  /* ColorFloodfill */
8498         {
8499           DrawInfo
8500             *draw_info;
8501
8502           MagickBooleanType
8503             invert;
8504
8505           PixelInfo
8506             target;
8507
8508           draw_info=CloneDrawInfo(info ? info->image_info :
8509             (ImageInfo *) NULL,(DrawInfo *) NULL);
8510           if (attribute_flag[0] != 0)
8511             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8512               &geometry,exception);
8513           if (attribute_flag[1] != 0)
8514             geometry.x=argument_list[1].integer_reference;
8515           if (attribute_flag[2] != 0)
8516             geometry.y=argument_list[2].integer_reference;
8517           if (attribute_flag[3] != 0)
8518             (void) QueryColorCompliance(argument_list[3].string_reference,
8519               AllCompliance,&draw_info->fill,exception);
8520           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
8521             geometry.x,geometry.y,&target,exception);
8522           invert=MagickFalse;
8523           if (attribute_flag[4] != 0)
8524             {
8525               QueryColorCompliance(argument_list[4].string_reference,
8526                 AllCompliance,&target,exception);
8527               invert=MagickTrue;
8528             }
8529           if (attribute_flag[5] != 0)
8530             image->fuzz=StringToDoubleInterval(
8531               argument_list[5].string_reference,(double) QuantumRange+1.0);
8532           if (attribute_flag[6] != 0)
8533             invert=(MagickBooleanType) argument_list[6].integer_reference;
8534           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8535             geometry.y,invert,exception);
8536           draw_info=DestroyDrawInfo(draw_info);
8537           break;
8538         }
8539         case 35:  /* Composite */
8540         {
8541           char
8542             composite_geometry[MaxTextExtent];
8543
8544           Image
8545             *composite_image,
8546             *rotate_image;
8547
8548           MagickBooleanType
8549             clip_to_self;
8550
8551           compose=OverCompositeOp;
8552           if (attribute_flag[0] != 0)
8553             composite_image=argument_list[0].image_reference;
8554           else
8555             {
8556               ThrowPerlException(exception,OptionError,
8557                 "CompositeImageRequired",PackageName);
8558               goto PerlException;
8559             }
8560           /*
8561             Parameter Handling used for BOTH normal and tiled composition.
8562           */
8563           if (attribute_flag[1] != 0) /* compose */
8564             compose=(CompositeOperator) argument_list[1].integer_reference;
8565           if (attribute_flag[6] != 0) /* opacity  */
8566             {
8567               if (compose != DissolveCompositeOp)
8568                 (void) SetImageAlpha(composite_image,(Quantum)
8569                   StringToDoubleInterval(argument_list[6].string_reference,
8570                   (double) QuantumRange+1.0),exception);
8571               else
8572                 {
8573                   CacheView
8574                     *composite_view;
8575
8576                   double
8577                     opacity;
8578
8579                   MagickBooleanType
8580                     sync;
8581
8582                   register ssize_t
8583                     x;
8584
8585                   register Quantum
8586                     *q;
8587
8588                   ssize_t
8589                     y;
8590
8591                   /*
8592                     Handle dissolve composite operator (patch by
8593                     Kevin A. McGrail).
8594                   */
8595                   (void) CloneString(&image->geometry,
8596                     argument_list[6].string_reference);
8597                   opacity=(Quantum) StringToDoubleInterval(
8598                     argument_list[6].string_reference,(double) QuantumRange+
8599                     1.0);
8600                   if (composite_image->alpha_trait == BlendPixelTrait)
8601                     (void) SetImageAlpha(composite_image,OpaqueAlpha,exception);
8602                   composite_view=AcquireAuthenticCacheView(composite_image,exception);
8603                   for (y=0; y < (ssize_t) composite_image->rows ; y++)
8604                   {
8605                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8606                       composite_image->columns,1,exception);
8607                     for (x=0; x < (ssize_t) composite_image->columns; x++)
8608                     {
8609                       if (GetPixelAlpha(image,q) == OpaqueAlpha)
8610                         SetPixelAlpha(composite_image,ClampToQuantum(opacity),
8611                           q);
8612                       q+=GetPixelChannels(composite_image);
8613                     }
8614                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8615                     if (sync == MagickFalse)
8616                       break;
8617                   }
8618                   composite_view=DestroyCacheView(composite_view);
8619                 }
8620             }
8621           if (attribute_flag[9] != 0)    /* "color=>" */
8622             QueryColorCompliance(argument_list[9].string_reference,
8623               AllCompliance,&composite_image->background_color,exception);
8624           if (attribute_flag[12] != 0) /* "interpolate=>" */
8625             image->interpolate=(PixelInterpolateMethod)
8626               argument_list[12].integer_reference;
8627           if (attribute_flag[13] != 0)   /* "args=>" */
8628             (void) SetImageArtifact(composite_image,"compose:args",
8629               argument_list[13].string_reference);
8630           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8631             (void) SetImageArtifact(composite_image,"compose:args",
8632               argument_list[14].string_reference);
8633           clip_to_self=MagickTrue;
8634           if (attribute_flag[15] != 0)
8635             clip_to_self=(MagickBooleanType)
8636               argument_list[15].integer_reference;
8637           /*
8638             Tiling Composition (with orthogonal rotate).
8639           */
8640           rotate_image=(Image *) NULL;
8641           if (attribute_flag[8] != 0)   /* "rotate=>" */
8642             {
8643                /*
8644                  Rotate image.
8645                */
8646                rotate_image=RotateImage(composite_image,
8647                  argument_list[8].real_reference,exception);
8648                if (rotate_image == (Image *) NULL)
8649                  break;
8650             }
8651           if ((attribute_flag[7] != 0) &&
8652               (argument_list[7].integer_reference != 0)) /* tile */
8653             {
8654               ssize_t
8655                 x,
8656                 y;
8657
8658               /*
8659                 Tile the composite image.
8660               */
8661              if (attribute_flag[8] != 0)   /* "tile=>" */
8662                (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8663                  "false");
8664              else
8665                (void) SetImageArtifact(composite_image,
8666                  "compose:outside-overlay","false");
8667              for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8668                 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8669                 {
8670                   if (attribute_flag[8] != 0) /* rotate */
8671                     (void) CompositeImage(image,rotate_image,compose,
8672                       MagickTrue,x,y,exception);
8673                   else
8674                     (void) CompositeImage(image,composite_image,compose,
8675                       MagickTrue,x,y,exception);
8676                 }
8677               if (attribute_flag[8] != 0) /* rotate */
8678                 rotate_image=DestroyImage(rotate_image);
8679               break;
8680             }
8681           /*
8682             Parameter Handling used used ONLY for normal composition.
8683           */
8684           if (attribute_flag[5] != 0) /* gravity */
8685             image->gravity=(GravityType) argument_list[5].integer_reference;
8686           if (attribute_flag[2] != 0) /* geometry offset */
8687             {
8688               SetGeometry(image,&geometry);
8689               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8690                 &geometry);
8691               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8692                 &geometry);
8693             }
8694           if (attribute_flag[3] != 0) /* x offset */
8695             geometry.x=argument_list[3].integer_reference;
8696           if (attribute_flag[4] != 0) /* y offset */
8697             geometry.y=argument_list[4].integer_reference;
8698           if (attribute_flag[10] != 0) /* mask */
8699             {
8700               if ((image->compose == DisplaceCompositeOp) ||
8701                   (image->compose == DistortCompositeOp))
8702                 {
8703                   /*
8704                     Merge Y displacement into X displacement image.
8705                   */
8706                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8707                     exception);
8708                   (void) CompositeImage(composite_image,
8709                     argument_list[10].image_reference,CopyGreenCompositeOp,
8710                     MagickTrue,0,0,exception);
8711                 }
8712               else
8713                 {
8714                   Image
8715                     *mask_image;
8716
8717                   /*
8718                     Set a blending mask for the composition.
8719                   */
8720                   mask_image=CloneImage(argument_list[10].image_reference,0,0,
8721                     MagickTrue,exception);
8722                   (void) SetImageMask(composite_image,mask_image,exception);
8723                   mask_image=DestroyImage(mask_image);
8724                 }
8725             }
8726           if (attribute_flag[11] != 0) /* channel */
8727             channel=(ChannelType) argument_list[11].integer_reference;
8728           /*
8729             Composite two images (normal composition).
8730           */
8731           (void) FormatLocaleString(composite_geometry,MaxTextExtent,
8732             "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8733             (double) composite_image->rows,(double) geometry.x,(double)
8734             geometry.y);
8735           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8736             exception);
8737           channel_mask=SetImageChannelMask(image,channel);
8738           if (attribute_flag[8] == 0) /* no rotate */
8739             CompositeImage(image,composite_image,compose,clip_to_self,
8740               geometry.x,geometry.y,exception);
8741           else
8742             {
8743               /*
8744                 Position adjust rotated image then composite.
8745               */
8746               geometry.x-=(ssize_t) (rotate_image->columns-
8747                 composite_image->columns)/2;
8748               geometry.y-=(ssize_t) (rotate_image->rows-
8749                 composite_image->rows)/2;
8750               CompositeImage(image,rotate_image,compose,clip_to_self,geometry.x,
8751                 geometry.y,exception);
8752               rotate_image=DestroyImage(rotate_image);
8753             }
8754           if (attribute_flag[10] != 0) /* mask */
8755             {
8756               if ((image->compose == DisplaceCompositeOp) ||
8757                   (image->compose == DistortCompositeOp))
8758                 composite_image=DestroyImage(composite_image);
8759               else
8760                 (void) SetImageMask(image,(Image *) NULL,exception);
8761             }
8762           (void) SetImageChannelMask(image,channel_mask);
8763           break;
8764         }
8765         case 36:  /* Contrast */
8766         {
8767           if (attribute_flag[0] == 0)
8768             argument_list[0].integer_reference=0;
8769           (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8770             MagickTrue : MagickFalse,exception);
8771           break;
8772         }
8773         case 37:  /* CycleColormap */
8774         {
8775           if (attribute_flag[0] == 0)
8776             argument_list[0].integer_reference=6;
8777           (void) CycleColormapImage(image,argument_list[0].integer_reference,
8778             exception);
8779           break;
8780         }
8781         case 38:  /* Draw */
8782         {
8783           DrawInfo
8784             *draw_info;
8785
8786           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8787             (DrawInfo *) NULL);
8788           (void) CloneString(&draw_info->primitive,"point");
8789           if (attribute_flag[0] != 0)
8790             {
8791               if (argument_list[0].integer_reference < 0)
8792                 (void) CloneString(&draw_info->primitive,
8793                   argument_list[0].string_reference);
8794               else
8795                 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8796                   MagickPrimitiveOptions,argument_list[0].integer_reference));
8797             }
8798           if (attribute_flag[1] != 0)
8799             {
8800               if (LocaleCompare(draw_info->primitive,"path") == 0)
8801                 {
8802                   (void) ConcatenateString(&draw_info->primitive," '");
8803                   ConcatenateString(&draw_info->primitive,
8804                     argument_list[1].string_reference);
8805                   (void) ConcatenateString(&draw_info->primitive,"'");
8806                 }
8807               else
8808                 {
8809                   (void) ConcatenateString(&draw_info->primitive," ");
8810                   ConcatenateString(&draw_info->primitive,
8811                     argument_list[1].string_reference);
8812                 }
8813             }
8814           if (attribute_flag[2] != 0)
8815             {
8816               (void) ConcatenateString(&draw_info->primitive," ");
8817               (void) ConcatenateString(&draw_info->primitive,
8818                 CommandOptionToMnemonic(MagickMethodOptions,
8819                 argument_list[2].integer_reference));
8820             }
8821           if (attribute_flag[3] != 0)
8822             {
8823               (void) QueryColorCompliance(argument_list[3].string_reference,
8824                 AllCompliance,&draw_info->stroke,exception);
8825               if (argument_list[3].image_reference != (Image *) NULL)
8826                 draw_info->stroke_pattern=CloneImage(
8827                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8828             }
8829           if (attribute_flag[4] != 0)
8830             {
8831               (void) QueryColorCompliance(argument_list[4].string_reference,
8832                 AllCompliance,&draw_info->fill,exception);
8833               if (argument_list[4].image_reference != (Image *) NULL)
8834                 draw_info->fill_pattern=CloneImage(
8835                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8836             }
8837           if (attribute_flag[5] != 0)
8838             draw_info->stroke_width=argument_list[5].real_reference;
8839           if (attribute_flag[6] != 0)
8840             (void) CloneString(&draw_info->font,
8841               argument_list[6].string_reference);
8842           if (attribute_flag[7] != 0)
8843             (void) QueryColorCompliance(argument_list[7].string_reference,
8844               AllCompliance,&draw_info->border_color,exception);
8845           if (attribute_flag[8] != 0)
8846             draw_info->affine.tx=argument_list[8].real_reference;
8847           if (attribute_flag[9] != 0)
8848             draw_info->affine.ty=argument_list[9].real_reference;
8849           if (attribute_flag[20] != 0)
8850             {
8851               AV
8852                 *av;
8853
8854               av=(AV *) argument_list[20].array_reference;
8855               if ((av_len(av) != 3) && (av_len(av) != 5))
8856                 {
8857                   ThrowPerlException(exception,OptionError,
8858                     "affine matrix must have 4 or 6 elements",PackageName);
8859                   goto PerlException;
8860                 }
8861               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8862               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8863               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8864               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8865               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8866                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8867                 {
8868                   ThrowPerlException(exception,OptionError,
8869                     "affine matrix is singular",PackageName);
8870                    goto PerlException;
8871                 }
8872               if (av_len(av) == 5)
8873                 {
8874                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8875                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8876                 }
8877             }
8878           for (j=10; j < 15; j++)
8879           {
8880             if (attribute_flag[j] == 0)
8881               continue;
8882             value=argument_list[j].string_reference;
8883             angle=argument_list[j].real_reference;
8884             current=draw_info->affine;
8885             GetAffineMatrix(&affine);
8886             switch (j)
8887             {
8888               case 10:
8889               {
8890                 /*
8891                   Translate.
8892                 */
8893                 flags=ParseGeometry(value,&geometry_info);
8894                 affine.tx=geometry_info.xi;
8895                 affine.ty=geometry_info.psi;
8896                 if ((flags & PsiValue) == 0)
8897                   affine.ty=affine.tx;
8898                 break;
8899               }
8900               case 11:
8901               {
8902                 /*
8903                   Scale.
8904                 */
8905                 flags=ParseGeometry(value,&geometry_info);
8906                 affine.sx=geometry_info.rho;
8907                 affine.sy=geometry_info.sigma;
8908                 if ((flags & SigmaValue) == 0)
8909                   affine.sy=affine.sx;
8910                 break;
8911               }
8912               case 12:
8913               {
8914                 /*
8915                   Rotate.
8916                 */
8917                 if (angle == 0.0)
8918                   break;
8919                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8920                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8921                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8922                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8923                 break;
8924               }
8925               case 13:
8926               {
8927                 /*
8928                   SkewX.
8929                 */
8930                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8931                 break;
8932               }
8933               case 14:
8934               {
8935                 /*
8936                   SkewY.
8937                 */
8938                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8939                 break;
8940               }
8941             }
8942             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8943             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8944             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8945             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8946             draw_info->affine.tx=
8947               current.sx*affine.tx+current.ry*affine.ty+current.tx;
8948             draw_info->affine.ty=
8949               current.rx*affine.tx+current.sy*affine.ty+current.ty;
8950           }
8951           if (attribute_flag[15] != 0)
8952             draw_info->fill_pattern=CloneImage(
8953               argument_list[15].image_reference,0,0,MagickTrue,exception);
8954           if (attribute_flag[16] != 0)
8955             draw_info->pointsize=argument_list[16].real_reference;
8956           if (attribute_flag[17] != 0)
8957             {
8958               draw_info->stroke_antialias=argument_list[17].integer_reference != 0
8959                 ? MagickTrue : MagickFalse;
8960               draw_info->text_antialias=draw_info->stroke_antialias;
8961             }
8962           if (attribute_flag[18] != 0)
8963             (void) CloneString(&draw_info->density,
8964               argument_list[18].string_reference);
8965           if (attribute_flag[19] != 0)
8966             draw_info->stroke_width=argument_list[19].real_reference;
8967           if (attribute_flag[21] != 0)
8968             draw_info->dash_offset=argument_list[21].real_reference;
8969           if (attribute_flag[22] != 0)
8970             {
8971               AV
8972                 *av;
8973
8974               av=(AV *) argument_list[22].array_reference;
8975               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
8976                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
8977               if (draw_info->dash_pattern != (double *) NULL)
8978                 {
8979                   for (i=0; i <= av_len(av); i++)
8980                     draw_info->dash_pattern[i]=(double)
8981                       SvNV(*(av_fetch(av,i,0)));
8982                   draw_info->dash_pattern[i]=0.0;
8983                 }
8984             }
8985           if (attribute_flag[23] != 0)
8986             image->interpolate=(PixelInterpolateMethod)
8987               argument_list[23].integer_reference;
8988           if ((attribute_flag[24] != 0) &&
8989               (draw_info->fill_pattern != (Image *) NULL))
8990             flags=ParsePageGeometry(draw_info->fill_pattern,
8991               argument_list[24].string_reference,
8992               &draw_info->fill_pattern->tile_offset,exception);
8993           if (attribute_flag[25] != 0)
8994             {
8995               (void) ConcatenateString(&draw_info->primitive," '");
8996               (void) ConcatenateString(&draw_info->primitive,
8997                 argument_list[25].string_reference);
8998               (void) ConcatenateString(&draw_info->primitive,"'");
8999             }
9000           if (attribute_flag[26] != 0)
9001             draw_info->fill_pattern=CloneImage(
9002               argument_list[26].image_reference,0,0,MagickTrue,exception);
9003           if (attribute_flag[27] != 0)
9004             draw_info->stroke_pattern=CloneImage(
9005               argument_list[27].image_reference,0,0,MagickTrue,exception);
9006           if (attribute_flag[28] != 0)
9007             (void) CloneString(&draw_info->primitive,
9008               argument_list[28].string_reference);
9009           if (attribute_flag[29] != 0)
9010             draw_info->kerning=argument_list[29].real_reference;
9011           if (attribute_flag[30] != 0)
9012             draw_info->interline_spacing=argument_list[30].real_reference;
9013           if (attribute_flag[31] != 0)
9014             draw_info->interword_spacing=argument_list[31].real_reference;
9015           if (attribute_flag[32] != 0)
9016             draw_info->direction=(DirectionType)
9017               argument_list[32].integer_reference;
9018           DrawImage(image,draw_info,exception);
9019           draw_info=DestroyDrawInfo(draw_info);
9020           break;
9021         }
9022         case 39:  /* Equalize */
9023         {
9024           if (attribute_flag[0] != 0)
9025             channel=(ChannelType) argument_list[0].integer_reference;
9026           channel_mask=SetImageChannelMask(image,channel);
9027           EqualizeImage(image,exception);
9028           (void) SetImageChannelMask(image,channel_mask);
9029           break;
9030         }
9031         case 40:  /* Gamma */
9032         {
9033           if (attribute_flag[1] != 0)
9034             channel=(ChannelType) argument_list[1].integer_reference;
9035           if (attribute_flag[2] == 0)
9036             argument_list[2].real_reference=1.0;
9037           if (attribute_flag[3] == 0)
9038             argument_list[3].real_reference=1.0;
9039           if (attribute_flag[4] == 0)
9040             argument_list[4].real_reference=1.0;
9041           if (attribute_flag[0] == 0)
9042             {
9043               (void) FormatLocaleString(message,MaxTextExtent,
9044                 "%.15g,%.15g,%.15g",(double) argument_list[2].real_reference,
9045                 (double) argument_list[3].real_reference,
9046                 (double) argument_list[4].real_reference);
9047               argument_list[0].string_reference=message;
9048             }
9049           (void) GammaImage(image,StringToDouble(
9050             argument_list[0].string_reference,(char **) NULL),exception);
9051           break;
9052         }
9053         case 41:  /* Map */
9054         {
9055           QuantizeInfo
9056             *quantize_info;
9057
9058           if (attribute_flag[0] == 0)
9059             {
9060               ThrowPerlException(exception,OptionError,"MapImageRequired",
9061                 PackageName);
9062               goto PerlException;
9063             }
9064           quantize_info=AcquireQuantizeInfo(info->image_info);
9065           if (attribute_flag[1] != 0)
9066             quantize_info->dither_method=(DitherMethod)
9067               argument_list[1].integer_reference;
9068           (void) RemapImages(quantize_info,image,
9069             argument_list[0].image_reference,exception);
9070           quantize_info=DestroyQuantizeInfo(quantize_info);
9071           break;
9072         }
9073         case 42:  /* MatteFloodfill */
9074         {
9075           DrawInfo
9076             *draw_info;
9077
9078           MagickBooleanType
9079             invert;
9080
9081           PixelInfo
9082             target;
9083
9084           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9085             (DrawInfo *) NULL);
9086           if (attribute_flag[0] != 0)
9087             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9088               &geometry,exception);
9089           if (attribute_flag[1] != 0)
9090             geometry.x=argument_list[1].integer_reference;
9091           if (attribute_flag[2] != 0)
9092             geometry.y=argument_list[2].integer_reference;
9093           if (image->alpha_trait != BlendPixelTrait)
9094             (void) SetImageAlpha(image,OpaqueAlpha,exception);
9095           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
9096             geometry.x,geometry.y,&target,exception);
9097           if (attribute_flag[4] != 0)
9098             QueryColorCompliance(argument_list[4].string_reference,
9099               AllCompliance,&target,exception);
9100           if (attribute_flag[3] != 0)
9101             target.alpha=StringToDoubleInterval(
9102               argument_list[3].string_reference,(double) (double) QuantumRange+
9103               1.0);
9104           if (attribute_flag[5] != 0)
9105             image->fuzz=StringToDoubleInterval(
9106               argument_list[5].string_reference,(double) QuantumRange+1.0);
9107           invert=MagickFalse;
9108           if (attribute_flag[6] != 0)
9109             invert=(MagickBooleanType) argument_list[6].integer_reference;
9110           channel_mask=SetImageChannelMask(image,AlphaChannel);
9111           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
9112             geometry.y,invert,exception);
9113           (void) SetImageChannelMask(image,channel_mask);
9114           draw_info=DestroyDrawInfo(draw_info);
9115           break;
9116         }
9117         case 43:  /* Modulate */
9118         {
9119           char
9120             modulate[MaxTextExtent];
9121
9122           geometry_info.rho=100.0;
9123           geometry_info.sigma=100.0;
9124           geometry_info.xi=100.0;
9125           if (attribute_flag[0] != 0)
9126             (void)ParseGeometry(argument_list[0].string_reference,
9127               &geometry_info);
9128           if (attribute_flag[1] != 0)
9129             geometry_info.xi=argument_list[1].real_reference;
9130           if (attribute_flag[2] != 0)
9131             geometry_info.sigma=argument_list[2].real_reference;
9132           if (attribute_flag[3] != 0)
9133             {
9134               geometry_info.sigma=argument_list[3].real_reference;
9135               SetImageArtifact(image,"modulate:colorspace","HWB");
9136             }
9137           if (attribute_flag[4] != 0)
9138             {
9139               geometry_info.rho=argument_list[4].real_reference;
9140               SetImageArtifact(image,"modulate:colorspace","HSB");
9141             }
9142           if (attribute_flag[5] != 0)
9143             {
9144               geometry_info.sigma=argument_list[5].real_reference;
9145               SetImageArtifact(image,"modulate:colorspace","HSL");
9146             }
9147           if (attribute_flag[6] != 0)
9148             {
9149               geometry_info.rho=argument_list[6].real_reference;
9150               SetImageArtifact(image,"modulate:colorspace","HWB");
9151             }
9152           (void) FormatLocaleString(modulate,MaxTextExtent,"%.15g,%.15g,%.15g",
9153             geometry_info.rho,geometry_info.sigma,geometry_info.xi);
9154           (void) ModulateImage(image,modulate,exception);
9155           break;
9156         }
9157         case 44:  /* Negate */
9158         {
9159           if (attribute_flag[0] == 0)
9160             argument_list[0].integer_reference=0;
9161           if (attribute_flag[1] != 0)
9162             channel=(ChannelType) argument_list[1].integer_reference;
9163           channel_mask=SetImageChannelMask(image,channel);
9164           (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
9165             MagickTrue : MagickFalse,exception);
9166           (void) SetImageChannelMask(image,channel_mask);
9167           break;
9168         }
9169         case 45:  /* Normalize */
9170         {
9171           if (attribute_flag[0] != 0)
9172             channel=(ChannelType) argument_list[0].integer_reference;
9173           channel_mask=SetImageChannelMask(image,channel);
9174           NormalizeImage(image,exception);
9175           (void) SetImageChannelMask(image,channel_mask);
9176           break;
9177         }
9178         case 46:  /* NumberColors */
9179           break;
9180         case 47:  /* Opaque */
9181         {
9182           MagickBooleanType
9183             invert;
9184
9185           PixelInfo
9186             fill_color,
9187             target;
9188
9189           (void) QueryColorCompliance("none",AllCompliance,&target,
9190              exception);
9191           (void) QueryColorCompliance("none",AllCompliance,&fill_color,
9192             exception);
9193           if (attribute_flag[0] != 0)
9194             (void) QueryColorCompliance(argument_list[0].string_reference,
9195               AllCompliance,&target,exception);
9196           if (attribute_flag[1] != 0)
9197             (void) QueryColorCompliance(argument_list[1].string_reference,
9198               AllCompliance,&fill_color,exception);
9199           if (attribute_flag[2] != 0)
9200             image->fuzz=StringToDoubleInterval(
9201               argument_list[2].string_reference,(double) QuantumRange+1.0);
9202           if (attribute_flag[3] != 0)
9203             channel=(ChannelType) argument_list[3].integer_reference;
9204           invert=MagickFalse;
9205           if (attribute_flag[4] != 0)
9206             invert=(MagickBooleanType) argument_list[4].integer_reference;
9207           channel_mask=SetImageChannelMask(image,channel);
9208           (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
9209           (void) SetImageChannelMask(image,channel_mask);
9210           break;
9211         }
9212         case 48:  /* Quantize */
9213         {
9214           QuantizeInfo
9215             *quantize_info;
9216
9217           quantize_info=AcquireQuantizeInfo(info->image_info);
9218           if (attribute_flag[0] != 0)
9219             quantize_info->number_colors=(size_t)
9220               argument_list[0].integer_reference;
9221           if (attribute_flag[1] != 0)
9222             quantize_info->tree_depth=(size_t)
9223               argument_list[1].integer_reference;
9224           if (attribute_flag[2] != 0)
9225             quantize_info->colorspace=(ColorspaceType)
9226               argument_list[2].integer_reference;
9227           if (attribute_flag[3] != 0)
9228             quantize_info->dither_method=(DitherMethod)
9229               argument_list[3].integer_reference;
9230           if (attribute_flag[4] != 0)
9231             quantize_info->measure_error=
9232               argument_list[4].integer_reference != 0 ? MagickTrue : MagickFalse;
9233           if (attribute_flag[6] != 0)
9234             (void) QueryColorCompliance(argument_list[6].string_reference,
9235               AllCompliance,&image->transparent_color,exception);
9236           if (attribute_flag[7] != 0)
9237             quantize_info->dither_method=(DitherMethod)
9238               argument_list[7].integer_reference;
9239           if (attribute_flag[5] && argument_list[5].integer_reference)
9240             (void) QuantizeImages(quantize_info,image,exception);
9241           else
9242             if ((image->storage_class == DirectClass) ||
9243                (image->colors > quantize_info->number_colors) ||
9244                (quantize_info->colorspace == GRAYColorspace))
9245              (void) QuantizeImage(quantize_info,image,exception);
9246            else
9247              CompressImageColormap(image,exception);
9248           quantize_info=DestroyQuantizeInfo(quantize_info);
9249           break;
9250         }
9251         case 49:  /* Raise */
9252         {
9253           if (attribute_flag[0] != 0)
9254             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9255               &geometry,exception);
9256           if (attribute_flag[1] != 0)
9257             geometry.width=argument_list[1].integer_reference;
9258           if (attribute_flag[2] != 0)
9259             geometry.height=argument_list[2].integer_reference;
9260           if (attribute_flag[3] == 0)
9261             argument_list[3].integer_reference=1;
9262           (void) RaiseImage(image,&geometry,
9263             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
9264             exception);
9265           break;
9266         }
9267         case 50:  /* Segment */
9268         {
9269           ColorspaceType
9270             colorspace;
9271
9272           double
9273             cluster_threshold,
9274             smoothing_threshold;
9275
9276           MagickBooleanType
9277             verbose;
9278
9279           cluster_threshold=1.0;
9280           smoothing_threshold=1.5;
9281           colorspace=sRGBColorspace;
9282           verbose=MagickFalse;
9283           if (attribute_flag[0] != 0)
9284             {
9285               flags=ParseGeometry(argument_list[0].string_reference,
9286                 &geometry_info);
9287               cluster_threshold=geometry_info.rho;
9288               if (flags & SigmaValue)
9289                 smoothing_threshold=geometry_info.sigma;
9290             }
9291           if (attribute_flag[1] != 0)
9292             cluster_threshold=argument_list[1].real_reference;
9293           if (attribute_flag[2] != 0)
9294             smoothing_threshold=argument_list[2].real_reference;
9295           if (attribute_flag[3] != 0)
9296             colorspace=(ColorspaceType) argument_list[3].integer_reference;
9297           if (attribute_flag[4] != 0)
9298             verbose=argument_list[4].integer_reference != 0 ?
9299               MagickTrue : MagickFalse;
9300           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
9301             smoothing_threshold,exception);
9302           break;
9303         }
9304         case 51:  /* Signature */
9305         {
9306           (void) SignatureImage(image,exception);
9307           break;
9308         }
9309         case 52:  /* Solarize */
9310         {
9311           geometry_info.rho=QuantumRange/2.0;
9312           if (attribute_flag[0] != 0)
9313             flags=ParseGeometry(argument_list[0].string_reference,
9314               &geometry_info);
9315           if (attribute_flag[1] != 0)
9316             geometry_info.rho=StringToDoubleInterval(
9317               argument_list[1].string_reference,(double) QuantumRange+1.0);
9318           (void) SolarizeImage(image,geometry_info.rho,exception);
9319           break;
9320         }
9321         case 53:  /* Sync */
9322         {
9323           (void) SyncImage(image,exception);
9324           break;
9325         }
9326         case 54:  /* Texture */
9327         {
9328           if (attribute_flag[0] == 0)
9329             break;
9330           TextureImage(image,argument_list[0].image_reference,exception);
9331           break;
9332         }
9333         case 55:  /* Evalute */
9334         {
9335           MagickEvaluateOperator
9336             op;
9337
9338           op=SetEvaluateOperator;
9339           if (attribute_flag[0] == MagickFalse)
9340             argument_list[0].real_reference=0.0;
9341           if (attribute_flag[1] != MagickFalse)
9342             op=(MagickEvaluateOperator) argument_list[1].integer_reference;
9343           if (attribute_flag[2] != MagickFalse)
9344             channel=(ChannelType) argument_list[2].integer_reference;
9345           channel_mask=SetImageChannelMask(image,channel);
9346           (void) EvaluateImage(image,op,argument_list[0].real_reference,
9347             exception);
9348           (void) SetImageChannelMask(image,channel_mask);
9349           break;
9350         }
9351         case 56:  /* Transparent */
9352         {
9353           double
9354             opacity;
9355
9356           MagickBooleanType
9357             invert;
9358
9359           PixelInfo
9360             target;
9361
9362           (void) QueryColorCompliance("none",AllCompliance,&target,
9363             exception);
9364           if (attribute_flag[0] != 0)
9365             (void) QueryColorCompliance(argument_list[0].string_reference,
9366               AllCompliance,&target,exception);
9367           opacity=TransparentAlpha;
9368           if (attribute_flag[1] != 0)
9369             opacity=StringToDoubleInterval(argument_list[1].string_reference,
9370               (double) QuantumRange+1.0);
9371           if (attribute_flag[2] != 0)
9372             image->fuzz=StringToDoubleInterval(
9373               argument_list[2].string_reference,(double) QuantumRange+1.0);
9374           if (attribute_flag[3] == 0)
9375             argument_list[3].integer_reference=0;
9376           invert=MagickFalse;
9377           if (attribute_flag[3] != 0)
9378             invert=(MagickBooleanType) argument_list[3].integer_reference;
9379           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9380             invert,exception);
9381           break;
9382         }
9383         case 57:  /* Threshold */
9384         {
9385           double
9386             threshold;
9387
9388           if (attribute_flag[0] == 0)
9389             argument_list[0].string_reference="50%";
9390           if (attribute_flag[1] != 0)
9391             channel=(ChannelType) argument_list[1].integer_reference;
9392           threshold=StringToDoubleInterval(argument_list[0].string_reference,
9393             (double) QuantumRange+1.0);
9394           channel_mask=SetImageChannelMask(image,channel);
9395           (void) BilevelImage(image,threshold,exception);
9396           (void) SetImageChannelMask(image,channel_mask);
9397           break;
9398         }
9399         case 58:  /* Charcoal */
9400         {
9401           if (attribute_flag[0] != 0)
9402             {
9403               flags=ParseGeometry(argument_list[0].string_reference,
9404                 &geometry_info);
9405               if ((flags & SigmaValue) == 0)
9406                 geometry_info.sigma=1.0;
9407             }
9408           if (attribute_flag[1] != 0)
9409             geometry_info.rho=argument_list[1].real_reference;
9410           if (attribute_flag[2] != 0)
9411             geometry_info.sigma=argument_list[2].real_reference;
9412           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9413             exception);
9414           break;
9415         }
9416         case 59:  /* Trim */
9417         {
9418           if (attribute_flag[0] != 0)
9419             image->fuzz=StringToDoubleInterval(
9420               argument_list[0].string_reference,(double) QuantumRange+1.0);
9421           image=TrimImage(image,exception);
9422           break;
9423         }
9424         case 60:  /* Wave */
9425         {
9426           PixelInterpolateMethod
9427             method;
9428
9429           if (attribute_flag[0] != 0)
9430             {
9431               flags=ParseGeometry(argument_list[0].string_reference,
9432                 &geometry_info);
9433               if ((flags & SigmaValue) == 0)
9434                 geometry_info.sigma=1.0;
9435             }
9436           if (attribute_flag[1] != 0)
9437             geometry_info.rho=argument_list[1].real_reference;
9438           if (attribute_flag[2] != 0)
9439             geometry_info.sigma=argument_list[2].real_reference;
9440           method=UndefinedInterpolatePixel;
9441           if (attribute_flag[3] != 0)
9442             method=(PixelInterpolateMethod) argument_list[3].integer_reference;
9443           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9444             method,exception);
9445           break;
9446         }
9447         case 61:  /* Separate */
9448         {
9449           if (attribute_flag[0] != 0)
9450             channel=(ChannelType) argument_list[0].integer_reference;
9451           image=SeparateImage(image,channel,exception);
9452           break;
9453         }
9454         case 63:  /* Stereo */
9455         {
9456           if (attribute_flag[0] == 0)
9457             {
9458               ThrowPerlException(exception,OptionError,"StereoImageRequired",
9459                 PackageName);
9460               goto PerlException;
9461             }
9462           if (attribute_flag[1] != 0)
9463             geometry.x=argument_list[1].integer_reference;
9464           if (attribute_flag[2] != 0)
9465             geometry.y=argument_list[2].integer_reference;
9466           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9467             geometry.x,geometry.y,exception);
9468           break;
9469         }
9470         case 64:  /* Stegano */
9471         {
9472           if (attribute_flag[0] == 0)
9473             {
9474               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9475                 PackageName);
9476               goto PerlException;
9477             }
9478           if (attribute_flag[1] == 0)
9479             argument_list[1].integer_reference=0;
9480           image->offset=argument_list[1].integer_reference;
9481           image=SteganoImage(image,argument_list[0].image_reference,exception);
9482           break;
9483         }
9484         case 65:  /* Deconstruct */
9485         {
9486           image=CompareImagesLayers(image,CompareAnyLayer,exception);
9487           break;
9488         }
9489         case 66:  /* GaussianBlur */
9490         {
9491           if (attribute_flag[0] != 0)
9492             {
9493               flags=ParseGeometry(argument_list[0].string_reference,
9494                 &geometry_info);
9495               if ((flags & SigmaValue) == 0)
9496                 geometry_info.sigma=1.0;
9497             }
9498           if (attribute_flag[1] != 0)
9499             geometry_info.rho=argument_list[1].real_reference;
9500           if (attribute_flag[2] != 0)
9501             geometry_info.sigma=argument_list[2].real_reference;
9502           if (attribute_flag[3] != 0)
9503             channel=(ChannelType) argument_list[3].integer_reference;
9504           channel_mask=SetImageChannelMask(image,channel);
9505           image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9506             exception);
9507           if (image != (Image *) NULL)
9508             (void) SetImageChannelMask(image,channel_mask);
9509           break;
9510         }
9511         case 67:  /* Convolve */
9512         {
9513           KernelInfo
9514             *kernel;
9515
9516           kernel=(KernelInfo *) NULL;
9517           if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9518             break;
9519           if (attribute_flag[0] != 0)
9520             {
9521               AV
9522                 *av;
9523
9524               size_t
9525                 order;
9526
9527               kernel=AcquireKernelInfo((const char *) NULL);
9528               if (kernel == (KernelInfo *) NULL)
9529                 break;
9530               av=(AV *) argument_list[0].array_reference;
9531               order=(size_t) sqrt(av_len(av)+1);
9532               kernel->width=order;
9533               kernel->height=order;
9534               kernel->values=(MagickRealType *) AcquireAlignedMemory(order,
9535                 order*sizeof(*kernel->values));
9536               if (kernel->values == (MagickRealType *) NULL)
9537                 {
9538                   kernel=DestroyKernelInfo(kernel);
9539                   ThrowPerlException(exception,ResourceLimitFatalError,
9540                     "MemoryAllocationFailed",PackageName);
9541                   goto PerlException;
9542                 }
9543               for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9544                 kernel->values[j]=(MagickRealType) SvNV(*(av_fetch(av,j,0)));
9545               for ( ; j < (ssize_t) (order*order); j++)
9546                 kernel->values[j]=0.0;
9547             }
9548           if (attribute_flag[1] != 0)
9549             channel=(ChannelType) argument_list[1].integer_reference;
9550           if (attribute_flag[2] != 0)
9551             SetImageArtifact(image,"filter:blur",
9552               argument_list[2].string_reference);
9553           if (attribute_flag[3] != 0)
9554             {
9555               kernel=AcquireKernelInfo(argument_list[3].string_reference);
9556               if (kernel == (KernelInfo *) NULL)
9557                 break;
9558             }
9559           channel_mask=SetImageChannelMask(image,channel);
9560           image=ConvolveImage(image,kernel,exception);
9561           if (image != (Image *) NULL)
9562             (void) SetImageChannelMask(image,channel_mask);
9563           kernel=DestroyKernelInfo(kernel);
9564           break;
9565         }
9566         case 68:  /* Profile */
9567         {
9568           const char
9569             *name;
9570
9571           Image
9572             *profile_image;
9573
9574           ImageInfo
9575             *profile_info;
9576
9577           StringInfo
9578             *profile;
9579
9580           name="*";
9581           if (attribute_flag[0] != 0)
9582             name=argument_list[0].string_reference;
9583           if (attribute_flag[2] != 0)
9584             image->rendering_intent=(RenderingIntent)
9585               argument_list[2].integer_reference;
9586           if (attribute_flag[3] != 0)
9587             image->black_point_compensation=
9588               argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9589           if (attribute_flag[1] != 0)
9590             {
9591               if (argument_list[1].length == 0)
9592                 {
9593                   /*
9594                     Remove a profile from the image.
9595                   */
9596                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9597                     exception);
9598                   break;
9599                 }
9600               /*
9601                 Associate user supplied profile with the image.
9602               */
9603               profile=AcquireStringInfo(argument_list[1].length);
9604               SetStringInfoDatum(profile,(const unsigned char *)
9605                 argument_list[1].string_reference);
9606               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9607                 (size_t) GetStringInfoLength(profile),exception);
9608               profile=DestroyStringInfo(profile);
9609               break;
9610             }
9611           /*
9612             Associate a profile with the image.
9613           */
9614           profile_info=CloneImageInfo(info ? info->image_info :
9615             (ImageInfo *) NULL);
9616           profile_image=ReadImages(profile_info,name,exception);
9617           if (profile_image == (Image *) NULL)
9618             break;
9619           ResetImageProfileIterator(profile_image);
9620           name=GetNextImageProfile(profile_image);
9621           while (name != (const char *) NULL)
9622           {
9623             const StringInfo
9624               *profile;
9625
9626             profile=GetImageProfile(profile_image,name);
9627             if (profile != (const StringInfo *) NULL)
9628               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9629                 (size_t) GetStringInfoLength(profile),exception);
9630             name=GetNextImageProfile(profile_image);
9631           }
9632           profile_image=DestroyImage(profile_image);
9633           profile_info=DestroyImageInfo(profile_info);
9634           break;
9635         }
9636         case 69:  /* UnsharpMask */
9637         {
9638           if (attribute_flag[0] != 0)
9639             {
9640               flags=ParseGeometry(argument_list[0].string_reference,
9641                 &geometry_info);
9642               if ((flags & SigmaValue) == 0)
9643                 geometry_info.sigma=1.0;
9644               if ((flags & XiValue) == 0)
9645                 geometry_info.xi=1.0;
9646               if ((flags & PsiValue) == 0)
9647                 geometry_info.psi=0.5;
9648             }
9649           if (attribute_flag[1] != 0)
9650             geometry_info.rho=argument_list[1].real_reference;
9651           if (attribute_flag[2] != 0)
9652             geometry_info.sigma=argument_list[2].real_reference;
9653           if (attribute_flag[3] != 0)
9654             geometry_info.xi=argument_list[3].real_reference;
9655           if (attribute_flag[4] != 0)
9656             geometry_info.psi=argument_list[4].real_reference;
9657           if (attribute_flag[5] != 0)
9658             channel=(ChannelType) argument_list[5].integer_reference;
9659           channel_mask=SetImageChannelMask(image,channel);
9660           image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9661             geometry_info.xi,geometry_info.psi,exception);
9662           if (image != (Image *) NULL)
9663             (void) SetImageChannelMask(image,channel_mask);
9664           break;
9665         }
9666         case 70:  /* MotionBlur */
9667         {
9668           if (attribute_flag[0] != 0)
9669             {
9670               flags=ParseGeometry(argument_list[0].string_reference,
9671                 &geometry_info);
9672               if ((flags & SigmaValue) == 0)
9673                 geometry_info.sigma=1.0;
9674               if ((flags & XiValue) == 0)
9675                 geometry_info.xi=1.0;
9676             }
9677           if (attribute_flag[1] != 0)
9678             geometry_info.rho=argument_list[1].real_reference;
9679           if (attribute_flag[2] != 0)
9680             geometry_info.sigma=argument_list[2].real_reference;
9681           if (attribute_flag[3] != 0)
9682             geometry_info.xi=argument_list[3].real_reference;
9683           if (attribute_flag[4] != 0)
9684             channel=(ChannelType) argument_list[4].integer_reference;
9685           channel_mask=SetImageChannelMask(image,channel);
9686           image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9687             geometry_info.xi,exception);
9688           if (image != (Image *) NULL)
9689             (void) SetImageChannelMask(image,channel_mask);
9690           break;
9691         }
9692         case 71:  /* OrderedDither */
9693         {
9694           if (attribute_flag[0] == 0)
9695             argument_list[0].string_reference="o8x8";
9696           if (attribute_flag[1] != 0)
9697             channel=(ChannelType) argument_list[1].integer_reference;
9698           channel_mask=SetImageChannelMask(image,channel);
9699           (void) OrderedPosterizeImage(image,argument_list[0].string_reference,
9700             exception);
9701           (void) SetImageChannelMask(image,channel_mask);
9702           break;
9703         }
9704         case 72:  /* Shave */
9705         {
9706           if (attribute_flag[0] != 0)
9707             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9708               &geometry,exception);
9709           if (attribute_flag[1] != 0)
9710             geometry.width=argument_list[1].integer_reference;
9711           if (attribute_flag[2] != 0)
9712             geometry.height=argument_list[2].integer_reference;
9713           image=ShaveImage(image,&geometry,exception);
9714           break;
9715         }
9716         case 73:  /* Level */
9717         {
9718           double
9719             black_point,
9720             gamma,
9721             white_point;
9722
9723           black_point=0.0;
9724           white_point=(double) image->columns*image->rows;
9725           gamma=1.0;
9726           if (attribute_flag[0] != 0)
9727             {
9728               flags=ParseGeometry(argument_list[0].string_reference,
9729                 &geometry_info);
9730               black_point=geometry_info.rho;
9731               if ((flags & SigmaValue) != 0)
9732                 white_point=geometry_info.sigma;
9733               if ((flags & XiValue) != 0)
9734                 gamma=geometry_info.xi;
9735               if ((flags & PercentValue) != 0)
9736                 {
9737                   black_point*=(double) (QuantumRange/100.0);
9738                   white_point*=(double) (QuantumRange/100.0);
9739                 }
9740               if ((flags & SigmaValue) == 0)
9741                 white_point=(double) QuantumRange-black_point;
9742             }
9743           if (attribute_flag[1] != 0)
9744             black_point=argument_list[1].real_reference;
9745           if (attribute_flag[2] != 0)
9746             white_point=argument_list[2].real_reference;
9747           if (attribute_flag[3] != 0)
9748             gamma=argument_list[3].real_reference;
9749           if (attribute_flag[4] != 0)
9750             channel=(ChannelType) argument_list[4].integer_reference;
9751           if (attribute_flag[5] != 0)
9752             {
9753               argument_list[0].real_reference=argument_list[5].real_reference;
9754               attribute_flag[0]=attribute_flag[5];
9755             }
9756           channel_mask=SetImageChannelMask(image,channel);
9757           (void) LevelImage(image,black_point,white_point,gamma,exception);
9758           (void) SetImageChannelMask(image,channel_mask);
9759           break;
9760         }
9761         case 74:  /* Clip */
9762         {
9763           if (attribute_flag[0] == 0)
9764             argument_list[0].string_reference="#1";
9765           if (attribute_flag[1] == 0)
9766             argument_list[1].integer_reference=MagickTrue;
9767           (void) ClipImagePath(image,argument_list[0].string_reference,
9768             argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse,
9769             exception);
9770           break;
9771         }
9772         case 75:  /* AffineTransform */
9773         {
9774           DrawInfo
9775             *draw_info;
9776
9777           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9778             (DrawInfo *) NULL);
9779           if (attribute_flag[0] != 0)
9780             {
9781               AV
9782                 *av;
9783
9784               av=(AV *) argument_list[0].array_reference;
9785               if ((av_len(av) != 3) && (av_len(av) != 5))
9786                 {
9787                   ThrowPerlException(exception,OptionError,
9788                     "affine matrix must have 4 or 6 elements",PackageName);
9789                   goto PerlException;
9790                 }
9791               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9792               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9793               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9794               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9795               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9796                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9797                 {
9798                   ThrowPerlException(exception,OptionError,
9799                     "affine matrix is singular",PackageName);
9800                    goto PerlException;
9801                 }
9802               if (av_len(av) == 5)
9803                 {
9804                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9805                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9806                 }
9807             }
9808           for (j=1; j < 6; j++)
9809           {
9810             if (attribute_flag[j] == 0)
9811               continue;
9812             value=argument_list[j].string_reference;
9813             angle=argument_list[j].real_reference;
9814             current=draw_info->affine;
9815             GetAffineMatrix(&affine);
9816             switch (j)
9817             {
9818               case 1:
9819               {
9820                 /*
9821                   Translate.
9822                 */
9823                 flags=ParseGeometry(value,&geometry_info);
9824                 affine.tx=geometry_info.xi;
9825                 affine.ty=geometry_info.psi;
9826                 if ((flags & PsiValue) == 0)
9827                   affine.ty=affine.tx;
9828                 break;
9829               }
9830               case 2:
9831               {
9832                 /*
9833                   Scale.
9834                 */
9835                 flags=ParseGeometry(value,&geometry_info);
9836                 affine.sx=geometry_info.rho;
9837                 affine.sy=geometry_info.sigma;
9838                 if ((flags & SigmaValue) == 0)
9839                   affine.sy=affine.sx;
9840                 break;
9841               }
9842               case 3:
9843               {
9844                 /*
9845                   Rotate.
9846                 */
9847                 if (angle == 0.0)
9848                   break;
9849                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9850                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9851                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9852                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9853                 break;
9854               }
9855               case 4:
9856               {
9857                 /*
9858                   SkewX.
9859                 */
9860                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9861                 break;
9862               }
9863               case 5:
9864               {
9865                 /*
9866                   SkewY.
9867                 */
9868                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9869                 break;
9870               }
9871             }
9872             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9873             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9874             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9875             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9876             draw_info->affine.tx=
9877               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9878             draw_info->affine.ty=
9879               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9880           }
9881           if (attribute_flag[6] != 0)
9882             image->interpolate=(PixelInterpolateMethod)
9883               argument_list[6].integer_reference;
9884           if (attribute_flag[7] != 0)
9885             QueryColorCompliance(argument_list[7].string_reference,
9886               AllCompliance,&image->background_color,exception);
9887           image=AffineTransformImage(image,&draw_info->affine,exception);
9888           draw_info=DestroyDrawInfo(draw_info);
9889           break;
9890         }
9891         case 76:  /* Difference */
9892         {
9893           if (attribute_flag[0] == 0)
9894             {
9895               ThrowPerlException(exception,OptionError,
9896                 "ReferenceImageRequired",PackageName);
9897               goto PerlException;
9898             }
9899           if (attribute_flag[1] != 0)
9900             image->fuzz=StringToDoubleInterval(
9901               argument_list[1].string_reference,(double) QuantumRange+1.0);
9902           (void) IsImagesEqual(image,argument_list[0].image_reference,
9903             exception);
9904           break;
9905         }
9906         case 77:  /* AdaptiveThreshold */
9907         {
9908           if (attribute_flag[0] != 0)
9909             {
9910               flags=ParseGeometry(argument_list[0].string_reference,
9911                 &geometry_info);
9912               if ((flags & PercentValue) != 0)
9913                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9914             }
9915           if (attribute_flag[1] != 0)
9916             geometry_info.rho=argument_list[1].integer_reference;
9917           if (attribute_flag[2] != 0)
9918             geometry_info.sigma=argument_list[2].integer_reference;
9919           if (attribute_flag[3] != 0)
9920             geometry_info.xi=argument_list[3].integer_reference;;
9921           image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
9922             (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
9923           break;
9924         }
9925         case 78:  /* Resample */
9926         {
9927           size_t
9928             height,
9929             width;
9930
9931           if (attribute_flag[0] != 0)
9932             {
9933               flags=ParseGeometry(argument_list[0].string_reference,
9934                 &geometry_info);
9935               if ((flags & SigmaValue) == 0)
9936                 geometry_info.sigma=geometry_info.rho;
9937             }
9938           if (attribute_flag[1] != 0)
9939             geometry_info.rho=argument_list[1].real_reference;
9940           if (attribute_flag[2] != 0)
9941             geometry_info.sigma=argument_list[2].real_reference;
9942           if (attribute_flag[3] == 0)
9943             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
9944           if (attribute_flag[4] == 0)
9945             SetImageArtifact(image,"filter:support",
9946               argument_list[4].string_reference);
9947           width=(size_t) (geometry_info.rho*image->columns/
9948             (image->resolution.x == 0.0 ? 72.0 : image->resolution.x)+0.5);
9949           height=(size_t) (geometry_info.sigma*image->rows/
9950             (image->resolution.y == 0.0 ? 72.0 : image->resolution.y)+0.5);
9951           image=ResizeImage(image,width,height,(FilterTypes)
9952             argument_list[3].integer_reference,exception);
9953           if (image != (Image *) NULL)
9954             {
9955               image->resolution.x=geometry_info.rho;
9956               image->resolution.y=geometry_info.sigma;
9957             }
9958           break;
9959         }
9960         case 79:  /* Describe */
9961         {
9962           if (attribute_flag[0] == 0)
9963             argument_list[0].file_reference=(FILE *) NULL;
9964           if (attribute_flag[1] != 0)
9965             (void) SetImageArtifact(image,"identify:features",
9966               argument_list[1].string_reference);
9967           (void) IdentifyImage(image,argument_list[0].file_reference,
9968             MagickTrue,exception);
9969           break;
9970         }
9971         case 80:  /* BlackThreshold */
9972         {
9973           if (attribute_flag[0] == 0)
9974             argument_list[0].string_reference="50%";
9975           if (attribute_flag[2] != 0)
9976             channel=(ChannelType) argument_list[2].integer_reference;
9977           channel_mask=SetImageChannelMask(image,channel);
9978           BlackThresholdImage(image,argument_list[0].string_reference,
9979             exception);
9980           (void) SetImageChannelMask(image,channel_mask);
9981           break;
9982         }
9983         case 81:  /* WhiteThreshold */
9984         {
9985           if (attribute_flag[0] == 0)
9986             argument_list[0].string_reference="50%";
9987           if (attribute_flag[2] != 0)
9988             channel=(ChannelType) argument_list[2].integer_reference;
9989           channel_mask=SetImageChannelMask(image,channel);
9990           WhiteThresholdImage(image,argument_list[0].string_reference,
9991             exception);
9992           (void) SetImageChannelMask(image,channel_mask);
9993           break;
9994         }
9995         case 82:  /* RotationalBlur */
9996         {
9997           if (attribute_flag[0] != 0)
9998             {
9999               flags=ParseGeometry(argument_list[0].string_reference,
10000                 &geometry_info);
10001             }
10002           if (attribute_flag[1] != 0)
10003             geometry_info.rho=argument_list[1].real_reference;
10004           if (attribute_flag[2] != 0)
10005             channel=(ChannelType) argument_list[2].integer_reference;
10006           channel_mask=SetImageChannelMask(image,channel);
10007           image=RotationalBlurImage(image,geometry_info.rho,exception);
10008           if (image != (Image *) NULL)
10009             (void) SetImageChannelMask(image,channel_mask);
10010           break;
10011         }
10012         case 83:  /* Thumbnail */
10013         {
10014           if (attribute_flag[0] != 0)
10015             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10016               &geometry,exception);
10017           if (attribute_flag[1] != 0)
10018             geometry.width=argument_list[1].integer_reference;
10019           if (attribute_flag[2] != 0)
10020             geometry.height=argument_list[2].integer_reference;
10021           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
10022           break;
10023         }
10024         case 84:  /* Strip */
10025         {
10026           (void) StripImage(image,exception);
10027           break;
10028         }
10029         case 85:  /* Tint */
10030         {
10031           PixelInfo
10032             tint;
10033
10034           GetPixelInfo(image,&tint);
10035           if (attribute_flag[0] != 0)
10036             (void) QueryColorCompliance(argument_list[0].string_reference,
10037               AllCompliance,&tint,exception);
10038           if (attribute_flag[1] == 0)
10039             argument_list[1].string_reference="100";
10040           image=TintImage(image,argument_list[1].string_reference,&tint,
10041             exception);
10042           break;
10043         }
10044         case 86:  /* Channel */
10045         {
10046           if (attribute_flag[0] != 0)
10047             channel=(ChannelType) argument_list[0].integer_reference;
10048           image=SeparateImage(image,channel,exception);
10049           break;
10050         }
10051         case 87:  /* Splice */
10052         {
10053           if (attribute_flag[0] != 0)
10054             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
10055               &geometry,exception);
10056           if (attribute_flag[1] != 0)
10057             geometry.width=argument_list[1].integer_reference;
10058           if (attribute_flag[2] != 0)
10059             geometry.height=argument_list[2].integer_reference;
10060           if (attribute_flag[3] != 0)
10061             geometry.x=argument_list[3].integer_reference;
10062           if (attribute_flag[4] != 0)
10063             geometry.y=argument_list[4].integer_reference;
10064           if (attribute_flag[5] != 0)
10065             image->fuzz=StringToDoubleInterval(
10066               argument_list[5].string_reference,(double) QuantumRange+1.0);
10067           if (attribute_flag[6] != 0)
10068             (void) QueryColorCompliance(argument_list[6].string_reference,
10069               AllCompliance,&image->background_color,exception);
10070           if (attribute_flag[7] != 0)
10071             image->gravity=(GravityType) argument_list[7].integer_reference;
10072           image=SpliceImage(image,&geometry,exception);
10073           break;
10074         }
10075         case 88:  /* Posterize */
10076         {
10077           if (attribute_flag[0] == 0)
10078             argument_list[0].integer_reference=3;
10079           if (attribute_flag[1] == 0)
10080             argument_list[1].integer_reference=0;
10081           (void) PosterizeImage(image,argument_list[0].integer_reference,
10082             argument_list[1].integer_reference ? RiemersmaDitherMethod :
10083             NoDitherMethod,exception);
10084           break;
10085         }
10086         case 89:  /* Shadow */
10087         {
10088           if (attribute_flag[0] != 0)
10089             {
10090               flags=ParseGeometry(argument_list[0].string_reference,
10091                 &geometry_info);
10092               if ((flags & SigmaValue) == 0)
10093                 geometry_info.sigma=1.0;
10094               if ((flags & XiValue) == 0)
10095                 geometry_info.xi=4.0;
10096               if ((flags & PsiValue) == 0)
10097                 geometry_info.psi=4.0;
10098             }
10099           if (attribute_flag[1] != 0)
10100             geometry_info.rho=argument_list[1].real_reference;
10101           if (attribute_flag[2] != 0)
10102             geometry_info.sigma=argument_list[2].real_reference;
10103           if (attribute_flag[3] != 0)
10104             geometry_info.xi=argument_list[3].integer_reference;
10105           if (attribute_flag[4] != 0)
10106             geometry_info.psi=argument_list[4].integer_reference;
10107           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
10108             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10109             ceil(geometry_info.psi-0.5),exception);
10110           break;
10111         }
10112         case 90:  /* Identify */
10113         {
10114           if (attribute_flag[0] == 0)
10115             argument_list[0].file_reference=(FILE *) NULL;
10116           if (attribute_flag[1] != 0)
10117             (void) SetImageArtifact(image,"identify:features",
10118               argument_list[1].string_reference);
10119           if ((attribute_flag[2] != 0) &&
10120               (argument_list[2].integer_reference != 0))
10121             (void) SetImageArtifact(image,"identify:unique","true");
10122           (void) IdentifyImage(image,argument_list[0].file_reference,
10123             MagickTrue,exception);
10124           break;
10125         }
10126         case 91:  /* SepiaTone */
10127         {
10128           if (attribute_flag[0] == 0)
10129             argument_list[0].real_reference=80.0*QuantumRange/100.0;
10130           image=SepiaToneImage(image,argument_list[0].real_reference,
10131             exception);
10132           break;
10133         }
10134         case 92:  /* SigmoidalContrast */
10135         {
10136           MagickBooleanType
10137             sharpen;
10138
10139           if (attribute_flag[0] != 0)
10140             {
10141               flags=ParseGeometry(argument_list[0].string_reference,
10142                 &geometry_info);
10143               if ((flags & SigmaValue) == 0)
10144                 geometry_info.sigma=QuantumRange/2.0;
10145               if ((flags & PercentValue) != 0)
10146                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
10147             }
10148           if (attribute_flag[1] != 0)
10149             geometry_info.rho=argument_list[1].real_reference;
10150           if (attribute_flag[2] != 0)
10151             geometry_info.sigma=argument_list[2].real_reference;
10152           if (attribute_flag[3] != 0)
10153             channel=(ChannelType) argument_list[3].integer_reference;
10154           sharpen=MagickTrue;
10155           if (attribute_flag[4] != 0)
10156             sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
10157               MagickFalse;
10158           channel_mask=SetImageChannelMask(image,channel);
10159           (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
10160             geometry_info.sigma,exception);
10161           (void) SetImageChannelMask(image,channel_mask);
10162           break;
10163         }
10164         case 93:  /* Extent */
10165         {
10166           if (attribute_flag[7] != 0)
10167             image->gravity=(GravityType) argument_list[7].integer_reference;
10168           if (attribute_flag[0] != 0)
10169             {
10170               int
10171                 flags;
10172
10173               flags=ParseGravityGeometry(image,
10174                 argument_list[0].string_reference,&geometry,exception);
10175               (void) flags;
10176               if (geometry.width == 0)
10177                 geometry.width=image->columns;
10178               if (geometry.height == 0)
10179                 geometry.height=image->rows;
10180             }
10181           if (attribute_flag[1] != 0)
10182             geometry.width=argument_list[1].integer_reference;
10183           if (attribute_flag[2] != 0)
10184             geometry.height=argument_list[2].integer_reference;
10185           if (attribute_flag[3] != 0)
10186             geometry.x=argument_list[3].integer_reference;
10187           if (attribute_flag[4] != 0)
10188             geometry.y=argument_list[4].integer_reference;
10189           if (attribute_flag[5] != 0)
10190             image->fuzz=StringToDoubleInterval(
10191               argument_list[5].string_reference,(double) QuantumRange+1.0);
10192           if (attribute_flag[6] != 0)
10193             (void) QueryColorCompliance(argument_list[6].string_reference,
10194               AllCompliance,&image->background_color,exception);
10195           image=ExtentImage(image,&geometry,exception);
10196           break;
10197         }
10198         case 94:  /* Vignette */
10199         {
10200           if (attribute_flag[0] != 0)
10201             {
10202               flags=ParseGeometry(argument_list[0].string_reference,
10203                 &geometry_info);
10204               if ((flags & SigmaValue) == 0)
10205                 geometry_info.sigma=1.0;
10206               if ((flags & XiValue) == 0)
10207                 geometry_info.xi=0.1*image->columns;
10208               if ((flags & PsiValue) == 0)
10209                 geometry_info.psi=0.1*image->rows;
10210             }
10211           if (attribute_flag[1] != 0)
10212             geometry_info.rho=argument_list[1].real_reference;
10213           if (attribute_flag[2] != 0)
10214             geometry_info.sigma=argument_list[2].real_reference;
10215           if (attribute_flag[3] != 0)
10216             geometry_info.xi=argument_list[3].integer_reference;
10217           if (attribute_flag[4] != 0)
10218             geometry_info.psi=argument_list[4].integer_reference;
10219           if (attribute_flag[5] != 0)
10220             (void) QueryColorCompliance(argument_list[5].string_reference,
10221               AllCompliance,&image->background_color,exception);
10222           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
10223             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10224             ceil(geometry_info.psi-0.5),exception);
10225           break;
10226         }
10227         case 95:  /* ContrastStretch */
10228         {
10229           double
10230             black_point,
10231             white_point;
10232
10233           black_point=0.0;
10234           white_point=(double) image->columns*image->rows;
10235           if (attribute_flag[0] != 0)
10236             {
10237               flags=ParseGeometry(argument_list[0].string_reference,
10238                 &geometry_info);
10239               black_point=geometry_info.rho;
10240               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
10241                 black_point;
10242               if ((flags & PercentValue) != 0)
10243                 {
10244                   black_point*=(double) image->columns*image->rows/100.0;
10245                   white_point*=(double) image->columns*image->rows/100.0;
10246                 }
10247               white_point=(double) image->columns*image->rows-
10248                 white_point;
10249             }
10250           if (attribute_flag[1] != 0)
10251             black_point=argument_list[1].real_reference;
10252           if (attribute_flag[2] != 0)
10253             white_point=argument_list[2].real_reference;
10254           if (attribute_flag[4] != 0)
10255             channel=(ChannelType) argument_list[4].integer_reference;
10256           channel_mask=SetImageChannelMask(image,channel);
10257           (void) ContrastStretchImage(image,black_point,white_point,exception);
10258           (void) SetImageChannelMask(image,channel_mask);
10259           break;
10260         }
10261         case 96:  /* Sans0 */
10262         {
10263           break;
10264         }
10265         case 97:  /* Sans1 */
10266         {
10267           break;
10268         }
10269         case 98:  /* AdaptiveSharpen */
10270         {
10271           if (attribute_flag[0] != 0)
10272             {
10273               flags=ParseGeometry(argument_list[0].string_reference,
10274                 &geometry_info);
10275               if ((flags & SigmaValue) == 0)
10276                 geometry_info.sigma=1.0;
10277               if ((flags & XiValue) == 0)
10278                 geometry_info.xi=0.0;
10279             }
10280           if (attribute_flag[1] != 0)
10281             geometry_info.rho=argument_list[1].real_reference;
10282           if (attribute_flag[2] != 0)
10283             geometry_info.sigma=argument_list[2].real_reference;
10284           if (attribute_flag[3] != 0)
10285             geometry_info.xi=argument_list[3].real_reference;
10286           if (attribute_flag[4] != 0)
10287             channel=(ChannelType) argument_list[4].integer_reference;
10288           channel_mask=SetImageChannelMask(image,channel);
10289           image=AdaptiveSharpenImage(image,geometry_info.rho,
10290             geometry_info.sigma,exception);
10291           if (image != (Image *) NULL)
10292             (void) SetImageChannelMask(image,channel_mask);
10293           break;
10294         }
10295         case 99:  /* Transpose */
10296         {
10297           image=TransposeImage(image,exception);
10298           break;
10299         }
10300         case 100:  /* Tranverse */
10301         {
10302           image=TransverseImage(image,exception);
10303           break;
10304         }
10305         case 101:  /* AutoOrient */
10306         {
10307           image=AutoOrientImage(image,image->orientation,exception);
10308           break;
10309         }
10310         case 102:  /* AdaptiveBlur */
10311         {
10312           if (attribute_flag[0] != 0)
10313             {
10314               flags=ParseGeometry(argument_list[0].string_reference,
10315                 &geometry_info);
10316               if ((flags & SigmaValue) == 0)
10317                 geometry_info.sigma=1.0;
10318               if ((flags & XiValue) == 0)
10319                 geometry_info.xi=0.0;
10320             }
10321           if (attribute_flag[1] != 0)
10322             geometry_info.rho=argument_list[1].real_reference;
10323           if (attribute_flag[2] != 0)
10324             geometry_info.sigma=argument_list[2].real_reference;
10325           if (attribute_flag[3] != 0)
10326             channel=(ChannelType) argument_list[3].integer_reference;
10327           channel_mask=SetImageChannelMask(image,channel);
10328           image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10329             exception);
10330           if (image != (Image *) NULL)
10331             (void) SetImageChannelMask(image,channel_mask);
10332           break;
10333         }
10334         case 103:  /* Sketch */
10335         {
10336           if (attribute_flag[0] != 0)
10337             {
10338               flags=ParseGeometry(argument_list[0].string_reference,
10339                 &geometry_info);
10340               if ((flags & SigmaValue) == 0)
10341                 geometry_info.sigma=1.0;
10342               if ((flags & XiValue) == 0)
10343                 geometry_info.xi=1.0;
10344             }
10345           if (attribute_flag[1] != 0)
10346             geometry_info.rho=argument_list[1].real_reference;
10347           if (attribute_flag[2] != 0)
10348             geometry_info.sigma=argument_list[2].real_reference;
10349           if (attribute_flag[3] != 0)
10350             geometry_info.xi=argument_list[3].real_reference;
10351           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10352             geometry_info.xi,exception);
10353           break;
10354         }
10355         case 104:  /* UniqueColors */
10356         {
10357           image=UniqueImageColors(image,exception);
10358           break;
10359         }
10360         case 105:  /* AdaptiveResize */
10361         {
10362           if (attribute_flag[0] != 0)
10363             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10364               &geometry,exception);
10365           if (attribute_flag[1] != 0)
10366             geometry.width=argument_list[1].integer_reference;
10367           if (attribute_flag[2] != 0)
10368             geometry.height=argument_list[2].integer_reference;
10369           if (attribute_flag[3] != 0)
10370             image->filter=(FilterTypes) argument_list[4].integer_reference;
10371           if (attribute_flag[4] != 0)
10372             SetImageArtifact(image,"filter:support",
10373               argument_list[4].string_reference);
10374           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10375             exception);
10376           break;
10377         }
10378         case 106:  /* ClipMask */
10379         {
10380           Image
10381             *mask_image;
10382
10383           if (attribute_flag[0] == 0)
10384             {
10385               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10386                 PackageName);
10387               goto PerlException;
10388             }
10389           mask_image=CloneImage(argument_list[0].image_reference,0,0,MagickTrue,
10390             exception);
10391           (void) SetImageMask(image,mask_image,exception);
10392           mask_image=DestroyImage(mask_image);
10393           break;
10394         }
10395         case 107:  /* LinearStretch */
10396         {
10397            double
10398              black_point,
10399              white_point;
10400
10401            black_point=0.0;
10402            white_point=(double) image->columns*image->rows;
10403            if (attribute_flag[0] != 0)
10404              {
10405                flags=ParseGeometry(argument_list[0].string_reference,
10406                  &geometry_info);
10407                if ((flags & SigmaValue) != 0)
10408                   white_point=geometry_info.sigma;
10409                if ((flags & PercentValue) != 0)
10410                  {
10411                    black_point*=(double) image->columns*image->rows/100.0;
10412                    white_point*=(double) image->columns*image->rows/100.0;
10413                  }
10414                if ((flags & SigmaValue) == 0)
10415                  white_point=(double) image->columns*image->rows-black_point;
10416              }
10417           if (attribute_flag[1] != 0)
10418             black_point=argument_list[1].real_reference;
10419           if (attribute_flag[2] != 0)
10420             white_point=argument_list[2].real_reference;
10421           (void) LinearStretchImage(image,black_point,white_point,exception);
10422           break;
10423         }
10424         case 108:  /* ColorMatrix */
10425         {
10426           AV
10427             *av;
10428
10429           double
10430             *color_matrix;
10431
10432           KernelInfo
10433             *kernel_info;
10434
10435           size_t
10436             order;
10437
10438           if (attribute_flag[0] == 0)
10439             break;
10440           av=(AV *) argument_list[0].array_reference;
10441           order=(size_t) sqrt(av_len(av)+1);
10442           color_matrix=(double *) AcquireQuantumMemory(order,order*
10443             sizeof(*color_matrix));
10444           if (color_matrix == (double *) NULL)
10445             {
10446               ThrowPerlException(exception,ResourceLimitFatalError,
10447                 "MemoryAllocationFailed",PackageName);
10448               goto PerlException;
10449            }
10450           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10451             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10452           for ( ; j < (ssize_t) (order*order); j++)
10453             color_matrix[j]=0.0;
10454           kernel_info=AcquireKernelInfo((const char *) NULL);
10455           if (kernel_info == (KernelInfo *) NULL)
10456             break;
10457           kernel_info->width=order;
10458           kernel_info->height=order;
10459           kernel_info->values=(MagickRealType *) AcquireAlignedMemory(order,
10460             order*sizeof(*kernel_info->values));
10461           if (kernel_info->values != (MagickRealType *) NULL)
10462             {
10463               for (i=0; i < (ssize_t) (order*order); i++)
10464                 kernel_info->values[i]=(MagickRealType) color_matrix[i];
10465               image=ColorMatrixImage(image,kernel_info,exception);
10466             }
10467           kernel_info=DestroyKernelInfo(kernel_info);
10468           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10469           break;
10470         }
10471         case 109:  /* Mask */
10472         {
10473           Image
10474             *mask_image;
10475
10476           if (attribute_flag[0] == 0)
10477             {
10478               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10479                 PackageName);
10480               goto PerlException;
10481             }
10482           mask_image=CloneImage(argument_list[0].image_reference,0,0,
10483             MagickTrue,exception);
10484           (void) SetImageMask(image,mask_image,exception);
10485           mask_image=DestroyImage(mask_image);
10486           break;
10487         }
10488         case 110:  /* Polaroid */
10489         {
10490           char
10491             *caption;
10492
10493           DrawInfo
10494             *draw_info;
10495
10496           double
10497             angle;
10498
10499           PixelInterpolateMethod
10500             method;
10501
10502           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10503             (DrawInfo *) NULL);
10504           caption=(char *) NULL;
10505           if (attribute_flag[0] != 0)
10506             caption=InterpretImageProperties(info ? info->image_info :
10507               (ImageInfo *) NULL,image,argument_list[0].string_reference,
10508               exception);
10509           angle=0.0;
10510           if (attribute_flag[1] != 0)
10511             angle=argument_list[1].real_reference;
10512           if (attribute_flag[2] != 0)
10513             (void) CloneString(&draw_info->font,
10514               argument_list[2].string_reference);
10515           if (attribute_flag[3] != 0)
10516             (void) QueryColorCompliance(argument_list[3].string_reference,
10517               AllCompliance,&draw_info->stroke,exception);
10518           if (attribute_flag[4] != 0)
10519             (void) QueryColorCompliance(argument_list[4].string_reference,
10520               AllCompliance,&draw_info->fill,exception);
10521           if (attribute_flag[5] != 0)
10522             draw_info->stroke_width=argument_list[5].real_reference;
10523           if (attribute_flag[6] != 0)
10524             draw_info->pointsize=argument_list[6].real_reference;
10525           if (attribute_flag[7] != 0)
10526             draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10527           if (attribute_flag[8] != 0)
10528             (void) QueryColorCompliance(argument_list[8].string_reference,
10529               AllCompliance,&image->background_color,exception);
10530           method=UndefinedInterpolatePixel;
10531           if (attribute_flag[9] != 0)
10532             method=(PixelInterpolateMethod) argument_list[9].integer_reference;
10533           image=PolaroidImage(image,draw_info,caption,angle,method,exception);
10534           draw_info=DestroyDrawInfo(draw_info);
10535           if (caption != (char *) NULL)
10536             caption=DestroyString(caption);
10537           break;
10538         }
10539         case 111:  /* FloodfillPaint */
10540         {
10541           DrawInfo
10542             *draw_info;
10543
10544           MagickBooleanType
10545             invert;
10546
10547           PixelInfo
10548             target;
10549
10550           draw_info=CloneDrawInfo(info ? info->image_info :
10551             (ImageInfo *) NULL,(DrawInfo *) NULL);
10552           if (attribute_flag[0] != 0)
10553             flags=ParsePageGeometry(image,argument_list[0].string_reference,
10554               &geometry,exception);
10555           if (attribute_flag[1] != 0)
10556             geometry.x=argument_list[1].integer_reference;
10557           if (attribute_flag[2] != 0)
10558             geometry.y=argument_list[2].integer_reference;
10559           if (attribute_flag[3] != 0)
10560             (void) QueryColorCompliance(argument_list[3].string_reference,
10561               AllCompliance,&draw_info->fill,exception);
10562           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
10563             geometry.x,geometry.y,&target,exception);
10564           if (attribute_flag[4] != 0)
10565             QueryColorCompliance(argument_list[4].string_reference,
10566               AllCompliance,&target,exception);
10567           if (attribute_flag[5] != 0)
10568             image->fuzz=StringToDoubleInterval(
10569               argument_list[5].string_reference,(double) QuantumRange+1.0);
10570           if (attribute_flag[6] != 0)
10571             channel=(ChannelType) argument_list[6].integer_reference;
10572           invert=MagickFalse;
10573           if (attribute_flag[7] != 0)
10574             invert=(MagickBooleanType) argument_list[7].integer_reference;
10575           channel_mask=SetImageChannelMask(image,channel);
10576           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10577             geometry.y,invert,exception);
10578           (void) SetImageChannelMask(image,channel_mask);
10579           draw_info=DestroyDrawInfo(draw_info);
10580           break;
10581         }
10582         case 112:  /* Distort */
10583         {
10584           AV
10585             *av;
10586
10587           double
10588             *coordinates;
10589
10590           DistortImageMethod
10591             method;
10592
10593           size_t
10594             number_coordinates;
10595
10596           VirtualPixelMethod
10597             virtual_pixel;
10598
10599           if (attribute_flag[0] == 0)
10600             break;
10601           method=UndefinedDistortion;
10602           if (attribute_flag[1] != 0)
10603             method=(DistortImageMethod) argument_list[1].integer_reference;
10604           av=(AV *) argument_list[0].array_reference;
10605           number_coordinates=(size_t) av_len(av)+1;
10606           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10607             sizeof(*coordinates));
10608           if (coordinates == (double *) NULL)
10609             {
10610               ThrowPerlException(exception,ResourceLimitFatalError,
10611                 "MemoryAllocationFailed",PackageName);
10612               goto PerlException;
10613             }
10614           for (j=0; j < (ssize_t) number_coordinates; j++)
10615             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10616           virtual_pixel=UndefinedVirtualPixelMethod;
10617           if (attribute_flag[2] != 0)
10618             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10619               argument_list[2].integer_reference,exception);
10620           image=DistortImage(image,method,number_coordinates,coordinates,
10621             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10622             exception);
10623           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10624             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10625               exception);
10626           coordinates=(double *) RelinquishMagickMemory(coordinates);
10627           break;
10628         }
10629         case 113:  /* Clut */
10630         {
10631           PixelInterpolateMethod
10632             method;
10633
10634           if (attribute_flag[0] == 0)
10635             {
10636               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10637                 PackageName);
10638               goto PerlException;
10639             }
10640           method=UndefinedInterpolatePixel;
10641           if (attribute_flag[1] != 0)
10642             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
10643           if (attribute_flag[2] != 0)
10644             channel=(ChannelType) argument_list[2].integer_reference;
10645           channel_mask=SetImageChannelMask(image,channel);
10646           (void) ClutImage(image,argument_list[0].image_reference,method,
10647             exception);
10648           (void) SetImageChannelMask(image,channel_mask);
10649           break;
10650         }
10651         case 114:  /* LiquidRescale */
10652         {
10653           if (attribute_flag[0] != 0)
10654             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10655               &geometry,exception);
10656           if (attribute_flag[1] != 0)
10657             geometry.width=argument_list[1].integer_reference;
10658           if (attribute_flag[2] != 0)
10659             geometry.height=argument_list[2].integer_reference;
10660           if (attribute_flag[3] == 0)
10661             argument_list[3].real_reference=1.0;
10662           if (attribute_flag[4] == 0)
10663             argument_list[4].real_reference=0.0;
10664           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10665             argument_list[3].real_reference,argument_list[4].real_reference,
10666             exception);
10667           break;
10668         }
10669         case 115:  /* EncipherImage */
10670         {
10671           (void) EncipherImage(image,argument_list[0].string_reference,
10672             exception);
10673           break;
10674         }
10675         case 116:  /* DecipherImage */
10676         {
10677           (void) DecipherImage(image,argument_list[0].string_reference,
10678             exception);
10679           break;
10680         }
10681         case 117:  /* Deskew */
10682         {
10683           geometry_info.rho=QuantumRange/2.0;
10684           if (attribute_flag[0] != 0)
10685             flags=ParseGeometry(argument_list[0].string_reference,
10686               &geometry_info);
10687           if (attribute_flag[1] != 0)
10688             geometry_info.rho=StringToDoubleInterval(
10689               argument_list[1].string_reference,(double) QuantumRange+1.0);
10690           image=DeskewImage(image,geometry_info.rho,exception);
10691           break;
10692         }
10693         case 118:  /* Remap */
10694         {
10695           QuantizeInfo
10696             *quantize_info;
10697
10698           if (attribute_flag[0] == 0)
10699             {
10700               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10701                 PackageName);
10702               goto PerlException;
10703             }
10704           quantize_info=AcquireQuantizeInfo(info->image_info);
10705           if (attribute_flag[1] != 0)
10706             quantize_info->dither_method=(DitherMethod)
10707               argument_list[1].integer_reference;
10708           (void) RemapImages(quantize_info,image,
10709             argument_list[0].image_reference,exception);
10710           quantize_info=DestroyQuantizeInfo(quantize_info);
10711           break;
10712         }
10713         case 119:  /* SparseColor */
10714         {
10715           AV
10716             *av;
10717
10718           double
10719             *coordinates;
10720
10721           SparseColorMethod
10722             method;
10723
10724           size_t
10725             number_coordinates;
10726
10727           VirtualPixelMethod
10728             virtual_pixel;
10729
10730           if (attribute_flag[0] == 0)
10731             break;
10732           method=UndefinedColorInterpolate;
10733           if (attribute_flag[1] != 0)
10734             method=(SparseColorMethod) argument_list[1].integer_reference;
10735           av=(AV *) argument_list[0].array_reference;
10736           number_coordinates=(size_t) av_len(av)+1;
10737           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10738             sizeof(*coordinates));
10739           if (coordinates == (double *) NULL)
10740             {
10741               ThrowPerlException(exception,ResourceLimitFatalError,
10742                 "MemoryAllocationFailed",PackageName);
10743               goto PerlException;
10744             }
10745           for (j=0; j < (ssize_t) number_coordinates; j++)
10746             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10747           virtual_pixel=UndefinedVirtualPixelMethod;
10748           if (attribute_flag[2] != 0)
10749             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10750               argument_list[2].integer_reference,exception);
10751           if (attribute_flag[3] != 0)
10752             channel=(ChannelType) argument_list[3].integer_reference;
10753           channel_mask=SetImageChannelMask(image,channel);
10754           image=SparseColorImage(image,method,number_coordinates,coordinates,
10755             exception);
10756           if (image != (Image *) NULL)
10757             (void) SetImageChannelMask(image,channel_mask);
10758           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10759             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10760               exception);
10761           coordinates=(double *) RelinquishMagickMemory(coordinates);
10762           break;
10763         }
10764         case 120:  /* Function */
10765         {
10766           AV
10767             *av;
10768
10769           double
10770             *parameters;
10771
10772           MagickFunction
10773             function;
10774
10775           size_t
10776             number_parameters;
10777
10778           VirtualPixelMethod
10779             virtual_pixel;
10780
10781           if (attribute_flag[0] == 0)
10782             break;
10783           function=UndefinedFunction;
10784           if (attribute_flag[1] != 0)
10785             function=(MagickFunction) argument_list[1].integer_reference;
10786           av=(AV *) argument_list[0].array_reference;
10787           number_parameters=(size_t) av_len(av)+1;
10788           parameters=(double *) AcquireQuantumMemory(number_parameters,
10789             sizeof(*parameters));
10790           if (parameters == (double *) NULL)
10791             {
10792               ThrowPerlException(exception,ResourceLimitFatalError,
10793                 "MemoryAllocationFailed",PackageName);
10794               goto PerlException;
10795             }
10796           for (j=0; j < (ssize_t) number_parameters; j++)
10797             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10798           virtual_pixel=UndefinedVirtualPixelMethod;
10799           if (attribute_flag[2] != 0)
10800             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10801               argument_list[2].integer_reference,exception);
10802           (void) FunctionImage(image,function,number_parameters,parameters,
10803             exception);
10804           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10805             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10806               exception);
10807           parameters=(double *) RelinquishMagickMemory(parameters);
10808           break;
10809         }
10810         case 121:  /* SelectiveBlur */
10811         {
10812           if (attribute_flag[0] != 0)
10813             {
10814               flags=ParseGeometry(argument_list[0].string_reference,
10815                 &geometry_info);
10816               if ((flags & SigmaValue) == 0)
10817                 geometry_info.sigma=1.0;
10818               if ((flags & PercentValue) != 0)
10819                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10820             }
10821           if (attribute_flag[1] != 0)
10822             geometry_info.rho=argument_list[1].real_reference;
10823           if (attribute_flag[2] != 0)
10824             geometry_info.sigma=argument_list[2].real_reference;
10825           if (attribute_flag[3] != 0)
10826             geometry_info.xi=argument_list[3].integer_reference;;
10827           if (attribute_flag[5] != 0)
10828             channel=(ChannelType) argument_list[5].integer_reference;
10829           channel_mask=SetImageChannelMask(image,channel);
10830           image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10831             geometry_info.xi,exception);
10832           if (image != (Image *) NULL)
10833             (void) SetImageChannelMask(image,channel_mask);
10834           break;
10835         }
10836         case 122:  /* HaldClut */
10837         {
10838           if (attribute_flag[0] == 0)
10839             {
10840               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10841                 PackageName);
10842               goto PerlException;
10843             }
10844           if (attribute_flag[1] != 0)
10845             channel=(ChannelType) argument_list[1].integer_reference;
10846           channel_mask=SetImageChannelMask(image,channel);
10847           (void) HaldClutImage(image,argument_list[0].image_reference,
10848             exception);
10849           (void) SetImageChannelMask(image,channel_mask);
10850           break;
10851         }
10852         case 123:  /* BlueShift */
10853         {
10854           if (attribute_flag[0] != 0)
10855             (void) ParseGeometry(argument_list[0].string_reference,
10856               &geometry_info);
10857           image=BlueShiftImage(image,geometry_info.rho,exception);
10858           break;
10859         }
10860         case 124:  /* ForwardFourierTransformImage */
10861         {
10862           image=ForwardFourierTransformImage(image,
10863             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10864             exception);
10865           break;
10866         }
10867         case 125:  /* InverseFourierTransformImage */
10868         {
10869           image=InverseFourierTransformImage(image,image->next,
10870             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10871             exception);
10872           break;
10873         }
10874         case 126:  /* ColorDecisionList */
10875         {
10876           if (attribute_flag[0] == 0)
10877             argument_list[0].string_reference=(char *) NULL;
10878           (void) ColorDecisionListImage(image,
10879             argument_list[0].string_reference,exception);
10880           break;
10881         }
10882         case 127:  /* AutoGamma */
10883         {
10884           if (attribute_flag[0] != 0)
10885             channel=(ChannelType) argument_list[0].integer_reference;
10886           channel_mask=SetImageChannelMask(image,channel);
10887           (void) AutoGammaImage(image,exception);
10888           (void) SetImageChannelMask(image,channel_mask);
10889           break;
10890         }
10891         case 128:  /* AutoLevel */
10892         {
10893           if (attribute_flag[0] != 0)
10894             channel=(ChannelType) argument_list[0].integer_reference;
10895           channel_mask=SetImageChannelMask(image,channel);
10896           (void) AutoLevelImage(image,exception);
10897           (void) SetImageChannelMask(image,channel_mask);
10898           break;
10899         }
10900         case 129:  /* LevelColors */
10901         {
10902           PixelInfo
10903             black_point,
10904             white_point;
10905
10906           (void) QueryColorCompliance("#000000",AllCompliance,&black_point,
10907             exception);
10908           (void) QueryColorCompliance("#ffffff",AllCompliance,&white_point,
10909             exception);
10910           if (attribute_flag[1] != 0)
10911              (void) QueryColorCompliance(
10912                argument_list[1].string_reference,AllCompliance,&black_point,
10913                exception);
10914           if (attribute_flag[2] != 0)
10915              (void) QueryColorCompliance(
10916                argument_list[2].string_reference,AllCompliance,&white_point,
10917                exception);
10918           if (attribute_flag[3] != 0)
10919             channel=(ChannelType) argument_list[3].integer_reference;
10920           channel_mask=SetImageChannelMask(image,channel);
10921           (void) LevelImageColors(image,&black_point,&white_point,
10922             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10923             exception);
10924           (void) SetImageChannelMask(image,channel_mask);
10925           break;
10926         }
10927         case 130:  /* Clamp */
10928         {
10929           if (attribute_flag[0] != 0)
10930             channel=(ChannelType) argument_list[0].integer_reference;
10931           channel_mask=SetImageChannelMask(image,channel);
10932           (void) ClampImage(image,exception);
10933           (void) SetImageChannelMask(image,channel_mask);
10934           break;
10935         }
10936         case 131:  /* BrightnessContrast */
10937         {
10938           double
10939             brightness,
10940             contrast;
10941
10942           brightness=0.0;
10943           contrast=0.0;
10944           if (attribute_flag[0] != 0)
10945             {
10946               flags=ParseGeometry(argument_list[0].string_reference,
10947                 &geometry_info);
10948               brightness=geometry_info.rho;
10949               if ((flags & SigmaValue) == 0)
10950                 contrast=geometry_info.sigma;
10951             }
10952           if (attribute_flag[1] != 0)
10953             brightness=argument_list[1].real_reference;
10954           if (attribute_flag[2] != 0)
10955             contrast=argument_list[2].real_reference;
10956           if (attribute_flag[4] != 0)
10957             channel=(ChannelType) argument_list[4].integer_reference;
10958           channel_mask=SetImageChannelMask(image,channel);
10959           (void) BrightnessContrastImage(image,brightness,contrast,exception);
10960           (void) SetImageChannelMask(image,channel_mask);
10961           break;
10962         }
10963         case 132:  /* Morphology */
10964         {
10965           KernelInfo
10966             *kernel;
10967
10968           MorphologyMethod
10969             method;
10970
10971           ssize_t
10972             iterations;
10973
10974           if (attribute_flag[0] == 0)
10975             break;
10976           kernel=AcquireKernelInfo(argument_list[0].string_reference);
10977           if (kernel == (KernelInfo *) NULL)
10978             break;
10979           if (attribute_flag[1] != 0)
10980             channel=(ChannelType) argument_list[1].integer_reference;
10981           method=UndefinedMorphology;
10982           if (attribute_flag[2] != 0)
10983             method=argument_list[2].integer_reference;
10984           iterations=1;
10985           if (attribute_flag[3] != 0)
10986             iterations=argument_list[3].integer_reference;
10987           channel_mask=SetImageChannelMask(image,channel);
10988           image=MorphologyImage(image,method,iterations,kernel,exception);
10989           if (image != (Image *) NULL)
10990             (void) SetImageChannelMask(image,channel_mask);
10991           kernel=DestroyKernelInfo(kernel);
10992           break;
10993         }
10994         case 133:  /* Mode */
10995         {
10996           if (attribute_flag[0] != 0)
10997             {
10998               flags=ParseGeometry(argument_list[0].string_reference,
10999                 &geometry_info);
11000               if ((flags & SigmaValue) == 0)
11001                 geometry_info.sigma=1.0;
11002             }
11003           if (attribute_flag[1] != 0)
11004             geometry_info.rho=argument_list[1].real_reference;
11005           if (attribute_flag[2] != 0)
11006             geometry_info.sigma=argument_list[2].real_reference;
11007           if (attribute_flag[3] != 0)
11008             channel=(ChannelType) argument_list[3].integer_reference;
11009           channel_mask=SetImageChannelMask(image,channel);
11010           image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
11011             (size_t) geometry_info.sigma,exception);
11012           if (image != (Image *) NULL)
11013             (void) SetImageChannelMask(image,channel_mask);
11014           break;
11015         }
11016         case 134:  /* Statistic */
11017         {
11018           StatisticType
11019             statistic;
11020
11021           statistic=UndefinedStatistic;
11022           if (attribute_flag[0] != 0)
11023             {
11024               flags=ParseGeometry(argument_list[0].string_reference,
11025                 &geometry_info);
11026               if ((flags & SigmaValue) == 0)
11027                 geometry_info.sigma=1.0;
11028             }
11029           if (attribute_flag[1] != 0)
11030             geometry_info.rho=argument_list[1].real_reference;
11031           if (attribute_flag[2] != 0)
11032             geometry_info.sigma=argument_list[2].real_reference;
11033           if (attribute_flag[3] != 0)
11034             channel=(ChannelType) argument_list[3].integer_reference;
11035           if (attribute_flag[4] != 0)
11036             statistic=(StatisticType) argument_list[4].integer_reference;
11037           channel_mask=SetImageChannelMask(image,channel);
11038           image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
11039             (size_t) geometry_info.sigma,exception);
11040           if (image != (Image *) NULL)
11041             (void) SetImageChannelMask(image,channel_mask);
11042           break;
11043         }
11044         case 135:  /* Perceptible */
11045         {
11046           double
11047             epsilon;
11048
11049           epsilon=MagickEpsilon;
11050           if (attribute_flag[0] != 0)
11051             epsilon=argument_list[0].real_reference;
11052           if (attribute_flag[1] != 0)
11053             channel=(ChannelType) argument_list[1].integer_reference;
11054           channel_mask=SetImageChannelMask(image,channel);
11055           (void) PerceptibleImage(image,epsilon,exception);
11056           (void) SetImageChannelMask(image,channel_mask);
11057           break;
11058         }
11059         case 136:  /* Poly */
11060         {
11061           AV
11062             *av;
11063
11064           double
11065             *terms;
11066
11067           size_t
11068             number_terms;
11069
11070           if (attribute_flag[0] == 0)
11071             break;
11072           if (attribute_flag[1] != 0)
11073             channel=(ChannelType) argument_list[1].integer_reference;
11074           av=(AV *) argument_list[0].array_reference;
11075           number_terms=(size_t) av_len(av);
11076           terms=(double *) AcquireQuantumMemory(number_terms,sizeof(*terms));
11077           if (terms == (double *) NULL)
11078             {
11079               ThrowPerlException(exception,ResourceLimitFatalError,
11080                 "MemoryAllocationFailed",PackageName);
11081               goto PerlException;
11082             }
11083           for (j=0; j < av_len(av); j++)
11084             terms[j]=(double) SvNV(*(av_fetch(av,j,0)));
11085           image=PolynomialImage(image,number_terms >> 1,terms,exception);
11086           terms=(double *) RelinquishMagickMemory(terms);
11087           break;
11088         }
11089         case 137:  /* Grayscale */
11090         {
11091           PixelIntensityMethod
11092             method;
11093
11094           method=UndefinedPixelIntensityMethod;
11095           if (attribute_flag[0] != 0)
11096             method=(PixelIntensityMethod) argument_list[0].integer_reference;
11097           (void) GrayscaleImage(image,method,exception);
11098           break;
11099         }
11100         case 138:  /* Canny */
11101         {
11102           if (attribute_flag[0] != 0)
11103             {
11104               flags=ParseGeometry(argument_list[0].string_reference,
11105                 &geometry_info);
11106               if ((flags & SigmaValue) == 0)
11107                 geometry_info.sigma=1.0;
11108               if ((flags & XiValue) == 0)
11109                 geometry_info.xi=0.10;
11110               if ((flags & PsiValue) == 0)
11111                 geometry_info.psi=0.30;
11112               if ((flags & PercentValue) != 0)
11113                 {
11114                   geometry_info.xi/=100.0;
11115                   geometry_info.psi/=100.0;
11116                 }
11117             }
11118           if (attribute_flag[1] != 0)
11119             geometry_info.rho=argument_list[1].real_reference;
11120           if (attribute_flag[2] != 0)
11121             geometry_info.sigma=argument_list[2].real_reference;
11122           if (attribute_flag[3] != 0)
11123             geometry_info.xi=argument_list[3].real_reference;
11124           if (attribute_flag[4] != 0)
11125             geometry_info.psi=argument_list[4].real_reference;
11126           if (attribute_flag[5] != 0)
11127             channel=(ChannelType) argument_list[5].integer_reference;
11128           channel_mask=SetImageChannelMask(image,channel);
11129           image=CannyEdgeImage(image,geometry_info.rho,geometry_info.sigma,
11130             geometry_info.xi,geometry_info.psi,exception);
11131           if (image != (Image *) NULL)
11132             (void) SetImageChannelMask(image,channel_mask);
11133           break;
11134         }
11135       }
11136       if (next != (Image *) NULL)
11137         (void) CatchImageException(next);
11138       if (region_image != (Image *) NULL)
11139         {
11140           /*
11141             Composite region.
11142           */
11143           status=CompositeImage(region_image,image,CopyCompositeOp,MagickTrue,
11144             region_info.x,region_info.y,exception);
11145           (void) status;
11146           (void) CatchImageException(region_image);
11147           image=DestroyImage(image);
11148           image=region_image;
11149         }
11150       if (image != (Image *) NULL)
11151         {
11152           number_images++;
11153           if (next && (next != image))
11154             {
11155               image->next=next->next;
11156               if (image->next != (Image *) NULL)
11157                 image->next->previous=image;
11158               DeleteImageFromRegistry(*pv,next);
11159             }
11160           sv_setiv(*pv,PTR2IV(image));
11161           next=image;
11162         }
11163       if (*pv)
11164         pv++;
11165     }
11166
11167   PerlException:
11168     if (reference_vector)
11169       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
11170     InheritPerlException(exception,perl_exception);
11171     exception=DestroyExceptionInfo(exception);
11172     sv_setiv(perl_exception,(IV) number_images);
11173     SvPOK_on(perl_exception);
11174     ST(0)=sv_2mortal(perl_exception);
11175     XSRETURN(1);
11176   }
11177 \f
11178 #
11179 ###############################################################################
11180 #                                                                             #
11181 #                                                                             #
11182 #                                                                             #
11183 #   M o n t a g e                                                             #
11184 #                                                                             #
11185 #                                                                             #
11186 #                                                                             #
11187 ###############################################################################
11188 #
11189 #
11190 void
11191 Montage(ref,...)
11192   Image::Magick ref=NO_INIT
11193   ALIAS:
11194     MontageImage  = 1
11195     montage       = 2
11196     montageimage  = 3
11197   PPCODE:
11198   {
11199     AV
11200       *av;
11201
11202     char
11203       *attribute;
11204
11205     ExceptionInfo
11206       *exception;
11207
11208     HV
11209       *hv;
11210
11211     Image
11212       *image,
11213       *next;
11214
11215     PixelInfo
11216       transparent_color;
11217
11218     MontageInfo
11219       *montage_info;
11220
11221     register ssize_t
11222       i;
11223
11224     ssize_t
11225       sp;
11226
11227     struct PackageInfo
11228       *info;
11229
11230     SV
11231       *av_reference,
11232       *perl_exception,
11233       *reference,
11234       *rv,
11235       *sv;
11236
11237     PERL_UNUSED_VAR(ref);
11238     PERL_UNUSED_VAR(ix);
11239     exception=AcquireExceptionInfo();
11240     perl_exception=newSVpv("",0);
11241     sv=NULL;
11242     attribute=NULL;
11243     if (sv_isobject(ST(0)) == 0)
11244       {
11245         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11246           PackageName);
11247         goto PerlException;
11248       }
11249     reference=SvRV(ST(0));
11250     hv=SvSTASH(reference);
11251     av=newAV();
11252     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11253     SvREFCNT_dec(av);
11254     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11255     if (image == (Image *) NULL)
11256       {
11257         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11258           PackageName);
11259         goto PerlException;
11260       }
11261     /*
11262       Get options.
11263     */
11264     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11265     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
11266     (void) QueryColorCompliance("none",AllCompliance,&transparent_color,
11267       exception);
11268     for (i=2; i < items; i+=2)
11269     {
11270       attribute=(char *) SvPV(ST(i-1),na);
11271       switch (*attribute)
11272       {
11273         case 'B':
11274         case 'b':
11275         {
11276           if (LocaleCompare(attribute,"background") == 0)
11277             {
11278               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11279                 &montage_info->background_color,exception);
11280               for (next=image; next; next=next->next)
11281                 next->background_color=montage_info->background_color;
11282               break;
11283             }
11284           if (LocaleCompare(attribute,"border") == 0)
11285             {
11286               montage_info->border_width=SvIV(ST(i));
11287               break;
11288             }
11289           if (LocaleCompare(attribute,"bordercolor") == 0)
11290             {
11291               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11292                 &montage_info->border_color,exception);
11293               for (next=image; next; next=next->next)
11294                 next->border_color=montage_info->border_color;
11295               break;
11296             }
11297           if (LocaleCompare(attribute,"borderwidth") == 0)
11298             {
11299               montage_info->border_width=SvIV(ST(i));
11300               break;
11301             }
11302           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11303             attribute);
11304           break;
11305         }
11306         case 'C':
11307         case 'c':
11308         {
11309           if (LocaleCompare(attribute,"compose") == 0)
11310             {
11311               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11312                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
11313               if (sp < 0)
11314                 {
11315                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11316                     SvPV(ST(i),na));
11317                   break;
11318                 }
11319               for (next=image; next; next=next->next)
11320                 next->compose=(CompositeOperator) sp;
11321               break;
11322             }
11323           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11324             attribute);
11325           break;
11326         }
11327         case 'F':
11328         case 'f':
11329         {
11330           if (LocaleCompare(attribute,"fill") == 0)
11331             {
11332               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11333                 &montage_info->fill,exception);
11334               break;
11335             }
11336           if (LocaleCompare(attribute,"font") == 0)
11337             {
11338               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
11339               break;
11340             }
11341           if (LocaleCompare(attribute,"frame") == 0)
11342             {
11343               char
11344                 *p;
11345
11346               p=SvPV(ST(i),na);
11347               if (IsGeometry(p) == MagickFalse)
11348                 {
11349                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11350                     p);
11351                   break;
11352                 }
11353               (void) CloneString(&montage_info->frame,p);
11354               if (*p == '\0')
11355                 montage_info->frame=(char *) NULL;
11356               break;
11357             }
11358           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11359             attribute);
11360           break;
11361         }
11362         case 'G':
11363         case 'g':
11364         {
11365           if (LocaleCompare(attribute,"geometry") == 0)
11366             {
11367               char
11368                 *p;
11369
11370               p=SvPV(ST(i),na);
11371               if (IsGeometry(p) == MagickFalse)
11372                 {
11373                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11374                     p);
11375                   break;
11376                 }
11377              (void) CloneString(&montage_info->geometry,p);
11378              if (*p == '\0')
11379                montage_info->geometry=(char *) NULL;
11380              break;
11381            }
11382          if (LocaleCompare(attribute,"gravity") == 0)
11383            {
11384              ssize_t
11385                in;
11386
11387              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11388                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11389              if (in < 0)
11390                {
11391                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
11392                    SvPV(ST(i),na));
11393                  return;
11394                }
11395              montage_info->gravity=(GravityType) in;
11396              for (next=image; next; next=next->next)
11397                next->gravity=(GravityType) in;
11398              break;
11399            }
11400           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11401             attribute);
11402           break;
11403         }
11404         case 'L':
11405         case 'l':
11406         {
11407           if (LocaleCompare(attribute,"label") == 0)
11408             {
11409               for (next=image; next; next=next->next)
11410                 (void) SetImageProperty(next,"label",InterpretImageProperties(
11411                   info ? info->image_info : (ImageInfo *) NULL,next,
11412                   SvPV(ST(i),na),exception),exception);
11413               break;
11414             }
11415           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11416             attribute);
11417           break;
11418         }
11419         case 'M':
11420         case 'm':
11421         {
11422           if (LocaleCompare(attribute,"mattecolor") == 0)
11423             {
11424               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11425                 &montage_info->matte_color,exception);
11426               for (next=image; next; next=next->next)
11427                 next->matte_color=montage_info->matte_color;
11428               break;
11429             }
11430           if (LocaleCompare(attribute,"mode") == 0)
11431             {
11432               ssize_t
11433                 in;
11434
11435               in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11436                 MagickModeOptions,MagickFalse,SvPV(ST(i),na));
11437               switch (in)
11438               {
11439                 default:
11440                 {
11441                   ThrowPerlException(exception,OptionError,
11442                     "UnrecognizedModeType",SvPV(ST(i),na));
11443                   break;
11444                 }
11445                 case FrameMode:
11446                 {
11447                   (void) CloneString(&montage_info->frame,"15x15+3+3");
11448                   montage_info->shadow=MagickTrue;
11449                   break;
11450                 }
11451                 case UnframeMode:
11452                 {
11453                   montage_info->frame=(char *) NULL;
11454                   montage_info->shadow=MagickFalse;
11455                   montage_info->border_width=0;
11456                   break;
11457                 }
11458                 case ConcatenateMode:
11459                 {
11460                   montage_info->frame=(char *) NULL;
11461                   montage_info->shadow=MagickFalse;
11462                   (void) CloneString(&montage_info->geometry,"+0+0");
11463                   montage_info->border_width=0;
11464                 }
11465               }
11466               break;
11467             }
11468           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11469             attribute);
11470           break;
11471         }
11472         case 'P':
11473         case 'p':
11474         {
11475           if (LocaleCompare(attribute,"pointsize") == 0)
11476             {
11477               montage_info->pointsize=SvIV(ST(i));
11478               break;
11479             }
11480           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11481             attribute);
11482           break;
11483         }
11484         case 'S':
11485         case 's':
11486         {
11487           if (LocaleCompare(attribute,"shadow") == 0)
11488             {
11489               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11490                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11491               if (sp < 0)
11492                 {
11493                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11494                     SvPV(ST(i),na));
11495                   break;
11496                 }
11497              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11498              break;
11499             }
11500           if (LocaleCompare(attribute,"stroke") == 0)
11501             {
11502               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11503                 &montage_info->stroke,exception);
11504               break;
11505             }
11506           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11507             attribute);
11508           break;
11509         }
11510         case 'T':
11511         case 't':
11512         {
11513           if (LocaleCompare(attribute,"texture") == 0)
11514             {
11515               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11516               break;
11517             }
11518           if (LocaleCompare(attribute,"tile") == 0)
11519             {
11520               char *p=SvPV(ST(i),na);
11521               if (IsGeometry(p) == MagickFalse)
11522                 {
11523                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11524                     p);
11525                   break;
11526                 }
11527               (void) CloneString(&montage_info->tile,p);
11528               if (*p == '\0')
11529                 montage_info->tile=(char *) NULL;
11530               break;
11531             }
11532           if (LocaleCompare(attribute,"title") == 0)
11533             {
11534               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11535               break;
11536             }
11537           if (LocaleCompare(attribute,"transparent") == 0)
11538             {
11539               PixelInfo
11540                 transparent_color;
11541
11542               QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11543                 &transparent_color,exception);
11544               for (next=image; next; next=next->next)
11545                 (void) TransparentPaintImage(next,&transparent_color,
11546                   TransparentAlpha,MagickFalse,exception);
11547               break;
11548             }
11549           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11550             attribute);
11551           break;
11552         }
11553         default:
11554         {
11555           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11556             attribute);
11557           break;
11558         }
11559       }
11560     }
11561     image=MontageImageList(info->image_info,montage_info,image,exception);
11562     montage_info=DestroyMontageInfo(montage_info);
11563     if (image == (Image *) NULL)
11564       goto PerlException;
11565     if (transparent_color.alpha != TransparentAlpha)
11566       for (next=image; next; next=next->next)
11567         (void) TransparentPaintImage(next,&transparent_color,
11568           TransparentAlpha,MagickFalse,exception);
11569     for (  ; image; image=image->next)
11570     {
11571       AddImageToRegistry(sv,image);
11572       rv=newRV(sv);
11573       av_push(av,sv_bless(rv,hv));
11574       SvREFCNT_dec(sv);
11575     }
11576     exception=DestroyExceptionInfo(exception);
11577     ST(0)=av_reference;
11578     SvREFCNT_dec(perl_exception);
11579     XSRETURN(1);
11580
11581   PerlException:
11582     InheritPerlException(exception,perl_exception);
11583     exception=DestroyExceptionInfo(exception);
11584     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11585     SvPOK_on(perl_exception);
11586     ST(0)=sv_2mortal(perl_exception);
11587     XSRETURN(1);
11588   }
11589 \f
11590 #
11591 ###############################################################################
11592 #                                                                             #
11593 #                                                                             #
11594 #                                                                             #
11595 #   M o r p h                                                                 #
11596 #                                                                             #
11597 #                                                                             #
11598 #                                                                             #
11599 ###############################################################################
11600 #
11601 #
11602 void
11603 Morph(ref,...)
11604   Image::Magick ref=NO_INIT
11605   ALIAS:
11606     MorphImage  = 1
11607     morph       = 2
11608     morphimage  = 3
11609   PPCODE:
11610   {
11611     AV
11612       *av;
11613
11614     char
11615       *attribute;
11616
11617     ExceptionInfo
11618       *exception;
11619
11620     HV
11621       *hv;
11622
11623     Image
11624       *image;
11625
11626     register ssize_t
11627       i;
11628
11629     ssize_t
11630       number_frames;
11631
11632     struct PackageInfo
11633       *info;
11634
11635     SV
11636       *av_reference,
11637       *perl_exception,
11638       *reference,
11639       *rv,
11640       *sv;
11641
11642     PERL_UNUSED_VAR(ref);
11643     PERL_UNUSED_VAR(ix);
11644     exception=AcquireExceptionInfo();
11645     perl_exception=newSVpv("",0);
11646     sv=NULL;
11647     av=NULL;
11648     attribute=NULL;
11649     if (sv_isobject(ST(0)) == 0)
11650       {
11651         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11652           PackageName);
11653         goto PerlException;
11654       }
11655     reference=SvRV(ST(0));
11656     hv=SvSTASH(reference);
11657     av=newAV();
11658     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11659     SvREFCNT_dec(av);
11660     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11661     if (image == (Image *) NULL)
11662       {
11663         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11664           PackageName);
11665         goto PerlException;
11666       }
11667     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11668     /*
11669       Get attribute.
11670     */
11671     number_frames=30;
11672     for (i=2; i < items; i+=2)
11673     {
11674       attribute=(char *) SvPV(ST(i-1),na);
11675       switch (*attribute)
11676       {
11677         case 'F':
11678         case 'f':
11679         {
11680           if (LocaleCompare(attribute,"frames") == 0)
11681             {
11682               number_frames=SvIV(ST(i));
11683               break;
11684             }
11685           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11686             attribute);
11687           break;
11688         }
11689         default:
11690         {
11691           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11692             attribute);
11693           break;
11694         }
11695       }
11696     }
11697     image=MorphImages(image,number_frames,exception);
11698     if (image == (Image *) NULL)
11699       goto PerlException;
11700     for ( ; image; image=image->next)
11701     {
11702       AddImageToRegistry(sv,image);
11703       rv=newRV(sv);
11704       av_push(av,sv_bless(rv,hv));
11705       SvREFCNT_dec(sv);
11706     }
11707     exception=DestroyExceptionInfo(exception);
11708     ST(0)=av_reference;
11709     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11710     XSRETURN(1);
11711
11712   PerlException:
11713     InheritPerlException(exception,perl_exception);
11714     exception=DestroyExceptionInfo(exception);
11715     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11716     SvPOK_on(perl_exception);
11717     ST(0)=sv_2mortal(perl_exception);
11718     XSRETURN(1);
11719   }
11720 \f
11721 #
11722 ###############################################################################
11723 #                                                                             #
11724 #                                                                             #
11725 #                                                                             #
11726 #   M o s a i c                                                               #
11727 #                                                                             #
11728 #                                                                             #
11729 #                                                                             #
11730 ###############################################################################
11731 #
11732 #
11733 void
11734 Mosaic(ref)
11735   Image::Magick ref=NO_INIT
11736   ALIAS:
11737     MosaicImage   = 1
11738     mosaic        = 2
11739     mosaicimage   = 3
11740   PPCODE:
11741   {
11742     AV
11743       *av;
11744
11745     ExceptionInfo
11746       *exception;
11747
11748     HV
11749       *hv;
11750
11751     Image
11752       *image;
11753
11754     struct PackageInfo
11755       *info;
11756
11757     SV
11758       *perl_exception,
11759       *reference,
11760       *rv,
11761       *sv;
11762
11763     PERL_UNUSED_VAR(ref);
11764     PERL_UNUSED_VAR(ix);
11765     exception=AcquireExceptionInfo();
11766     perl_exception=newSVpv("",0);
11767     sv=NULL;
11768     if (sv_isobject(ST(0)) == 0)
11769       {
11770         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11771           PackageName);
11772         goto PerlException;
11773       }
11774     reference=SvRV(ST(0));
11775     hv=SvSTASH(reference);
11776     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11777     if (image == (Image *) NULL)
11778       {
11779         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11780           PackageName);
11781         goto PerlException;
11782       }
11783     image=MergeImageLayers(image,MosaicLayer,exception);
11784     /*
11785       Create blessed Perl array for the returned image.
11786     */
11787     av=newAV();
11788     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11789     SvREFCNT_dec(av);
11790     AddImageToRegistry(sv,image);
11791     rv=newRV(sv);
11792     av_push(av,sv_bless(rv,hv));
11793     SvREFCNT_dec(sv);
11794     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11795     (void) CopyMagickString(info->image_info->filename,image->filename,
11796       MaxTextExtent);
11797     SetImageInfo(info->image_info,0,exception);
11798     exception=DestroyExceptionInfo(exception);
11799     SvREFCNT_dec(perl_exception);
11800     XSRETURN(1);
11801
11802   PerlException:
11803     InheritPerlException(exception,perl_exception);
11804     exception=DestroyExceptionInfo(exception);
11805     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11806     SvPOK_on(perl_exception);  /* return messages in string context */
11807     ST(0)=sv_2mortal(perl_exception);
11808     XSRETURN(1);
11809   }
11810 \f
11811 #
11812 ###############################################################################
11813 #                                                                             #
11814 #                                                                             #
11815 #                                                                             #
11816 #   P i n g                                                                   #
11817 #                                                                             #
11818 #                                                                             #
11819 #                                                                             #
11820 ###############################################################################
11821 #
11822 #
11823 void
11824 Ping(ref,...)
11825   Image::Magick ref=NO_INIT
11826   ALIAS:
11827     PingImage  = 1
11828     ping       = 2
11829     pingimage  = 3
11830   PPCODE:
11831   {
11832     AV
11833       *av;
11834
11835     char
11836       **keep,
11837       **list;
11838
11839     ExceptionInfo
11840       *exception;
11841
11842     Image
11843       *image,
11844       *next;
11845
11846     int
11847       n;
11848
11849     MagickBooleanType
11850       status;
11851
11852     register char
11853       **p;
11854
11855     register ssize_t
11856       i;
11857
11858     ssize_t
11859       ac;
11860
11861     STRLEN
11862       *length;
11863
11864     struct PackageInfo
11865       *info,
11866       *package_info;
11867
11868     SV
11869       *perl_exception,
11870       *reference;
11871
11872     size_t
11873       count;
11874
11875     PERL_UNUSED_VAR(ref);
11876     PERL_UNUSED_VAR(ix);
11877     exception=AcquireExceptionInfo();
11878     perl_exception=newSVpv("",0);
11879     package_info=(struct PackageInfo *) NULL;
11880     ac=(items < 2) ? 1 : items-1;
11881     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
11882     keep=list;
11883     length=(STRLEN *) NULL;
11884     if (list == (char **) NULL)
11885       {
11886         ThrowPerlException(exception,ResourceLimitError,
11887           "MemoryAllocationFailed",PackageName);
11888         goto PerlException;
11889       }
11890     keep=list;
11891     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
11892     if (length == (STRLEN *) NULL)
11893       {
11894         ThrowPerlException(exception,ResourceLimitError,
11895           "MemoryAllocationFailed",PackageName);
11896         goto PerlException;
11897       }
11898     if (sv_isobject(ST(0)) == 0)
11899       {
11900         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11901           PackageName);
11902         goto PerlException;
11903       }
11904     reference=SvRV(ST(0));
11905     if (SvTYPE(reference) != SVt_PVAV)
11906       {
11907         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11908           PackageName);
11909         goto PerlException;
11910       }
11911     av=(AV *) reference;
11912     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11913       exception);
11914     package_info=ClonePackageInfo(info,exception);
11915     n=1;
11916     if (items <= 1)
11917       *list=(char *) (*package_info->image_info->filename ?
11918         package_info->image_info->filename : "XC:black");
11919     else
11920       for (n=0, i=0; i < ac; i++)
11921       {
11922         list[n]=(char *) SvPV(ST(i+1),length[n]);
11923         if ((items >= 3) && strEQcase(list[n],"blob"))
11924           {
11925             void
11926               *blob;
11927
11928             i++;
11929             blob=(void *) (SvPV(ST(i+1),length[n]));
11930             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
11931           }
11932         if ((items >= 3) && strEQcase(list[n],"filename"))
11933           continue;
11934         if ((items >= 3) && strEQcase(list[n],"file"))
11935           {
11936             FILE
11937               *file;
11938
11939             PerlIO
11940               *io_info;
11941
11942             i++;
11943             io_info=IoIFP(sv_2io(ST(i+1)));
11944             if (io_info == (PerlIO *) NULL)
11945               {
11946                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11947                   PackageName);
11948                 continue;
11949               }
11950             file=PerlIO_findFILE(io_info);
11951             if (file == (FILE *) NULL)
11952               {
11953                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11954                   PackageName);
11955                 continue;
11956               }
11957             SetImageInfoFile(package_info->image_info,file);
11958           }
11959         if ((items >= 3) && strEQcase(list[n],"magick"))
11960           continue;
11961         n++;
11962       }
11963     list[n]=(char *) NULL;
11964     keep=list;
11965     status=ExpandFilenames(&n,&list);
11966     if (status == MagickFalse)
11967       {
11968         ThrowPerlException(exception,ResourceLimitError,
11969           "MemoryAllocationFailed",PackageName);
11970         goto PerlException;
11971       }
11972     count=0;
11973     for (i=0; i < n; i++)
11974     {
11975       (void) CopyMagickString(package_info->image_info->filename,list[i],
11976         MaxTextExtent);
11977       image=PingImage(package_info->image_info,exception);
11978       if (image == (Image *) NULL)
11979         break;
11980       if ((package_info->image_info->file != (FILE *) NULL) ||
11981           (package_info->image_info->blob != (void *) NULL))
11982         DisassociateImageStream(image);
11983       count+=GetImageListLength(image);
11984       EXTEND(sp,4*count);
11985       for (next=image; next; next=next->next)
11986       {
11987         PUSHs(sv_2mortal(newSViv(next->columns)));
11988         PUSHs(sv_2mortal(newSViv(next->rows)));
11989         PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
11990         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
11991       }
11992       image=DestroyImageList(image);
11993     }
11994     /*
11995       Free resources.
11996     */
11997     for (i=0; i < n; i++)
11998       if (list[i] != (char *) NULL)
11999         for (p=keep; list[i] != *p++; )
12000           if (*p == NULL)
12001             {
12002               list[i]=(char *) RelinquishMagickMemory(list[i]);
12003               break;
12004             }
12005
12006   PerlException:
12007     if (package_info != (struct PackageInfo *) NULL)
12008       DestroyPackageInfo(package_info);
12009     if (list && (list != keep))
12010       list=(char **) RelinquishMagickMemory(list);
12011     if (keep)
12012       keep=(char **) RelinquishMagickMemory(keep);
12013     if (length)
12014       length=(STRLEN *) RelinquishMagickMemory(length);
12015     InheritPerlException(exception,perl_exception);
12016     exception=DestroyExceptionInfo(exception);
12017     SvREFCNT_dec(perl_exception);  /* throw away all errors */
12018   }
12019 \f
12020 #
12021 ###############################################################################
12022 #                                                                             #
12023 #                                                                             #
12024 #                                                                             #
12025 #   P r e v i e w                                                             #
12026 #                                                                             #
12027 #                                                                             #
12028 #                                                                             #
12029 ###############################################################################
12030 #
12031 #
12032 void
12033 Preview(ref,...)
12034   Image::Magick ref=NO_INIT
12035   ALIAS:
12036     PreviewImage = 1
12037     preview      = 2
12038     previewimage = 3
12039   PPCODE:
12040   {
12041     AV
12042       *av;
12043
12044     ExceptionInfo
12045       *exception;
12046
12047     HV
12048       *hv;
12049
12050     Image
12051       *image,
12052       *preview_image;
12053
12054     PreviewType
12055       preview_type;
12056
12057     struct PackageInfo
12058       *info;
12059
12060     SV
12061       *av_reference,
12062       *perl_exception,
12063       *reference,
12064       *rv,
12065       *sv;
12066
12067     PERL_UNUSED_VAR(ref);
12068     PERL_UNUSED_VAR(ix);
12069     exception=AcquireExceptionInfo();
12070     perl_exception=newSVpv("",0);
12071     sv=NULL;
12072     av=NULL;
12073     if (sv_isobject(ST(0)) == 0)
12074       {
12075         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12076           PackageName);
12077         goto PerlException;
12078       }
12079     reference=SvRV(ST(0));
12080     hv=SvSTASH(reference);
12081     av=newAV();
12082     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12083     SvREFCNT_dec(av);
12084     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12085     if (image == (Image *) NULL)
12086       {
12087         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12088           PackageName);
12089         goto PerlException;
12090       }
12091     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
12092     preview_type=GammaPreview;
12093     if (items > 1)
12094       preview_type=(PreviewType)
12095         ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
12096     for ( ; image; image=image->next)
12097     {
12098       preview_image=PreviewImage(image,preview_type,exception);
12099       if (preview_image == (Image *) NULL)
12100         goto PerlException;
12101       AddImageToRegistry(sv,preview_image);
12102       rv=newRV(sv);
12103       av_push(av,sv_bless(rv,hv));
12104       SvREFCNT_dec(sv);
12105     }
12106     exception=DestroyExceptionInfo(exception);
12107     ST(0)=av_reference;
12108     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12109     XSRETURN(1);
12110
12111   PerlException:
12112     InheritPerlException(exception,perl_exception);
12113     exception=DestroyExceptionInfo(exception);
12114     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12115     SvPOK_on(perl_exception);
12116     ST(0)=sv_2mortal(perl_exception);
12117     XSRETURN(1);
12118   }
12119 \f
12120 #
12121 ###############################################################################
12122 #                                                                             #
12123 #                                                                             #
12124 #                                                                             #
12125 #   Q u e r y C o l o r                                                       #
12126 #                                                                             #
12127 #                                                                             #
12128 #                                                                             #
12129 ###############################################################################
12130 #
12131 #
12132 void
12133 QueryColor(ref,...)
12134   Image::Magick ref=NO_INIT
12135   ALIAS:
12136     querycolor = 1
12137   PPCODE:
12138   {
12139     char
12140       *name;
12141
12142     ExceptionInfo
12143       *exception;
12144
12145     PixelInfo
12146       color;
12147
12148     register ssize_t
12149       i;
12150
12151     SV
12152       *perl_exception;
12153
12154     PERL_UNUSED_VAR(ref);
12155     PERL_UNUSED_VAR(ix);
12156     exception=AcquireExceptionInfo();
12157     perl_exception=newSVpv("",0);
12158     if (items == 1)
12159       {
12160         const ColorInfo
12161           **colorlist;
12162
12163         size_t
12164           colors;
12165
12166         colorlist=GetColorInfoList("*",&colors,exception);
12167         EXTEND(sp,colors);
12168         for (i=0; i < (ssize_t) colors; i++)
12169         {
12170           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
12171         }
12172         colorlist=(const ColorInfo **)
12173           RelinquishMagickMemory((ColorInfo **) colorlist);
12174         goto PerlException;
12175       }
12176     EXTEND(sp,5*items);
12177     for (i=1; i < items; i++)
12178     {
12179       name=(char *) SvPV(ST(i),na);
12180       if (QueryColorCompliance(name,AllCompliance,&color,exception) == MagickFalse)
12181         {
12182           PUSHs(&sv_undef);
12183           continue;
12184         }
12185       PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
12186       PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
12187       PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
12188       if (color.colorspace == CMYKColorspace)
12189         PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
12190       if (color.alpha_trait == BlendPixelTrait)
12191         PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
12192     }
12193
12194   PerlException:
12195     InheritPerlException(exception,perl_exception);
12196     exception=DestroyExceptionInfo(exception);
12197     SvREFCNT_dec(perl_exception);
12198   }
12199 \f
12200 #
12201 ###############################################################################
12202 #                                                                             #
12203 #                                                                             #
12204 #                                                                             #
12205 #   Q u e r y C o l o r N a m e                                               #
12206 #                                                                             #
12207 #                                                                             #
12208 #                                                                             #
12209 ###############################################################################
12210 #
12211 #
12212 void
12213 QueryColorname(ref,...)
12214   Image::Magick ref=NO_INIT
12215   ALIAS:
12216     querycolorname = 1
12217   PPCODE:
12218   {
12219     AV
12220       *av;
12221
12222     char
12223       message[MaxTextExtent];
12224
12225     ExceptionInfo
12226       *exception;
12227
12228     Image
12229       *image;
12230
12231     PixelInfo
12232       target_color;
12233
12234     register ssize_t
12235       i;
12236
12237     struct PackageInfo
12238       *info;
12239
12240     SV
12241       *perl_exception,
12242       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12243
12244     PERL_UNUSED_VAR(ref);
12245     PERL_UNUSED_VAR(ix);
12246     exception=AcquireExceptionInfo();
12247     perl_exception=newSVpv("",0);
12248     reference=SvRV(ST(0));
12249     av=(AV *) reference;
12250     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12251       exception);
12252     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12253     if (image == (Image *) NULL)
12254       {
12255         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12256           PackageName);
12257         goto PerlException;
12258       }
12259     EXTEND(sp,items);
12260     for (i=1; i < items; i++)
12261     {
12262       (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,&target_color,
12263         exception);
12264       (void) QueryColorname(image,&target_color,SVGCompliance,message,
12265         exception);
12266       PUSHs(sv_2mortal(newSVpv(message,0)));
12267     }
12268
12269   PerlException:
12270     InheritPerlException(exception,perl_exception);
12271     exception=DestroyExceptionInfo(exception);
12272     SvREFCNT_dec(perl_exception);
12273   }
12274 \f
12275 #
12276 ###############################################################################
12277 #                                                                             #
12278 #                                                                             #
12279 #                                                                             #
12280 #   Q u e r y F o n t                                                         #
12281 #                                                                             #
12282 #                                                                             #
12283 #                                                                             #
12284 ###############################################################################
12285 #
12286 #
12287 void
12288 QueryFont(ref,...)
12289   Image::Magick ref=NO_INIT
12290   ALIAS:
12291     queryfont = 1
12292   PPCODE:
12293   {
12294     char
12295       *name,
12296       message[MaxTextExtent];
12297
12298     ExceptionInfo
12299       *exception;
12300
12301     register ssize_t
12302       i;
12303
12304     SV
12305       *perl_exception;
12306
12307     volatile const TypeInfo
12308       *type_info;
12309
12310     PERL_UNUSED_VAR(ref);
12311     PERL_UNUSED_VAR(ix);
12312     exception=AcquireExceptionInfo();
12313     perl_exception=newSVpv("",0);
12314     if (items == 1)
12315       {
12316         const TypeInfo
12317           **typelist;
12318
12319         size_t
12320           types;
12321
12322         typelist=GetTypeInfoList("*",&types,exception);
12323         EXTEND(sp,types);
12324         for (i=0; i < (ssize_t) types; i++)
12325         {
12326           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
12327         }
12328         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
12329           typelist);
12330         goto PerlException;
12331       }
12332     EXTEND(sp,10*items);
12333     for (i=1; i < items; i++)
12334     {
12335       name=(char *) SvPV(ST(i),na);
12336       type_info=GetTypeInfo(name,exception);
12337       if (type_info == (TypeInfo *) NULL)
12338         {
12339           PUSHs(&sv_undef);
12340           continue;
12341         }
12342       if (type_info->name == (char *) NULL)
12343         PUSHs(&sv_undef);
12344       else
12345         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
12346       if (type_info->description == (char *) NULL)
12347         PUSHs(&sv_undef);
12348       else
12349         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
12350       if (type_info->family == (char *) NULL)
12351         PUSHs(&sv_undef);
12352       else
12353         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
12354       if (type_info->style == UndefinedStyle)
12355         PUSHs(&sv_undef);
12356       else
12357         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
12358           type_info->style),0)));
12359       if (type_info->stretch == UndefinedStretch)
12360         PUSHs(&sv_undef);
12361       else
12362         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
12363           type_info->stretch),0)));
12364       (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
12365         type_info->weight);
12366       PUSHs(sv_2mortal(newSVpv(message,0)));
12367       if (type_info->encoding == (char *) NULL)
12368         PUSHs(&sv_undef);
12369       else
12370         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
12371       if (type_info->foundry == (char *) NULL)
12372         PUSHs(&sv_undef);
12373       else
12374         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
12375       if (type_info->format == (char *) NULL)
12376         PUSHs(&sv_undef);
12377       else
12378         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
12379       if (type_info->metrics == (char *) NULL)
12380         PUSHs(&sv_undef);
12381       else
12382         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
12383       if (type_info->glyphs == (char *) NULL)
12384         PUSHs(&sv_undef);
12385       else
12386         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
12387     }
12388
12389   PerlException:
12390     InheritPerlException(exception,perl_exception);
12391     exception=DestroyExceptionInfo(exception);
12392     SvREFCNT_dec(perl_exception);
12393   }
12394 \f
12395 #
12396 ###############################################################################
12397 #                                                                             #
12398 #                                                                             #
12399 #                                                                             #
12400 #   Q u e r y F o n t M e t r i c s                                           #
12401 #                                                                             #
12402 #                                                                             #
12403 #                                                                             #
12404 ###############################################################################
12405 #
12406 #
12407 void
12408 QueryFontMetrics(ref,...)
12409   Image::Magick ref=NO_INIT
12410   ALIAS:
12411     queryfontmetrics = 1
12412   PPCODE:
12413   {
12414     AffineMatrix
12415       affine,
12416       current;
12417
12418     AV
12419       *av;
12420
12421     char
12422       *attribute;
12423
12424     double
12425       x,
12426       y;
12427
12428     DrawInfo
12429       *draw_info;
12430
12431     ExceptionInfo
12432       *exception;
12433
12434     GeometryInfo
12435       geometry_info;
12436
12437     Image
12438       *image;
12439
12440     MagickBooleanType
12441       status;
12442
12443     MagickStatusType
12444       flags;
12445
12446     register ssize_t
12447       i;
12448
12449     ssize_t
12450       type;
12451
12452     struct PackageInfo
12453       *info,
12454       *package_info;
12455
12456     SV
12457       *perl_exception,
12458       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12459
12460     TypeMetric
12461       metrics;
12462
12463     PERL_UNUSED_VAR(ref);
12464     PERL_UNUSED_VAR(ix);
12465     exception=AcquireExceptionInfo();
12466     package_info=(struct PackageInfo *) NULL;
12467     perl_exception=newSVpv("",0);
12468     reference=SvRV(ST(0));
12469     av=(AV *) reference;
12470     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12471       exception);
12472     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12473     if (image == (Image *) NULL)
12474       {
12475         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12476           PackageName);
12477         goto PerlException;
12478       }
12479     package_info=ClonePackageInfo(info,exception);
12480     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12481     CloneString(&draw_info->text,"");
12482     current=draw_info->affine;
12483     GetAffineMatrix(&affine);
12484     x=0.0;
12485     y=0.0;
12486     EXTEND(sp,7*items);
12487     for (i=2; i < items; i+=2)
12488     {
12489       attribute=(char *) SvPV(ST(i-1),na);
12490       switch (*attribute)
12491       {
12492         case 'A':
12493         case 'a':
12494         {
12495           if (LocaleCompare(attribute,"antialias") == 0)
12496             {
12497               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12498                 SvPV(ST(i),na));
12499               if (type < 0)
12500                 {
12501                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12502                     SvPV(ST(i),na));
12503                   break;
12504                 }
12505               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12506               break;
12507             }
12508           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12509             attribute);
12510           break;
12511         }
12512         case 'd':
12513         case 'D':
12514         {
12515           if (LocaleCompare(attribute,"density") == 0)
12516             {
12517               CloneString(&draw_info->density,SvPV(ST(i),na));
12518               break;
12519             }
12520           if (LocaleCompare(attribute,"direction") == 0)
12521             {
12522               draw_info->direction=(DirectionType) ParseCommandOption(
12523                 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12524               break;
12525             }
12526           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12527             attribute);
12528           break;
12529         }
12530         case 'e':
12531         case 'E':
12532         {
12533           if (LocaleCompare(attribute,"encoding") == 0)
12534             {
12535               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12536               break;
12537             }
12538           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12539             attribute);
12540           break;
12541         }
12542         case 'f':
12543         case 'F':
12544         {
12545           if (LocaleCompare(attribute,"family") == 0)
12546             {
12547               CloneString(&draw_info->family,SvPV(ST(i),na));
12548               break;
12549             }
12550           if (LocaleCompare(attribute,"fill") == 0)
12551             {
12552               if (info)
12553                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12554                   &draw_info->fill,exception);
12555               break;
12556             }
12557           if (LocaleCompare(attribute,"font") == 0)
12558             {
12559               CloneString(&draw_info->font,SvPV(ST(i),na));
12560               break;
12561             }
12562           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12563             attribute);
12564           break;
12565         }
12566         case 'g':
12567         case 'G':
12568         {
12569           if (LocaleCompare(attribute,"geometry") == 0)
12570             {
12571               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12572               break;
12573             }
12574           if (LocaleCompare(attribute,"gravity") == 0)
12575             {
12576               draw_info->gravity=(GravityType) ParseCommandOption(
12577                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12578               break;
12579             }
12580           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12581             attribute);
12582           break;
12583         }
12584         case 'i':
12585         case 'I':
12586         {
12587           if (LocaleCompare(attribute,"interline-spacing") == 0)
12588             {
12589               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12590               draw_info->interline_spacing=geometry_info.rho;
12591               break;
12592             }
12593           if (LocaleCompare(attribute,"interword-spacing") == 0)
12594             {
12595               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12596               draw_info->interword_spacing=geometry_info.rho;
12597               break;
12598             }
12599           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12600             attribute);
12601           break;
12602         }
12603         case 'k':
12604         case 'K':
12605         {
12606           if (LocaleCompare(attribute,"kerning") == 0)
12607             {
12608               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12609               draw_info->kerning=geometry_info.rho;
12610               break;
12611             }
12612           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12613             attribute);
12614           break;
12615         }
12616         case 'p':
12617         case 'P':
12618         {
12619           if (LocaleCompare(attribute,"pointsize") == 0)
12620             {
12621               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12622               draw_info->pointsize=geometry_info.rho;
12623               break;
12624             }
12625           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12626             attribute);
12627           break;
12628         }
12629         case 'r':
12630         case 'R':
12631         {
12632           if (LocaleCompare(attribute,"rotate") == 0)
12633             {
12634               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12635               affine.rx=geometry_info.rho;
12636               affine.ry=geometry_info.sigma;
12637               if ((flags & SigmaValue) == 0)
12638                 affine.ry=affine.rx;
12639               break;
12640             }
12641           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12642             attribute);
12643           break;
12644         }
12645         case 's':
12646         case 'S':
12647         {
12648           if (LocaleCompare(attribute,"scale") == 0)
12649             {
12650               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12651               affine.sx=geometry_info.rho;
12652               affine.sy=geometry_info.sigma;
12653               if ((flags & SigmaValue) == 0)
12654                 affine.sy=affine.sx;
12655               break;
12656             }
12657           if (LocaleCompare(attribute,"skew") == 0)
12658             {
12659               double
12660                 x_angle,
12661                 y_angle;
12662
12663               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12664               x_angle=geometry_info.rho;
12665               y_angle=geometry_info.sigma;
12666               if ((flags & SigmaValue) == 0)
12667                 y_angle=x_angle;
12668               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12669               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12670               break;
12671             }
12672           if (LocaleCompare(attribute,"stroke") == 0)
12673             {
12674               if (info)
12675                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12676                   &draw_info->stroke,exception);
12677               break;
12678             }
12679           if (LocaleCompare(attribute,"style") == 0)
12680             {
12681               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12682                 SvPV(ST(i),na));
12683               if (type < 0)
12684                 {
12685                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12686                     SvPV(ST(i),na));
12687                   break;
12688                 }
12689               draw_info->style=(StyleType) type;
12690               break;
12691             }
12692           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12693             attribute);
12694           break;
12695         }
12696         case 't':
12697         case 'T':
12698         {
12699           if (LocaleCompare(attribute,"text") == 0)
12700             {
12701               CloneString(&draw_info->text,SvPV(ST(i),na));
12702               break;
12703             }
12704           if (LocaleCompare(attribute,"translate") == 0)
12705             {
12706               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12707               affine.tx=geometry_info.rho;
12708               affine.ty=geometry_info.sigma;
12709               if ((flags & SigmaValue) == 0)
12710                 affine.ty=affine.tx;
12711               break;
12712             }
12713           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12714             attribute);
12715           break;
12716         }
12717         case 'w':
12718         case 'W':
12719         {
12720           if (LocaleCompare(attribute,"weight") == 0)
12721             {
12722               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12723               draw_info->weight=(size_t) geometry_info.rho;
12724               break;
12725             }
12726           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12727             attribute);
12728           break;
12729         }
12730         case 'x':
12731         case 'X':
12732         {
12733           if (LocaleCompare(attribute,"x") == 0)
12734             {
12735               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12736               x=geometry_info.rho;
12737               break;
12738             }
12739           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12740             attribute);
12741           break;
12742         }
12743         case 'y':
12744         case 'Y':
12745         {
12746           if (LocaleCompare(attribute,"y") == 0)
12747             {
12748               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12749               y=geometry_info.rho;
12750               break;
12751             }
12752           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12753             attribute);
12754           break;
12755         }
12756         default:
12757         {
12758           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12759             attribute);
12760           break;
12761         }
12762       }
12763     }
12764     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12765     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12766     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12767     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12768     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12769     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12770     if (draw_info->geometry == (char *) NULL)
12771       {
12772         draw_info->geometry=AcquireString((char *) NULL);
12773         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12774           "%.15g,%.15g",x,y);
12775       }
12776     status=GetTypeMetrics(image,draw_info,&metrics,exception);
12777     (void) CatchImageException(image);
12778     if (status == MagickFalse)
12779       PUSHs(&sv_undef);
12780     else
12781       {
12782         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12783         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12784         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12785         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12786         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12787         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12788         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12789         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12790         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12791         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12792         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12793         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12794         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12795       }
12796     draw_info=DestroyDrawInfo(draw_info);
12797
12798   PerlException:
12799     if (package_info != (struct PackageInfo *) NULL)
12800       DestroyPackageInfo(package_info);
12801     InheritPerlException(exception,perl_exception);
12802     exception=DestroyExceptionInfo(exception);
12803     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12804   }
12805 \f
12806 #
12807 ###############################################################################
12808 #                                                                             #
12809 #                                                                             #
12810 #                                                                             #
12811 #   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                         #
12812 #                                                                             #
12813 #                                                                             #
12814 #                                                                             #
12815 ###############################################################################
12816 #
12817 #
12818 void
12819 QueryMultilineFontMetrics(ref,...)
12820   Image::Magick ref=NO_INIT
12821   ALIAS:
12822     querymultilinefontmetrics = 1
12823   PPCODE:
12824   {
12825     AffineMatrix
12826       affine,
12827       current;
12828
12829     AV
12830       *av;
12831
12832     char
12833       *attribute;
12834
12835     double
12836       x,
12837       y;
12838
12839     DrawInfo
12840       *draw_info;
12841
12842     ExceptionInfo
12843       *exception;
12844
12845     GeometryInfo
12846       geometry_info;
12847
12848     Image
12849       *image;
12850
12851     MagickBooleanType
12852       status;
12853
12854     MagickStatusType
12855       flags;
12856
12857     register ssize_t
12858       i;
12859
12860     ssize_t
12861       type;
12862
12863     struct PackageInfo
12864       *info,
12865       *package_info;
12866
12867     SV
12868       *perl_exception,
12869       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12870
12871     TypeMetric
12872       metrics;
12873
12874     PERL_UNUSED_VAR(ref);
12875     PERL_UNUSED_VAR(ix);
12876     exception=AcquireExceptionInfo();
12877     package_info=(struct PackageInfo *) NULL;
12878     perl_exception=newSVpv("",0);
12879     reference=SvRV(ST(0));
12880     av=(AV *) reference;
12881     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12882       exception);
12883     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12884     if (image == (Image *) NULL)
12885       {
12886         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12887           PackageName);
12888         goto PerlException;
12889       }
12890     package_info=ClonePackageInfo(info,exception);
12891     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12892     CloneString(&draw_info->text,"");
12893     current=draw_info->affine;
12894     GetAffineMatrix(&affine);
12895     x=0.0;
12896     y=0.0;
12897     EXTEND(sp,7*items);
12898     for (i=2; i < items; i+=2)
12899     {
12900       attribute=(char *) SvPV(ST(i-1),na);
12901       switch (*attribute)
12902       {
12903         case 'A':
12904         case 'a':
12905         {
12906           if (LocaleCompare(attribute,"antialias") == 0)
12907             {
12908               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12909                 SvPV(ST(i),na));
12910               if (type < 0)
12911                 {
12912                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12913                     SvPV(ST(i),na));
12914                   break;
12915                 }
12916               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12917               break;
12918             }
12919           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12920             attribute);
12921           break;
12922         }
12923         case 'd':
12924         case 'D':
12925         {
12926           if (LocaleCompare(attribute,"density") == 0)
12927             {
12928               CloneString(&draw_info->density,SvPV(ST(i),na));
12929               break;
12930             }
12931           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12932             attribute);
12933           break;
12934         }
12935         case 'e':
12936         case 'E':
12937         {
12938           if (LocaleCompare(attribute,"encoding") == 0)
12939             {
12940               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12941               break;
12942             }
12943           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12944             attribute);
12945           break;
12946         }
12947         case 'f':
12948         case 'F':
12949         {
12950           if (LocaleCompare(attribute,"family") == 0)
12951             {
12952               CloneString(&draw_info->family,SvPV(ST(i),na));
12953               break;
12954             }
12955           if (LocaleCompare(attribute,"fill") == 0)
12956             {
12957               if (info)
12958                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12959                   &draw_info->fill,exception);
12960               break;
12961             }
12962           if (LocaleCompare(attribute,"font") == 0)
12963             {
12964               CloneString(&draw_info->font,SvPV(ST(i),na));
12965               break;
12966             }
12967           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12968             attribute);
12969           break;
12970         }
12971         case 'g':
12972         case 'G':
12973         {
12974           if (LocaleCompare(attribute,"geometry") == 0)
12975             {
12976               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12977               break;
12978             }
12979           if (LocaleCompare(attribute,"gravity") == 0)
12980             {
12981               draw_info->gravity=(GravityType) ParseCommandOption(
12982                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12983               break;
12984             }
12985           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12986             attribute);
12987           break;
12988         }
12989         case 'p':
12990         case 'P':
12991         {
12992           if (LocaleCompare(attribute,"pointsize") == 0)
12993             {
12994               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12995               draw_info->pointsize=geometry_info.rho;
12996               break;
12997             }
12998           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12999             attribute);
13000           break;
13001         }
13002         case 'r':
13003         case 'R':
13004         {
13005           if (LocaleCompare(attribute,"rotate") == 0)
13006             {
13007               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13008               affine.rx=geometry_info.rho;
13009               affine.ry=geometry_info.sigma;
13010               if ((flags & SigmaValue) == 0)
13011                 affine.ry=affine.rx;
13012               break;
13013             }
13014           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13015             attribute);
13016           break;
13017         }
13018         case 's':
13019         case 'S':
13020         {
13021           if (LocaleCompare(attribute,"scale") == 0)
13022             {
13023               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13024               affine.sx=geometry_info.rho;
13025               affine.sy=geometry_info.sigma;
13026               if ((flags & SigmaValue) == 0)
13027                 affine.sy=affine.sx;
13028               break;
13029             }
13030           if (LocaleCompare(attribute,"skew") == 0)
13031             {
13032               double
13033                 x_angle,
13034                 y_angle;
13035
13036               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13037               x_angle=geometry_info.rho;
13038               y_angle=geometry_info.sigma;
13039               if ((flags & SigmaValue) == 0)
13040                 y_angle=x_angle;
13041               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
13042               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
13043               break;
13044             }
13045           if (LocaleCompare(attribute,"stroke") == 0)
13046             {
13047               if (info)
13048                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13049                   &draw_info->stroke,exception);
13050               break;
13051             }
13052           if (LocaleCompare(attribute,"style") == 0)
13053             {
13054               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
13055                 SvPV(ST(i),na));
13056               if (type < 0)
13057                 {
13058                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13059                     SvPV(ST(i),na));
13060                   break;
13061                 }
13062               draw_info->style=(StyleType) type;
13063               break;
13064             }
13065           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13066             attribute);
13067           break;
13068         }
13069         case 't':
13070         case 'T':
13071         {
13072           if (LocaleCompare(attribute,"text") == 0)
13073             {
13074               CloneString(&draw_info->text,SvPV(ST(i),na));
13075               break;
13076             }
13077           if (LocaleCompare(attribute,"translate") == 0)
13078             {
13079               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13080               affine.tx=geometry_info.rho;
13081               affine.ty=geometry_info.sigma;
13082               if ((flags & SigmaValue) == 0)
13083                 affine.ty=affine.tx;
13084               break;
13085             }
13086           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13087             attribute);
13088           break;
13089         }
13090         case 'w':
13091         case 'W':
13092         {
13093           if (LocaleCompare(attribute,"weight") == 0)
13094             {
13095               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13096               draw_info->weight=(size_t) geometry_info.rho;
13097               break;
13098             }
13099           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13100             attribute);
13101           break;
13102         }
13103         case 'x':
13104         case 'X':
13105         {
13106           if (LocaleCompare(attribute,"x") == 0)
13107             {
13108               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13109               x=geometry_info.rho;
13110               break;
13111             }
13112           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13113             attribute);
13114           break;
13115         }
13116         case 'y':
13117         case 'Y':
13118         {
13119           if (LocaleCompare(attribute,"y") == 0)
13120             {
13121               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13122               y=geometry_info.rho;
13123               break;
13124             }
13125           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13126             attribute);
13127           break;
13128         }
13129         default:
13130         {
13131           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13132             attribute);
13133           break;
13134         }
13135       }
13136     }
13137     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
13138     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
13139     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
13140     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
13141     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
13142     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
13143     if (draw_info->geometry == (char *) NULL)
13144       {
13145         draw_info->geometry=AcquireString((char *) NULL);
13146         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
13147           "%.15g,%.15g",x,y);
13148       }
13149     status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
13150     (void) CatchException(exception);
13151     if (status == MagickFalse)
13152       PUSHs(&sv_undef);
13153     else
13154       {
13155         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
13156         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
13157         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
13158         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13159         PUSHs(sv_2mortal(newSVnv(metrics.width)));
13160         PUSHs(sv_2mortal(newSVnv(metrics.height)));
13161         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13162         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13163         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13164         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13165         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13166         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13167         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13168       }
13169     draw_info=DestroyDrawInfo(draw_info);
13170
13171   PerlException:
13172     if (package_info != (struct PackageInfo *) NULL)
13173       DestroyPackageInfo(package_info);
13174     InheritPerlException(exception,perl_exception);
13175     exception=DestroyExceptionInfo(exception);
13176     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13177   }
13178 \f
13179 #
13180 ###############################################################################
13181 #                                                                             #
13182 #                                                                             #
13183 #                                                                             #
13184 #   Q u e r y F o r m a t                                                     #
13185 #                                                                             #
13186 #                                                                             #
13187 #                                                                             #
13188 ###############################################################################
13189 #
13190 #
13191 void
13192 QueryFormat(ref,...)
13193   Image::Magick ref=NO_INIT
13194   ALIAS:
13195     queryformat = 1
13196   PPCODE:
13197   {
13198     char
13199       *name;
13200
13201     ExceptionInfo
13202       *exception;
13203
13204     register ssize_t
13205       i;
13206
13207     SV
13208       *perl_exception;
13209
13210     volatile const MagickInfo
13211       *magick_info;
13212
13213     PERL_UNUSED_VAR(ref);
13214     PERL_UNUSED_VAR(ix);
13215     exception=AcquireExceptionInfo();
13216     perl_exception=newSVpv("",0);
13217     if (items == 1)
13218       {
13219         char
13220           format[MaxTextExtent];
13221
13222         const MagickInfo
13223           **format_list;
13224
13225         size_t
13226           types;
13227
13228         format_list=GetMagickInfoList("*",&types,exception);
13229         EXTEND(sp,types);
13230         for (i=0; i < (ssize_t) types; i++)
13231         {
13232           (void) CopyMagickString(format,format_list[i]->name,MaxTextExtent);
13233           LocaleLower(format);
13234           PUSHs(sv_2mortal(newSVpv(format,0)));
13235         }
13236         format_list=(const MagickInfo **)
13237           RelinquishMagickMemory((MagickInfo *) format_list);
13238         goto PerlException;
13239       }
13240     EXTEND(sp,8*items);
13241     for (i=1; i < items; i++)
13242     {
13243       name=(char *) SvPV(ST(i),na);
13244       magick_info=GetMagickInfo(name,exception);
13245       if (magick_info == (const MagickInfo *) NULL)
13246         {
13247           PUSHs(&sv_undef);
13248           continue;
13249         }
13250       PUSHs(sv_2mortal(newSViv(magick_info->adjoin)));
13251       PUSHs(sv_2mortal(newSViv(magick_info->blob_support)));
13252       PUSHs(sv_2mortal(newSViv(magick_info->raw)));
13253       PUSHs(sv_2mortal(newSViv((long) magick_info->decoder)));
13254       PUSHs(sv_2mortal(newSViv((long) magick_info->encoder)));
13255       if (magick_info->description == (char *) NULL)
13256         PUSHs(&sv_undef);
13257       else
13258         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
13259       if (magick_info->module == (char *) NULL)
13260         PUSHs(&sv_undef);
13261       else
13262         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
13263     }
13264
13265   PerlException:
13266     InheritPerlException(exception,perl_exception);
13267     exception=DestroyExceptionInfo(exception);
13268     SvREFCNT_dec(perl_exception);
13269   }
13270 \f
13271 #
13272 ###############################################################################
13273 #                                                                             #
13274 #                                                                             #
13275 #                                                                             #
13276 #   Q u e r y O p t i o n                                                     #
13277 #                                                                             #
13278 #                                                                             #
13279 #                                                                             #
13280 ###############################################################################
13281 #
13282 #
13283 void
13284 QueryOption(ref,...)
13285   Image::Magick ref=NO_INIT
13286   ALIAS:
13287     queryoption = 1
13288   PPCODE:
13289   {
13290     char
13291       **options;
13292
13293     ExceptionInfo
13294       *exception;
13295
13296     register ssize_t
13297       i;
13298
13299     ssize_t
13300       j,
13301       option;
13302
13303     SV
13304       *perl_exception;
13305
13306     PERL_UNUSED_VAR(ref);
13307     PERL_UNUSED_VAR(ix);
13308     exception=AcquireExceptionInfo();
13309     perl_exception=newSVpv("",0);
13310     EXTEND(sp,8*items);
13311     for (i=1; i < items; i++)
13312     {
13313       option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
13314         SvPV(ST(i),na));
13315       options=GetCommandOptions((CommandOption) option);
13316       if (options == (char **) NULL)
13317         PUSHs(&sv_undef);
13318       else
13319         {
13320           for (j=0; options[j] != (char *) NULL; j++)
13321             PUSHs(sv_2mortal(newSVpv(options[j],0)));
13322           options=DestroyStringList(options);
13323         }
13324     }
13325
13326     InheritPerlException(exception,perl_exception);
13327     exception=DestroyExceptionInfo(exception);
13328     SvREFCNT_dec(perl_exception);
13329   }
13330 \f
13331 #
13332 ###############################################################################
13333 #                                                                             #
13334 #                                                                             #
13335 #                                                                             #
13336 #   R e a d                                                                   #
13337 #                                                                             #
13338 #                                                                             #
13339 #                                                                             #
13340 ###############################################################################
13341 #
13342 #
13343 void
13344 Read(ref,...)
13345   Image::Magick ref=NO_INIT
13346   ALIAS:
13347     ReadImage  = 1
13348     read       = 2
13349     readimage  = 3
13350   PPCODE:
13351   {
13352     AV
13353       *av;
13354
13355     char
13356       **keep,
13357       **list;
13358
13359     ExceptionInfo
13360       *exception;
13361
13362     HV
13363       *hv;
13364
13365     Image
13366       *image;
13367
13368     int
13369       n;
13370
13371     MagickBooleanType
13372       status;
13373
13374     register char
13375       **p;
13376
13377     register ssize_t
13378       i;
13379
13380     ssize_t
13381       ac,
13382       number_images;
13383
13384     STRLEN
13385       *length;
13386
13387     struct PackageInfo
13388       *info,
13389       *package_info;
13390
13391     SV
13392       *perl_exception,  /* Perl variable for storing messages */
13393       *reference,
13394       *rv,
13395       *sv;
13396
13397     PERL_UNUSED_VAR(ref);
13398     PERL_UNUSED_VAR(ix);
13399     exception=AcquireExceptionInfo();
13400     perl_exception=newSVpv("",0);
13401     sv=NULL;
13402     package_info=(struct PackageInfo *) NULL;
13403     number_images=0;
13404     ac=(items < 2) ? 1 : items-1;
13405     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
13406     keep=list;
13407     length=(STRLEN *) NULL;
13408     if (list == (char **) NULL)
13409       {
13410         ThrowPerlException(exception,ResourceLimitError,
13411           "MemoryAllocationFailed",PackageName);
13412         goto PerlException;
13413       }
13414     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
13415     if (length == (STRLEN *) NULL)
13416       {
13417         ThrowPerlException(exception,ResourceLimitError,
13418           "MemoryAllocationFailed",PackageName);
13419         goto PerlException;
13420       }
13421     if (sv_isobject(ST(0)) == 0)
13422       {
13423         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13424           PackageName);
13425         goto PerlException;
13426       }
13427     reference=SvRV(ST(0));
13428     hv=SvSTASH(reference);
13429     if (SvTYPE(reference) != SVt_PVAV)
13430       {
13431         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13432           PackageName);
13433         goto PerlException;
13434       }
13435     av=(AV *) reference;
13436     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13437       exception);
13438     package_info=ClonePackageInfo(info,exception);
13439     n=1;
13440     if (items <= 1)
13441       *list=(char *) (*package_info->image_info->filename ?
13442         package_info->image_info->filename : "XC:black");
13443     else
13444       for (n=0, i=0; i < ac; i++)
13445       {
13446         list[n]=(char *) SvPV(ST(i+1),length[n]);
13447         if ((items >= 3) && strEQcase(list[n],"blob"))
13448           {
13449             void
13450               *blob;
13451
13452             i++;
13453             blob=(void *) (SvPV(ST(i+1),length[n]));
13454             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13455           }
13456         if ((items >= 3) && strEQcase(list[n],"filename"))
13457           continue;
13458         if ((items >= 3) && strEQcase(list[n],"file"))
13459           {
13460             FILE
13461               *file;
13462
13463             PerlIO
13464               *io_info;
13465
13466             i++;
13467             io_info=IoIFP(sv_2io(ST(i+1)));
13468             if (io_info == (PerlIO *) NULL)
13469               {
13470                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13471                   PackageName);
13472                 continue;
13473               }
13474             file=PerlIO_findFILE(io_info);
13475             if (file == (FILE *) NULL)
13476               {
13477                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13478                   PackageName);
13479                 continue;
13480               }
13481             SetImageInfoFile(package_info->image_info,file);
13482           }
13483         if ((items >= 3) && strEQcase(list[n],"magick"))
13484           continue;
13485         n++;
13486       }
13487     list[n]=(char *) NULL;
13488     keep=list;
13489     status=ExpandFilenames(&n,&list);
13490     if (status == MagickFalse)
13491       {
13492         ThrowPerlException(exception,ResourceLimitError,
13493           "MemoryAllocationFailed",PackageName);
13494         goto PerlException;
13495       }
13496     number_images=0;
13497     for (i=0; i < n; i++)
13498     {
13499       if ((package_info->image_info->file == (FILE *) NULL) &&
13500           (package_info->image_info->blob == (void *) NULL))
13501         image=ReadImages(package_info->image_info,list[i],exception);
13502       else
13503         {
13504           image=ReadImages(package_info->image_info,
13505             package_info->image_info->filename,exception);
13506           if (image != (Image *) NULL)
13507             DisassociateImageStream(image);
13508         }
13509       if (image == (Image *) NULL)
13510         break;
13511       for ( ; image; image=image->next)
13512       {
13513         AddImageToRegistry(sv,image);
13514         rv=newRV(sv);
13515         av_push(av,sv_bless(rv,hv));
13516         SvREFCNT_dec(sv);
13517         number_images++;
13518       }
13519     }
13520     /*
13521       Free resources.
13522     */
13523     for (i=0; i < n; i++)
13524       if (list[i] != (char *) NULL)
13525         for (p=keep; list[i] != *p++; )
13526           if (*p == (char *) NULL)
13527             {
13528               list[i]=(char *) RelinquishMagickMemory(list[i]);
13529               break;
13530             }
13531
13532   PerlException:
13533     if (package_info != (struct PackageInfo *) NULL)
13534       DestroyPackageInfo(package_info);
13535     if (list && (list != keep))
13536       list=(char **) RelinquishMagickMemory(list);
13537     if (keep)
13538       keep=(char **) RelinquishMagickMemory(keep);
13539     if (length)
13540       length=(STRLEN *) RelinquishMagickMemory(length);
13541     InheritPerlException(exception,perl_exception);
13542     exception=DestroyExceptionInfo(exception);
13543     sv_setiv(perl_exception,(IV) number_images);
13544     SvPOK_on(perl_exception);
13545     ST(0)=sv_2mortal(perl_exception);
13546     XSRETURN(1);
13547   }
13548 \f
13549 #
13550 ###############################################################################
13551 #                                                                             #
13552 #                                                                             #
13553 #                                                                             #
13554 #   R e m o t e                                                               #
13555 #                                                                             #
13556 #                                                                             #
13557 #                                                                             #
13558 ###############################################################################
13559 #
13560 #
13561 void
13562 Remote(ref,...)
13563   Image::Magick ref=NO_INIT
13564   ALIAS:
13565     RemoteCommand  = 1
13566     remote         = 2
13567     remoteCommand  = 3
13568   PPCODE:
13569   {
13570     AV
13571       *av;
13572
13573     ExceptionInfo
13574       *exception;
13575
13576     register ssize_t
13577       i;
13578
13579     SV
13580       *perl_exception,
13581       *reference;
13582
13583     struct PackageInfo
13584       *info;
13585
13586     PERL_UNUSED_VAR(ref);
13587     PERL_UNUSED_VAR(ix);
13588     exception=AcquireExceptionInfo();
13589     perl_exception=newSVpv("",0);
13590     reference=SvRV(ST(0));
13591     av=(AV *) reference;
13592     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13593       exception);
13594     for (i=1; i < items; i++)
13595       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13596         SvPV(ST(i),na),exception);
13597     InheritPerlException(exception,perl_exception);
13598     exception=DestroyExceptionInfo(exception);
13599     SvREFCNT_dec(perl_exception);    /* throw away all errors */
13600   }
13601 \f
13602 #
13603 ###############################################################################
13604 #                                                                             #
13605 #                                                                             #
13606 #                                                                             #
13607 #   S e t                                                                     #
13608 #                                                                             #
13609 #                                                                             #
13610 #                                                                             #
13611 ###############################################################################
13612 #
13613 #
13614 void
13615 Set(ref,...)
13616   Image::Magick ref=NO_INIT
13617   ALIAS:
13618     SetAttributes  = 1
13619     SetAttribute   = 2
13620     set            = 3
13621     setattributes  = 4
13622     setattribute   = 5
13623   PPCODE:
13624   {
13625     ExceptionInfo
13626       *exception;
13627
13628     Image
13629       *image;
13630
13631     register ssize_t
13632       i;
13633
13634     struct PackageInfo
13635       *info;
13636
13637     SV
13638       *perl_exception,
13639       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13640
13641     PERL_UNUSED_VAR(ref);
13642     PERL_UNUSED_VAR(ix);
13643     exception=AcquireExceptionInfo();
13644     perl_exception=newSVpv("",0);
13645     if (sv_isobject(ST(0)) == 0)
13646       {
13647         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13648           PackageName);
13649         goto PerlException;
13650       }
13651     reference=SvRV(ST(0));
13652     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13653     if (items == 2)
13654       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13655     else
13656       for (i=2; i < items; i+=2)
13657         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13658
13659   PerlException:
13660     InheritPerlException(exception,perl_exception);
13661     exception=DestroyExceptionInfo(exception);
13662     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13663     SvPOK_on(perl_exception);
13664     ST(0)=sv_2mortal(perl_exception);
13665     XSRETURN(1);
13666   }
13667 \f
13668 #
13669 ###############################################################################
13670 #                                                                             #
13671 #                                                                             #
13672 #                                                                             #
13673 #   S e t P i x e l                                                           #
13674 #                                                                             #
13675 #                                                                             #
13676 #                                                                             #
13677 ###############################################################################
13678 #
13679 #
13680 void
13681 SetPixel(ref,...)
13682   Image::Magick ref=NO_INIT
13683   ALIAS:
13684     setpixel = 1
13685     setPixel = 2
13686   PPCODE:
13687   {
13688     AV
13689       *av;
13690
13691     char
13692       *attribute;
13693
13694     ChannelType
13695       channel,
13696       channel_mask;
13697
13698     ExceptionInfo
13699       *exception;
13700
13701     Image
13702       *image;
13703
13704     MagickBooleanType
13705       normalize;
13706
13707     RectangleInfo
13708       region;
13709
13710     register ssize_t
13711       i;
13712
13713     register Quantum
13714       *q;
13715
13716     ssize_t
13717       option;
13718
13719     struct PackageInfo
13720       *info;
13721
13722     SV
13723       *perl_exception,
13724       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13725
13726     PERL_UNUSED_VAR(ref);
13727     PERL_UNUSED_VAR(ix);
13728     exception=AcquireExceptionInfo();
13729     perl_exception=newSVpv("",0);
13730     reference=SvRV(ST(0));
13731     av=(AV *) reference;
13732     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13733       exception);
13734     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13735     if (image == (Image *) NULL)
13736       {
13737         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13738           PackageName);
13739         goto PerlException;
13740       }
13741     av=(AV *) NULL;
13742     normalize=MagickTrue;
13743     region.x=0;
13744     region.y=0;
13745     region.width=image->columns;
13746     region.height=1;
13747     if (items == 1)
13748       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13749     channel=DefaultChannels;
13750     for (i=2; i < items; i+=2)
13751     {
13752       attribute=(char *) SvPV(ST(i-1),na);
13753       switch (*attribute)
13754       {
13755         case 'C':
13756         case 'c':
13757         {
13758           if (LocaleCompare(attribute,"channel") == 0)
13759             {
13760               ssize_t
13761                 option;
13762
13763               option=ParseChannelOption(SvPV(ST(i),na));
13764               if (option < 0)
13765                 {
13766                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13767                     SvPV(ST(i),na));
13768                   return;
13769                 }
13770               channel=(ChannelType) option;
13771               break;
13772             }
13773           if (LocaleCompare(attribute,"color") == 0)
13774             {
13775               if (SvTYPE(ST(i)) != SVt_RV)
13776                 {
13777                   char
13778                     message[MaxTextExtent];
13779
13780                   (void) FormatLocaleString(message,MaxTextExtent,
13781                     "invalid %.60s value",attribute);
13782                   ThrowPerlException(exception,OptionError,message,
13783                     SvPV(ST(i),na));
13784                 }
13785               av=(AV *) SvRV(ST(i));
13786               break;
13787             }
13788           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13789             attribute);
13790           break;
13791         }
13792         case 'g':
13793         case 'G':
13794         {
13795           if (LocaleCompare(attribute,"geometry") == 0)
13796             {
13797               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
13798               break;
13799             }
13800           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13801             attribute);
13802           break;
13803         }
13804         case 'N':
13805         case 'n':
13806         {
13807           if (LocaleCompare(attribute,"normalize") == 0)
13808             {
13809               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13810                 SvPV(ST(i),na));
13811               if (option < 0)
13812                 {
13813                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13814                     SvPV(ST(i),na));
13815                   break;
13816                 }
13817              normalize=option != 0 ? MagickTrue : MagickFalse;
13818              break;
13819             }
13820           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13821             attribute);
13822           break;
13823         }
13824         case 'x':
13825         case 'X':
13826         {
13827           if (LocaleCompare(attribute,"x") == 0)
13828             {
13829               region.x=SvIV(ST(i));
13830               break;
13831             }
13832           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13833             attribute);
13834           break;
13835         }
13836         case 'y':
13837         case 'Y':
13838         {
13839           if (LocaleCompare(attribute,"y") == 0)
13840             {
13841               region.y=SvIV(ST(i));
13842               break;
13843             }
13844           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13845             attribute);
13846           break;
13847         }
13848         default:
13849         {
13850           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13851             attribute);
13852           break;
13853         }
13854       }
13855     }
13856     (void) SetImageStorageClass(image,DirectClass,exception);
13857     channel_mask=SetImageChannelMask(image,channel);
13858     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
13859     if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
13860         (SvTYPE(av) != SVt_PVAV))
13861       PUSHs(&sv_undef);
13862     else
13863       {
13864         double
13865           scale;
13866
13867         register ssize_t
13868           i;
13869
13870         i=0;
13871         scale=1.0;
13872         if (normalize != MagickFalse)
13873           scale=QuantumRange;
13874         if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
13875             (i <= av_len(av)))
13876           {
13877             SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
13878               av_fetch(av,i,0)))),q);
13879             i++;
13880           }
13881         if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
13882             (i <= av_len(av)))
13883           {
13884             SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
13885               av_fetch(av,i,0)))),q);
13886             i++;
13887           }
13888         if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
13889             (i <= av_len(av)))
13890           {
13891             SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
13892               av_fetch(av,i,0)))),q);
13893             i++;
13894           }
13895         if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
13896             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
13897           {
13898             SetPixelBlack(image,ClampToQuantum(scale*
13899               SvNV(*(av_fetch(av,i,0)))),q);
13900             i++;
13901           }
13902         if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
13903             (i <= av_len(av)))
13904           {
13905             SetPixelAlpha(image,ClampToQuantum(scale*
13906               SvNV(*(av_fetch(av,i,0)))),q);
13907             i++;
13908           }
13909         (void) SyncAuthenticPixels(image,exception);
13910       }
13911     (void) SetImageChannelMask(image,channel_mask);
13912
13913   PerlException:
13914     InheritPerlException(exception,perl_exception);
13915     exception=DestroyExceptionInfo(exception);
13916     SvREFCNT_dec(perl_exception);
13917   }
13918 \f
13919 #
13920 ###############################################################################
13921 #                                                                             #
13922 #                                                                             #
13923 #                                                                             #
13924 #   S m u s h                                                                 #
13925 #                                                                             #
13926 #                                                                             #
13927 #                                                                             #
13928 ###############################################################################
13929 #
13930 #
13931 void
13932 Smush(ref,...)
13933   Image::Magick ref=NO_INIT
13934   ALIAS:
13935     SmushImage  = 1
13936     smush       = 2
13937     smushimage  = 3
13938   PPCODE:
13939   {
13940     AV
13941       *av;
13942
13943     char
13944       *attribute;
13945
13946     ExceptionInfo
13947       *exception;
13948
13949     HV
13950       *hv;
13951
13952     Image
13953       *image;
13954
13955     register ssize_t
13956       i;
13957
13958     ssize_t
13959       offset,
13960       stack;
13961
13962     struct PackageInfo
13963       *info;
13964
13965     SV
13966       *av_reference,
13967       *perl_exception,
13968       *reference,
13969       *rv,
13970       *sv;
13971
13972     PERL_UNUSED_VAR(ref);
13973     PERL_UNUSED_VAR(ix);
13974     exception=AcquireExceptionInfo();
13975     perl_exception=newSVpv("",0);
13976     sv=NULL;
13977     attribute=NULL;
13978     av=NULL;
13979     if (sv_isobject(ST(0)) == 0)
13980       {
13981         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13982           PackageName);
13983         goto PerlException;
13984       }
13985     reference=SvRV(ST(0));
13986     hv=SvSTASH(reference);
13987     av=newAV();
13988     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13989     SvREFCNT_dec(av);
13990     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13991     if (image == (Image *) NULL)
13992       {
13993         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13994           PackageName);
13995         goto PerlException;
13996       }
13997     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13998     /*
13999       Get options.
14000     */
14001     offset=0;
14002     stack=MagickTrue;
14003     for (i=2; i < items; i+=2)
14004     {
14005       attribute=(char *) SvPV(ST(i-1),na);
14006       switch (*attribute)
14007       {
14008         case 'O':
14009         case 'o':
14010         {
14011           if (LocaleCompare(attribute,"offset") == 0)
14012             {
14013               offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
14014               break;
14015             }
14016           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14017             attribute);
14018           break;
14019         }
14020         case 'S':
14021         case 's':
14022         {
14023           if (LocaleCompare(attribute,"stack") == 0)
14024             {
14025               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14026                 SvPV(ST(i),na));
14027               if (stack < 0)
14028                 {
14029                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
14030                     SvPV(ST(i),na));
14031                   return;
14032                 }
14033               break;
14034             }
14035           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14036             attribute);
14037           break;
14038         }
14039         default:
14040         {
14041           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14042             attribute);
14043           break;
14044         }
14045       }
14046     }
14047     image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
14048       exception);
14049     if (image == (Image *) NULL)
14050       goto PerlException;
14051     for ( ; image; image=image->next)
14052     {
14053       AddImageToRegistry(sv,image);
14054       rv=newRV(sv);
14055       av_push(av,sv_bless(rv,hv));
14056       SvREFCNT_dec(sv);
14057     }
14058     exception=DestroyExceptionInfo(exception);
14059     ST(0)=av_reference;
14060     SvREFCNT_dec(perl_exception);
14061     XSRETURN(1);
14062
14063   PerlException:
14064     InheritPerlException(exception,perl_exception);
14065     exception=DestroyExceptionInfo(exception);
14066     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14067     SvPOK_on(perl_exception);
14068     ST(0)=sv_2mortal(perl_exception);
14069     XSRETURN(1);
14070   }
14071 \f
14072 #
14073 ###############################################################################
14074 #                                                                             #
14075 #                                                                             #
14076 #                                                                             #
14077 #   S t a t i s t i c s                                                       #
14078 #                                                                             #
14079 #                                                                             #
14080 #                                                                             #
14081 ###############################################################################
14082 #
14083 #
14084 void
14085 Statistics(ref,...)
14086   Image::Magick ref=NO_INIT
14087   ALIAS:
14088     StatisticsImage = 1
14089     statistics      = 2
14090     statisticsimage = 3
14091   PPCODE:
14092   {
14093 #define ChannelStatistics(channel) \
14094 { \
14095   (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
14096     (double) channel_statistics[channel].depth); \
14097   PUSHs(sv_2mortal(newSVpv(message,0))); \
14098   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
14099     channel_statistics[channel].minima/scale); \
14100   PUSHs(sv_2mortal(newSVpv(message,0))); \
14101   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
14102     channel_statistics[channel].maxima/scale); \
14103   PUSHs(sv_2mortal(newSVpv(message,0))); \
14104   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
14105     channel_statistics[channel].mean/scale); \
14106   PUSHs(sv_2mortal(newSVpv(message,0))); \
14107   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
14108     channel_statistics[channel].standard_deviation/scale); \
14109   PUSHs(sv_2mortal(newSVpv(message,0))); \
14110   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
14111     channel_statistics[channel].kurtosis); \
14112   PUSHs(sv_2mortal(newSVpv(message,0))); \
14113   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
14114     channel_statistics[channel].skewness); \
14115   PUSHs(sv_2mortal(newSVpv(message,0))); \
14116 }
14117
14118     AV
14119       *av;
14120
14121     char
14122       message[MaxTextExtent];
14123
14124     ChannelStatistics
14125       *channel_statistics;
14126
14127     double
14128       scale;
14129
14130     ExceptionInfo
14131       *exception;
14132
14133     Image
14134       *image;
14135
14136     ssize_t
14137       count;
14138
14139     struct PackageInfo
14140       *info;
14141
14142     SV
14143       *perl_exception,
14144       *reference;
14145
14146     PERL_UNUSED_VAR(ref);
14147     PERL_UNUSED_VAR(ix);
14148     exception=AcquireExceptionInfo();
14149     perl_exception=newSVpv("",0);
14150     av=NULL;
14151     if (sv_isobject(ST(0)) == 0)
14152       {
14153         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14154           PackageName);
14155         goto PerlException;
14156       }
14157     reference=SvRV(ST(0));
14158     av=newAV();
14159     SvREFCNT_dec(av);
14160     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14161     if (image == (Image *) NULL)
14162       {
14163         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14164           PackageName);
14165         goto PerlException;
14166       }
14167     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14168     count=0;
14169     for ( ; image; image=image->next)
14170     {
14171       channel_statistics=GetImageStatistics(image,exception);
14172       if (channel_statistics == (ChannelStatistics *) NULL)
14173         continue;
14174       count++;
14175       EXTEND(sp,35*count);
14176       scale=(double) QuantumRange;
14177       ChannelStatistics(RedChannel);
14178       ChannelStatistics(GreenChannel);
14179       ChannelStatistics(BlueChannel);
14180       if (image->colorspace == CMYKColorspace)
14181         ChannelStatistics(BlackChannel);
14182       if (image->alpha_trait == BlendPixelTrait)
14183         ChannelStatistics(AlphaChannel);
14184       channel_statistics=(ChannelStatistics *)
14185         RelinquishMagickMemory(channel_statistics);
14186     }
14187
14188   PerlException:
14189     InheritPerlException(exception,perl_exception);
14190     exception=DestroyExceptionInfo(exception);
14191     SvREFCNT_dec(perl_exception);
14192   }
14193 \f
14194 #
14195 ###############################################################################
14196 #                                                                             #
14197 #                                                                             #
14198 #                                                                             #
14199 #   S y n c A u t h e n t i c P i x e l s                                     #
14200 #                                                                             #
14201 #                                                                             #
14202 #                                                                             #
14203 ###############################################################################
14204 #
14205 #
14206 void
14207 SyncAuthenticPixels(ref,...)
14208   Image::Magick ref = NO_INIT
14209   ALIAS:
14210     Syncauthenticpixels = 1
14211     SyncImagePixels = 2
14212     syncimagepixels = 3
14213   CODE:
14214   {
14215     ExceptionInfo
14216       *exception;
14217
14218     Image
14219       *image;
14220
14221     MagickBooleanType
14222       status;
14223
14224     struct PackageInfo
14225       *info;
14226
14227     SV
14228       *perl_exception,
14229       *reference;
14230
14231     PERL_UNUSED_VAR(ref);
14232     PERL_UNUSED_VAR(ix);
14233     exception=AcquireExceptionInfo();
14234     perl_exception=newSVpv("",0);
14235     if (sv_isobject(ST(0)) == 0)
14236       {
14237         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14238           PackageName);
14239         goto PerlException;
14240       }
14241
14242     reference=SvRV(ST(0));
14243     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14244     if (image == (Image *) NULL)
14245       {
14246         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14247           PackageName);
14248         goto PerlException;
14249       }
14250
14251     status=SyncAuthenticPixels(image,exception);
14252     if (status != MagickFalse)
14253       return;
14254
14255   PerlException:
14256     InheritPerlException(exception,perl_exception);
14257     exception=DestroyExceptionInfo(exception);
14258     SvREFCNT_dec(perl_exception);  /* throw away all errors */
14259   }
14260 \f
14261 #
14262 ###############################################################################
14263 #                                                                             #
14264 #                                                                             #
14265 #                                                                             #
14266 #   T r a n s f o r m                                                         #
14267 #                                                                             #
14268 #                                                                             #
14269 #                                                                             #
14270 ###############################################################################
14271 #
14272 #
14273 void
14274 Transform(ref,...)
14275   Image::Magick ref=NO_INIT
14276   ALIAS:
14277     TransformImage = 1
14278     transform      = 2
14279     transformimage = 3
14280   PPCODE:
14281   {
14282     AV
14283       *av;
14284
14285     char
14286       *attribute,
14287       *crop_geometry,
14288       *geometry;
14289
14290     ExceptionInfo
14291       *exception;
14292
14293     HV
14294       *hv;
14295
14296     Image
14297       *clone,
14298       *image;
14299
14300     register ssize_t
14301       i;
14302
14303     struct PackageInfo
14304       *info;
14305
14306     SV
14307       *av_reference,
14308       *perl_exception,
14309       *reference,
14310       *rv,
14311       *sv;
14312
14313     PERL_UNUSED_VAR(ref);
14314     PERL_UNUSED_VAR(ix);
14315     exception=AcquireExceptionInfo();
14316     perl_exception=newSVpv("",0);
14317     sv=NULL;
14318     av=NULL;
14319     attribute=NULL;
14320     if (sv_isobject(ST(0)) == 0)
14321       {
14322         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14323           PackageName);
14324         goto PerlException;
14325       }
14326     reference=SvRV(ST(0));
14327     hv=SvSTASH(reference);
14328     av=newAV();
14329     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14330     SvREFCNT_dec(av);
14331     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14332     if (image == (Image *) NULL)
14333       {
14334         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14335           PackageName);
14336         goto PerlException;
14337       }
14338     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14339     /*
14340       Get attribute.
14341     */
14342     crop_geometry=(char *) NULL;
14343     geometry=(char *) NULL;
14344     for (i=2; i < items; i+=2)
14345     {
14346       attribute=(char *) SvPV(ST(i-1),na);
14347       switch (*attribute)
14348       {
14349         case 'c':
14350         case 'C':
14351         {
14352           if (LocaleCompare(attribute,"crop") == 0)
14353             {
14354               crop_geometry=SvPV(ST(i),na);
14355               break;
14356             }
14357           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14358             attribute);
14359           break;
14360         }
14361         case 'g':
14362         case 'G':
14363         {
14364           if (LocaleCompare(attribute,"geometry") == 0)
14365             {
14366               geometry=SvPV(ST(i),na);
14367               break;
14368             }
14369           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14370             attribute);
14371           break;
14372         }
14373         default:
14374         {
14375           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14376             attribute);
14377           break;
14378         }
14379       }
14380     }
14381     for ( ; image; image=image->next)
14382     {
14383       clone=CloneImage(image,0,0,MagickTrue,exception);
14384       if (clone == (Image *) NULL)
14385         goto PerlException;
14386       TransformImage(&clone,crop_geometry,geometry,exception);
14387       for ( ; clone; clone=clone->next)
14388       {
14389         AddImageToRegistry(sv,clone);
14390         rv=newRV(sv);
14391         av_push(av,sv_bless(rv,hv));
14392         SvREFCNT_dec(sv);
14393       }
14394     }
14395     exception=DestroyExceptionInfo(exception);
14396     ST(0)=av_reference;
14397     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
14398     XSRETURN(1);
14399
14400   PerlException:
14401     InheritPerlException(exception,perl_exception);
14402     exception=DestroyExceptionInfo(exception);
14403     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14404     SvPOK_on(perl_exception);
14405     ST(0)=sv_2mortal(perl_exception);
14406     XSRETURN(1);
14407   }
14408 \f
14409 #
14410 ###############################################################################
14411 #                                                                             #
14412 #                                                                             #
14413 #                                                                             #
14414 #   W r i t e                                                                 #
14415 #                                                                             #
14416 #                                                                             #
14417 #                                                                             #
14418 ###############################################################################
14419 #
14420 #
14421 void
14422 Write(ref,...)
14423   Image::Magick ref=NO_INIT
14424   ALIAS:
14425     WriteImage    = 1
14426     write         = 2
14427     writeimage    = 3
14428   PPCODE:
14429   {
14430     char
14431       filename[MaxTextExtent];
14432
14433     ExceptionInfo
14434       *exception;
14435
14436     Image
14437       *image,
14438       *next;
14439
14440     register ssize_t
14441       i;
14442
14443     ssize_t
14444       number_images,
14445       scene;
14446
14447     struct PackageInfo
14448       *info,
14449       *package_info;
14450
14451     SV
14452       *perl_exception,
14453       *reference;
14454
14455     PERL_UNUSED_VAR(ref);
14456     PERL_UNUSED_VAR(ix);
14457     exception=AcquireExceptionInfo();
14458     perl_exception=newSVpv("",0);
14459     number_images=0;
14460     package_info=(struct PackageInfo *) NULL;
14461     if (sv_isobject(ST(0)) == 0)
14462       {
14463         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14464           PackageName);
14465         goto PerlException;
14466       }
14467     reference=SvRV(ST(0));
14468     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14469     if (image == (Image *) NULL)
14470       {
14471         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14472           PackageName);
14473         goto PerlException;
14474       }
14475     package_info=ClonePackageInfo(info,exception);
14476     if (items == 2)
14477       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14478     else
14479       if (items > 2)
14480         for (i=2; i < items; i+=2)
14481           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14482             exception);
14483     (void) CopyMagickString(filename,package_info->image_info->filename,
14484       MaxTextExtent);
14485     scene=0;
14486     for (next=image; next; next=next->next)
14487     {
14488       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
14489       next->scene=scene++;
14490     }
14491     SetImageInfo(package_info->image_info,(unsigned int)
14492       GetImageListLength(image),exception);
14493     for (next=image; next; next=next->next)
14494     {
14495       (void) WriteImage(package_info->image_info,next,exception);
14496       number_images++;
14497       if (package_info->image_info->adjoin)
14498         break;
14499     }
14500
14501   PerlException:
14502     if (package_info != (struct PackageInfo *) NULL)
14503       DestroyPackageInfo(package_info);
14504     InheritPerlException(exception,perl_exception);
14505     exception=DestroyExceptionInfo(exception);
14506     sv_setiv(perl_exception,(IV) number_images);
14507     SvPOK_on(perl_exception);
14508     ST(0)=sv_2mortal(perl_exception);
14509     XSRETURN(1);
14510   }