]> granicus.if.org Git - imagemagick/blob - PerlMagick/Magick.xs
...
[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-2017 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 <MagickCore/MagickCore.h>
57 #include "EXTERN.h"
58 #include "perl.h"
59 #include "XSUB.h"
60 #include <math.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[MagickPathExtent]; \
117  \
118   if ((exception)->severity != UndefinedException) \
119     { \
120       (void) FormatLocaleString(message,MagickPathExtent,"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}, {"gravity", MagickGravityOptions} } },
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     { "Mode", { {"geometry", StringReference},
535       {"width", IntegerReference},{"height", IntegerReference},
536       {"channel", MagickChannelOptions} } },
537     { "Statistic", { {"geometry", StringReference},
538       {"width", IntegerReference},{"height", IntegerReference},
539       {"channel", MagickChannelOptions}, {"type", MagickStatisticOptions} } },
540     { "Perceptible", { {"epsilon", RealReference},
541       {"channel", MagickChannelOptions} } },
542     { "Poly", { {"terms", ArrayReference},
543       {"channel", MagickChannelOptions} } },
544     { "Grayscale", { {"method", MagickNoiseOptions} } },
545     { "CannyEdge", { {"geometry", StringReference},
546       {"radius", RealReference}, {"sigma", RealReference},
547       {"lower-percent", RealReference}, {"upper-percent", RealReference} } },
548     { "HoughLine", { {"geometry", StringReference},
549       {"width", IntegerReference}, {"height", IntegerReference},
550       {"threshold", IntegerReference} } },
551     { "MeanShift", { {"geometry", StringReference},
552       {"width", IntegerReference}, {"height", IntegerReference},
553       {"distance", RealReference} } },
554     { "Kuwahara", { {"geometry", StringReference}, {"radius", RealReference},
555       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
556     { "ConnectedComponents", { {"connectivity", IntegerReference} } },
557     { "CopyPixels", { {"image", ImageReference}, {"geometry", StringReference},
558       {"width", IntegerReference}, {"height", IntegerReference},
559       {"x", IntegerReference}, {"y", IntegerReference},
560       {"gravity", MagickGravityOptions}, {"offset", StringReference}, 
561       {"dx", IntegerReference}, {"dy", IntegerReference} } },
562     { "Color", { {"color", StringReference} } },
563     { "WaveletDenoise", {  {"geometry", StringReference},
564       {"threshold", RealReference}, {"softness", RealReference},
565       {"channel", MagickChannelOptions} } },
566     { "Colorspace", { {"colorspace", MagickColorspaceOptions} } },
567   };
568
569 static SplayTreeInfo
570   *magick_registry = (SplayTreeInfo *) NULL;
571 \f
572 /*
573   Forward declarations.
574 */
575 static Image
576   *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
577
578 static ssize_t
579   strEQcase(const char *,const char *);
580 \f
581 /*
582 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
583 %                                                                             %
584 %                                                                             %
585 %                                                                             %
586 %   C l o n e P a c k a g e I n f o                                           %
587 %                                                                             %
588 %                                                                             %
589 %                                                                             %
590 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
591 %
592 %  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
593 %  a new one.
594 %
595 %  The format of the ClonePackageInfo routine is:
596 %
597 %      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
598 %        exception)
599 %
600 %  A description of each parameter follows:
601 %
602 %    o info: a structure of type info.
603 %
604 %    o exception: Return any errors or warnings in this structure.
605 %
606 */
607 static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
608   ExceptionInfo *exception)
609 {
610   struct PackageInfo
611     *clone_info;
612
613   clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
614   if (clone_info == (struct PackageInfo *) NULL)
615     {
616       ThrowPerlException(exception,ResourceLimitError,
617         "UnableToClonePackageInfo",PackageName);
618       return((struct PackageInfo *) NULL);
619     }
620   if (info == (struct PackageInfo *) NULL)
621     {
622       clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
623       return(clone_info);
624     }
625   *clone_info=(*info);
626   clone_info->image_info=CloneImageInfo(info->image_info);
627   return(clone_info);
628 }
629 \f
630 /*
631 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
632 %                                                                             %
633 %                                                                             %
634 %                                                                             %
635 %   c o n s t a n t                                                           %
636 %                                                                             %
637 %                                                                             %
638 %                                                                             %
639 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
640 %
641 %  constant() returns a double value for the specified name.
642 %
643 %  The format of the constant routine is:
644 %
645 %      double constant(char *name,ssize_t sans)
646 %
647 %  A description of each parameter follows:
648 %
649 %    o value: Method constant returns a double value for the specified name.
650 %
651 %    o name: The name of the constant.
652 %
653 %    o sans: This integer value is not used.
654 %
655 */
656 static double constant(char *name,ssize_t sans)
657 {
658   (void) sans;
659   errno=0;
660   switch (*name)
661   {
662     case 'B':
663     {
664       if (strEQ(name,"BlobError"))
665         return(BlobError);
666       if (strEQ(name,"BlobWarning"))
667         return(BlobWarning);
668       break;
669     }
670     case 'C':
671     {
672       if (strEQ(name,"CacheError"))
673         return(CacheError);
674       if (strEQ(name,"CacheWarning"))
675         return(CacheWarning);
676       if (strEQ(name,"CoderError"))
677         return(CoderError);
678       if (strEQ(name,"CoderWarning"))
679         return(CoderWarning);
680       if (strEQ(name,"ConfigureError"))
681         return(ConfigureError);
682       if (strEQ(name,"ConfigureWarning"))
683         return(ConfigureWarning);
684       if (strEQ(name,"CorruptImageError"))
685         return(CorruptImageError);
686       if (strEQ(name,"CorruptImageWarning"))
687         return(CorruptImageWarning);
688       break;
689     }
690     case 'D':
691     {
692       if (strEQ(name,"DelegateError"))
693         return(DelegateError);
694       if (strEQ(name,"DelegateWarning"))
695         return(DelegateWarning);
696       if (strEQ(name,"DrawError"))
697         return(DrawError);
698       if (strEQ(name,"DrawWarning"))
699         return(DrawWarning);
700       break;
701     }
702     case 'E':
703     {
704       if (strEQ(name,"ErrorException"))
705         return(ErrorException);
706       if (strEQ(name,"ExceptionError"))
707         return(CoderError);
708       if (strEQ(name,"ExceptionWarning"))
709         return(CoderWarning);
710       break;
711     }
712     case 'F':
713     {
714       if (strEQ(name,"FatalErrorException"))
715         return(FatalErrorException);
716       if (strEQ(name,"FileOpenError"))
717         return(FileOpenError);
718       if (strEQ(name,"FileOpenWarning"))
719         return(FileOpenWarning);
720       break;
721     }
722     case 'I':
723     {
724       if (strEQ(name,"ImageError"))
725         return(ImageError);
726       if (strEQ(name,"ImageWarning"))
727         return(ImageWarning);
728       break;
729     }
730     case 'M':
731     {
732       if (strEQ(name,"MaxRGB"))
733         return(QuantumRange);
734       if (strEQ(name,"MissingDelegateError"))
735         return(MissingDelegateError);
736       if (strEQ(name,"MissingDelegateWarning"))
737         return(MissingDelegateWarning);
738       if (strEQ(name,"ModuleError"))
739         return(ModuleError);
740       if (strEQ(name,"ModuleWarning"))
741         return(ModuleWarning);
742       break;
743     }
744     case 'O':
745     {
746       if (strEQ(name,"Opaque"))
747         return(OpaqueAlpha);
748       if (strEQ(name,"OptionError"))
749         return(OptionError);
750       if (strEQ(name,"OptionWarning"))
751         return(OptionWarning);
752       break;
753     }
754     case 'Q':
755     {
756       if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
757         return(MAGICKCORE_QUANTUM_DEPTH);
758       if (strEQ(name,"QuantumDepth"))
759         return(MAGICKCORE_QUANTUM_DEPTH);
760       if (strEQ(name,"QuantumRange"))
761         return(QuantumRange);
762       break;
763     }
764     case 'R':
765     {
766       if (strEQ(name,"ResourceLimitError"))
767         return(ResourceLimitError);
768       if (strEQ(name,"ResourceLimitWarning"))
769         return(ResourceLimitWarning);
770       if (strEQ(name,"RegistryError"))
771         return(RegistryError);
772       if (strEQ(name,"RegistryWarning"))
773         return(RegistryWarning);
774       break;
775     }
776     case 'S':
777     {
778       if (strEQ(name,"StreamError"))
779         return(StreamError);
780       if (strEQ(name,"StreamWarning"))
781         return(StreamWarning);
782       if (strEQ(name,"Success"))
783         return(0);
784       break;
785     }
786     case 'T':
787     {
788       if (strEQ(name,"Transparent"))
789         return(TransparentAlpha);
790       if (strEQ(name,"TypeError"))
791         return(TypeError);
792       if (strEQ(name,"TypeWarning"))
793         return(TypeWarning);
794       break;
795     }
796     case 'W':
797     {
798       if (strEQ(name,"WarningException"))
799         return(WarningException);
800       break;
801     }
802     case 'X':
803     {
804       if (strEQ(name,"XServerError"))
805         return(XServerError);
806       if (strEQ(name,"XServerWarning"))
807         return(XServerWarning);
808       break;
809     }
810   }
811   errno=EINVAL;
812   return(0);
813 }
814 \f
815 /*
816 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
817 %                                                                             %
818 %                                                                             %
819 %                                                                             %
820 %   D e s t r o y P a c k a g e I n f o                                       %
821 %                                                                             %
822 %                                                                             %
823 %                                                                             %
824 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
825 %
826 %  Method DestroyPackageInfo frees a previously created info structure.
827 %
828 %  The format of the DestroyPackageInfo routine is:
829 %
830 %      DestroyPackageInfo(struct PackageInfo *info)
831 %
832 %  A description of each parameter follows:
833 %
834 %    o info: a structure of type info.
835 %
836 */
837 static void DestroyPackageInfo(struct PackageInfo *info)
838 {
839   info->image_info=DestroyImageInfo(info->image_info);
840   info=(struct PackageInfo *) RelinquishMagickMemory(info);
841 }
842 \f
843 /*
844 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
845 %                                                                             %
846 %                                                                             %
847 %                                                                             %
848 %   G e t L i s t                                                             %
849 %                                                                             %
850 %                                                                             %
851 %                                                                             %
852 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
853 %
854 %  Method GetList is recursively called by SetupList to traverse the
855 %  Image__Magick reference.  If building an reference_vector (see SetupList),
856 %  *current is the current position in *reference_vector and *last is the final
857 %  entry in *reference_vector.
858 %
859 %  The format of the GetList routine is:
860 %
861 %      GetList(info)
862 %
863 %  A description of each parameter follows:
864 %
865 %    o info: a structure of type info.
866 %
867 */
868 static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
869   ssize_t *current,ssize_t *last,ExceptionInfo *exception)
870 {
871   Image
872     *image;
873
874   if (reference == (SV *) NULL)
875     return(NULL);
876   switch (SvTYPE(reference))
877   {
878     case SVt_PVAV:
879     {
880       AV
881         *av;
882
883       Image
884         *head,
885         *previous;
886
887       register ssize_t
888         i;
889
890       ssize_t
891         n;
892
893       /*
894         Array of images.
895       */
896       previous=(Image *) NULL;
897       head=(Image *) NULL;
898       av=(AV *) reference;
899       n=av_len(av);
900       for (i=0; i <= n; i++)
901       {
902         SV
903           **rv;
904
905         rv=av_fetch(av,i,0);
906         if (rv && *rv && sv_isobject(*rv))
907           {
908             image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
909               exception);
910             if (image == (Image *) NULL)
911               continue;
912             if (image == previous)
913               {
914                 image=CloneImage(image,0,0,MagickTrue,exception);
915                 if (image == (Image *) NULL)
916                   return(NULL);
917               }
918             image->previous=previous;
919             *(previous ? &previous->next : &head)=image;
920             for (previous=image; previous->next; previous=previous->next) ;
921           }
922       }
923       return(head);
924     }
925     case SVt_PVMG:
926     {
927       /*
928         Blessed scalar, one image.
929       */
930       image=INT2PTR(Image *,SvIV(reference));
931       if (image == (Image *) NULL)
932         return(NULL);
933       image->previous=(Image *) NULL;
934       image->next=(Image *) NULL;
935       if (reference_vector)
936         {
937           if (*current == *last)
938             {
939               *last+=256;
940               if (*reference_vector == (SV **) NULL)
941                 *reference_vector=(SV **) AcquireQuantumMemory(*last,
942                   sizeof(*reference_vector));
943               else
944                 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
945                   *last,sizeof(*reference_vector));
946             }
947           if (*reference_vector == (SV **) NULL)
948             {
949               ThrowPerlException(exception,ResourceLimitError,
950                 "MemoryAllocationFailed",PackageName);
951               return((Image *) NULL);
952             }
953           (*reference_vector)[*current]=reference;
954           (*reference_vector)[++(*current)]=NULL;
955         }
956       return(image);
957     }
958     default:
959       break;
960   }
961   (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
962     (double) SvTYPE(reference));
963   return((Image *) NULL);
964 }
965 \f
966 /*
967 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
968 %                                                                             %
969 %                                                                             %
970 %                                                                             %
971 %   G e t P a c k a g e I n f o                                               %
972 %                                                                             %
973 %                                                                             %
974 %                                                                             %
975 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
976 %
977 %  Method GetPackageInfo looks up or creates an info structure for the given
978 %  Image__Magick reference.  If it does create a new one, the information in
979 %  package_info is used to initialize it.
980 %
981 %  The format of the GetPackageInfo routine is:
982 %
983 %      struct PackageInfo *GetPackageInfo(void *reference,
984 %        struct PackageInfo *package_info,ExceptionInfo *exception)
985 %
986 %  A description of each parameter follows:
987 %
988 %    o info: a structure of type info.
989 %
990 %    o exception: Return any errors or warnings in this structure.
991 %
992 */
993 static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
994   struct PackageInfo *package_info,ExceptionInfo *exception)
995 {
996   char
997     message[MagickPathExtent];
998
999   struct PackageInfo
1000     *clone_info;
1001
1002   SV
1003     *sv;
1004
1005   (void) FormatLocaleString(message,MagickPathExtent,"%s::package%s%p",
1006     PackageName,XS_VERSION,reference);
1007   sv=perl_get_sv(message,(TRUE | 0x02));
1008   if (sv == (SV *) NULL)
1009     {
1010       ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
1011         message);
1012       return(package_info);
1013     }
1014   if (SvREFCNT(sv) == 0)
1015     (void) SvREFCNT_inc(sv);
1016   if (SvIOKp(sv) && (clone_info=INT2PTR(struct PackageInfo *,SvIV(sv))))
1017     return(clone_info);
1018   clone_info=ClonePackageInfo(package_info,exception);
1019   sv_setiv(sv,PTR2IV(clone_info));
1020   return(clone_info);
1021 }
1022 \f
1023 /*
1024 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1025 %                                                                             %
1026 %                                                                             %
1027 %                                                                             %
1028 %   S e t A t t r i b u t e                                                   %
1029 %                                                                             %
1030 %                                                                             %
1031 %                                                                             %
1032 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1033 %
1034 %  SetAttribute() sets the attribute to the value in sval.  This can change
1035 %  either or both of image or info.
1036 %
1037 %  The format of the SetAttribute routine is:
1038 %
1039 %      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1040 %        SV *sval,ExceptionInfo *exception)
1041 %
1042 %  A description of each parameter follows:
1043 %
1044 %    o list: a list of strings.
1045 %
1046 %    o string: a character string.
1047 %
1048 */
1049
1050 static double SiPrefixToDoubleInterval(const char *string,const double interval)
1051 {
1052   char
1053     *q;
1054
1055   double
1056     value;
1057
1058   value=InterpretSiPrefixValue(string,&q);
1059   if (*q == '%')
1060     value*=interval/100.0;
1061   return(value);
1062 }
1063
1064 static inline double StringToDouble(const char *string,char **sentinal)
1065 {
1066   return(InterpretLocaleValue(string,sentinal));
1067 }
1068
1069 static double StringToDoubleInterval(const char *string,const double interval)
1070 {
1071   char
1072     *q;
1073
1074   double
1075     value;
1076
1077   value=InterpretLocaleValue(string,&q);
1078   if (*q == '%')
1079     value*=interval/100.0;
1080   return(value);
1081 }
1082
1083 static inline ssize_t StringToLong(const char *value)
1084 {
1085   return(strtol(value,(char **) NULL,10));
1086 }
1087
1088 static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1089   const char *attribute,SV *sval,ExceptionInfo *exception)
1090 {
1091   GeometryInfo
1092     geometry_info;
1093
1094   long
1095     x,
1096     y;
1097
1098   PixelInfo
1099     pixel;
1100
1101   MagickStatusType
1102     flags;
1103
1104   PixelInfo
1105     *color,
1106     target_color;
1107
1108   ssize_t
1109     sp;
1110
1111   switch (*attribute)
1112   {
1113     case 'A':
1114     case 'a':
1115     {
1116       if (LocaleCompare(attribute,"adjoin") == 0)
1117         {
1118           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1119             SvPV(sval,na)) : SvIV(sval);
1120           if (sp < 0)
1121             {
1122               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1123                 SvPV(sval,na));
1124               break;
1125             }
1126           if (info)
1127             info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1128           break;
1129         }
1130       if (LocaleCompare(attribute,"alpha") == 0)
1131         {
1132           sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaChannelOptions,
1133             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1134           if (sp < 0)
1135             {
1136               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1137                 SvPV(sval,na));
1138               break;
1139             }
1140           for ( ; image; image=image->next)
1141             (void) SetImageAlphaChannel(image,(AlphaChannelOption) sp,
1142               exception);
1143           break;
1144         }
1145       if (LocaleCompare(attribute,"antialias") == 0)
1146         {
1147           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1148             SvPV(sval,na)) : SvIV(sval);
1149           if (sp < 0)
1150             {
1151               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1152                 SvPV(sval,na));
1153               break;
1154             }
1155           if (info)
1156             info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1157           break;
1158         }
1159       if (LocaleCompare(attribute,"area-limit") == 0)
1160         {
1161           MagickSizeType
1162             limit;
1163
1164           limit=MagickResourceInfinity;
1165           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1166             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1167               100.0);
1168           (void) SetMagickResourceLimit(AreaResource,limit);
1169           break;
1170         }
1171       if (LocaleCompare(attribute,"attenuate") == 0)
1172         {
1173           if (info)
1174             (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1175           break;
1176         }
1177       if (LocaleCompare(attribute,"authenticate") == 0)
1178         {
1179           if (info)
1180             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1181           break;
1182         }
1183       if (info)
1184         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1185       for ( ; image; image=image->next)
1186         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1187       break;
1188     }
1189     case 'B':
1190     case 'b':
1191     {
1192       if (LocaleCompare(attribute,"background") == 0)
1193         {
1194           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1195             exception);
1196           if (info)
1197             info->image_info->background_color=target_color;
1198           for ( ; image; image=image->next)
1199             image->background_color=target_color;
1200           break;
1201         }
1202       if (LocaleCompare(attribute,"blue-primary") == 0)
1203         {
1204           for ( ; image; image=image->next)
1205           {
1206             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1207             image->chromaticity.blue_primary.x=geometry_info.rho;
1208             image->chromaticity.blue_primary.y=geometry_info.sigma;
1209             if ((flags & SigmaValue) == 0)
1210               image->chromaticity.blue_primary.y=
1211                 image->chromaticity.blue_primary.x;
1212           }
1213           break;
1214         }
1215       if (LocaleCompare(attribute,"bordercolor") == 0)
1216         {
1217           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1218             exception);
1219           if (info)
1220             info->image_info->border_color=target_color;
1221           for ( ; image; image=image->next)
1222             image->border_color=target_color;
1223           break;
1224         }
1225       if (info)
1226         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1227       for ( ; image; image=image->next)
1228         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1229       break;
1230     }
1231     case 'C':
1232     case 'c':
1233     {
1234       if (LocaleCompare(attribute,"cache-threshold") == 0)
1235         {
1236           (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1237             SiPrefixToDoubleInterval(SvPV(sval,na),100.0));
1238           (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1239             (2.0*SiPrefixToDoubleInterval(SvPV(sval,na),100.0)));
1240           break;
1241         }
1242       if (LocaleCompare(attribute,"clip-mask") == 0)
1243         {
1244           Image
1245             *clip_mask;
1246
1247           clip_mask=(Image *) NULL;
1248           if (SvPOK(sval))
1249             clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1250           for ( ; image; image=image->next)
1251             SetImageMask(image,ReadPixelMask,clip_mask,exception);
1252           break;
1253         }
1254       if (LocaleNCompare(attribute,"colormap",8) == 0)
1255         {
1256           for ( ; image; image=image->next)
1257           {
1258             int
1259               items;
1260
1261             long
1262               i;
1263
1264             if (image->storage_class == DirectClass)
1265               continue;
1266             i=0;
1267             items=sscanf(attribute,"%*[^[][%ld",&i);
1268             (void) items;
1269             if (i > (ssize_t) image->colors)
1270               i%=image->colors;
1271             if ((strchr(SvPV(sval,na),',') == 0) ||
1272                 (strchr(SvPV(sval,na),')') != 0))
1273               QueryColorCompliance(SvPV(sval,na),AllCompliance,
1274                 image->colormap+i,exception);
1275             else
1276               {
1277                 color=image->colormap+i;
1278                 pixel.red=color->red;
1279                 pixel.green=color->green;
1280                 pixel.blue=color->blue;
1281                 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1282                 pixel.red=geometry_info.rho;
1283                 pixel.green=geometry_info.sigma;
1284                 pixel.blue=geometry_info.xi;
1285                 color->red=ClampToQuantum(pixel.red);
1286                 color->green=ClampToQuantum(pixel.green);
1287                 color->blue=ClampToQuantum(pixel.blue);
1288               }
1289           }
1290           break;
1291         }
1292       if (LocaleCompare(attribute,"colorspace") == 0)
1293         {
1294           sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1295             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1296           if (sp < 0)
1297             {
1298               ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1299                 SvPV(sval,na));
1300               break;
1301             }
1302           for ( ; image; image=image->next)
1303             (void) SetImageColorspace(image,(ColorspaceType) sp,exception);
1304           break;
1305         }
1306       if (LocaleCompare(attribute,"comment") == 0)
1307         {
1308           for ( ; image; image=image->next)
1309             (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1310               info ? info->image_info : (ImageInfo *) NULL,image,
1311               SvPV(sval,na),exception),exception);
1312           break;
1313         }
1314       if (LocaleCompare(attribute,"compression") == 0)
1315         {
1316           sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1317             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1318           if (sp < 0)
1319             {
1320               ThrowPerlException(exception,OptionError,
1321                 "UnrecognizedImageCompression",SvPV(sval,na));
1322               break;
1323             }
1324           if (info)
1325             info->image_info->compression=(CompressionType) sp;
1326           for ( ; image; image=image->next)
1327             image->compression=(CompressionType) sp;
1328           break;
1329         }
1330       if (info)
1331         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1332       for ( ; image; image=image->next)
1333         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1334       break;
1335     }
1336     case 'D':
1337     case 'd':
1338     {
1339       if (LocaleCompare(attribute,"debug") == 0)
1340         {
1341           SetLogEventMask(SvPV(sval,na));
1342           break;
1343         }
1344       if (LocaleCompare(attribute,"delay") == 0)
1345         {
1346           flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1347           for ( ; image; image=image->next)
1348           {
1349             image->delay=(size_t) floor(geometry_info.rho+0.5);
1350             if ((flags & SigmaValue) != 0)
1351               image->ticks_per_second=(ssize_t)
1352                 floor(geometry_info.sigma+0.5);
1353           }
1354           break;
1355         }
1356       if (LocaleCompare(attribute,"disk-limit") == 0)
1357         {
1358           MagickSizeType
1359             limit;
1360
1361           limit=MagickResourceInfinity;
1362           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1363             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1364               100.0);
1365           (void) SetMagickResourceLimit(DiskResource,limit);
1366           break;
1367         }
1368       if (LocaleCompare(attribute,"density") == 0)
1369         {
1370           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1371             {
1372               ThrowPerlException(exception,OptionError,"MissingGeometry",
1373                 SvPV(sval,na));
1374               break;
1375             }
1376           if (info)
1377             (void) CloneString(&info->image_info->density,SvPV(sval,na));
1378           for ( ; image; image=image->next)
1379           {
1380             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1381             image->resolution.x=geometry_info.rho;
1382             image->resolution.y=geometry_info.sigma;
1383             if ((flags & SigmaValue) == 0)
1384               image->resolution.y=image->resolution.x;
1385           }
1386           break;
1387         }
1388       if (LocaleCompare(attribute,"depth") == 0)
1389         {
1390           if (info)
1391             info->image_info->depth=SvIV(sval);
1392           for ( ; image; image=image->next)
1393             (void) SetImageDepth(image,SvIV(sval),exception);
1394           break;
1395         }
1396       if (LocaleCompare(attribute,"dispose") == 0)
1397         {
1398           sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1399             SvPV(sval,na)) : SvIV(sval);
1400           if (sp < 0)
1401             {
1402               ThrowPerlException(exception,OptionError,
1403                 "UnrecognizedDisposeMethod",SvPV(sval,na));
1404               break;
1405             }
1406           for ( ; image; image=image->next)
1407             image->dispose=(DisposeType) sp;
1408           break;
1409         }
1410       if (LocaleCompare(attribute,"dither") == 0)
1411         {
1412           if (info)
1413             {
1414               sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1415                 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1416               if (sp < 0)
1417                 {
1418                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
1419                     SvPV(sval,na));
1420                   break;
1421                 }
1422               info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1423             }
1424           break;
1425         }
1426       if (LocaleCompare(attribute,"display") == 0)
1427         {
1428           display:
1429           if (info)
1430             (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1431           break;
1432         }
1433       if (info)
1434         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1435       for ( ; image; image=image->next)
1436         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1437       break;
1438     }
1439     case 'E':
1440     case 'e':
1441     {
1442       if (LocaleCompare(attribute,"endian") == 0)
1443         {
1444           sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1445             SvPV(sval,na)) : SvIV(sval);
1446           if (sp < 0)
1447             {
1448               ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1449                 SvPV(sval,na));
1450               break;
1451             }
1452           if (info)
1453             info->image_info->endian=(EndianType) sp;
1454           for ( ; image; image=image->next)
1455             image->endian=(EndianType) sp;
1456           break;
1457         }
1458       if (LocaleCompare(attribute,"extract") == 0)
1459         {
1460           /*
1461             Set image extract geometry.
1462           */
1463           (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1464           break;
1465         }
1466       if (info)
1467         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1468       for ( ; image; image=image->next)
1469         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1470       break;
1471     }
1472     case 'F':
1473     case 'f':
1474     {
1475       if (LocaleCompare(attribute,"filename") == 0)
1476         {
1477           if (info)
1478             (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1479               MagickPathExtent);
1480           for ( ; image; image=image->next)
1481             (void) CopyMagickString(image->filename,SvPV(sval,na),
1482               MagickPathExtent);
1483           break;
1484         }
1485       if (LocaleCompare(attribute,"file") == 0)
1486         {
1487           FILE
1488             *file;
1489
1490           PerlIO
1491             *io_info;
1492
1493           if (info == (struct PackageInfo *) NULL)
1494             break;
1495           io_info=IoIFP(sv_2io(sval));
1496           if (io_info == (PerlIO *) NULL)
1497             {
1498               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1499                 PackageName);
1500               break;
1501             }
1502           file=PerlIO_findFILE(io_info);
1503           if (file == (FILE *) NULL)
1504             {
1505               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1506                 PackageName);
1507               break;
1508             }
1509           SetImageInfoFile(info->image_info,file);
1510           break;
1511         }
1512       if (LocaleCompare(attribute,"fill") == 0)
1513         {
1514           if (info)
1515             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1516           break;
1517         }
1518       if (LocaleCompare(attribute,"font") == 0)
1519         {
1520           if (info)
1521             (void) CloneString(&info->image_info->font,SvPV(sval,na));
1522           break;
1523         }
1524       if (LocaleCompare(attribute,"foreground") == 0)
1525         break;
1526       if (LocaleCompare(attribute,"fuzz") == 0)
1527         {
1528           if (info)
1529             info->image_info->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1530               QuantumRange+1.0);
1531           for ( ; image; image=image->next)
1532             image->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1533               QuantumRange+1.0);
1534           break;
1535         }
1536       if (info)
1537         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1538       for ( ; image; image=image->next)
1539         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1540       break;
1541     }
1542     case 'G':
1543     case 'g':
1544     {
1545       if (LocaleCompare(attribute,"gamma") == 0)
1546         {
1547           for ( ; image; image=image->next)
1548             image->gamma=SvNV(sval);
1549           break;
1550         }
1551       if (LocaleCompare(attribute,"gravity") == 0)
1552         {
1553           sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1554             SvPV(sval,na)) : SvIV(sval);
1555           if (sp < 0)
1556             {
1557               ThrowPerlException(exception,OptionError,
1558                 "UnrecognizedGravityType",SvPV(sval,na));
1559               break;
1560             }
1561           if (info)
1562             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1563           for ( ; image; image=image->next)
1564             image->gravity=(GravityType) sp;
1565           break;
1566         }
1567       if (LocaleCompare(attribute,"green-primary") == 0)
1568         {
1569           for ( ; image; image=image->next)
1570           {
1571             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1572             image->chromaticity.green_primary.x=geometry_info.rho;
1573             image->chromaticity.green_primary.y=geometry_info.sigma;
1574             if ((flags & SigmaValue) == 0)
1575               image->chromaticity.green_primary.y=
1576                 image->chromaticity.green_primary.x;
1577           }
1578           break;
1579         }
1580       if (info)
1581         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1582       for ( ; image; image=image->next)
1583         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1584       break;
1585     }
1586     case 'I':
1587     case 'i':
1588     {
1589       if (LocaleNCompare(attribute,"index",5) == 0)
1590         {
1591           int
1592             items;
1593
1594           long
1595             index;
1596
1597           register Quantum
1598             *q;
1599
1600           CacheView
1601             *image_view;
1602
1603           for ( ; image; image=image->next)
1604           {
1605             if (image->storage_class != PseudoClass)
1606               continue;
1607             x=0;
1608             y=0;
1609             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1610             (void) items;
1611             image_view=AcquireAuthenticCacheView(image,exception);
1612             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1613             if (q != (Quantum *) NULL)
1614               {
1615                 items=sscanf(SvPV(sval,na),"%ld",&index);
1616                 if ((index >= 0) && (index < (ssize_t) image->colors))
1617                   SetPixelIndex(image,index,q);
1618                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1619               }
1620             image_view=DestroyCacheView(image_view);
1621           }
1622           break;
1623         }
1624       if (LocaleCompare(attribute,"iterations") == 0)
1625         {
1626   iterations:
1627           for ( ; image; image=image->next)
1628             image->iterations=SvIV(sval);
1629           break;
1630         }
1631       if (LocaleCompare(attribute,"interlace") == 0)
1632         {
1633           sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1634             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1635           if (sp < 0)
1636             {
1637               ThrowPerlException(exception,OptionError,
1638                 "UnrecognizedInterlaceType",SvPV(sval,na));
1639               break;
1640             }
1641           if (info)
1642             info->image_info->interlace=(InterlaceType) sp;
1643           for ( ; image; image=image->next)
1644             image->interlace=(InterlaceType) sp;
1645           break;
1646         }
1647       if (info)
1648         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1649       for ( ; image; image=image->next)
1650         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1651       break;
1652     }
1653     case 'L':
1654     case 'l':
1655     {
1656       if (LocaleCompare(attribute,"label") == 0)
1657         {
1658           for ( ; image; image=image->next)
1659             (void) SetImageProperty(image,"label",InterpretImageProperties(
1660               info ? info->image_info : (ImageInfo *) NULL,image,
1661               SvPV(sval,na),exception),exception);
1662           break;
1663         }
1664       if (LocaleCompare(attribute,"loop") == 0)
1665         goto iterations;
1666       if (info)
1667         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1668       for ( ; image; image=image->next)
1669         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1670       break;
1671     }
1672     case 'M':
1673     case 'm':
1674     {
1675       if (LocaleCompare(attribute,"magick") == 0)
1676         {
1677           if (info)
1678             (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
1679               "%s:",SvPV(sval,na));
1680           for ( ; image; image=image->next)
1681             (void) CopyMagickString(image->magick,SvPV(sval,na),MagickPathExtent);
1682           break;
1683         }
1684       if (LocaleCompare(attribute,"map-limit") == 0)
1685         {
1686           MagickSizeType
1687             limit;
1688
1689           limit=MagickResourceInfinity;
1690           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1691             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1692               100.0);
1693           (void) SetMagickResourceLimit(MapResource,limit);
1694           break;
1695         }
1696       if (LocaleCompare(attribute,"mask") == 0)
1697         {
1698           Image
1699             *mask;
1700
1701           mask=(Image *) NULL;
1702           if (SvPOK(sval))
1703             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1704           for ( ; image; image=image->next)
1705             SetImageMask(image,ReadPixelMask,mask,exception);
1706           break;
1707         }
1708       if (LocaleCompare(attribute,"mattecolor") == 0)
1709         {
1710           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1711             exception);
1712           if (info)
1713             info->image_info->alpha_color=target_color;
1714           for ( ; image; image=image->next)
1715             image->alpha_color=target_color;
1716           break;
1717         }
1718       if (LocaleCompare(attribute,"matte") == 0)
1719         {
1720           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1721             SvPV(sval,na)) : SvIV(sval);
1722           if (sp < 0)
1723             {
1724               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1725                 SvPV(sval,na));
1726               break;
1727             }
1728           for ( ; image; image=image->next)
1729             image->alpha_trait=sp != 0 ? BlendPixelTrait : UndefinedPixelTrait;
1730           break;
1731         }
1732       if (LocaleCompare(attribute,"memory-limit") == 0)
1733         {
1734           MagickSizeType
1735             limit;
1736
1737           limit=MagickResourceInfinity;
1738           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1739             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1740               100.0);
1741           (void) SetMagickResourceLimit(MemoryResource,limit);
1742           break;
1743         }
1744       if (LocaleCompare(attribute,"monochrome") == 0)
1745         {
1746           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1747             SvPV(sval,na)) : SvIV(sval);
1748           if (sp < 0)
1749             {
1750               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1751                 SvPV(sval,na));
1752               break;
1753             }
1754           if (info)
1755             info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1756           for ( ; image; image=image->next)
1757             (void) SetImageType(image,BilevelType,exception);
1758           break;
1759         }
1760       if (info)
1761         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1762       for ( ; image; image=image->next)
1763         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1764       break;
1765     }
1766     case 'O':
1767     case 'o':
1768     {
1769       if (LocaleCompare(attribute,"option") == 0)
1770         {
1771           if (info)
1772             DefineImageOption(info->image_info,SvPV(sval,na));
1773           break;
1774         }
1775       if (LocaleCompare(attribute,"orientation") == 0)
1776         {
1777           sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1778             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1779           if (sp < 0)
1780             {
1781               ThrowPerlException(exception,OptionError,
1782                 "UnrecognizedOrientationType",SvPV(sval,na));
1783               break;
1784             }
1785           if (info)
1786             info->image_info->orientation=(OrientationType) sp;
1787           for ( ; image; image=image->next)
1788             image->orientation=(OrientationType) sp;
1789           break;
1790         }
1791       if (info)
1792         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1793       for ( ; image; image=image->next)
1794         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1795       break;
1796     }
1797     case 'P':
1798     case 'p':
1799     {
1800       if (LocaleCompare(attribute,"page") == 0)
1801         {
1802           char
1803             *geometry;
1804
1805           geometry=GetPageGeometry(SvPV(sval,na));
1806           if (info)
1807             (void) CloneString(&info->image_info->page,geometry);
1808           for ( ; image; image=image->next)
1809             (void) ParsePageGeometry(image,geometry,&image->page,exception);
1810           geometry=(char *) RelinquishMagickMemory(geometry);
1811           break;
1812         }
1813       if (LocaleNCompare(attribute,"pixel",5) == 0)
1814         {
1815           int
1816             items;
1817
1818           PixelInfo
1819             pixel;
1820
1821           register Quantum
1822             *q;
1823
1824           CacheView
1825             *image_view;
1826
1827           for ( ; image; image=image->next)
1828           {
1829             if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1830               break;
1831             x=0;
1832             y=0;
1833             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1834             (void) items;
1835             image_view=AcquireVirtualCacheView(image,exception);
1836             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1837             if (q != (Quantum *) NULL)
1838               {
1839                 if ((strchr(SvPV(sval,na),',') == 0) ||
1840                     (strchr(SvPV(sval,na),')') != 0))
1841                   QueryColorCompliance(SvPV(sval,na),AllCompliance,
1842                     &pixel,exception);
1843                 else
1844                   {
1845                     GetPixelInfo(image,&pixel);
1846                     flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1847                     pixel.red=geometry_info.rho;
1848                     if ((flags & SigmaValue) != 0)
1849                       pixel.green=geometry_info.sigma;
1850                     if ((flags & XiValue) != 0)
1851                       pixel.blue=geometry_info.xi;
1852                     if ((flags & PsiValue) != 0)
1853                       pixel.alpha=geometry_info.psi;
1854                     if ((flags & ChiValue) != 0)
1855                       pixel.black=geometry_info.chi;
1856                   }
1857                 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1858                 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1859                 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1860                 if (image->colorspace == CMYKColorspace)
1861                   SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1862                 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1863                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1864               }
1865             image_view=DestroyCacheView(image_view);
1866           }
1867           break;
1868         }
1869       if (LocaleCompare(attribute,"pointsize") == 0)
1870         {
1871           if (info)
1872             {
1873               (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1874               info->image_info->pointsize=geometry_info.rho;
1875             }
1876           break;
1877         }
1878       if (info)
1879         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1880       for ( ; image; image=image->next)
1881         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1882       break;
1883     }
1884     case 'Q':
1885     case 'q':
1886     {
1887       if (LocaleCompare(attribute,"quality") == 0)
1888         {
1889           if (info)
1890             info->image_info->quality=SvIV(sval);
1891           for ( ; image; image=image->next)
1892             image->quality=SvIV(sval);
1893           break;
1894         }
1895       if (info)
1896         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1897       for ( ; image; image=image->next)
1898         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1899       break;
1900     }
1901     case 'R':
1902     case 'r':
1903     {
1904       if (LocaleCompare(attribute,"read-mask") == 0)
1905         {
1906           Image
1907             *mask;
1908
1909           mask=(Image *) NULL;
1910           if (SvPOK(sval))
1911             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1912           for ( ; image; image=image->next)
1913             SetImageMask(image,ReadPixelMask,mask,exception);
1914           break;
1915         }
1916       if (LocaleCompare(attribute,"red-primary") == 0)
1917         {
1918           for ( ; image; image=image->next)
1919           {
1920             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1921             image->chromaticity.red_primary.x=geometry_info.rho;
1922             image->chromaticity.red_primary.y=geometry_info.sigma;
1923             if ((flags & SigmaValue) == 0)
1924               image->chromaticity.red_primary.y=
1925                 image->chromaticity.red_primary.x;
1926           }
1927           break;
1928         }
1929       if (LocaleCompare(attribute,"render") == 0)
1930         {
1931           sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1932             SvPV(sval,na)) : SvIV(sval);
1933           if (sp < 0)
1934             {
1935               ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1936                 SvPV(sval,na));
1937               break;
1938             }
1939          for ( ; image; image=image->next)
1940            image->rendering_intent=(RenderingIntent) sp;
1941          break;
1942        }
1943       if (LocaleCompare(attribute,"repage") == 0)
1944         {
1945           RectangleInfo
1946             geometry;
1947
1948           for ( ; image; image=image->next)
1949           {
1950             flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
1951             if ((flags & WidthValue) != 0)
1952               {
1953                 if ((flags & HeightValue) == 0)
1954                   geometry.height=geometry.width;
1955                 image->page.width=geometry.width;
1956                 image->page.height=geometry.height;
1957               }
1958             if ((flags & AspectValue) != 0)
1959               {
1960                 if ((flags & XValue) != 0)
1961                   image->page.x+=geometry.x;
1962                 if ((flags & YValue) != 0)
1963                   image->page.y+=geometry.y;
1964               }
1965             else
1966               {
1967                 if ((flags & XValue) != 0)
1968                   {
1969                     image->page.x=geometry.x;
1970                     if (((flags & WidthValue) != 0) && (geometry.x > 0))
1971                       image->page.width=image->columns+geometry.x;
1972                   }
1973                 if ((flags & YValue) != 0)
1974                   {
1975                     image->page.y=geometry.y;
1976                     if (((flags & HeightValue) != 0) && (geometry.y > 0))
1977                       image->page.height=image->rows+geometry.y;
1978                   }
1979               }
1980           }
1981           break;
1982         }
1983       if (info)
1984         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1985       for ( ; image; image=image->next)
1986         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1987       break;
1988     }
1989     case 'S':
1990     case 's':
1991     {
1992       if (LocaleCompare(attribute,"sampling-factor") == 0)
1993         {
1994           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1995             {
1996               ThrowPerlException(exception,OptionError,"MissingGeometry",
1997                 SvPV(sval,na));
1998               break;
1999             }
2000           if (info)
2001             (void) CloneString(&info->image_info->sampling_factor,
2002               SvPV(sval,na));
2003           break;
2004         }
2005       if (LocaleCompare(attribute,"scene") == 0)
2006         {
2007           for ( ; image; image=image->next)
2008             image->scene=SvIV(sval);
2009           break;
2010         }
2011       if (LocaleCompare(attribute,"server") == 0)
2012         goto display;
2013       if (LocaleCompare(attribute,"size") == 0)
2014         {
2015           if (info)
2016             {
2017               if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2018                 {
2019                   ThrowPerlException(exception,OptionError,"MissingGeometry",
2020                     SvPV(sval,na));
2021                   break;
2022                 }
2023               (void) CloneString(&info->image_info->size,SvPV(sval,na));
2024             }
2025           break;
2026         }
2027       if (LocaleCompare(attribute,"stroke") == 0)
2028         {
2029           if (info)
2030             (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2031           break;
2032         }
2033       if (info)
2034         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2035       for ( ; image; image=image->next)
2036         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2037       break;
2038     }
2039     case 'T':
2040     case 't':
2041     {
2042       if (LocaleCompare(attribute,"texture") == 0)
2043         {
2044           if (info)
2045             (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2046           break;
2047         }
2048       if (LocaleCompare(attribute,"thread-limit") == 0)
2049         {
2050           MagickSizeType
2051             limit;
2052
2053           limit=MagickResourceInfinity;
2054           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2055             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2056               100.0);
2057           (void) SetMagickResourceLimit(ThreadResource,limit);
2058           break;
2059         }
2060       if (LocaleCompare(attribute,"tile-offset") == 0)
2061         {
2062           char
2063             *geometry;
2064
2065           geometry=GetPageGeometry(SvPV(sval,na));
2066           if (info)
2067             (void) CloneString(&info->image_info->page,geometry);
2068           for ( ; image; image=image->next)
2069             (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2070               exception);
2071           geometry=(char *) RelinquishMagickMemory(geometry);
2072           break;
2073         }
2074       if (LocaleCompare(attribute,"time-limit") == 0)
2075         {
2076           MagickSizeType
2077             limit;
2078
2079           limit=MagickResourceInfinity;
2080           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2081             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2082               100.0);
2083           (void) SetMagickResourceLimit(TimeResource,limit);
2084           break;
2085         }
2086       if (LocaleCompare(attribute,"transparent-color") == 0)
2087         {
2088           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
2089             exception);
2090           if (info)
2091             info->image_info->transparent_color=target_color;
2092           for ( ; image; image=image->next)
2093             image->transparent_color=target_color;
2094           break;
2095         }
2096       if (LocaleCompare(attribute,"type") == 0)
2097         {
2098           sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2099             SvPV(sval,na)) : SvIV(sval);
2100           if (sp < 0)
2101             {
2102               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2103                 SvPV(sval,na));
2104               break;
2105             }
2106           if (info)
2107             info->image_info->type=(ImageType) sp;
2108           for ( ; image; image=image->next)
2109             SetImageType(image,(ImageType) sp,exception);
2110           break;
2111         }
2112       if (info)
2113         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2114       for ( ; image; image=image->next)
2115         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2116       break;
2117     }
2118     case 'U':
2119     case 'u':
2120     {
2121       if (LocaleCompare(attribute,"units") == 0)
2122         {
2123           sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2124             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2125           if (sp < 0)
2126             {
2127               ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2128                 SvPV(sval,na));
2129               break;
2130             }
2131           if (info)
2132             info->image_info->units=(ResolutionType) sp;
2133           for ( ; image; image=image->next)
2134           {
2135             ResolutionType
2136               units;
2137
2138             units=(ResolutionType) sp;
2139             if (image->units != units)
2140               switch (image->units)
2141               {
2142                 case UndefinedResolution:
2143                 case PixelsPerInchResolution:
2144                 {
2145                   if (units == PixelsPerCentimeterResolution)
2146                     {
2147                       image->resolution.x*=2.54;
2148                       image->resolution.y*=2.54;
2149                     }
2150                   break;
2151                 }
2152                 case PixelsPerCentimeterResolution:
2153                 {
2154                   if (units == PixelsPerInchResolution)
2155                     {
2156                       image->resolution.x/=2.54;
2157                       image->resolution.y/=2.54;
2158                     }
2159                   break;
2160                 }
2161               }
2162             image->units=units;
2163           }
2164           break;
2165         }
2166       if (info)
2167         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2168       for ( ; image; image=image->next)
2169         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2170       break;
2171     }
2172     case 'V':
2173     case 'v':
2174     {
2175       if (LocaleCompare(attribute,"verbose") == 0)
2176         {
2177           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2178             SvPV(sval,na)) : SvIV(sval);
2179           if (sp < 0)
2180             {
2181               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2182                 SvPV(sval,na));
2183               break;
2184             }
2185           if (info)
2186             info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2187           break;
2188         }
2189       if (LocaleCompare(attribute,"virtual-pixel") == 0)
2190         {
2191           sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2192             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2193           if (sp < 0)
2194             {
2195               ThrowPerlException(exception,OptionError,
2196                 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2197               break;
2198             }
2199           for ( ; image; image=image->next)
2200             SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp,exception);
2201           break;
2202         }
2203       if (info)
2204         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2205       for ( ; image; image=image->next)
2206         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2207       break;
2208     }
2209     case 'W':
2210     case 'w':
2211     {
2212       if (LocaleCompare(attribute,"white-point") == 0)
2213         {
2214           for ( ; image; image=image->next)
2215           {
2216             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2217             image->chromaticity.white_point.x=geometry_info.rho;
2218             image->chromaticity.white_point.y=geometry_info.sigma;
2219             if ((flags & SigmaValue) == 0)
2220               image->chromaticity.white_point.y=
2221                 image->chromaticity.white_point.x;
2222           }
2223           break;
2224         }
2225       if (LocaleCompare(attribute,"write-mask") == 0)
2226         {
2227           Image
2228             *mask;
2229
2230           mask=(Image *) NULL;
2231           if (SvPOK(sval))
2232             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
2233           for ( ; image; image=image->next)
2234             SetImageMask(image,WritePixelMask,mask,exception);
2235           break;
2236         }
2237       if (info)
2238         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2239       for ( ; image; image=image->next)
2240         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2241       break;
2242     }
2243     default:
2244     {
2245       if (info)
2246         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2247       for ( ; image; image=image->next)
2248         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2249       break;
2250     }
2251   }
2252 }
2253 \f
2254 /*
2255 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2256 %                                                                             %
2257 %                                                                             %
2258 %                                                                             %
2259 %   S e t u p L i s t                                                         %
2260 %                                                                             %
2261 %                                                                             %
2262 %                                                                             %
2263 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2264 %
2265 %  Method SetupList returns the list of all the images linked by their
2266 %  image->next and image->previous link lists for use with ImageMagick.  If
2267 %  info is non-NULL, an info structure is returned in *info.  If
2268 %  reference_vector is non-NULL,an array of SV* are returned in
2269 %  *reference_vector.  Reference_vector is used when the images are going to be
2270 %  replaced with new Image*'s.
2271 %
2272 %  The format of the SetupList routine is:
2273 %
2274 %      Image *SetupList(SV *reference,struct PackageInfo **info,
2275 %        SV ***reference_vector,ExceptionInfo *exception)
2276 %
2277 %  A description of each parameter follows:
2278 %
2279 %    o list: a list of strings.
2280 %
2281 %    o string: a character string.
2282 %
2283 %    o exception: Return any errors or warnings in this structure.
2284 %
2285 */
2286 static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2287   SV ***reference_vector,ExceptionInfo *exception)
2288 {
2289   Image
2290     *image;
2291
2292   ssize_t
2293     current,
2294     last;
2295
2296   if (reference_vector)
2297     *reference_vector=NULL;
2298   if (info)
2299     *info=NULL;
2300   current=0;
2301   last=0;
2302   image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2303   if (info && (SvTYPE(reference) == SVt_PVAV))
2304     *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2305       exception);
2306   return(image);
2307 }
2308 \f
2309 /*
2310 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2311 %                                                                             %
2312 %                                                                             %
2313 %                                                                             %
2314 %   s t r E Q c a s e                                                         %
2315 %                                                                             %
2316 %                                                                             %
2317 %                                                                             %
2318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2319 %
2320 %  strEQcase() compares two strings and returns 0 if they are the
2321 %  same or if the second string runs out first.  The comparison is case
2322 %  insensitive.
2323 %
2324 %  The format of the strEQcase routine is:
2325 %
2326 %      ssize_t strEQcase(const char *p,const char *q)
2327 %
2328 %  A description of each parameter follows:
2329 %
2330 %    o p: a character string.
2331 %
2332 %    o q: a character string.
2333 %
2334 %
2335 */
2336 static ssize_t strEQcase(const char *p,const char *q)
2337 {
2338   char
2339     c;
2340
2341   register ssize_t
2342     i;
2343
2344   for (i=0 ; (c=(*q)) != 0; i++)
2345   {
2346     if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2347         (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2348       return(0);
2349     p++;
2350     q++;
2351   }
2352   return(((*q == 0) && (*p == 0)) ? i : 0);
2353 }
2354 \f
2355 /*
2356 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2357 %                                                                             %
2358 %                                                                             %
2359 %                                                                             %
2360 %   I m a g e : : M a g i c k                                                 %
2361 %                                                                             %
2362 %                                                                             %
2363 %                                                                             %
2364 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2365 %
2366 %
2367 */
2368 MODULE = Image::Magick PACKAGE = Image::Magick
2369
2370 PROTOTYPES: ENABLE
2371
2372 BOOT:
2373   MagickCoreGenesis("PerlMagick",MagickFalse);
2374   SetWarningHandler(NULL);
2375   SetErrorHandler(NULL);
2376   magick_registry=NewSplayTree((int (*)(const void *,const void *))
2377     NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2378
2379 void
2380 UNLOAD()
2381   PPCODE:
2382   {
2383     if (magick_registry != (SplayTreeInfo *) NULL)
2384       magick_registry=DestroySplayTree(magick_registry);
2385     MagickCoreTerminus();
2386   }
2387
2388 double
2389 constant(name,argument)
2390   char *name
2391   ssize_t argument
2392 \f
2393 #
2394 ###############################################################################
2395 #                                                                             #
2396 #                                                                             #
2397 #                                                                             #
2398 #   A n i m a t e                                                             #
2399 #                                                                             #
2400 #                                                                             #
2401 #                                                                             #
2402 ###############################################################################
2403 #
2404 #
2405 void
2406 Animate(ref,...)
2407   Image::Magick ref=NO_INIT
2408   ALIAS:
2409     AnimateImage  = 1
2410     animate       = 2
2411     animateimage  = 3
2412   PPCODE:
2413   {
2414     ExceptionInfo
2415       *exception;
2416
2417     Image
2418       *image;
2419
2420     register ssize_t
2421       i;
2422
2423     struct PackageInfo
2424       *info,
2425       *package_info;
2426
2427     SV
2428       *perl_exception,
2429       *reference;
2430
2431     PERL_UNUSED_VAR(ref);
2432     PERL_UNUSED_VAR(ix);
2433     exception=AcquireExceptionInfo();
2434     perl_exception=newSVpv("",0);
2435     package_info=(struct PackageInfo *) NULL;
2436     if (sv_isobject(ST(0)) == 0)
2437       {
2438         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2439           PackageName);
2440         goto PerlException;
2441       }
2442     reference=SvRV(ST(0));
2443     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2444     if (image == (Image *) NULL)
2445       {
2446         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2447           PackageName);
2448         goto PerlException;
2449       }
2450     package_info=ClonePackageInfo(info,exception);
2451     if (items == 2)
2452       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2453     else
2454       if (items > 2)
2455         for (i=2; i < items; i+=2)
2456           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2457             exception);
2458     (void) AnimateImages(package_info->image_info,image,exception);
2459     (void) CatchImageException(image);
2460
2461   PerlException:
2462     if (package_info != (struct PackageInfo *) NULL)
2463       DestroyPackageInfo(package_info);
2464     InheritPerlException(exception,perl_exception);
2465     exception=DestroyExceptionInfo(exception);
2466     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2467     SvPOK_on(perl_exception);
2468     ST(0)=sv_2mortal(perl_exception);
2469     XSRETURN(1);
2470   }
2471 \f
2472 #
2473 ###############################################################################
2474 #                                                                             #
2475 #                                                                             #
2476 #                                                                             #
2477 #   A p p e n d                                                               #
2478 #                                                                             #
2479 #                                                                             #
2480 #                                                                             #
2481 ###############################################################################
2482 #
2483 #
2484 void
2485 Append(ref,...)
2486   Image::Magick ref=NO_INIT
2487   ALIAS:
2488     AppendImage  = 1
2489     append       = 2
2490     appendimage  = 3
2491   PPCODE:
2492   {
2493     AV
2494       *av;
2495
2496     char
2497       *attribute;
2498
2499     ExceptionInfo
2500       *exception;
2501
2502     HV
2503       *hv;
2504
2505     Image
2506       *image;
2507
2508     register ssize_t
2509       i;
2510
2511     ssize_t
2512       stack;
2513
2514     struct PackageInfo
2515       *info;
2516
2517     SV
2518       *av_reference,
2519       *perl_exception,
2520       *reference,
2521       *rv,
2522       *sv;
2523
2524     PERL_UNUSED_VAR(ref);
2525     PERL_UNUSED_VAR(ix);
2526     exception=AcquireExceptionInfo();
2527     perl_exception=newSVpv("",0);
2528     sv=NULL;
2529     attribute=NULL;
2530     av=NULL;
2531     if (sv_isobject(ST(0)) == 0)
2532       {
2533         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2534           PackageName);
2535         goto PerlException;
2536       }
2537     reference=SvRV(ST(0));
2538     hv=SvSTASH(reference);
2539     av=newAV();
2540     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2541     SvREFCNT_dec(av);
2542     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2543     if (image == (Image *) NULL)
2544       {
2545         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2546           PackageName);
2547         goto PerlException;
2548       }
2549     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2550     /*
2551       Get options.
2552     */
2553     stack=MagickTrue;
2554     for (i=2; i < items; i+=2)
2555     {
2556       attribute=(char *) SvPV(ST(i-1),na);
2557       switch (*attribute)
2558       {
2559         case 'S':
2560         case 's':
2561         {
2562           if (LocaleCompare(attribute,"stack") == 0)
2563             {
2564               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2565                 SvPV(ST(i),na));
2566               if (stack < 0)
2567                 {
2568                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
2569                     SvPV(ST(i),na));
2570                   return;
2571                 }
2572               break;
2573             }
2574           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2575             attribute);
2576           break;
2577         }
2578         default:
2579         {
2580           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2581             attribute);
2582           break;
2583         }
2584       }
2585     }
2586     image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2587     if (image == (Image *) NULL)
2588       goto PerlException;
2589     for ( ; image; image=image->next)
2590     {
2591       AddImageToRegistry(sv,image);
2592       rv=newRV(sv);
2593       av_push(av,sv_bless(rv,hv));
2594       SvREFCNT_dec(sv);
2595     }
2596     exception=DestroyExceptionInfo(exception);
2597     ST(0)=av_reference;
2598     SvREFCNT_dec(perl_exception);
2599     XSRETURN(1);
2600
2601   PerlException:
2602     InheritPerlException(exception,perl_exception);
2603     exception=DestroyExceptionInfo(exception);
2604     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2605     SvPOK_on(perl_exception);
2606     ST(0)=sv_2mortal(perl_exception);
2607     XSRETURN(1);
2608   }
2609 \f
2610 #
2611 ###############################################################################
2612 #                                                                             #
2613 #                                                                             #
2614 #                                                                             #
2615 #   A v e r a g e                                                             #
2616 #                                                                             #
2617 #                                                                             #
2618 #                                                                             #
2619 ###############################################################################
2620 #
2621 #
2622 void
2623 Average(ref)
2624   Image::Magick ref=NO_INIT
2625   ALIAS:
2626     AverageImage   = 1
2627     average        = 2
2628     averageimage   = 3
2629   PPCODE:
2630   {
2631     AV
2632       *av;
2633
2634     char
2635       *p;
2636
2637     ExceptionInfo
2638       *exception;
2639
2640     HV
2641       *hv;
2642
2643     Image
2644       *image;
2645
2646     struct PackageInfo
2647       *info;
2648
2649     SV
2650       *perl_exception,
2651       *reference,
2652       *rv,
2653       *sv;
2654
2655     PERL_UNUSED_VAR(ref);
2656     PERL_UNUSED_VAR(ix);
2657     exception=AcquireExceptionInfo();
2658     perl_exception=newSVpv("",0);
2659     sv=NULL;
2660     if (sv_isobject(ST(0)) == 0)
2661       {
2662         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2663           PackageName);
2664         goto PerlException;
2665       }
2666     reference=SvRV(ST(0));
2667     hv=SvSTASH(reference);
2668     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2669     if (image == (Image *) NULL)
2670       {
2671         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2672           PackageName);
2673         goto PerlException;
2674       }
2675     image=EvaluateImages(image,MeanEvaluateOperator,exception);
2676     if (image == (Image *) NULL)
2677       goto PerlException;
2678     /*
2679       Create blessed Perl array for the returned image.
2680     */
2681     av=newAV();
2682     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2683     SvREFCNT_dec(av);
2684     AddImageToRegistry(sv,image);
2685     rv=newRV(sv);
2686     av_push(av,sv_bless(rv,hv));
2687     SvREFCNT_dec(sv);
2688     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2689     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
2690       "average-%.*s",(int) (MagickPathExtent-9),
2691       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2692     (void) CopyMagickString(image->filename,info->image_info->filename,
2693       MagickPathExtent);
2694     SetImageInfo(info->image_info,0,exception);
2695     exception=DestroyExceptionInfo(exception);
2696     SvREFCNT_dec(perl_exception);
2697     XSRETURN(1);
2698
2699   PerlException:
2700     InheritPerlException(exception,perl_exception);
2701     exception=DestroyExceptionInfo(exception);
2702     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2703     SvPOK_on(perl_exception);
2704     ST(0)=sv_2mortal(perl_exception);
2705     XSRETURN(1);
2706   }
2707 \f
2708 #
2709 ###############################################################################
2710 #                                                                             #
2711 #                                                                             #
2712 #                                                                             #
2713 #   B l o b T o I m a g e                                                     #
2714 #                                                                             #
2715 #                                                                             #
2716 #                                                                             #
2717 ###############################################################################
2718 #
2719 #
2720 void
2721 BlobToImage(ref,...)
2722   Image::Magick ref=NO_INIT
2723   ALIAS:
2724     BlobToImage  = 1
2725     blobtoimage  = 2
2726     blobto       = 3
2727   PPCODE:
2728   {
2729     AV
2730       *av;
2731
2732     char
2733       **keep,
2734       **list;
2735
2736     ExceptionInfo
2737       *exception;
2738
2739     HV
2740       *hv;
2741
2742     Image
2743       *image;
2744
2745     register char
2746       **p;
2747
2748     register ssize_t
2749       i;
2750
2751     ssize_t
2752       ac,
2753       n,
2754       number_images;
2755
2756     STRLEN
2757       *length;
2758
2759     struct PackageInfo
2760       *info;
2761
2762     SV
2763       *perl_exception,
2764       *reference,
2765       *rv,
2766       *sv;
2767
2768     PERL_UNUSED_VAR(ref);
2769     PERL_UNUSED_VAR(ix);
2770     exception=AcquireExceptionInfo();
2771     perl_exception=newSVpv("",0);
2772     sv=NULL;
2773     number_images=0;
2774     ac=(items < 2) ? 1 : items-1;
2775     length=(STRLEN *) NULL;
2776     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2777     if (list == (char **) NULL)
2778       {
2779         ThrowPerlException(exception,ResourceLimitError,
2780           "MemoryAllocationFailed",PackageName);
2781         goto PerlException;
2782       }
2783     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2784     if (length == (STRLEN *) NULL)
2785       {
2786         ThrowPerlException(exception,ResourceLimitError,
2787           "MemoryAllocationFailed",PackageName);
2788         goto PerlException;
2789       }
2790     if (sv_isobject(ST(0)) == 0)
2791       {
2792         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2793           PackageName);
2794         goto PerlException;
2795       }
2796     reference=SvRV(ST(0));
2797     hv=SvSTASH(reference);
2798     if (SvTYPE(reference) != SVt_PVAV)
2799       {
2800         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2801           PackageName);
2802         goto PerlException;
2803       }
2804     av=(AV *) reference;
2805     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2806       exception);
2807     n=1;
2808     if (items <= 1)
2809       {
2810         ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2811         goto PerlException;
2812       }
2813     for (n=0, i=0; i < ac; i++)
2814     {
2815       list[n]=(char *) (SvPV(ST(i+1),length[n]));
2816       if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2817         {
2818           list[n]=(char *) (SvPV(ST(i+2),length[n]));
2819           continue;
2820         }
2821       n++;
2822     }
2823     list[n]=(char *) NULL;
2824     keep=list;
2825     for (i=number_images=0; i < n; i++)
2826     {
2827       image=BlobToImage(info->image_info,list[i],length[i],exception);
2828       if (image == (Image *) NULL)
2829         break;
2830       for ( ; image; image=image->next)
2831       {
2832         AddImageToRegistry(sv,image);
2833         rv=newRV(sv);
2834         av_push(av,sv_bless(rv,hv));
2835         SvREFCNT_dec(sv);
2836         number_images++;
2837       }
2838     }
2839     /*
2840       Free resources.
2841     */
2842     for (i=0; i < n; i++)
2843       if (list[i] != (char *) NULL)
2844         for (p=keep; list[i] != *p++; )
2845           if (*p == (char *) NULL)
2846             {
2847               list[i]=(char *) RelinquishMagickMemory(list[i]);
2848               break;
2849             }
2850
2851   PerlException:
2852     if (list)
2853       list=(char **) RelinquishMagickMemory(list);
2854     if (length)
2855       length=(STRLEN *) RelinquishMagickMemory(length);
2856     InheritPerlException(exception,perl_exception);
2857     exception=DestroyExceptionInfo(exception);
2858     sv_setiv(perl_exception,(IV) number_images);
2859     SvPOK_on(perl_exception);
2860     ST(0)=sv_2mortal(perl_exception);
2861     XSRETURN(1);
2862   }
2863 \f
2864 #
2865 ###############################################################################
2866 #                                                                             #
2867 #                                                                             #
2868 #                                                                             #
2869 #   C h a n n e l F x                                                         #
2870 #                                                                             #
2871 #                                                                             #
2872 #                                                                             #
2873 ###############################################################################
2874 #
2875 #
2876 void
2877 ChannelFx(ref,...)
2878   Image::Magick ref=NO_INIT
2879   ALIAS:
2880     ChannelFxImage  = 1
2881     channelfx       = 2
2882     channelfximage  = 3
2883   PPCODE:
2884   {
2885     AV
2886       *av;
2887
2888     char
2889       *attribute,
2890       expression[MagickPathExtent];
2891
2892     ChannelType
2893       channel,
2894       channel_mask;
2895
2896     ExceptionInfo
2897       *exception;
2898
2899     HV
2900       *hv;
2901
2902     Image
2903       *image;
2904
2905     register ssize_t
2906       i;
2907
2908     struct PackageInfo
2909       *info;
2910
2911     SV
2912       *av_reference,
2913       *perl_exception,
2914       *reference,
2915       *rv,
2916       *sv;
2917
2918     PERL_UNUSED_VAR(ref);
2919     PERL_UNUSED_VAR(ix);
2920     exception=AcquireExceptionInfo();
2921     perl_exception=newSVpv("",0);
2922     sv=NULL;
2923     attribute=NULL;
2924     av=NULL;
2925     if (sv_isobject(ST(0)) == 0)
2926       {
2927         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2928           PackageName);
2929         goto PerlException;
2930       }
2931     reference=SvRV(ST(0));
2932     hv=SvSTASH(reference);
2933     av=newAV();
2934     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2935     SvREFCNT_dec(av);
2936     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2937     if (image == (Image *) NULL)
2938       {
2939         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2940           PackageName);
2941         goto PerlException;
2942       }
2943     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2944     /*
2945       Get options.
2946     */
2947     channel=DefaultChannels;
2948     (void) CopyMagickString(expression,"u",MagickPathExtent);
2949     if (items == 2)
2950       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
2951     else
2952       for (i=2; i < items; i+=2)
2953       {
2954         attribute=(char *) SvPV(ST(i-1),na);
2955         switch (*attribute)
2956         {
2957           case 'C':
2958           case 'c':
2959           {
2960             if (LocaleCompare(attribute,"channel") == 0)
2961               {
2962                 ssize_t
2963                   option;
2964
2965                 option=ParseChannelOption(SvPV(ST(i),na));
2966                 if (option < 0)
2967                   {
2968                     ThrowPerlException(exception,OptionError,
2969                       "UnrecognizedType",SvPV(ST(i),na));
2970                     return;
2971                   }
2972                 channel=(ChannelType) option;
2973                 break;
2974               }
2975             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2976               attribute);
2977             break;
2978           }
2979           case 'E':
2980           case 'e':
2981           {
2982             if (LocaleCompare(attribute,"expression") == 0)
2983               {
2984                 (void) CopyMagickString(expression,SvPV(ST(i),na),
2985                   MagickPathExtent);
2986                 break;
2987               }
2988             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2989               attribute);
2990             break;
2991           }
2992           default:
2993           {
2994             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2995               attribute);
2996             break;
2997           }
2998         }
2999       }
3000     channel_mask=SetImageChannelMask(image,channel);
3001     image=ChannelFxImage(image,expression,exception);
3002     if (image != (Image *) NULL)
3003       (void) SetImageChannelMask(image,channel_mask);
3004     if (image == (Image *) NULL)
3005       goto PerlException;
3006     for ( ; image; image=image->next)
3007     {
3008       AddImageToRegistry(sv,image);
3009       rv=newRV(sv);
3010       av_push(av,sv_bless(rv,hv));
3011       SvREFCNT_dec(sv);
3012     }
3013     exception=DestroyExceptionInfo(exception);
3014     ST(0)=av_reference;
3015     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3016     XSRETURN(1);
3017
3018   PerlException:
3019     InheritPerlException(exception,perl_exception);
3020     exception=DestroyExceptionInfo(exception);
3021     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3022     SvPOK_on(perl_exception);
3023     ST(0)=sv_2mortal(perl_exception);
3024     XSRETURN(1);
3025   }
3026 \f
3027 #
3028 ###############################################################################
3029 #                                                                             #
3030 #                                                                             #
3031 #                                                                             #
3032 #   C l o n e                                                                 #
3033 #                                                                             #
3034 #                                                                             #
3035 #                                                                             #
3036 ###############################################################################
3037 #
3038 #
3039 void
3040 Clone(ref)
3041   Image::Magick ref=NO_INIT
3042   ALIAS:
3043     CopyImage   = 1
3044     copy        = 2
3045     copyimage   = 3
3046     CloneImage  = 4
3047     clone       = 5
3048     cloneimage  = 6
3049     Clone       = 7
3050   PPCODE:
3051   {
3052     AV
3053       *av;
3054
3055     ExceptionInfo
3056       *exception;
3057
3058     HV
3059       *hv;
3060
3061     Image
3062       *clone,
3063       *image;
3064
3065     struct PackageInfo
3066       *info;
3067
3068     SV
3069       *perl_exception,
3070       *reference,
3071       *rv,
3072       *sv;
3073
3074     PERL_UNUSED_VAR(ref);
3075     PERL_UNUSED_VAR(ix);
3076     exception=AcquireExceptionInfo();
3077     perl_exception=newSVpv("",0);
3078     sv=NULL;
3079     if (sv_isobject(ST(0)) == 0)
3080       {
3081         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3082           PackageName);
3083         goto PerlException;
3084       }
3085     reference=SvRV(ST(0));
3086     hv=SvSTASH(reference);
3087     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3088     if (image == (Image *) NULL)
3089       {
3090         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3091           PackageName);
3092         goto PerlException;
3093       }
3094     /*
3095       Create blessed Perl array for the returned image.
3096     */
3097     av=newAV();
3098     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3099     SvREFCNT_dec(av);
3100     for ( ; image; image=image->next)
3101     {
3102       clone=CloneImage(image,0,0,MagickTrue,exception);
3103       if (clone == (Image *) NULL)
3104         break;
3105       AddImageToRegistry(sv,clone);
3106       rv=newRV(sv);
3107       av_push(av,sv_bless(rv,hv));
3108       SvREFCNT_dec(sv);
3109     }
3110     exception=DestroyExceptionInfo(exception);
3111     SvREFCNT_dec(perl_exception);
3112     XSRETURN(1);
3113
3114   PerlException:
3115     InheritPerlException(exception,perl_exception);
3116     exception=DestroyExceptionInfo(exception);
3117     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3118     SvPOK_on(perl_exception);
3119     ST(0)=sv_2mortal(perl_exception);
3120     XSRETURN(1);
3121   }
3122 \f
3123 #
3124 ###############################################################################
3125 #                                                                             #
3126 #                                                                             #
3127 #                                                                             #
3128 #   C L O N E                                                                 #
3129 #                                                                             #
3130 #                                                                             #
3131 #                                                                             #
3132 ###############################################################################
3133 #
3134 #
3135 void
3136 CLONE(ref,...)
3137   SV *ref;
3138   CODE:
3139   {
3140     PERL_UNUSED_VAR(ref);
3141     if (magick_registry != (SplayTreeInfo *) NULL)
3142       {
3143         register Image
3144           *p;
3145
3146         ResetSplayTreeIterator(magick_registry);
3147         p=(Image *) GetNextKeyInSplayTree(magick_registry);
3148         while (p != (Image *) NULL)
3149         {
3150           ReferenceImage(p);
3151           p=(Image *) GetNextKeyInSplayTree(magick_registry);
3152         }
3153       }
3154   }
3155 \f
3156 #
3157 ###############################################################################
3158 #                                                                             #
3159 #                                                                             #
3160 #                                                                             #
3161 #   C o a l e s c e                                                           #
3162 #                                                                             #
3163 #                                                                             #
3164 #                                                                             #
3165 ###############################################################################
3166 #
3167 #
3168 void
3169 Coalesce(ref)
3170   Image::Magick ref=NO_INIT
3171   ALIAS:
3172     CoalesceImage   = 1
3173     coalesce        = 2
3174     coalesceimage   = 3
3175   PPCODE:
3176   {
3177     AV
3178       *av;
3179
3180     ExceptionInfo
3181       *exception;
3182
3183     HV
3184       *hv;
3185
3186     Image
3187       *image;
3188
3189     struct PackageInfo
3190       *info;
3191
3192     SV
3193       *av_reference,
3194       *perl_exception,
3195       *reference,
3196       *rv,
3197       *sv;
3198
3199     PERL_UNUSED_VAR(ref);
3200     PERL_UNUSED_VAR(ix);
3201     exception=AcquireExceptionInfo();
3202     perl_exception=newSVpv("",0);
3203     sv=NULL;
3204     if (sv_isobject(ST(0)) == 0)
3205       {
3206         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3207           PackageName);
3208         goto PerlException;
3209       }
3210     reference=SvRV(ST(0));
3211     hv=SvSTASH(reference);
3212     av=newAV();
3213     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3214     SvREFCNT_dec(av);
3215     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3216     if (image == (Image *) NULL)
3217       {
3218         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3219           PackageName);
3220         goto PerlException;
3221       }
3222     image=CoalesceImages(image,exception);
3223     if (image == (Image *) NULL)
3224       goto PerlException;
3225     for ( ; image; image=image->next)
3226     {
3227       AddImageToRegistry(sv,image);
3228       rv=newRV(sv);
3229       av_push(av,sv_bless(rv,hv));
3230       SvREFCNT_dec(sv);
3231     }
3232     exception=DestroyExceptionInfo(exception);
3233     ST(0)=av_reference;
3234     SvREFCNT_dec(perl_exception);
3235     XSRETURN(1);
3236
3237   PerlException:
3238     InheritPerlException(exception,perl_exception);
3239     exception=DestroyExceptionInfo(exception);
3240     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3241     SvPOK_on(perl_exception);
3242     ST(0)=sv_2mortal(perl_exception);
3243     XSRETURN(1);
3244   }
3245 \f
3246 #
3247 ###############################################################################
3248 #                                                                             #
3249 #                                                                             #
3250 #                                                                             #
3251 #   C o m p a r e                                                             #
3252 #                                                                             #
3253 #                                                                             #
3254 #                                                                             #
3255 ###############################################################################
3256 #
3257 #
3258 void
3259 Compare(ref,...)
3260   Image::Magick ref=NO_INIT
3261   ALIAS:
3262     CompareImages = 1
3263     compare      = 2
3264     compareimage = 3
3265   PPCODE:
3266   {
3267     AV
3268       *av;
3269
3270     char
3271       *attribute;
3272
3273     double
3274       distortion;
3275
3276     ExceptionInfo
3277       *exception;
3278
3279     HV
3280       *hv;
3281
3282     Image
3283       *difference_image,
3284       *image,
3285       *reconstruct_image;
3286
3287     MetricType
3288       metric;
3289
3290     register ssize_t
3291       i;
3292
3293     ssize_t
3294       option;
3295
3296     struct PackageInfo
3297       *info;
3298
3299     SV
3300       *av_reference,
3301       *perl_exception,
3302       *reference,
3303       *rv,
3304       *sv;
3305
3306     PERL_UNUSED_VAR(ref);
3307     PERL_UNUSED_VAR(ix);
3308     exception=AcquireExceptionInfo();
3309     perl_exception=newSVpv("",0);
3310     sv=NULL;
3311     av=NULL;
3312     attribute=NULL;
3313     if (sv_isobject(ST(0)) == 0)
3314       {
3315         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3316           PackageName);
3317         goto PerlException;
3318       }
3319     reference=SvRV(ST(0));
3320     hv=SvSTASH(reference);
3321     av=newAV();
3322     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3323     SvREFCNT_dec(av);
3324     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3325     if (image == (Image *) NULL)
3326       {
3327         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3328           PackageName);
3329         goto PerlException;
3330       }
3331     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3332     /*
3333       Get attribute.
3334     */
3335     reconstruct_image=image;
3336     metric=RootMeanSquaredErrorMetric;
3337     for (i=2; i < items; i+=2)
3338     {
3339       attribute=(char *) SvPV(ST(i-1),na);
3340       switch (*attribute)
3341       {
3342         case 'C':
3343         case 'c':
3344         {
3345           if (LocaleCompare(attribute,"channel") == 0)
3346             {
3347               ssize_t
3348                 option;
3349
3350               option=ParseChannelOption(SvPV(ST(i),na));
3351               if (option < 0)
3352                 {
3353                   ThrowPerlException(exception,OptionError,
3354                     "UnrecognizedType",SvPV(ST(i),na));
3355                   return;
3356                 }
3357               (void) SetPixelChannelMask(image,(ChannelType) option);
3358               break;
3359             }
3360           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3361             attribute);
3362           break;
3363         }
3364         case 'F':
3365         case 'f':
3366         {
3367           if (LocaleCompare(attribute,"fuzz") == 0)
3368             {
3369               image->fuzz=StringToDoubleInterval(SvPV(ST(i),na),100.0);
3370               break;
3371             }
3372           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3373             attribute);
3374           break;
3375         }
3376         case 'I':
3377         case 'i':
3378         {
3379           if (LocaleCompare(attribute,"image") == 0)
3380             {
3381               reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3382                 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3383               break;
3384             }
3385           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3386             attribute);
3387           break;
3388         }
3389         case 'M':
3390         case 'm':
3391         {
3392           if (LocaleCompare(attribute,"metric") == 0)
3393             {
3394               option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3395                 SvPV(ST(i),na));
3396               if (option < 0)
3397                 {
3398                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3399                     SvPV(ST(i),na));
3400                   break;
3401                 }
3402               metric=(MetricType) option;
3403               break;
3404             }
3405           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3406             attribute);
3407           break;
3408         }
3409         default:
3410         {
3411           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3412             attribute);
3413           break;
3414         }
3415       }
3416     }
3417     difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3418       exception);
3419     if (difference_image != (Image *) NULL)
3420       {
3421         difference_image->error.mean_error_per_pixel=distortion;
3422         AddImageToRegistry(sv,difference_image);
3423         rv=newRV(sv);
3424         av_push(av,sv_bless(rv,hv));
3425         SvREFCNT_dec(sv);
3426       }
3427     exception=DestroyExceptionInfo(exception);
3428     ST(0)=av_reference;
3429     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3430     XSRETURN(1);
3431
3432   PerlException:
3433     InheritPerlException(exception,perl_exception);
3434     exception=DestroyExceptionInfo(exception);
3435     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3436     SvPOK_on(perl_exception);
3437     ST(0)=sv_2mortal(perl_exception);
3438     XSRETURN(1);
3439   }
3440 \f
3441 #
3442 ###############################################################################
3443 #                                                                             #
3444 #                                                                             #
3445 #                                                                             #
3446 #   C o m p l e x I m a g e s                                                 #
3447 #                                                                             #
3448 #                                                                             #
3449 #                                                                             #
3450 ###############################################################################
3451 #
3452 #
3453 void
3454 ComplexImages(ref)
3455   Image::Magick ref=NO_INIT
3456   ALIAS:
3457     ComplexImages   = 1
3458     compleximages   = 2
3459   PPCODE:
3460   {
3461     AV
3462       *av;
3463
3464     char
3465       *attribute,
3466       *p;
3467
3468     ComplexOperator
3469       op;
3470
3471     ExceptionInfo
3472       *exception;
3473
3474     HV
3475       *hv;
3476
3477     Image
3478       *image;
3479
3480     register ssize_t
3481       i;
3482
3483     struct PackageInfo
3484       *info;
3485
3486     SV
3487       *perl_exception,
3488       *reference,
3489       *rv,
3490       *sv;
3491
3492     PERL_UNUSED_VAR(ref);
3493     PERL_UNUSED_VAR(ix);
3494     exception=AcquireExceptionInfo();
3495     perl_exception=newSVpv("",0);
3496     sv=NULL;
3497     if (sv_isobject(ST(0)) == 0)
3498       {
3499         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3500           PackageName);
3501         goto PerlException;
3502       }
3503     reference=SvRV(ST(0));
3504     hv=SvSTASH(reference);
3505     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3506     if (image == (Image *) NULL)
3507       {
3508         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3509           PackageName);
3510         goto PerlException;
3511       }
3512     op=UndefinedComplexOperator;
3513     if (items == 2)
3514       {
3515         ssize_t
3516           in;
3517
3518         in=ParseCommandOption(MagickComplexOptions,MagickFalse,(char *)
3519           SvPV(ST(1),na));
3520         if (in < 0)
3521           {
3522             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3523               SvPV(ST(1),na));
3524             return;
3525           }
3526         op=(ComplexOperator) in;
3527       }
3528     else
3529       for (i=2; i < items; i+=2)
3530       {
3531         attribute=(char *) SvPV(ST(i-1),na);
3532         switch (*attribute)
3533         {
3534           case 'O':
3535           case 'o':
3536           {
3537             if (LocaleCompare(attribute,"operator") == 0)
3538               {
3539                 ssize_t
3540                   in;
3541
3542                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3543                   MagickComplexOptions,MagickFalse,SvPV(ST(i),na));
3544                 if (in < 0)
3545                   {
3546                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3547                       SvPV(ST(i),na));
3548                     return;
3549                   }
3550                 op=(ComplexOperator) in;
3551                 break;
3552               }
3553             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3554               attribute);
3555             break;
3556           }
3557           default:
3558           {
3559             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3560               attribute);
3561             break;
3562           }
3563         }
3564       }
3565     image=ComplexImages(image,op,exception);
3566     if (image == (Image *) NULL)
3567       goto PerlException;
3568     /*
3569       Create blessed Perl array for the returned image.
3570     */
3571     av=newAV();
3572     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3573     SvREFCNT_dec(av);
3574     AddImageToRegistry(sv,image);
3575     rv=newRV(sv);
3576     av_push(av,sv_bless(rv,hv));
3577     SvREFCNT_dec(sv);
3578     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3579     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
3580       "complex-%.*s",(int) (MagickPathExtent-9),
3581       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3582     (void) CopyMagickString(image->filename,info->image_info->filename,
3583       MagickPathExtent);
3584     SetImageInfo(info->image_info,0,exception);
3585     exception=DestroyExceptionInfo(exception);
3586     SvREFCNT_dec(perl_exception);
3587     XSRETURN(1);
3588
3589   PerlException:
3590     InheritPerlException(exception,perl_exception);
3591     exception=DestroyExceptionInfo(exception);
3592     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3593     SvPOK_on(perl_exception);
3594     ST(0)=sv_2mortal(perl_exception);
3595     XSRETURN(1);
3596   }
3597 \f
3598 #
3599 ###############################################################################
3600 #                                                                             #
3601 #                                                                             #
3602 #                                                                             #
3603 #   C o m p a r e L a y e r s                                                 #
3604 #                                                                             #
3605 #                                                                             #
3606 #                                                                             #
3607 ###############################################################################
3608 #
3609 #
3610 void
3611 CompareLayers(ref)
3612   Image::Magick ref=NO_INIT
3613   ALIAS:
3614     CompareImagesLayers   = 1
3615     comparelayers        = 2
3616     compareimagelayers   = 3
3617   PPCODE:
3618   {
3619     AV
3620       *av;
3621
3622     char
3623       *attribute;
3624
3625     ExceptionInfo
3626       *exception;
3627
3628     HV
3629       *hv;
3630
3631     Image
3632       *image;
3633
3634     LayerMethod
3635       method;
3636
3637     register ssize_t
3638       i;
3639
3640     ssize_t
3641       option;
3642
3643     struct PackageInfo
3644       *info;
3645
3646     SV
3647       *av_reference,
3648       *perl_exception,
3649       *reference,
3650       *rv,
3651       *sv;
3652
3653     PERL_UNUSED_VAR(ref);
3654     PERL_UNUSED_VAR(ix);
3655     exception=AcquireExceptionInfo();
3656     perl_exception=newSVpv("",0);
3657     sv=NULL;
3658     if (sv_isobject(ST(0)) == 0)
3659       {
3660         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3661           PackageName);
3662         goto PerlException;
3663       }
3664     reference=SvRV(ST(0));
3665     hv=SvSTASH(reference);
3666     av=newAV();
3667     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3668     SvREFCNT_dec(av);
3669     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3670     if (image == (Image *) NULL)
3671       {
3672         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3673           PackageName);
3674         goto PerlException;
3675       }
3676     method=CompareAnyLayer;
3677     for (i=2; i < items; i+=2)
3678     {
3679       attribute=(char *) SvPV(ST(i-1),na);
3680       switch (*attribute)
3681       {
3682         case 'M':
3683         case 'm':
3684         {
3685           if (LocaleCompare(attribute,"method") == 0)
3686             {
3687               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3688                 SvPV(ST(i),na));
3689               if (option < 0)
3690                 {
3691                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3692                     SvPV(ST(i),na));
3693                   break;
3694                 }
3695                method=(LayerMethod) option;
3696               break;
3697             }
3698           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3699             attribute);
3700           break;
3701         }
3702         default:
3703         {
3704           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3705             attribute);
3706           break;
3707         }
3708       }
3709     }
3710     image=CompareImagesLayers(image,method,exception);
3711     if (image == (Image *) NULL)
3712       goto PerlException;
3713     for ( ; image; image=image->next)
3714     {
3715       AddImageToRegistry(sv,image);
3716       rv=newRV(sv);
3717       av_push(av,sv_bless(rv,hv));
3718       SvREFCNT_dec(sv);
3719     }
3720     exception=DestroyExceptionInfo(exception);
3721     ST(0)=av_reference;
3722     SvREFCNT_dec(perl_exception);
3723     XSRETURN(1);
3724
3725   PerlException:
3726     InheritPerlException(exception,perl_exception);
3727     exception=DestroyExceptionInfo(exception);
3728     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3729     SvPOK_on(perl_exception);
3730     ST(0)=sv_2mortal(perl_exception);
3731     XSRETURN(1);
3732   }
3733 \f
3734 #
3735 ###############################################################################
3736 #                                                                             #
3737 #                                                                             #
3738 #                                                                             #
3739 #   D e s t r o y                                                             #
3740 #                                                                             #
3741 #                                                                             #
3742 #                                                                             #
3743 ###############################################################################
3744 #
3745 #
3746 void
3747 DESTROY(ref)
3748   Image::Magick ref=NO_INIT
3749   PPCODE:
3750   {
3751     SV
3752       *reference;
3753
3754     PERL_UNUSED_VAR(ref);
3755     if (sv_isobject(ST(0)) == 0)
3756       croak("ReferenceIsNotMyType");
3757     reference=SvRV(ST(0));
3758     switch (SvTYPE(reference))
3759     {
3760       case SVt_PVAV:
3761       {
3762         char
3763           message[MagickPathExtent];
3764
3765         const SV
3766           *key;
3767
3768         HV
3769           *hv;
3770
3771         GV
3772           **gvp;
3773
3774         struct PackageInfo
3775           *info;
3776
3777         SV
3778           *sv;
3779
3780         /*
3781           Array (AV *) reference
3782         */
3783         (void) FormatLocaleString(message,MagickPathExtent,"package%s%p",
3784           XS_VERSION,reference);
3785         hv=gv_stashpv(PackageName, FALSE);
3786         if (!hv)
3787           break;
3788         gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3789         if (!gvp)
3790           break;
3791         sv=GvSV(*gvp);
3792         if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3793           {
3794             info=INT2PTR(struct PackageInfo *,SvIV(sv));
3795             DestroyPackageInfo(info);
3796           }
3797         key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3798         (void) key;
3799         break;
3800       }
3801       case SVt_PVMG:
3802       {
3803         Image
3804           *image;
3805
3806         /*
3807           Blessed scalar = (Image *) SvIV(reference)
3808         */
3809         image=INT2PTR(Image *,SvIV(reference));
3810         if (image != (Image *) NULL)
3811           DeleteImageFromRegistry(reference,image);
3812         break;
3813       }
3814       default:
3815         break;
3816     }
3817   }
3818 \f
3819 #
3820 ###############################################################################
3821 #                                                                             #
3822 #                                                                             #
3823 #                                                                             #
3824 #   D i s p l a y                                                             #
3825 #                                                                             #
3826 #                                                                             #
3827 #                                                                             #
3828 ###############################################################################
3829 #
3830 #
3831 void
3832 Display(ref,...)
3833   Image::Magick ref=NO_INIT
3834   ALIAS:
3835     DisplayImage  = 1
3836     display       = 2
3837     displayimage  = 3
3838   PPCODE:
3839   {
3840     ExceptionInfo
3841       *exception;
3842
3843     Image
3844       *image;
3845
3846     register ssize_t
3847       i;
3848
3849     struct PackageInfo
3850       *info,
3851       *package_info;
3852
3853     SV
3854       *perl_exception,
3855       *reference;
3856
3857     PERL_UNUSED_VAR(ref);
3858     PERL_UNUSED_VAR(ix);
3859     exception=AcquireExceptionInfo();
3860     perl_exception=newSVpv("",0);
3861     package_info=(struct PackageInfo *) NULL;
3862     if (sv_isobject(ST(0)) == 0)
3863       {
3864         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3865           PackageName);
3866         goto PerlException;
3867       }
3868     reference=SvRV(ST(0));
3869     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3870     if (image == (Image *) NULL)
3871       {
3872         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3873           PackageName);
3874         goto PerlException;
3875       }
3876     package_info=ClonePackageInfo(info,exception);
3877     if (items == 2)
3878       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3879     else
3880       if (items > 2)
3881         for (i=2; i < items; i+=2)
3882           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3883             exception);
3884     (void) DisplayImages(package_info->image_info,image,exception);
3885     (void) CatchImageException(image);
3886
3887   PerlException:
3888     if (package_info != (struct PackageInfo *) NULL)
3889       DestroyPackageInfo(package_info);
3890     InheritPerlException(exception,perl_exception);
3891     exception=DestroyExceptionInfo(exception);
3892     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3893     SvPOK_on(perl_exception);
3894     ST(0)=sv_2mortal(perl_exception);
3895     XSRETURN(1);
3896   }
3897 \f
3898 #
3899 ###############################################################################
3900 #                                                                             #
3901 #                                                                             #
3902 #                                                                             #
3903 #   E v a l u a t e I m a g e s                                               #
3904 #                                                                             #
3905 #                                                                             #
3906 #                                                                             #
3907 ###############################################################################
3908 #
3909 #
3910 void
3911 EvaluateImages(ref)
3912   Image::Magick ref=NO_INIT
3913   ALIAS:
3914     EvaluateImages   = 1
3915     evaluateimages   = 2
3916   PPCODE:
3917   {
3918     AV
3919       *av;
3920
3921     char
3922       *attribute,
3923       *p;
3924
3925     ExceptionInfo
3926       *exception;
3927
3928     HV
3929       *hv;
3930
3931     Image
3932       *image;
3933
3934     MagickEvaluateOperator
3935       op;
3936
3937     register ssize_t
3938       i;
3939
3940     struct PackageInfo
3941       *info;
3942
3943     SV
3944       *perl_exception,
3945       *reference,
3946       *rv,
3947       *sv;
3948
3949     PERL_UNUSED_VAR(ref);
3950     PERL_UNUSED_VAR(ix);
3951     exception=AcquireExceptionInfo();
3952     perl_exception=newSVpv("",0);
3953     sv=NULL;
3954     if (sv_isobject(ST(0)) == 0)
3955       {
3956         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3957           PackageName);
3958         goto PerlException;
3959       }
3960     reference=SvRV(ST(0));
3961     hv=SvSTASH(reference);
3962     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3963     if (image == (Image *) NULL)
3964       {
3965         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3966           PackageName);
3967         goto PerlException;
3968       }
3969     op=MeanEvaluateOperator;
3970     if (items == 2)
3971       {
3972         ssize_t
3973           in;
3974
3975         in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
3976           SvPV(ST(1),na));
3977         if (in < 0)
3978           {
3979             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3980               SvPV(ST(1),na));
3981             return;
3982           }
3983         op=(MagickEvaluateOperator) in;
3984       }
3985     else
3986       for (i=2; i < items; i+=2)
3987       {
3988         attribute=(char *) SvPV(ST(i-1),na);
3989         switch (*attribute)
3990         {
3991           case 'O':
3992           case 'o':
3993           {
3994             if (LocaleCompare(attribute,"operator") == 0)
3995               {
3996                 ssize_t
3997                   in;
3998
3999                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
4000                   MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
4001                 if (in < 0)
4002                   {
4003                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
4004                       SvPV(ST(i),na));
4005                     return;
4006                   }
4007                 op=(MagickEvaluateOperator) in;
4008                 break;
4009               }
4010             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4011               attribute);
4012             break;
4013           }
4014           default:
4015           {
4016             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4017               attribute);
4018             break;
4019           }
4020         }
4021       }
4022     image=EvaluateImages(image,op,exception);
4023     if (image == (Image *) NULL)
4024       goto PerlException;
4025     /*
4026       Create blessed Perl array for the returned image.
4027     */
4028     av=newAV();
4029     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4030     SvREFCNT_dec(av);
4031     AddImageToRegistry(sv,image);
4032     rv=newRV(sv);
4033     av_push(av,sv_bless(rv,hv));
4034     SvREFCNT_dec(sv);
4035     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4036     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4037       "evaluate-%.*s",(int) (MagickPathExtent-9),
4038       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4039     (void) CopyMagickString(image->filename,info->image_info->filename,
4040       MagickPathExtent);
4041     SetImageInfo(info->image_info,0,exception);
4042     exception=DestroyExceptionInfo(exception);
4043     SvREFCNT_dec(perl_exception);
4044     XSRETURN(1);
4045
4046   PerlException:
4047     InheritPerlException(exception,perl_exception);
4048     exception=DestroyExceptionInfo(exception);
4049     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4050     SvPOK_on(perl_exception);
4051     ST(0)=sv_2mortal(perl_exception);
4052     XSRETURN(1);
4053   }
4054 \f
4055 #
4056 ###############################################################################
4057 #                                                                             #
4058 #                                                                             #
4059 #                                                                             #
4060 #   F e a t u r e s                                                           #
4061 #                                                                             #
4062 #                                                                             #
4063 #                                                                             #
4064 ###############################################################################
4065 #
4066 #
4067 void
4068 Features(ref,...)
4069   Image::Magick ref=NO_INIT
4070   ALIAS:
4071     FeaturesImage = 1
4072     features      = 2
4073     featuresimage = 3
4074   PPCODE:
4075   {
4076 #define ChannelFeatures(channel,direction) \
4077 { \
4078   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4079     channel_features[channel].angular_second_moment[direction]); \
4080   PUSHs(sv_2mortal(newSVpv(message,0))); \
4081   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4082     channel_features[channel].contrast[direction]); \
4083   PUSHs(sv_2mortal(newSVpv(message,0))); \
4084   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4085     channel_features[channel].contrast[direction]); \
4086   PUSHs(sv_2mortal(newSVpv(message,0))); \
4087   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4088     channel_features[channel].variance_sum_of_squares[direction]); \
4089   PUSHs(sv_2mortal(newSVpv(message,0))); \
4090   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4091     channel_features[channel].inverse_difference_moment[direction]); \
4092   PUSHs(sv_2mortal(newSVpv(message,0))); \
4093   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4094     channel_features[channel].sum_average[direction]); \
4095   PUSHs(sv_2mortal(newSVpv(message,0))); \
4096   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4097     channel_features[channel].sum_variance[direction]); \
4098   PUSHs(sv_2mortal(newSVpv(message,0))); \
4099   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4100     channel_features[channel].sum_entropy[direction]); \
4101   PUSHs(sv_2mortal(newSVpv(message,0))); \
4102   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4103     channel_features[channel].entropy[direction]); \
4104   PUSHs(sv_2mortal(newSVpv(message,0))); \
4105   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4106     channel_features[channel].difference_variance[direction]); \
4107   PUSHs(sv_2mortal(newSVpv(message,0))); \
4108   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4109     channel_features[channel].difference_entropy[direction]); \
4110   PUSHs(sv_2mortal(newSVpv(message,0))); \
4111   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4112     channel_features[channel].measure_of_correlation_1[direction]); \
4113   PUSHs(sv_2mortal(newSVpv(message,0))); \
4114   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4115     channel_features[channel].measure_of_correlation_2[direction]); \
4116   PUSHs(sv_2mortal(newSVpv(message,0))); \
4117   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4118     channel_features[channel].maximum_correlation_coefficient[direction]); \
4119   PUSHs(sv_2mortal(newSVpv(message,0))); \
4120 }
4121
4122     AV
4123       *av;
4124
4125     char
4126       *attribute,
4127       message[MagickPathExtent];
4128
4129     ChannelFeatures
4130       *channel_features;
4131
4132     double
4133       distance;
4134
4135     ExceptionInfo
4136       *exception;
4137
4138     Image
4139       *image;
4140
4141     register ssize_t
4142       i;
4143
4144     ssize_t
4145       count;
4146
4147     struct PackageInfo
4148       *info;
4149
4150     SV
4151       *perl_exception,
4152       *reference;
4153
4154     PERL_UNUSED_VAR(ref);
4155     PERL_UNUSED_VAR(ix);
4156     exception=AcquireExceptionInfo();
4157     perl_exception=newSVpv("",0);
4158     av=NULL;
4159     if (sv_isobject(ST(0)) == 0)
4160       {
4161         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4162           PackageName);
4163         goto PerlException;
4164       }
4165     reference=SvRV(ST(0));
4166     av=newAV();
4167     SvREFCNT_dec(av);
4168     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4169     if (image == (Image *) NULL)
4170       {
4171         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4172           PackageName);
4173         goto PerlException;
4174       }
4175     distance=1.0;
4176     for (i=2; i < items; i+=2)
4177     {
4178       attribute=(char *) SvPV(ST(i-1),na);
4179       switch (*attribute)
4180       {
4181         case 'D':
4182         case 'd':
4183         {
4184           if (LocaleCompare(attribute,"distance") == 0)
4185             {
4186               distance=StringToLong((char *) SvPV(ST(1),na));
4187               break;
4188             }
4189           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4190             attribute);
4191           break;
4192         }
4193         default:
4194         {
4195           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4196             attribute);
4197           break;
4198         }
4199       }
4200     }
4201     count=0;
4202     for ( ; image; image=image->next)
4203     {
4204       channel_features=GetImageFeatures(image,distance,exception);
4205       if (channel_features == (ChannelFeatures *) NULL)
4206         continue;
4207       count++;
4208       EXTEND(sp,280*count);
4209       for (i=0; i < 4; i++)
4210       {
4211         ChannelFeatures(RedChannel,i);
4212         ChannelFeatures(GreenChannel,i);
4213         ChannelFeatures(BlueChannel,i);
4214         if (image->colorspace == CMYKColorspace)
4215           ChannelFeatures(BlackChannel,i);
4216         if (image->alpha_trait != UndefinedPixelTrait)
4217           ChannelFeatures(AlphaChannel,i);
4218       }
4219       channel_features=(ChannelFeatures *)
4220         RelinquishMagickMemory(channel_features);
4221     }
4222
4223   PerlException:
4224     InheritPerlException(exception,perl_exception);
4225     exception=DestroyExceptionInfo(exception);
4226     SvREFCNT_dec(perl_exception);
4227   }
4228 \f
4229 #
4230 ###############################################################################
4231 #                                                                             #
4232 #                                                                             #
4233 #                                                                             #
4234 #   F l a t t e n                                                             #
4235 #                                                                             #
4236 #                                                                             #
4237 #                                                                             #
4238 ###############################################################################
4239 #
4240 #
4241 void
4242 Flatten(ref)
4243   Image::Magick ref=NO_INIT
4244   ALIAS:
4245     FlattenImage   = 1
4246     flatten        = 2
4247     flattenimage   = 3
4248   PPCODE:
4249   {
4250     AV
4251       *av;
4252
4253     char
4254       *attribute,
4255       *p;
4256
4257     ExceptionInfo
4258       *exception;
4259
4260     HV
4261       *hv;
4262
4263     Image
4264       *image;
4265
4266     PixelInfo
4267       background_color;
4268
4269     register ssize_t
4270       i;
4271
4272     struct PackageInfo
4273       *info;
4274
4275     SV
4276       *perl_exception,
4277       *reference,
4278       *rv,
4279       *sv;
4280
4281     PERL_UNUSED_VAR(ref);
4282     PERL_UNUSED_VAR(ix);
4283     exception=AcquireExceptionInfo();
4284     perl_exception=newSVpv("",0);
4285     sv=NULL;
4286     if (sv_isobject(ST(0)) == 0)
4287       {
4288         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4289           PackageName);
4290         goto PerlException;
4291       }
4292     reference=SvRV(ST(0));
4293     hv=SvSTASH(reference);
4294     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4295     if (image == (Image *) NULL)
4296       {
4297         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4298           PackageName);
4299         goto PerlException;
4300       }
4301     background_color=image->background_color;
4302     if (items == 2)
4303       (void) QueryColorCompliance((char *) SvPV(ST(1),na),AllCompliance,
4304         &background_color,exception);
4305     else
4306       for (i=2; i < items; i+=2)
4307       {
4308         attribute=(char *) SvPV(ST(i-1),na);
4309         switch (*attribute)
4310         {
4311           case 'B':
4312           case 'b':
4313           {
4314             if (LocaleCompare(attribute,"background") == 0)
4315               {
4316                 (void) QueryColorCompliance((char *) SvPV(ST(1),na),
4317                   AllCompliance,&background_color,exception);
4318                 break;
4319               }
4320             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4321               attribute);
4322             break;
4323           }
4324           default:
4325           {
4326             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4327               attribute);
4328             break;
4329           }
4330         }
4331       }
4332     image->background_color=background_color;
4333     image=MergeImageLayers(image,FlattenLayer,exception);
4334     if (image == (Image *) NULL)
4335       goto PerlException;
4336     /*
4337       Create blessed Perl array for the returned image.
4338     */
4339     av=newAV();
4340     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4341     SvREFCNT_dec(av);
4342     AddImageToRegistry(sv,image);
4343     rv=newRV(sv);
4344     av_push(av,sv_bless(rv,hv));
4345     SvREFCNT_dec(sv);
4346     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4347     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4348       "flatten-%.*s",(int) (MagickPathExtent-9),
4349       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4350     (void) CopyMagickString(image->filename,info->image_info->filename,
4351       MagickPathExtent);
4352     SetImageInfo(info->image_info,0,exception);
4353     exception=DestroyExceptionInfo(exception);
4354     SvREFCNT_dec(perl_exception);
4355     XSRETURN(1);
4356
4357   PerlException:
4358     InheritPerlException(exception,perl_exception);
4359     exception=DestroyExceptionInfo(exception);
4360     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4361     SvPOK_on(perl_exception);  /* return messages in string context */
4362     ST(0)=sv_2mortal(perl_exception);
4363     XSRETURN(1);
4364   }
4365 \f
4366 #
4367 ###############################################################################
4368 #                                                                             #
4369 #                                                                             #
4370 #                                                                             #
4371 #   F x                                                                       #
4372 #                                                                             #
4373 #                                                                             #
4374 #                                                                             #
4375 ###############################################################################
4376 #
4377 #
4378 void
4379 Fx(ref,...)
4380   Image::Magick ref=NO_INIT
4381   ALIAS:
4382     FxImage  = 1
4383     fx       = 2
4384     fximage  = 3
4385   PPCODE:
4386   {
4387     AV
4388       *av;
4389
4390     char
4391       *attribute,
4392       expression[MagickPathExtent];
4393
4394     ChannelType
4395       channel,
4396       channel_mask;
4397
4398     ExceptionInfo
4399       *exception;
4400
4401     HV
4402       *hv;
4403
4404     Image
4405       *image;
4406
4407     register ssize_t
4408       i;
4409
4410     struct PackageInfo
4411       *info;
4412
4413     SV
4414       *av_reference,
4415       *perl_exception,
4416       *reference,
4417       *rv,
4418       *sv;
4419
4420     PERL_UNUSED_VAR(ref);
4421     PERL_UNUSED_VAR(ix);
4422     exception=AcquireExceptionInfo();
4423     perl_exception=newSVpv("",0);
4424     sv=NULL;
4425     attribute=NULL;
4426     av=NULL;
4427     if (sv_isobject(ST(0)) == 0)
4428       {
4429         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4430           PackageName);
4431         goto PerlException;
4432       }
4433     reference=SvRV(ST(0));
4434     hv=SvSTASH(reference);
4435     av=newAV();
4436     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4437     SvREFCNT_dec(av);
4438     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4439     if (image == (Image *) NULL)
4440       {
4441         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4442           PackageName);
4443         goto PerlException;
4444       }
4445     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4446     /*
4447       Get options.
4448     */
4449     channel=DefaultChannels;
4450     (void) CopyMagickString(expression,"u",MagickPathExtent);
4451     if (items == 2)
4452       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
4453     else
4454       for (i=2; i < items; i+=2)
4455       {
4456         attribute=(char *) SvPV(ST(i-1),na);
4457         switch (*attribute)
4458         {
4459           case 'C':
4460           case 'c':
4461           {
4462             if (LocaleCompare(attribute,"channel") == 0)
4463               {
4464                 ssize_t
4465                   option;
4466
4467                 option=ParseChannelOption(SvPV(ST(i),na));
4468                 if (option < 0)
4469                   {
4470                     ThrowPerlException(exception,OptionError,
4471                       "UnrecognizedType",SvPV(ST(i),na));
4472                     return;
4473                   }
4474                 channel=(ChannelType) option;
4475                 break;
4476               }
4477             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4478               attribute);
4479             break;
4480           }
4481           case 'E':
4482           case 'e':
4483           {
4484             if (LocaleCompare(attribute,"expression") == 0)
4485               {
4486                 (void) CopyMagickString(expression,SvPV(ST(i),na),
4487                   MagickPathExtent);
4488                 break;
4489               }
4490             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4491               attribute);
4492             break;
4493           }
4494           default:
4495           {
4496             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4497               attribute);
4498             break;
4499           }
4500         }
4501       }
4502     channel_mask=SetImageChannelMask(image,channel);
4503     image=FxImage(image,expression,exception);
4504     if (image != (Image *) NULL)
4505       (void) SetImageChannelMask(image,channel_mask);
4506     if (image == (Image *) NULL)
4507       goto PerlException;
4508     for ( ; image; image=image->next)
4509     {
4510       AddImageToRegistry(sv,image);
4511       rv=newRV(sv);
4512       av_push(av,sv_bless(rv,hv));
4513       SvREFCNT_dec(sv);
4514     }
4515     exception=DestroyExceptionInfo(exception);
4516     ST(0)=av_reference;
4517     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4518     XSRETURN(1);
4519
4520   PerlException:
4521     InheritPerlException(exception,perl_exception);
4522     exception=DestroyExceptionInfo(exception);
4523     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4524     SvPOK_on(perl_exception);
4525     ST(0)=sv_2mortal(perl_exception);
4526     XSRETURN(1);
4527   }
4528 \f
4529 #
4530 ###############################################################################
4531 #                                                                             #
4532 #                                                                             #
4533 #                                                                             #
4534 #   G e t                                                                     #
4535 #                                                                             #
4536 #                                                                             #
4537 #                                                                             #
4538 ###############################################################################
4539 #
4540 #
4541 void
4542 Get(ref,...)
4543   Image::Magick ref=NO_INIT
4544   ALIAS:
4545     GetAttributes = 1
4546     GetAttribute  = 2
4547     get           = 3
4548     getattributes = 4
4549     getattribute  = 5
4550   PPCODE:
4551   {
4552     char
4553       *attribute,
4554       color[MagickPathExtent];
4555
4556     const char
4557       *value;
4558
4559     ExceptionInfo
4560       *exception;
4561
4562     Image
4563       *image;
4564
4565     long
4566       j;
4567
4568     register ssize_t
4569       i;
4570
4571     struct PackageInfo
4572       *info;
4573
4574     SV
4575       *perl_exception,
4576       *reference,
4577       *s;
4578
4579     PERL_UNUSED_VAR(ref);
4580     PERL_UNUSED_VAR(ix);
4581     exception=AcquireExceptionInfo();
4582     perl_exception=newSVpv("",0);
4583     if (sv_isobject(ST(0)) == 0)
4584       {
4585         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4586           PackageName);
4587         XSRETURN_EMPTY;
4588       }
4589     reference=SvRV(ST(0));
4590     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4591     if (image == (Image *) NULL && !info)
4592       XSRETURN_EMPTY;
4593     EXTEND(sp,items);
4594     for (i=1; i < items; i++)
4595     {
4596       attribute=(char *) SvPV(ST(i),na);
4597       s=NULL;
4598       switch (*attribute)
4599       {
4600         case 'A':
4601         case 'a':
4602         {
4603           if (LocaleCompare(attribute,"adjoin") == 0)
4604             {
4605               if (info)
4606                 s=newSViv((ssize_t) info->image_info->adjoin);
4607               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4608               continue;
4609             }
4610           if (LocaleCompare(attribute,"antialias") == 0)
4611             {
4612               if (info)
4613                 s=newSViv((ssize_t) info->image_info->antialias);
4614               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4615               continue;
4616             }
4617           if (LocaleCompare(attribute,"area") == 0)
4618             {
4619               s=newSViv(GetMagickResource(AreaResource));
4620               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4621               continue;
4622             }
4623           if (LocaleCompare(attribute,"attenuate") == 0)
4624             {
4625               const char
4626                 *value;
4627
4628               value=GetImageProperty(image,attribute,exception);
4629               if (value != (const char *) NULL)
4630                 s=newSVpv(value,0);
4631               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4632               continue;
4633             }
4634           if (LocaleCompare(attribute,"authenticate") == 0)
4635             {
4636               if (info)
4637                 {
4638                   const char
4639                     *option;
4640
4641                   option=GetImageOption(info->image_info,attribute);
4642                   if (option != (const char *) NULL)
4643                     s=newSVpv(option,0);
4644                 }
4645               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4646               continue;
4647             }
4648           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4649             attribute);
4650           break;
4651         }
4652         case 'B':
4653         case 'b':
4654         {
4655           if (LocaleCompare(attribute,"background") == 0)
4656             {
4657               if (image == (Image *) NULL)
4658                 break;
4659               (void) FormatLocaleString(color,MagickPathExtent,
4660                 "%.20g,%.20g,%.20g,%.20g",(double) image->background_color.red,
4661                 (double) image->background_color.green,
4662                 (double) image->background_color.blue,
4663                 (double) image->background_color.alpha);
4664               s=newSVpv(color,0);
4665               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4666               continue;
4667             }
4668           if (LocaleCompare(attribute,"base-columns") == 0)
4669             {
4670               if (image != (Image *) NULL)
4671                 s=newSViv((ssize_t) image->magick_columns);
4672               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4673               continue;
4674             }
4675           if (LocaleCompare(attribute,"base-filename") == 0)
4676             {
4677               if (image != (Image *) NULL)
4678                 s=newSVpv(image->magick_filename,0);
4679               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4680               continue;
4681             }
4682           if (LocaleCompare(attribute,"base-height") == 0)
4683             {
4684               if (image != (Image *) NULL)
4685                 s=newSViv((ssize_t) image->magick_rows);
4686               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4687               continue;
4688             }
4689           if (LocaleCompare(attribute,"base-rows") == 0)
4690             {
4691               if (image != (Image *) NULL)
4692                 s=newSViv((ssize_t) image->magick_rows);
4693               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4694               continue;
4695             }
4696           if (LocaleCompare(attribute,"base-width") == 0)
4697             {
4698               if (image != (Image *) NULL)
4699                 s=newSViv((ssize_t) image->magick_columns);
4700               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4701               continue;
4702             }
4703           if (LocaleCompare(attribute,"blue-primary") == 0)
4704             {
4705               if (image == (Image *) NULL)
4706                 break;
4707               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
4708                 image->chromaticity.blue_primary.x,
4709                 image->chromaticity.blue_primary.y);
4710               s=newSVpv(color,0);
4711               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4712               continue;
4713             }
4714           if (LocaleCompare(attribute,"bordercolor") == 0)
4715             {
4716               if (image == (Image *) NULL)
4717                 break;
4718               (void) FormatLocaleString(color,MagickPathExtent,
4719                 "%.20g,%.20g,%.20g,%.20g",(double) image->border_color.red,
4720                 (double) image->border_color.green,
4721                 (double) image->border_color.blue,
4722                 (double) image->border_color.alpha);
4723               s=newSVpv(color,0);
4724               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4725               continue;
4726             }
4727           if (LocaleCompare(attribute,"bounding-box") == 0)
4728             {
4729               char
4730                 geometry[MagickPathExtent];
4731
4732               RectangleInfo
4733                 page;
4734
4735               if (image == (Image *) NULL)
4736                 break;
4737               page=GetImageBoundingBox(image,exception);
4738               (void) FormatLocaleString(geometry,MagickPathExtent,
4739                 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4740                 page.height,(double) page.x,(double) page.y);
4741               s=newSVpv(geometry,0);
4742               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4743               continue;
4744             }
4745           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4746             attribute);
4747           break;
4748         }
4749         case 'C':
4750         case 'c':
4751         {
4752           if (LocaleCompare(attribute,"class") == 0)
4753             {
4754               if (image == (Image *) NULL)
4755                 break;
4756               s=newSViv(image->storage_class);
4757               (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4758                 image->storage_class));
4759               SvIOK_on(s);
4760               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4761               continue;
4762             }
4763           if (LocaleCompare(attribute,"clip-mask") == 0)
4764             {
4765               if (image != (Image *) NULL)
4766                 {
4767                   Image
4768                     *mask_image;
4769
4770                   SV
4771                     *sv;
4772
4773                   sv=NULL;
4774                   if (image->read_mask == MagickFalse)
4775                     ClipImage(image,exception);
4776                   mask_image=GetImageMask(image,ReadPixelMask,exception);
4777                   if (mask_image != (Image *) NULL)
4778                     {
4779                       AddImageToRegistry(sv,mask_image);
4780                       s=sv_bless(newRV(sv),SvSTASH(reference));
4781                     }
4782                 }
4783               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4784               continue;
4785             }
4786           if (LocaleCompare(attribute,"clip-path") == 0)
4787             {
4788               if (image != (Image *) NULL)
4789                 {
4790                   Image
4791                     *mask_image;
4792
4793                   SV
4794                     *sv;
4795
4796                   sv=NULL;
4797                   if (image->read_mask != MagickFalse)
4798                     ClipImage(image,exception);
4799                   mask_image=GetImageMask(image,ReadPixelMask,exception);
4800                   if (mask_image != (Image *) NULL)
4801                     {
4802                       AddImageToRegistry(sv,mask_image);
4803                       s=sv_bless(newRV(sv),SvSTASH(reference));
4804                     }
4805                 }
4806               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4807               continue;
4808             }
4809           if (LocaleCompare(attribute,"compression") == 0)
4810             {
4811               j=info ? info->image_info->compression : image ?
4812                 image->compression : UndefinedCompression;
4813               if (info)
4814                 if (info->image_info->compression == UndefinedCompression)
4815                   j=image->compression;
4816               s=newSViv(j);
4817               (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4818                 j));
4819               SvIOK_on(s);
4820               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4821               continue;
4822             }
4823           if (LocaleCompare(attribute,"colorspace") == 0)
4824             {
4825               j=image ? image->colorspace : RGBColorspace;
4826               s=newSViv(j);
4827               (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4828                 j));
4829               SvIOK_on(s);
4830               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4831               continue;
4832             }
4833           if (LocaleCompare(attribute,"colors") == 0)
4834             {
4835               if (image != (Image *) NULL)
4836                 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4837                   exception));
4838               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4839               continue;
4840             }
4841           if (LocaleNCompare(attribute,"colormap",8) == 0)
4842             {
4843               int
4844                 items;
4845
4846               if (image == (Image *) NULL || !image->colormap)
4847                 break;
4848               j=0;
4849               items=sscanf(attribute,"%*[^[][%ld",&j);
4850               (void) items;
4851               if (j > (ssize_t) image->colors)
4852                 j%=image->colors;
4853               (void) FormatLocaleString(color,MagickPathExtent,
4854                 "%.20g,%.20g,%.20g,%.20g",(double) image->colormap[j].red,
4855                 (double) image->colormap[j].green,
4856                 (double) image->colormap[j].blue,
4857                 (double) image->colormap[j].alpha);
4858               s=newSVpv(color,0);
4859               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4860               continue;
4861             }
4862           if (LocaleCompare(attribute,"columns") == 0)
4863             {
4864               if (image != (Image *) NULL)
4865                 s=newSViv((ssize_t) image->columns);
4866               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4867               continue;
4868             }
4869           if (LocaleCompare(attribute,"comment") == 0)
4870             {
4871               const char
4872                 *value;
4873
4874               value=GetImageProperty(image,attribute,exception);
4875               if (value != (const char *) NULL)
4876                 s=newSVpv(value,0);
4877               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4878               continue;
4879             }
4880           if (LocaleCompare(attribute,"copyright") == 0)
4881             {
4882               s=newSVpv(GetMagickCopyright(),0);
4883               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4884               continue;
4885             }
4886           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4887             attribute);
4888           break;
4889         }
4890         case 'D':
4891         case 'd':
4892         {
4893           if (LocaleCompare(attribute,"density") == 0)
4894             {
4895               char
4896                 geometry[MagickPathExtent];
4897
4898               if (image == (Image *) NULL)
4899                 break;
4900               (void) FormatLocaleString(geometry,MagickPathExtent,"%.15gx%.15g",
4901                 image->resolution.x,image->resolution.y);
4902               s=newSVpv(geometry,0);
4903               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4904               continue;
4905             }
4906           if (LocaleCompare(attribute,"delay") == 0)
4907             {
4908               if (image != (Image *) NULL)
4909                 s=newSViv((ssize_t) image->delay);
4910               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4911               continue;
4912             }
4913           if (LocaleCompare(attribute,"depth") == 0)
4914             {
4915               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4916               if (image != (Image *) NULL)
4917                 s=newSViv((ssize_t) GetImageDepth(image,exception));
4918               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4919               continue;
4920             }
4921           if (LocaleCompare(attribute,"directory") == 0)
4922             {
4923               if (image && image->directory)
4924                 s=newSVpv(image->directory,0);
4925               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4926               continue;
4927             }
4928           if (LocaleCompare(attribute,"dispose") == 0)
4929             {
4930               if (image == (Image *) NULL)
4931                 break;
4932
4933               s=newSViv(image->dispose);
4934               (void) sv_setpv(s,
4935                 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
4936               SvIOK_on(s);
4937               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4938               continue;
4939             }
4940           if (LocaleCompare(attribute,"disk") == 0)
4941             {
4942               s=newSViv(GetMagickResource(DiskResource));
4943               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4944               continue;
4945             }
4946           if (LocaleCompare(attribute,"dither") == 0)
4947             {
4948               if (info)
4949                 s=newSViv((ssize_t) info->image_info->dither);
4950               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4951               continue;
4952             }
4953           if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4954             {
4955               if (info && info->image_info->server_name)
4956                 s=newSVpv(info->image_info->server_name,0);
4957               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4958               continue;
4959             }
4960           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4961             attribute);
4962           break;
4963         }
4964         case 'E':
4965         case 'e':
4966         {
4967           if (LocaleCompare(attribute,"elapsed-time") == 0)
4968             {
4969               if (image != (Image *) NULL)
4970                 s=newSVnv(GetElapsedTime(&image->timer));
4971               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4972               continue;
4973             }
4974           if (LocaleCompare(attribute,"endian") == 0)
4975             {
4976               j=info ? info->image_info->endian : image ? image->endian :
4977                 UndefinedEndian;
4978               s=newSViv(j);
4979               (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
4980               SvIOK_on(s);
4981               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4982               continue;
4983             }
4984           if (LocaleCompare(attribute,"error") == 0)
4985             {
4986               if (image != (Image *) NULL)
4987                 s=newSVnv(image->error.mean_error_per_pixel);
4988               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4989               continue;
4990             }
4991           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4992             attribute);
4993           break;
4994         }
4995         case 'F':
4996         case 'f':
4997         {
4998           if (LocaleCompare(attribute,"filesize") == 0)
4999             {
5000               if (image != (Image *) NULL)
5001                 s=newSViv((ssize_t) GetBlobSize(image));
5002               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5003               continue;
5004             }
5005           if (LocaleCompare(attribute,"filename") == 0)
5006             {
5007               if (info && info->image_info->filename &&
5008                   *info->image_info->filename)
5009                 s=newSVpv(info->image_info->filename,0);
5010               if (image != (Image *) NULL)
5011                 s=newSVpv(image->filename,0);
5012               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5013               continue;
5014             }
5015           if (LocaleCompare(attribute,"filter") == 0)
5016             {
5017               s=image ? newSViv(image->filter) : newSViv(0);
5018               (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
5019                 image->filter));
5020               SvIOK_on(s);
5021               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5022               continue;
5023             }
5024           if (LocaleCompare(attribute,"font") == 0)
5025             {
5026               if (info && info->image_info->font)
5027                 s=newSVpv(info->image_info->font,0);
5028               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5029               continue;
5030             }
5031           if (LocaleCompare(attribute,"foreground") == 0)
5032             continue;
5033           if (LocaleCompare(attribute,"format") == 0)
5034             {
5035               const MagickInfo
5036                 *magick_info;
5037
5038               magick_info=(const MagickInfo *) NULL;
5039               if (info && (*info->image_info->magick != '\0'))
5040                 magick_info=GetMagickInfo(info->image_info->magick,exception);
5041               if (image != (Image *) NULL)
5042                 magick_info=GetMagickInfo(image->magick,exception);
5043               if ((magick_info != (const MagickInfo *) NULL) &&
5044                   (*magick_info->description != '\0'))
5045                 s=newSVpv((char *) magick_info->description,0);
5046               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5047               continue;
5048             }
5049           if (LocaleCompare(attribute,"fuzz") == 0)
5050             {
5051               if (info)
5052                 s=newSVnv(info->image_info->fuzz);
5053               if (image != (Image *) NULL)
5054                 s=newSVnv(image->fuzz);
5055               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5056               continue;
5057             }
5058           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5059             attribute);
5060           break;
5061         }
5062         case 'G':
5063         case 'g':
5064         {
5065           if (LocaleCompare(attribute,"gamma") == 0)
5066             {
5067               if (image != (Image *) NULL)
5068                 s=newSVnv(image->gamma);
5069               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5070               continue;
5071             }
5072           if (LocaleCompare(attribute,"geometry") == 0)
5073             {
5074               if (image && image->geometry)
5075                 s=newSVpv(image->geometry,0);
5076               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5077               continue;
5078             }
5079           if (LocaleCompare(attribute,"gravity") == 0)
5080             {
5081               s=image ? newSViv(image->gravity) : newSViv(0);
5082               (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
5083                 image->gravity));
5084               SvIOK_on(s);
5085               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5086               continue;
5087             }
5088           if (LocaleCompare(attribute,"green-primary") == 0)
5089             {
5090               if (image == (Image *) NULL)
5091                 break;
5092               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
5093                 image->chromaticity.green_primary.x,
5094                 image->chromaticity.green_primary.y);
5095               s=newSVpv(color,0);
5096               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5097               continue;
5098             }
5099           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5100             attribute);
5101           break;
5102         }
5103         case 'H':
5104         case 'h':
5105         {
5106           if (LocaleCompare(attribute,"height") == 0)
5107             {
5108               if (image != (Image *) NULL)
5109                 s=newSViv((ssize_t) image->rows);
5110               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5111               continue;
5112             }
5113           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5114             attribute);
5115           break;
5116         }
5117         case 'I':
5118         case 'i':
5119         {
5120           if (LocaleCompare(attribute,"icc") == 0)
5121             {
5122               if (image != (Image *) NULL)
5123                 {
5124                   const StringInfo
5125                     *profile;
5126
5127                   profile=GetImageProfile(image,"icc");
5128                   if (profile != (StringInfo *) NULL)
5129                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5130                       GetStringInfoLength(profile));
5131                 }
5132               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5133               continue;
5134             }
5135           if (LocaleCompare(attribute,"icm") == 0)
5136             {
5137               if (image != (Image *) NULL)
5138                 {
5139                   const StringInfo
5140                     *profile;
5141
5142                   profile=GetImageProfile(image,"icm");
5143                   if (profile != (const StringInfo *) NULL)
5144                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5145                       GetStringInfoLength(profile));
5146                 }
5147               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5148               continue;
5149             }
5150           if (LocaleCompare(attribute,"id") == 0)
5151             {
5152               if (image != (Image *) NULL)
5153                 {
5154                   char
5155                     key[MagickPathExtent];
5156
5157                   MagickBooleanType
5158                     status;
5159
5160                   static ssize_t
5161                     id = 0;
5162
5163                   (void) FormatLocaleString(key,MagickPathExtent,"%.20g\n",(double)
5164                     id);
5165                   status=SetImageRegistry(ImageRegistryType,key,image,
5166                     exception);
5167                   (void) status;
5168                   s=newSViv(id++);
5169                 }
5170               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5171               continue;
5172             }
5173           if (LocaleNCompare(attribute,"index",5) == 0)
5174             {
5175               char
5176                 name[MagickPathExtent];
5177
5178               int
5179                 items;
5180
5181               long
5182                 x,
5183                 y;
5184
5185               register const Quantum
5186                 *p;
5187
5188               CacheView
5189                 *image_view;
5190
5191               if (image == (Image *) NULL)
5192                 break;
5193               if (image->storage_class != PseudoClass)
5194                 break;
5195               x=0;
5196               y=0;
5197               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5198               (void) items;
5199               image_view=AcquireVirtualCacheView(image,exception);
5200               p=GetCacheViewVirtualPixels(image_view,x,y,1,1,exception);
5201               if (p != (const Quantum *) NULL)
5202                 {
5203                   (void) FormatLocaleString(name,MagickPathExtent,QuantumFormat,
5204                     GetPixelIndex(image,p));
5205                   s=newSVpv(name,0);
5206                   PUSHs(s ? sv_2mortal(s) : &sv_undef);
5207                 }
5208               image_view=DestroyCacheView(image_view);
5209               continue;
5210             }
5211           if (LocaleCompare(attribute,"iptc") == 0)
5212             {
5213               if (image != (Image *) NULL)
5214                 {
5215                   const StringInfo
5216                     *profile;
5217
5218                   profile=GetImageProfile(image,"iptc");
5219                   if (profile != (const StringInfo *) NULL)
5220                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5221                       GetStringInfoLength(profile));
5222                 }
5223               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5224               continue;
5225             }
5226           if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
5227             {
5228               if (image != (Image *) NULL)
5229                 s=newSViv((ssize_t) image->iterations);
5230               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5231               continue;
5232             }
5233           if (LocaleCompare(attribute,"interlace") == 0)
5234             {
5235               j=info ? info->image_info->interlace : image ? image->interlace :
5236                 UndefinedInterlace;
5237               s=newSViv(j);
5238               (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
5239                 j));
5240               SvIOK_on(s);
5241               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5242               continue;
5243             }
5244           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5245             attribute);
5246           break;
5247         }
5248         case 'L':
5249         case 'l':
5250         {
5251           if (LocaleCompare(attribute,"label") == 0)
5252             {
5253               const char
5254                 *value;
5255
5256               if (image == (Image *) NULL)
5257                 break;
5258               value=GetImageProperty(image,"Label",exception);
5259               if (value != (const char *) NULL)
5260                 s=newSVpv(value,0);
5261               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5262               continue;
5263             }
5264           if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
5265             {
5266               if (image != (Image *) NULL)
5267                 s=newSViv((ssize_t) image->iterations);
5268               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5269               continue;
5270             }
5271           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5272             attribute);
5273           break;
5274         }
5275         case 'M':
5276         case 'm':
5277         {
5278           if (LocaleCompare(attribute,"magick") == 0)
5279             {
5280               if (info && *info->image_info->magick)
5281                 s=newSVpv(info->image_info->magick,0);
5282               if (image != (Image *) NULL)
5283                 s=newSVpv(image->magick,0);
5284               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5285               continue;
5286             }
5287           if (LocaleCompare(attribute,"map") == 0)
5288             {
5289               s=newSViv(GetMagickResource(MapResource));
5290               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5291               continue;
5292             }
5293           if (LocaleCompare(attribute,"maximum-error") == 0)
5294             {
5295               if (image != (Image *) NULL)
5296                 s=newSVnv(image->error.normalized_maximum_error);
5297               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5298               continue;
5299             }
5300           if (LocaleCompare(attribute,"memory") == 0)
5301             {
5302               s=newSViv(GetMagickResource(MemoryResource));
5303               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5304               continue;
5305             }
5306           if (LocaleCompare(attribute,"mean-error") == 0)
5307             {
5308               if (image != (Image *) NULL)
5309                 s=newSVnv(image->error.normalized_mean_error);
5310               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5311               continue;
5312             }
5313           if (LocaleCompare(attribute,"mime") == 0)
5314             {
5315               if (info && *info->image_info->magick)
5316                 s=newSVpv(MagickToMime(info->image_info->magick),0);
5317               if (image != (Image *) NULL)
5318                 s=newSVpv(MagickToMime(image->magick),0);
5319               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5320               continue;
5321             }
5322           if (LocaleCompare(attribute,"mattecolor") == 0)
5323             {
5324               if (image == (Image *) NULL)
5325                 break;
5326               (void) FormatLocaleString(color,MagickPathExtent,
5327                 "%.20g,%.20g,%.20g,%.20g",(double) image->alpha_color.red,
5328                 (double) image->alpha_color.green,
5329                 (double) image->alpha_color.blue,
5330                 (double) image->alpha_color.alpha);
5331               s=newSVpv(color,0);
5332               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5333               continue;
5334             }
5335           if (LocaleCompare(attribute,"matte") == 0)
5336             {
5337               if (image != (Image *) NULL)
5338                 s=newSViv((ssize_t) image->alpha_trait != UndefinedPixelTrait ?
5339                   1 : 0);
5340               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5341               continue;
5342             }
5343           if (LocaleCompare(attribute,"mime") == 0)
5344             {
5345               const char
5346                 *magick;
5347
5348               magick=NULL;
5349               if (info && *info->image_info->magick)
5350                 magick=info->image_info->magick;
5351               if (image != (Image *) NULL)
5352                 magick=image->magick;
5353               if (magick)
5354                 {
5355                   char
5356                     *mime;
5357
5358                   mime=MagickToMime(magick);
5359                   s=newSVpv(mime,0);
5360                   mime=(char *) RelinquishMagickMemory(mime);
5361                 }
5362               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5363               continue;
5364             }
5365           if (LocaleCompare(attribute,"monochrome") == 0)
5366             {
5367               if (image == (Image *) NULL)
5368                 continue;
5369               j=info ? info->image_info->monochrome :
5370                 SetImageMonochrome(image,exception);
5371               s=newSViv(j);
5372               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5373               continue;
5374             }
5375           if (LocaleCompare(attribute,"montage") == 0)
5376             {
5377               if (image && image->montage)
5378                 s=newSVpv(image->montage,0);
5379               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5380               continue;
5381             }
5382           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5383             attribute);
5384           break;
5385         }
5386         case 'O':
5387         case 'o':
5388         {
5389           if (LocaleCompare(attribute,"orientation") == 0)
5390             {
5391               j=info ? info->image_info->orientation : image ?
5392                 image->orientation : UndefinedOrientation;
5393               s=newSViv(j);
5394               (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5395                 j));
5396               SvIOK_on(s);
5397               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5398               continue;
5399             }
5400           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5401             attribute);
5402           break;
5403         }
5404         case 'P':
5405         case 'p':
5406         {
5407           if (LocaleCompare(attribute,"page") == 0)
5408             {
5409               if (info && info->image_info->page)
5410                 s=newSVpv(info->image_info->page,0);
5411               if (image != (Image *) NULL)
5412                 {
5413                   char
5414                     geometry[MagickPathExtent];
5415
5416                   (void) FormatLocaleString(geometry,MagickPathExtent,
5417                     "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5418                     (double) image->page.height,(double) image->page.x,(double)
5419                     image->page.y);
5420                   s=newSVpv(geometry,0);
5421                 }
5422               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5423               continue;
5424             }
5425           if (LocaleCompare(attribute,"page.x") == 0)
5426             {
5427               if (image != (Image *) NULL)
5428                 s=newSViv((ssize_t) image->page.x);
5429               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5430               continue;
5431             }
5432           if (LocaleCompare(attribute,"page.y") == 0)
5433             {
5434               if (image != (Image *) NULL)
5435                 s=newSViv((ssize_t) image->page.y);
5436               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5437               continue;
5438             }
5439           if (LocaleNCompare(attribute,"pixel",5) == 0)
5440             {
5441               char
5442                 tuple[MagickPathExtent];
5443
5444               int
5445                 items;
5446
5447               long
5448                 x,
5449                 y;
5450
5451               register const Quantum
5452                 *p;
5453
5454               if (image == (Image *) NULL)
5455                 break;
5456               x=0;
5457               y=0;
5458               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5459               (void) items;
5460               p=GetVirtualPixels(image,x,y,1,1,exception);
5461               if (image->colorspace != CMYKColorspace)
5462                 (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
5463                   QuantumFormat "," QuantumFormat "," QuantumFormat,
5464                   GetPixelRed(image,p),GetPixelGreen(image,p),
5465                   GetPixelBlue(image,p),GetPixelAlpha(image,p));
5466               else
5467                 (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
5468                   QuantumFormat "," QuantumFormat "," QuantumFormat ","
5469                   QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5470                   GetPixelBlue(image,p),GetPixelBlack(image,p),
5471                   GetPixelAlpha(image,p));
5472               s=newSVpv(tuple,0);
5473               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5474               continue;
5475             }
5476           if (LocaleCompare(attribute,"pointsize") == 0)
5477             {
5478               if (info)
5479                 s=newSViv((ssize_t) info->image_info->pointsize);
5480               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5481               continue;
5482             }
5483           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5484             attribute);
5485           break;
5486         }
5487         case 'Q':
5488         case 'q':
5489         {
5490           if (LocaleCompare(attribute,"quality") == 0)
5491             {
5492               if (info)
5493                 s=newSViv((ssize_t) info->image_info->quality);
5494               if (image != (Image *) NULL)
5495                 s=newSViv((ssize_t) image->quality);
5496               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5497               continue;
5498             }
5499           if (LocaleCompare(attribute,"quantum") == 0)
5500             {
5501               if (info)
5502                 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5503               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5504               continue;
5505             }
5506           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5507             attribute);
5508           break;
5509         }
5510         case 'R':
5511         case 'r':
5512         {
5513           if (LocaleCompare(attribute,"rendering-intent") == 0)
5514             {
5515               s=newSViv(image->rendering_intent);
5516               (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5517                 image->rendering_intent));
5518               SvIOK_on(s);
5519               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5520               continue;
5521             }
5522           if (LocaleCompare(attribute,"red-primary") == 0)
5523             {
5524               if (image == (Image *) NULL)
5525                 break;
5526               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
5527                 image->chromaticity.red_primary.x,
5528                 image->chromaticity.red_primary.y);
5529               s=newSVpv(color,0);
5530               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5531               continue;
5532             }
5533           if (LocaleCompare(attribute,"rows") == 0)
5534             {
5535               if (image != (Image *) NULL)
5536                 s=newSViv((ssize_t) image->rows);
5537               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5538               continue;
5539             }
5540           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5541             attribute);
5542           break;
5543         }
5544         case 'S':
5545         case 's':
5546         {
5547           if (LocaleCompare(attribute,"sampling-factor") == 0)
5548             {
5549               if (info && info->image_info->sampling_factor)
5550                 s=newSVpv(info->image_info->sampling_factor,0);
5551               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5552               continue;
5553             }
5554           if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5555             {
5556               if (info && info->image_info->server_name)
5557                 s=newSVpv(info->image_info->server_name,0);
5558               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5559               continue;
5560             }
5561           if (LocaleCompare(attribute,"size") == 0)
5562             {
5563               if (info && info->image_info->size)
5564                 s=newSVpv(info->image_info->size,0);
5565               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5566               continue;
5567             }
5568           if (LocaleCompare(attribute,"scene") == 0)
5569             {
5570               if (image != (Image *) NULL)
5571                 s=newSViv((ssize_t) image->scene);
5572               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5573               continue;
5574             }
5575           if (LocaleCompare(attribute,"scenes") == 0)
5576             {
5577               if (image != (Image *) NULL)
5578                 s=newSViv((ssize_t) info->image_info->number_scenes);
5579               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5580               continue;
5581             }
5582           if (LocaleCompare(attribute,"signature") == 0)
5583             {
5584               const char
5585                 *value;
5586
5587               if (image == (Image *) NULL)
5588                 break;
5589               (void) SignatureImage(image,exception);
5590               value=GetImageProperty(image,"Signature",exception);
5591               if (value != (const char *) NULL)
5592                 s=newSVpv(value,0);
5593               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5594               continue;
5595             }
5596           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5597             attribute);
5598           break;
5599         }
5600         case 'T':
5601         case 't':
5602         {
5603           if (LocaleCompare(attribute,"taint") == 0)
5604             {
5605               if (image != (Image *) NULL)
5606                 s=newSViv((ssize_t) IsTaintImage(image));
5607               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5608               continue;
5609             }
5610           if (LocaleCompare(attribute,"texture") == 0)
5611             {
5612               if (info && info->image_info->texture)
5613                 s=newSVpv(info->image_info->texture,0);
5614               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5615               continue;
5616             }
5617           if (LocaleCompare(attribute,"total-ink-density") == 0)
5618             {
5619               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5620               if (image != (Image *) NULL)
5621                 s=newSVnv(GetImageTotalInkDensity(image,exception));
5622               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5623               continue;
5624             }
5625           if (LocaleCompare(attribute,"transparent-color") == 0)
5626             {
5627               if (image == (Image *) NULL)
5628                 break;
5629               (void) FormatLocaleString(color,MagickPathExtent,
5630                 "%.20g,%.20g,%.20g,%.20g",(double) image->transparent_color.red,
5631                 (double) image->transparent_color.green,
5632                 (double) image->transparent_color.blue,
5633                 (double) image->transparent_color.alpha);
5634               s=newSVpv(color,0);
5635               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5636               continue;
5637             }
5638           if (LocaleCompare(attribute,"type") == 0)
5639             {
5640               if (image == (Image *) NULL)
5641                 break;
5642               j=(ssize_t) GetImageType(image);
5643               s=newSViv(j);
5644               (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5645               SvIOK_on(s);
5646               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5647               continue;
5648             }
5649           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5650             attribute);
5651           break;
5652         }
5653         case 'U':
5654         case 'u':
5655         {
5656           if (LocaleCompare(attribute,"units") == 0)
5657             {
5658               j=info ? info->image_info->units : image ? image->units :
5659                 UndefinedResolution;
5660               if (info && (info->image_info->units == UndefinedResolution))
5661                 if (image)
5662                   j=image->units;
5663               if (j == UndefinedResolution)
5664                 s=newSVpv("undefined units",0);
5665               else
5666                 if (j == PixelsPerInchResolution)
5667                   s=newSVpv("pixels / inch",0);
5668                 else
5669                   s=newSVpv("pixels / centimeter",0);
5670               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5671               continue;
5672             }
5673           if (LocaleCompare(attribute,"user-time") == 0)
5674             {
5675               if (image != (Image *) NULL)
5676                 s=newSVnv(GetUserTime(&image->timer));
5677               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5678               continue;
5679             }
5680           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5681             attribute);
5682           break;
5683         }
5684         case 'V':
5685         case 'v':
5686         {
5687           if (LocaleCompare(attribute,"verbose") == 0)
5688             {
5689               if (info)
5690                 s=newSViv((ssize_t) info->image_info->verbose);
5691               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5692               continue;
5693             }
5694           if (LocaleCompare(attribute,"version") == 0)
5695             {
5696               s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5697               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5698               continue;
5699             }
5700           if (LocaleCompare(attribute,"virtual-pixel") == 0)
5701             {
5702               if (image == (Image *) NULL)
5703                 break;
5704               j=(ssize_t) GetImageVirtualPixelMethod(image);
5705               s=newSViv(j);
5706               (void) sv_setpv(s,CommandOptionToMnemonic(
5707                 MagickVirtualPixelOptions,j));
5708               SvIOK_on(s);
5709               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5710               continue;
5711             }
5712           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5713             attribute);
5714           break;
5715         }
5716         case 'W':
5717         case 'w':
5718         {
5719           if (LocaleCompare(attribute,"white-point") == 0)
5720             {
5721               if (image == (Image *) NULL)
5722                 break;
5723               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
5724                 image->chromaticity.white_point.x,
5725                 image->chromaticity.white_point.y);
5726               s=newSVpv(color,0);
5727               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5728               continue;
5729             }
5730           if (LocaleCompare(attribute,"width") == 0)
5731             {
5732               if (image != (Image *) NULL)
5733                 s=newSViv((ssize_t) image->columns);
5734               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5735               continue;
5736             }
5737           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5738              attribute);
5739           break;
5740         }
5741         case 'X':
5742         case 'x':
5743         {
5744           if (LocaleCompare(attribute,"xmp") == 0)
5745             {
5746               if (image != (Image *) NULL)
5747                 {
5748                   const StringInfo
5749                     *profile;
5750
5751                   profile=GetImageProfile(image,"xmp");
5752                   if (profile != (StringInfo *) NULL)
5753                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5754                       GetStringInfoLength(profile));
5755                 }
5756               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5757               continue;
5758             }
5759           if (LocaleCompare(attribute,"x-resolution") == 0)
5760             {
5761               if (image != (Image *) NULL)
5762                 s=newSVnv(image->resolution.x);
5763               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5764               continue;
5765             }
5766           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5767             attribute);
5768           break;
5769         }
5770         case 'Y':
5771         case 'y':
5772         {
5773           if (LocaleCompare(attribute,"y-resolution") == 0)
5774             {
5775               if (image != (Image *) NULL)
5776                 s=newSVnv(image->resolution.y);
5777               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5778               continue;
5779             }
5780           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5781             attribute);
5782           break;
5783         }
5784         default:
5785           break;
5786       }
5787       if (image == (Image *) NULL)
5788         ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5789           attribute)
5790       else
5791         {
5792           value=GetImageProperty(image,attribute,exception);
5793           if (value != (const char *) NULL)
5794             {
5795               s=newSVpv(value,0);
5796               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5797             }
5798           else
5799             if (*attribute != '%')
5800               ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5801                 attribute)
5802             else
5803               {
5804                  char
5805                    *meta;
5806
5807                  meta=InterpretImageProperties(info ? info->image_info :
5808                    (ImageInfo *) NULL,image,attribute,exception);
5809                  s=newSVpv(meta,0);
5810                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5811                  meta=(char *) RelinquishMagickMemory(meta);
5812               }
5813         }
5814     }
5815     exception=DestroyExceptionInfo(exception);
5816     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5817   }
5818 \f
5819 #
5820 ###############################################################################
5821 #                                                                             #
5822 #                                                                             #
5823 #                                                                             #
5824 #   G e t A u t h e n t i c P i x e l s                                       #
5825 #                                                                             #
5826 #                                                                             #
5827 #                                                                             #
5828 ###############################################################################
5829 #
5830 #
5831 void *
5832 GetAuthenticPixels(ref,...)
5833   Image::Magick ref = NO_INIT
5834   ALIAS:
5835     getauthenticpixels = 1
5836     GetImagePixels = 2
5837     getimagepixels = 3
5838   CODE:
5839   {
5840     char
5841       *attribute;
5842
5843     ExceptionInfo
5844       *exception;
5845
5846     Image
5847       *image;
5848
5849     RectangleInfo
5850       region;
5851
5852     ssize_t
5853       i;
5854
5855     struct PackageInfo
5856       *info;
5857
5858     SV
5859       *perl_exception,
5860       *reference;
5861
5862     void
5863       *blob = NULL;
5864
5865     PERL_UNUSED_VAR(ref);
5866     PERL_UNUSED_VAR(ix);
5867     exception=AcquireExceptionInfo();
5868     perl_exception=newSVpv("",0);
5869     if (sv_isobject(ST(0)) == 0)
5870       {
5871         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5872           PackageName);
5873         goto PerlException;
5874       }
5875     reference=SvRV(ST(0));
5876
5877     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5878     if (image == (Image *) NULL)
5879       {
5880         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5881           PackageName);
5882         goto PerlException;
5883       }
5884
5885     region.x=0;
5886     region.y=0;
5887     region.width=image->columns;
5888     region.height=1;
5889     if (items == 1)
5890       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5891     for (i=2; i < items; i+=2)
5892     {
5893       attribute=(char *) SvPV(ST(i-1),na);
5894       switch (*attribute)
5895       {
5896         case 'g':
5897         case 'G':
5898         {
5899           if (LocaleCompare(attribute,"geometry") == 0)
5900             {
5901               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5902               break;
5903             }
5904           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5905             attribute);
5906           break;
5907         }
5908         case 'H':
5909         case 'h':
5910         {
5911           if (LocaleCompare(attribute,"height") == 0)
5912             {
5913               region.height=SvIV(ST(i));
5914               continue;
5915             }
5916           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5917             attribute);
5918           break;
5919         }
5920         case 'X':
5921         case 'x':
5922         {
5923           if (LocaleCompare(attribute,"x") == 0)
5924             {
5925               region.x=SvIV(ST(i));
5926               continue;
5927             }
5928           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5929             attribute);
5930           break;
5931         }
5932         case 'Y':
5933         case 'y':
5934         {
5935           if (LocaleCompare(attribute,"y") == 0)
5936             {
5937               region.y=SvIV(ST(i));
5938               continue;
5939             }
5940           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5941             attribute);
5942           break;
5943         }
5944         case 'W':
5945         case 'w':
5946         {
5947           if (LocaleCompare(attribute,"width") == 0)
5948             {
5949               region.width=SvIV(ST(i));
5950               continue;
5951             }
5952           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5953             attribute);
5954           break;
5955         }
5956       }
5957     }
5958     blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5959       region.height,exception);
5960     if (blob != (void *) NULL)
5961       goto PerlEnd;
5962
5963   PerlException:
5964     InheritPerlException(exception,perl_exception);
5965     exception=DestroyExceptionInfo(exception);
5966     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5967
5968   PerlEnd:
5969     RETVAL = blob;
5970   }
5971   OUTPUT:
5972     RETVAL
5973 \f
5974 #
5975 ###############################################################################
5976 #                                                                             #
5977 #                                                                             #
5978 #                                                                             #
5979 #   G e t V i r t u a l P i x e l s                                           #
5980 #                                                                             #
5981 #                                                                             #
5982 #                                                                             #
5983 ###############################################################################
5984 #
5985 #
5986 void *
5987 GetVirtualPixels(ref,...)
5988   Image::Magick ref = NO_INIT
5989   ALIAS:
5990     getvirtualpixels = 1
5991     AcquireImagePixels = 2
5992     acquireimagepixels = 3
5993   CODE:
5994   {
5995     char
5996       *attribute;
5997
5998     const void
5999       *blob = NULL;
6000
6001     ExceptionInfo
6002       *exception;
6003
6004     Image
6005       *image;
6006
6007     RectangleInfo
6008       region;
6009
6010     ssize_t
6011       i;
6012
6013     struct PackageInfo
6014       *info;
6015
6016     SV
6017       *perl_exception,
6018       *reference;
6019
6020     PERL_UNUSED_VAR(ref);
6021     PERL_UNUSED_VAR(ix);
6022     exception=AcquireExceptionInfo();
6023     perl_exception=newSVpv("",0);
6024     if (sv_isobject(ST(0)) == 0)
6025       {
6026         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6027           PackageName);
6028         goto PerlException;
6029       }
6030     reference=SvRV(ST(0));
6031
6032     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6033     if (image == (Image *) NULL)
6034       {
6035         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6036           PackageName);
6037         goto PerlException;
6038       }
6039
6040     region.x=0;
6041     region.y=0;
6042     region.width=image->columns;
6043     region.height=1;
6044     if (items == 1)
6045       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6046     for (i=2; i < items; i+=2)
6047     {
6048       attribute=(char *) SvPV(ST(i-1),na);
6049       switch (*attribute)
6050       {
6051         case 'g':
6052         case 'G':
6053         {
6054           if (LocaleCompare(attribute,"geometry") == 0)
6055             {
6056               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6057               break;
6058             }
6059           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6060             attribute);
6061           break;
6062         }
6063         case 'H':
6064         case 'h':
6065         {
6066           if (LocaleCompare(attribute,"height") == 0)
6067             {
6068               region.height=SvIV(ST(i));
6069               continue;
6070             }
6071           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6072             attribute);
6073           break;
6074         }
6075         case 'X':
6076         case 'x':
6077         {
6078           if (LocaleCompare(attribute,"x") == 0)
6079             {
6080               region.x=SvIV(ST(i));
6081               continue;
6082             }
6083           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6084             attribute);
6085           break;
6086         }
6087         case 'Y':
6088         case 'y':
6089         {
6090           if (LocaleCompare(attribute,"y") == 0)
6091             {
6092               region.y=SvIV(ST(i));
6093               continue;
6094             }
6095           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6096             attribute);
6097           break;
6098         }
6099         case 'W':
6100         case 'w':
6101         {
6102           if (LocaleCompare(attribute,"width") == 0)
6103             {
6104               region.width=SvIV(ST(i));
6105               continue;
6106             }
6107           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6108             attribute);
6109           break;
6110         }
6111       }
6112     }
6113     blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
6114       region.height,exception);
6115     if (blob != (void *) NULL)
6116       goto PerlEnd;
6117
6118   PerlException:
6119     InheritPerlException(exception,perl_exception);
6120     exception=DestroyExceptionInfo(exception);
6121     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6122
6123   PerlEnd:
6124     RETVAL = (void *) blob;
6125   }
6126   OUTPUT:
6127     RETVAL
6128 \f
6129 #
6130 ###############################################################################
6131 #                                                                             #
6132 #                                                                             #
6133 #                                                                             #
6134 #   G e t A u t h e n t i c M e t a c o n t e n t                             #
6135 #                                                                             #
6136 #                                                                             #
6137 #                                                                             #
6138 ###############################################################################
6139 #
6140 #
6141 void *
6142 GetAuthenticMetacontent(ref,...)
6143   Image::Magick ref = NO_INIT
6144   ALIAS:
6145     getauthenticmetacontent = 1
6146     GetMetacontent = 2
6147     getmetacontent = 3
6148   CODE:
6149   {
6150     ExceptionInfo
6151       *exception;
6152
6153     Image
6154       *image;
6155
6156     struct PackageInfo
6157       *info;
6158
6159     SV
6160       *perl_exception,
6161       *reference;
6162
6163     void
6164       *blob = NULL;
6165
6166     PERL_UNUSED_VAR(ref);
6167     PERL_UNUSED_VAR(ix);
6168     exception=AcquireExceptionInfo();
6169     perl_exception=newSVpv("",0);
6170     if (sv_isobject(ST(0)) == 0)
6171       {
6172         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6173           PackageName);
6174         goto PerlException;
6175       }
6176     reference=SvRV(ST(0));
6177
6178     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6179     if (image == (Image *) NULL)
6180       {
6181         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6182           PackageName);
6183         goto PerlException;
6184       }
6185
6186     blob=(void *) GetAuthenticMetacontent(image);
6187     if (blob != (void *) NULL)
6188       goto PerlEnd;
6189
6190   PerlException:
6191     InheritPerlException(exception,perl_exception);
6192     exception=DestroyExceptionInfo(exception);
6193     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6194
6195   PerlEnd:
6196     RETVAL = blob;
6197   }
6198   OUTPUT:
6199     RETVAL
6200 \f
6201 #
6202 ###############################################################################
6203 #                                                                             #
6204 #                                                                             #
6205 #                                                                             #
6206 #   G e t V i r t u a l M e t a c o n t e n t                                 #
6207 #                                                                             #
6208 #                                                                             #
6209 #                                                                             #
6210 ###############################################################################
6211 #
6212 #
6213 void *
6214 GetVirtualMetacontent(ref,...)
6215   Image::Magick ref = NO_INIT
6216   ALIAS:
6217     getvirtualmetacontent = 1
6218   CODE:
6219   {
6220     ExceptionInfo
6221       *exception;
6222
6223     Image
6224       *image;
6225
6226     struct PackageInfo
6227       *info;
6228
6229     SV
6230       *perl_exception,
6231       *reference;
6232
6233     void
6234       *blob = NULL;
6235
6236     PERL_UNUSED_VAR(ref);
6237     PERL_UNUSED_VAR(ix);
6238     exception=AcquireExceptionInfo();
6239     perl_exception=newSVpv("",0);
6240     if (sv_isobject(ST(0)) == 0)
6241       {
6242         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6243           PackageName);
6244         goto PerlException;
6245       }
6246     reference=SvRV(ST(0));
6247
6248     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6249     if (image == (Image *) NULL)
6250       {
6251         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6252           PackageName);
6253         goto PerlException;
6254       }
6255
6256     blob=(void *) GetVirtualMetacontent(image);
6257     if (blob != (void *) NULL)
6258       goto PerlEnd;
6259
6260   PerlException:
6261     InheritPerlException(exception,perl_exception);
6262     exception=DestroyExceptionInfo(exception);
6263     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6264
6265   PerlEnd:
6266     RETVAL = blob;
6267   }
6268   OUTPUT:
6269     RETVAL
6270 \f
6271 #
6272 ###############################################################################
6273 #                                                                             #
6274 #                                                                             #
6275 #                                                                             #
6276 #   H i s t o g r a m                                                         #
6277 #                                                                             #
6278 #                                                                             #
6279 #                                                                             #
6280 ###############################################################################
6281 #
6282 #
6283 void
6284 Histogram(ref,...)
6285   Image::Magick ref=NO_INIT
6286   ALIAS:
6287     HistogramImage = 1
6288     histogram      = 2
6289     histogramimage = 3
6290   PPCODE:
6291   {
6292     AV
6293       *av;
6294
6295     char
6296       message[MagickPathExtent];
6297
6298     PixelInfo
6299       *histogram;
6300
6301     ExceptionInfo
6302       *exception;
6303
6304     Image
6305       *image;
6306
6307     register ssize_t
6308       i;
6309
6310     ssize_t
6311       count;
6312
6313     struct PackageInfo
6314       *info;
6315
6316     SV
6317       *perl_exception,
6318       *reference;
6319
6320     size_t
6321       number_colors;
6322
6323     PERL_UNUSED_VAR(ref);
6324     PERL_UNUSED_VAR(ix);
6325     exception=AcquireExceptionInfo();
6326     perl_exception=newSVpv("",0);
6327     av=NULL;
6328     if (sv_isobject(ST(0)) == 0)
6329       {
6330         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6331           PackageName);
6332         goto PerlException;
6333       }
6334     reference=SvRV(ST(0));
6335     av=newAV();
6336     SvREFCNT_dec(av);
6337     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6338     if (image == (Image *) NULL)
6339       {
6340         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6341           PackageName);
6342         goto PerlException;
6343       }
6344     count=0;
6345     for ( ; image; image=image->next)
6346     {
6347       histogram=GetImageHistogram(image,&number_colors,exception);
6348       if (histogram == (PixelInfo *) NULL)
6349         continue;
6350       count+=(ssize_t) number_colors;
6351       EXTEND(sp,6*count);
6352       for (i=0; i < (ssize_t) number_colors; i++)
6353       {
6354         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6355           histogram[i].red);
6356         PUSHs(sv_2mortal(newSVpv(message,0)));
6357         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6358           histogram[i].green);
6359         PUSHs(sv_2mortal(newSVpv(message,0)));
6360         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6361           histogram[i].blue);
6362         PUSHs(sv_2mortal(newSVpv(message,0)));
6363         if (image->colorspace == CMYKColorspace)
6364           {
6365             (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6366               histogram[i].black);
6367             PUSHs(sv_2mortal(newSVpv(message,0)));
6368           }
6369         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6370           histogram[i].alpha);
6371         PUSHs(sv_2mortal(newSVpv(message,0)));
6372         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
6373           histogram[i].count);
6374         PUSHs(sv_2mortal(newSVpv(message,0)));
6375       }
6376       histogram=(PixelInfo *) RelinquishMagickMemory(histogram);
6377     }
6378
6379   PerlException:
6380     InheritPerlException(exception,perl_exception);
6381     exception=DestroyExceptionInfo(exception);
6382     SvREFCNT_dec(perl_exception);
6383   }
6384 \f
6385 #
6386 ###############################################################################
6387 #                                                                             #
6388 #                                                                             #
6389 #                                                                             #
6390 #   G e t P i x e l                                                           #
6391 #                                                                             #
6392 #                                                                             #
6393 #                                                                             #
6394 ###############################################################################
6395 #
6396 #
6397 void
6398 GetPixel(ref,...)
6399   Image::Magick ref=NO_INIT
6400   ALIAS:
6401     getpixel = 1
6402     getPixel = 2
6403   PPCODE:
6404   {
6405     AV
6406       *av;
6407
6408     char
6409       *attribute;
6410
6411     ExceptionInfo
6412       *exception;
6413
6414     Image
6415       *image;
6416
6417     MagickBooleanType
6418       normalize;
6419
6420     RectangleInfo
6421       region;
6422
6423     register const Quantum
6424       *p;
6425
6426     register ssize_t
6427       i;
6428
6429     ssize_t
6430       option;
6431
6432     struct PackageInfo
6433       *info;
6434
6435     SV
6436       *perl_exception,
6437       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6438
6439     PERL_UNUSED_VAR(ref);
6440     PERL_UNUSED_VAR(ix);
6441     exception=AcquireExceptionInfo();
6442     perl_exception=newSVpv("",0);
6443     reference=SvRV(ST(0));
6444     av=(AV *) reference;
6445     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6446       exception);
6447     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6448     if (image == (Image *) NULL)
6449       {
6450         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6451           PackageName);
6452         goto PerlException;
6453       }
6454     normalize=MagickTrue;
6455     region.x=0;
6456     region.y=0;
6457     region.width=image->columns;
6458     region.height=1;
6459     if (items == 1)
6460       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6461     for (i=2; i < items; i+=2)
6462     {
6463       attribute=(char *) SvPV(ST(i-1),na);
6464       switch (*attribute)
6465       {
6466         case 'C':
6467         case 'c':
6468         {
6469           if (LocaleCompare(attribute,"channel") == 0)
6470             {
6471               ssize_t
6472                 option;
6473
6474               option=ParseChannelOption(SvPV(ST(i),na));
6475               if (option < 0)
6476                 {
6477                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6478                     SvPV(ST(i),na));
6479                   return;
6480                 }
6481               (void) SetPixelChannelMask(image,(ChannelType) option);
6482               break;
6483             }
6484           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6485             attribute);
6486           break;
6487         }
6488         case 'g':
6489         case 'G':
6490         {
6491           if (LocaleCompare(attribute,"geometry") == 0)
6492             {
6493               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6494               break;
6495             }
6496           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6497             attribute);
6498           break;
6499         }
6500         case 'N':
6501         case 'n':
6502         {
6503           if (LocaleCompare(attribute,"normalize") == 0)
6504             {
6505               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6506                 SvPV(ST(i),na));
6507               if (option < 0)
6508                 {
6509                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6510                     SvPV(ST(i),na));
6511                   break;
6512                 }
6513              normalize=option != 0 ? MagickTrue : MagickFalse;
6514              break;
6515             }
6516           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6517             attribute);
6518           break;
6519         }
6520         case 'x':
6521         case 'X':
6522         {
6523           if (LocaleCompare(attribute,"x") == 0)
6524             {
6525               region.x=SvIV(ST(i));
6526               break;
6527             }
6528           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6529             attribute);
6530           break;
6531         }
6532         case 'y':
6533         case 'Y':
6534         {
6535           if (LocaleCompare(attribute,"y") == 0)
6536             {
6537               region.y=SvIV(ST(i));
6538               break;
6539             }
6540           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6541             attribute);
6542           break;
6543         }
6544         default:
6545         {
6546           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6547             attribute);
6548           break;
6549         }
6550       }
6551     }
6552     p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6553     if (p == (const Quantum *) NULL)
6554       PUSHs(&sv_undef);
6555     else
6556       {
6557         double
6558           scale;
6559
6560         scale=1.0;
6561         if (normalize != MagickFalse)
6562           scale=1.0/QuantumRange;
6563         if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
6564           PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6565         if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6566           PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6567         if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6568           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6569         if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6570             (image->colorspace == CMYKColorspace))
6571           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6572         if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
6573           PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6574       }
6575
6576   PerlException:
6577     InheritPerlException(exception,perl_exception);
6578     exception=DestroyExceptionInfo(exception);
6579     SvREFCNT_dec(perl_exception);
6580   }
6581 \f
6582 #
6583 ###############################################################################
6584 #                                                                             #
6585 #                                                                             #
6586 #                                                                             #
6587 #   G e t P i x e l s                                                         #
6588 #                                                                             #
6589 #                                                                             #
6590 #                                                                             #
6591 ###############################################################################
6592 #
6593 #
6594 void
6595 GetPixels(ref,...)
6596   Image::Magick ref=NO_INIT
6597   ALIAS:
6598     getpixels = 1
6599     getPixels = 2
6600   PPCODE:
6601   {
6602     AV
6603       *av;
6604
6605     char
6606       *attribute;
6607
6608     const char
6609       *map;
6610
6611     ExceptionInfo
6612       *exception;
6613
6614     Image
6615       *image;
6616
6617     MagickBooleanType
6618       normalize,
6619       status;
6620
6621     RectangleInfo
6622       region;
6623
6624     register ssize_t
6625       i;
6626
6627     ssize_t
6628       option;
6629
6630     struct PackageInfo
6631       *info;
6632
6633     SV
6634       *perl_exception,
6635       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6636
6637     PERL_UNUSED_VAR(ref);
6638     PERL_UNUSED_VAR(ix);
6639     exception=AcquireExceptionInfo();
6640     perl_exception=newSVpv("",0);
6641     reference=SvRV(ST(0));
6642     av=(AV *) reference;
6643     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6644       exception);
6645     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6646     if (image == (Image *) NULL)
6647       {
6648         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6649           PackageName);
6650         goto PerlException;
6651       }
6652     map="RGB";
6653     if (image->alpha_trait != UndefinedPixelTrait)
6654       map="RGBA";
6655     if (image->colorspace == CMYKColorspace)
6656       {
6657         map="CMYK";
6658         if (image->alpha_trait != UndefinedPixelTrait)
6659           map="CMYKA";
6660       }
6661     normalize=MagickFalse;
6662     region.x=0;
6663     region.y=0;
6664     region.width=image->columns;
6665     region.height=1;
6666     if (items == 1)
6667       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6668     for (i=2; i < items; i+=2)
6669     {
6670       attribute=(char *) SvPV(ST(i-1),na);
6671       switch (*attribute)
6672       {
6673         case 'g':
6674         case 'G':
6675         {
6676           if (LocaleCompare(attribute,"geometry") == 0)
6677             {
6678               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6679               break;
6680             }
6681           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6682             attribute);
6683           break;
6684         }
6685         case 'H':
6686         case 'h':
6687         {
6688           if (LocaleCompare(attribute,"height") == 0)
6689             {
6690               region.height=SvIV(ST(i));
6691               break;
6692             }
6693           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6694             attribute);
6695           break;
6696         }
6697         case 'M':
6698         case 'm':
6699         {
6700           if (LocaleCompare(attribute,"map") == 0)
6701             {
6702               map=SvPV(ST(i),na);
6703               break;
6704             }
6705           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6706             attribute);
6707           break;
6708         }
6709         case 'N':
6710         case 'n':
6711         {
6712           if (LocaleCompare(attribute,"normalize") == 0)
6713             {
6714               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6715                 SvPV(ST(i),na));
6716               if (option < 0)
6717                 {
6718                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6719                     SvPV(ST(i),na));
6720                   break;
6721                 }
6722              normalize=option != 0 ? MagickTrue : MagickFalse;
6723              break;
6724             }
6725           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6726             attribute);
6727           break;
6728         }
6729         case 'W':
6730         case 'w':
6731         {
6732           if (LocaleCompare(attribute,"width") == 0)
6733             {
6734               region.width=SvIV(ST(i));
6735               break;
6736             }
6737           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6738             attribute);
6739           break;
6740         }
6741         case 'x':
6742         case 'X':
6743         {
6744           if (LocaleCompare(attribute,"x") == 0)
6745             {
6746               region.x=SvIV(ST(i));
6747               break;
6748             }
6749           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6750             attribute);
6751           break;
6752         }
6753         case 'y':
6754         case 'Y':
6755         {
6756           if (LocaleCompare(attribute,"y") == 0)
6757             {
6758               region.y=SvIV(ST(i));
6759               break;
6760             }
6761           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6762             attribute);
6763           break;
6764         }
6765         default:
6766         {
6767           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6768             attribute);
6769           break;
6770         }
6771       }
6772     }
6773     if (normalize != MagickFalse)
6774       {
6775         float
6776           *pixels;
6777
6778         pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6779           region.height*sizeof(*pixels));
6780         if (pixels == (float *) NULL)
6781           {
6782             ThrowPerlException(exception,ResourceLimitError,
6783               "MemoryAllocationFailed",PackageName);
6784             goto PerlException;
6785           }
6786         status=ExportImagePixels(image,region.x,region.y,region.width,
6787           region.height,map,FloatPixel,pixels,exception);
6788         if (status == MagickFalse)
6789           PUSHs(&sv_undef);
6790         else
6791           {
6792             EXTEND(sp,strlen(map)*region.width*region.height);
6793             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6794               PUSHs(sv_2mortal(newSVnv(pixels[i])));
6795           }
6796         pixels=(float *) RelinquishMagickMemory(pixels);
6797       }
6798     else
6799       {
6800         Quantum
6801           *pixels;
6802
6803         pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6804           region.height*sizeof(*pixels));
6805         if (pixels == (Quantum *) NULL)
6806           {
6807             ThrowPerlException(exception,ResourceLimitError,
6808               "MemoryAllocationFailed",PackageName);
6809             goto PerlException;
6810           }
6811         status=ExportImagePixels(image,region.x,region.y,region.width,
6812           region.height,map,QuantumPixel,pixels,exception);
6813         if (status == MagickFalse)
6814           PUSHs(&sv_undef);
6815         else
6816           {
6817             EXTEND(sp,strlen(map)*region.width*region.height);
6818             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6819               PUSHs(sv_2mortal(newSViv(pixels[i])));
6820           }
6821         pixels=(Quantum *) RelinquishMagickMemory(pixels);
6822       }
6823
6824   PerlException:
6825     InheritPerlException(exception,perl_exception);
6826     exception=DestroyExceptionInfo(exception);
6827     SvREFCNT_dec(perl_exception);
6828   }
6829 \f
6830 #
6831 ###############################################################################
6832 #                                                                             #
6833 #                                                                             #
6834 #                                                                             #
6835 #   I m a g e T o B l o b                                                     #
6836 #                                                                             #
6837 #                                                                             #
6838 #                                                                             #
6839 ###############################################################################
6840 #
6841 #
6842 void
6843 ImageToBlob(ref,...)
6844   Image::Magick ref=NO_INIT
6845   ALIAS:
6846     ImageToBlob  = 1
6847     imagetoblob  = 2
6848     toblob       = 3
6849     blob         = 4
6850   PPCODE:
6851   {
6852     char
6853       filename[MagickPathExtent];
6854
6855     ExceptionInfo
6856       *exception;
6857
6858     Image
6859       *image,
6860       *next;
6861
6862     register ssize_t
6863       i;
6864
6865     struct PackageInfo
6866       *info,
6867       *package_info;
6868
6869     size_t
6870       length;
6871
6872     ssize_t
6873       scene;
6874
6875     SV
6876       *perl_exception,
6877       *reference;
6878
6879     void
6880       *blob;
6881
6882     PERL_UNUSED_VAR(ref);
6883     PERL_UNUSED_VAR(ix);
6884     exception=AcquireExceptionInfo();
6885     perl_exception=newSVpv("",0);
6886     package_info=(struct PackageInfo *) NULL;
6887     if (sv_isobject(ST(0)) == 0)
6888       {
6889         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6890           PackageName);
6891         goto PerlException;
6892       }
6893     reference=SvRV(ST(0));
6894     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6895     if (image == (Image *) NULL)
6896       {
6897         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6898           PackageName);
6899         goto PerlException;
6900       }
6901     package_info=ClonePackageInfo(info,exception);
6902     for (i=2; i < items; i+=2)
6903       SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6904     (void) CopyMagickString(filename,package_info->image_info->filename,
6905       MagickPathExtent);
6906     scene=0;
6907     for (next=image; next; next=next->next)
6908     {
6909       (void) CopyMagickString(next->filename,filename,MagickPathExtent);
6910       next->scene=scene++;
6911     }
6912     SetImageInfo(package_info->image_info,(unsigned int)
6913       GetImageListLength(image),exception);
6914     EXTEND(sp,(ssize_t) GetImageListLength(image));
6915     for ( ; image; image=image->next)
6916     {
6917       length=0;
6918       blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6919       if (blob != (char *) NULL)
6920         {
6921           PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6922           blob=(unsigned char *) RelinquishMagickMemory(blob);
6923         }
6924       if (package_info->image_info->adjoin)
6925         break;
6926     }
6927
6928   PerlException:
6929     if (package_info != (struct PackageInfo *) NULL)
6930       DestroyPackageInfo(package_info);
6931     InheritPerlException(exception,perl_exception);
6932     exception=DestroyExceptionInfo(exception);
6933     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6934   }
6935 \f
6936 #
6937 ###############################################################################
6938 #                                                                             #
6939 #                                                                             #
6940 #                                                                             #
6941 #   L a y e r s                                                               #
6942 #                                                                             #
6943 #                                                                             #
6944 #                                                                             #
6945 ###############################################################################
6946 #
6947 #
6948 void
6949 Layers(ref,...)
6950   Image::Magick ref=NO_INIT
6951   ALIAS:
6952     Layers                = 1
6953     layers           = 2
6954     OptimizeImageLayers   = 3
6955     optimizelayers        = 4
6956     optimizeimagelayers   = 5
6957   PPCODE:
6958   {
6959     AV
6960       *av;
6961
6962     char
6963       *attribute;
6964
6965     CompositeOperator
6966       compose;
6967
6968     ExceptionInfo
6969       *exception;
6970
6971     HV
6972       *hv;
6973
6974     Image
6975       *image,
6976       *layers;
6977
6978     LayerMethod
6979       method;
6980
6981     register ssize_t
6982       i;
6983
6984     ssize_t
6985       option,
6986       sp;
6987
6988     struct PackageInfo
6989       *info;
6990
6991     SV
6992       *av_reference,
6993       *perl_exception,
6994       *reference,
6995       *rv,
6996       *sv;
6997
6998     PERL_UNUSED_VAR(ref);
6999     PERL_UNUSED_VAR(ix);
7000     exception=AcquireExceptionInfo();
7001     perl_exception=newSVpv("",0);
7002     sv=NULL;
7003     if (sv_isobject(ST(0)) == 0)
7004       {
7005         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7006           PackageName);
7007         goto PerlException;
7008       }
7009     reference=SvRV(ST(0));
7010     hv=SvSTASH(reference);
7011     av=newAV();
7012     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
7013     SvREFCNT_dec(av);
7014     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
7015     if (image == (Image *) NULL)
7016       {
7017         ThrowPerlException(exception,OptionError,"NoImagesDefined",
7018           PackageName);
7019         goto PerlException;
7020       }
7021     compose=image->compose;
7022     method=OptimizeLayer;
7023     for (i=2; i < items; i+=2)
7024     {
7025       attribute=(char *) SvPV(ST(i-1),na);
7026       switch (*attribute)
7027       {
7028         case 'C':
7029         case 'c':
7030         {
7031           if (LocaleCompare(attribute,"compose") == 0)
7032             {
7033               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
7034                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
7035               if (sp < 0)
7036                 {
7037                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
7038                     SvPV(ST(i),na));
7039                   break;
7040                 }
7041               compose=(CompositeOperator) sp;
7042               break;
7043             }
7044           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7045             attribute);
7046           break;
7047         }
7048         case 'M':
7049         case 'm':
7050         {
7051           if (LocaleCompare(attribute,"method") == 0)
7052             {
7053               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
7054                 SvPV(ST(i),na));
7055               if (option < 0)
7056                 {
7057                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
7058                     SvPV(ST(i),na));
7059                   break;
7060                 }
7061               method=(LayerMethod) option;
7062               break;
7063             }
7064           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7065             attribute);
7066           break;
7067         }
7068         default:
7069         {
7070           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7071             attribute);
7072           break;
7073         }
7074       }
7075     }
7076     layers=(Image *) NULL;
7077     switch (method)
7078     {
7079       case CompareAnyLayer:
7080       case CompareClearLayer:
7081       case CompareOverlayLayer:
7082       default:
7083       {
7084         layers=CompareImagesLayers(image,method,exception);
7085         break;
7086       }
7087       case MergeLayer:
7088       case FlattenLayer:
7089       case MosaicLayer:
7090       {
7091         layers=MergeImageLayers(image,method,exception);
7092         break;
7093       }
7094       case DisposeLayer:
7095       {
7096         layers=DisposeImages(image,exception);
7097         break;
7098       }
7099       case OptimizeImageLayer:
7100       {
7101         layers=OptimizeImageLayers(image,exception);
7102         break;
7103       }
7104       case OptimizePlusLayer:
7105       {
7106         layers=OptimizePlusImageLayers(image,exception);
7107         break;
7108       }
7109       case OptimizeTransLayer:
7110       {
7111         OptimizeImageTransparency(image,exception);
7112         break;
7113       }
7114       case RemoveDupsLayer:
7115       {
7116         RemoveDuplicateLayers(&image,exception);
7117         break;
7118       }
7119       case RemoveZeroLayer:
7120       {
7121         RemoveZeroDelayLayers(&image,exception);
7122         break;
7123       }
7124       case OptimizeLayer:
7125       {
7126         QuantizeInfo
7127           *quantize_info;
7128
7129         /*
7130           General Purpose, GIF Animation Optimizer.
7131         */
7132         layers=CoalesceImages(image,exception);
7133         if (layers == (Image *) NULL)
7134           break;
7135         image=layers;
7136         layers=OptimizeImageLayers(image,exception);
7137         if (layers == (Image *) NULL)
7138           break;
7139         image=DestroyImageList(image);
7140         image=layers;
7141         layers=(Image *) NULL;
7142         OptimizeImageTransparency(image,exception);
7143         quantize_info=AcquireQuantizeInfo(info->image_info);
7144         (void) RemapImages(quantize_info,image,(Image *) NULL,exception);
7145         quantize_info=DestroyQuantizeInfo(quantize_info);
7146         break;
7147       }
7148       case CompositeLayer:
7149       {
7150         Image
7151           *source;
7152
7153         RectangleInfo
7154           geometry;
7155
7156         /*
7157           Split image sequence at the first 'NULL:' image.
7158         */
7159         source=image;
7160         while (source != (Image *) NULL)
7161         {
7162           source=GetNextImageInList(source);
7163           if ((source != (Image *) NULL) &&
7164               (LocaleCompare(source->magick,"NULL") == 0))
7165             break;
7166         }
7167         if (source != (Image *) NULL)
7168           {
7169             if ((GetPreviousImageInList(source) == (Image *) NULL) ||
7170                 (GetNextImageInList(source) == (Image *) NULL))
7171               source=(Image *) NULL;
7172             else
7173               {
7174                 /*
7175                   Separate the two lists, junk the null: image.
7176                 */
7177                 source=SplitImageList(source->previous);
7178                 DeleteImageFromList(&source);
7179               }
7180           }
7181         if (source == (Image *) NULL)
7182           {
7183             (void) ThrowMagickException(exception,GetMagickModule(),
7184               OptionError,"MissingNullSeparator","layers Composite");
7185             break;
7186           }
7187         /*
7188           Adjust offset with gravity and virtual canvas.
7189         */
7190         SetGeometry(image,&geometry);
7191         (void) ParseAbsoluteGeometry(image->geometry,&geometry);
7192         geometry.width=source->page.width != 0 ? source->page.width :
7193           source->columns;
7194         geometry.height=source->page.height != 0 ? source->page.height :
7195           source->rows;
7196         GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
7197           image->columns,image->page.height != 0 ? image->page.height :
7198           image->rows,image->gravity,&geometry);
7199         CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
7200         source=DestroyImageList(source);
7201         break;
7202       }
7203     }
7204     if (layers != (Image *) NULL)
7205       image=layers;
7206     else
7207       image=CloneImage(image,0,0,MagickTrue,exception);
7208     if (image == (Image *) NULL)
7209       goto PerlException;
7210     for ( ; image; image=image->next)
7211     {
7212       AddImageToRegistry(sv,image);
7213       rv=newRV(sv);
7214       av_push(av,sv_bless(rv,hv));
7215       SvREFCNT_dec(sv);
7216     }
7217     exception=DestroyExceptionInfo(exception);
7218     ST(0)=av_reference;
7219     SvREFCNT_dec(perl_exception);
7220     XSRETURN(1);
7221
7222   PerlException:
7223     InheritPerlException(exception,perl_exception);
7224     exception=DestroyExceptionInfo(exception);
7225     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
7226     SvPOK_on(perl_exception);
7227     ST(0)=sv_2mortal(perl_exception);
7228     XSRETURN(1);
7229   }
7230 \f
7231 #
7232 ###############################################################################
7233 #                                                                             #
7234 #                                                                             #
7235 #                                                                             #
7236 #   M a g i c k T o M i m e                                                   #
7237 #                                                                             #
7238 #                                                                             #
7239 #                                                                             #
7240 ###############################################################################
7241 #
7242 #
7243 SV *
7244 MagickToMime(ref,name)
7245   Image::Magick ref=NO_INIT
7246   char *name
7247   ALIAS:
7248     magicktomime = 1
7249   CODE:
7250   {
7251     char
7252       *mime;
7253
7254     PERL_UNUSED_VAR(ref);
7255     PERL_UNUSED_VAR(ix);
7256     mime=MagickToMime(name);
7257     RETVAL=newSVpv(mime,0);
7258     mime=(char *) RelinquishMagickMemory(mime);
7259   }
7260   OUTPUT:
7261     RETVAL
7262 \f
7263 #
7264 ###############################################################################
7265 #                                                                             #
7266 #                                                                             #
7267 #                                                                             #
7268 #   M o g r i f y                                                             #
7269 #                                                                             #
7270 #                                                                             #
7271 #                                                                             #
7272 ###############################################################################
7273 #
7274 #
7275 void
7276 Mogrify(ref,...)
7277   Image::Magick ref=NO_INIT
7278   ALIAS:
7279     Comment            =   1
7280     CommentImage       =   2
7281     Label              =   3
7282     LabelImage         =   4
7283     AddNoise           =   5
7284     AddNoiseImage      =   6
7285     Colorize           =   7
7286     ColorizeImage      =   8
7287     Border             =   9
7288     BorderImage        =  10
7289     Blur               =  11
7290     BlurImage          =  12
7291     Chop               =  13
7292     ChopImage          =  14
7293     Crop               =  15
7294     CropImage          =  16
7295     Despeckle          =  17
7296     DespeckleImage     =  18
7297     Edge               =  19
7298     EdgeImage          =  20
7299     Emboss             =  21
7300     EmbossImage        =  22
7301     Enhance            =  23
7302     EnhanceImage       =  24
7303     Flip               =  25
7304     FlipImage          =  26
7305     Flop               =  27
7306     FlopImage          =  28
7307     Frame              =  29
7308     FrameImage         =  30
7309     Implode            =  31
7310     ImplodeImage       =  32
7311     Magnify            =  33
7312     MagnifyImage       =  34
7313     MedianFilter       =  35
7314     MedianConvolveImage  =  36
7315     Minify             =  37
7316     MinifyImage        =  38
7317     OilPaint           =  39
7318     OilPaintImage      =  40
7319     ReduceNoise        =  41
7320     ReduceNoiseImage   =  42
7321     Roll               =  43
7322     RollImage          =  44
7323     Rotate             =  45
7324     RotateImage        =  46
7325     Sample             =  47
7326     SampleImage        =  48
7327     Scale              =  49
7328     ScaleImage         =  50
7329     Shade              =  51
7330     ShadeImage         =  52
7331     Sharpen            =  53
7332     SharpenImage       =  54
7333     Shear              =  55
7334     ShearImage         =  56
7335     Spread             =  57
7336     SpreadImage        =  58
7337     Swirl              =  59
7338     SwirlImage         =  60
7339     Resize             =  61
7340     ResizeImage        =  62
7341     Zoom               =  63
7342     ZoomImage          =  64
7343     Annotate           =  65
7344     AnnotateImage      =  66
7345     ColorFloodfill     =  67
7346     ColorFloodfillImage=  68
7347     Composite          =  69
7348     CompositeImage     =  70
7349     Contrast           =  71
7350     ContrastImage      =  72
7351     CycleColormap      =  73
7352     CycleColormapImage =  74
7353     Draw               =  75
7354     DrawImage          =  76
7355     Equalize           =  77
7356     EqualizeImage      =  78
7357     Gamma              =  79
7358     GammaImage         =  80
7359     Map                =  81
7360     MapImage           =  82
7361     MatteFloodfill     =  83
7362     MatteFloodfillImage=  84
7363     Modulate           =  85
7364     ModulateImage      =  86
7365     Negate             =  87
7366     NegateImage        =  88
7367     Normalize          =  89
7368     NormalizeImage     =  90
7369     NumberColors       =  91
7370     NumberColorsImage  =  92
7371     Opaque             =  93
7372     OpaqueImage        =  94
7373     Quantize           =  95
7374     QuantizeImage      =  96
7375     Raise              =  97
7376     RaiseImage         =  98
7377     Segment            =  99
7378     SegmentImage       = 100
7379     Signature          = 101
7380     SignatureImage     = 102
7381     Solarize           = 103
7382     SolarizeImage      = 104
7383     Sync               = 105
7384     SyncImage          = 106
7385     Texture            = 107
7386     TextureImage       = 108
7387     Evaluate           = 109
7388     EvaluateImage      = 110
7389     Transparent        = 111
7390     TransparentImage   = 112
7391     Threshold          = 113
7392     ThresholdImage     = 114
7393     Charcoal           = 115
7394     CharcoalImage      = 116
7395     Trim               = 117
7396     TrimImage          = 118
7397     Wave               = 119
7398     WaveImage          = 120
7399     Separate           = 121
7400     SeparateImage      = 122
7401     Stereo             = 125
7402     StereoImage        = 126
7403     Stegano            = 127
7404     SteganoImage       = 128
7405     Deconstruct        = 129
7406     DeconstructImage   = 130
7407     GaussianBlur       = 131
7408     GaussianBlurImage  = 132
7409     Convolve           = 133
7410     ConvolveImage      = 134
7411     Profile            = 135
7412     ProfileImage       = 136
7413     UnsharpMask        = 137
7414     UnsharpMaskImage   = 138
7415     MotionBlur         = 139
7416     MotionBlurImage    = 140
7417     OrderedDither      = 141
7418     OrderedDitherImage = 142
7419     Shave              = 143
7420     ShaveImage         = 144
7421     Level              = 145
7422     LevelImage         = 146
7423     Clip               = 147
7424     ClipImage          = 148
7425     AffineTransform    = 149
7426     AffineTransformImage = 150
7427     Difference         = 151
7428     DifferenceImage    = 152
7429     AdaptiveThreshold  = 153
7430     AdaptiveThresholdImage = 154
7431     Resample           = 155
7432     ResampleImage      = 156
7433     Describe           = 157
7434     DescribeImage      = 158
7435     BlackThreshold     = 159
7436     BlackThresholdImage= 160
7437     WhiteThreshold     = 161
7438     WhiteThresholdImage= 162
7439     RotationalBlur     = 163
7440     RotationalBlurImage= 164
7441     Thumbnail          = 165
7442     ThumbnailImage     = 166
7443     Strip              = 167
7444     StripImage         = 168
7445     Tint               = 169
7446     TintImage          = 170
7447     Channel            = 171
7448     ChannelImage       = 172
7449     Splice             = 173
7450     SpliceImage        = 174
7451     Posterize          = 175
7452     PosterizeImage     = 176
7453     Shadow             = 177
7454     ShadowImage        = 178
7455     Identify           = 179
7456     IdentifyImage      = 180
7457     SepiaTone          = 181
7458     SepiaToneImage     = 182
7459     SigmoidalContrast  = 183
7460     SigmoidalContrastImage = 184
7461     Extent             = 185
7462     ExtentImage        = 186
7463     Vignette           = 187
7464     VignetteImage      = 188
7465     ContrastStretch    = 189
7466     ContrastStretchImage = 190
7467     Sans0              = 191
7468     Sans0Image         = 192
7469     Sans1              = 193
7470     Sans1Image         = 194
7471     AdaptiveSharpen    = 195
7472     AdaptiveSharpenImage = 196
7473     Transpose          = 197
7474     TransposeImage     = 198
7475     Transverse         = 199
7476     TransverseImage    = 200
7477     AutoOrient         = 201
7478     AutoOrientImage    = 202
7479     AdaptiveBlur       = 203
7480     AdaptiveBlurImage  = 204
7481     Sketch             = 205
7482     SketchImage        = 206
7483     UniqueColors       = 207
7484     UniqueColorsImage  = 208
7485     AdaptiveResize     = 209
7486     AdaptiveResizeImage= 210
7487     ClipMask           = 211
7488     ClipMaskImage      = 212
7489     LinearStretch      = 213
7490     LinearStretchImage = 214
7491     ColorMatrix        = 215
7492     ColorMatrixImage   = 216
7493     Mask               = 217
7494     MaskImage          = 218
7495     Polaroid           = 219
7496     PolaroidImage      = 220
7497     FloodfillPaint     = 221
7498     FloodfillPaintImage= 222
7499     Distort            = 223
7500     DistortImage       = 224
7501     Clut               = 225
7502     ClutImage          = 226
7503     LiquidRescale      = 227
7504     LiquidRescaleImage = 228
7505     Encipher           = 229
7506     EncipherImage      = 230
7507     Decipher           = 231
7508     DecipherImage      = 232
7509     Deskew             = 233
7510     DeskewImage        = 234
7511     Remap              = 235
7512     RemapImage         = 236
7513     SparseColor        = 237
7514     SparseColorImage   = 238
7515     Function           = 239
7516     FunctionImage      = 240
7517     SelectiveBlur      = 241
7518     SelectiveBlurImage = 242
7519     HaldClut           = 243
7520     HaldClutImage      = 244
7521     BlueShift          = 245
7522     BlueShiftImage     = 246
7523     ForwardFourierTransform  = 247
7524     ForwardFourierTransformImage = 248
7525     InverseFourierTransform = 249
7526     InverseFourierTransformImage = 250
7527     ColorDecisionList  = 251
7528     ColorDecisionListImage = 252
7529     AutoGamma          = 253
7530     AutoGammaImage     = 254
7531     AutoLevel          = 255
7532     AutoLevelImage     = 256
7533     LevelColors        = 257
7534     LevelImageColors   = 258
7535     Clamp              = 259
7536     ClampImage         = 260
7537     BrightnessContrast = 261
7538     BrightnessContrastImage = 262
7539     Morphology         = 263
7540     MorphologyImage    = 264
7541     Mode               = 265
7542     ModeImage          = 266
7543     Statistic          = 267
7544     StatisticImage     = 268
7545     Perceptible        = 269
7546     PerceptibleImage   = 270
7547     Poly               = 271
7548     PolyImage          = 272
7549     Grayscale          = 273
7550     GrayscaleImage     = 274
7551     CannyEdge          = 275
7552     CannyEdgeImage     = 276
7553     HoughLine          = 277
7554     HoughLineImage     = 278
7555     MeanShift          = 279
7556     MeanShiftImage     = 280
7557     Kuwahara           = 281
7558     KuwaharaImage      = 282
7559     ConnectedComponent = 283
7560     ConnectedComponentImage = 284
7561     CopyPixels         = 285
7562     CopyImagePixels    = 286
7563     Color              = 287
7564     ColorImage         = 288
7565     WaveletDenoise     = 289
7566     WaveletDenoiseImage= 290
7567     Colorspace         = 291
7568     ColorspaceImage    = 292
7569     MogrifyRegion      = 666
7570   PPCODE:
7571   {
7572     AffineMatrix
7573       affine,
7574       current;
7575
7576     char
7577       attribute_flag[MaxArguments],
7578       message[MagickPathExtent];
7579
7580     ChannelType
7581       channel,
7582       channel_mask;
7583
7584     CompositeOperator
7585       compose;
7586
7587     const char
7588       *attribute,
7589       *value;
7590
7591     double
7592       angle;
7593
7594     ExceptionInfo
7595       *exception;
7596
7597     GeometryInfo
7598       geometry_info;
7599
7600     Image
7601       *image,
7602       *next,
7603       *region_image;
7604
7605     MagickBooleanType
7606       status;
7607
7608     MagickStatusType
7609       flags;
7610
7611     PixelInfo
7612       fill_color;
7613
7614     RectangleInfo
7615       geometry,
7616       region_info;
7617
7618     register ssize_t
7619       i;
7620
7621     ssize_t
7622       base,
7623       j,
7624       number_images;
7625
7626     struct Methods
7627       *rp;
7628
7629     struct PackageInfo
7630       *info;
7631
7632     SV
7633       *perl_exception,
7634       **pv,
7635       *reference,
7636       **reference_vector;
7637
7638     struct ArgumentList
7639       argument_list[MaxArguments];
7640
7641     PERL_UNUSED_VAR(ref);
7642     PERL_UNUSED_VAR(ix);
7643     exception=AcquireExceptionInfo();
7644     perl_exception=newSVpv("",0);
7645     reference_vector=NULL;
7646     region_image=NULL;
7647     number_images=0;
7648     base=2;
7649     if (sv_isobject(ST(0)) == 0)
7650       {
7651         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7652           PackageName);
7653         goto PerlException;
7654       }
7655     reference=SvRV(ST(0));
7656     region_info.width=0;
7657     region_info.height=0;
7658     region_info.x=0;
7659     region_info.y=0;
7660     region_image=(Image *) NULL;
7661     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7662     if (ix && (ix != 666))
7663       {
7664         /*
7665           Called as Method(...)
7666         */
7667         ix=(ix+1)/2;
7668         rp=(&Methods[ix-1]);
7669         attribute=rp->name;
7670       }
7671     else
7672       {
7673         /*
7674           Called as Mogrify("Method",...)
7675         */
7676         attribute=(char *) SvPV(ST(1),na);
7677         if (ix)
7678           {
7679             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7680             attribute=(char *) SvPV(ST(2),na);
7681             base++;
7682           }
7683         for (rp=Methods; ; rp++)
7684         {
7685           if (rp >= EndOf(Methods))
7686             {
7687               ThrowPerlException(exception,OptionError,
7688                 "UnrecognizedPerlMagickMethod",attribute);
7689               goto PerlException;
7690             }
7691           if (strEQcase(attribute,rp->name))
7692             break;
7693         }
7694         ix=rp-Methods+1;
7695         base++;
7696       }
7697     if (image == (Image *) NULL)
7698       {
7699         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7700         goto PerlException;
7701       }
7702     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7703     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7704     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7705     {
7706       Arguments
7707         *pp,
7708         *qq;
7709
7710       ssize_t
7711         ssize_test;
7712
7713       struct ArgumentList
7714         *al;
7715
7716       SV
7717         *sv;
7718
7719       sv=NULL;
7720       ssize_test=0;
7721       pp=(Arguments *) NULL;
7722       qq=rp->arguments;
7723       if (i == items)
7724         {
7725           pp=rp->arguments,
7726           sv=ST(i-1);
7727         }
7728       else
7729         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7730         {
7731           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7732             break;
7733           if (strEQcase(attribute,qq->method) > ssize_test)
7734             {
7735               pp=qq;
7736               ssize_test=strEQcase(attribute,qq->method);
7737             }
7738         }
7739       if (pp == (Arguments *) NULL)
7740         {
7741           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7742             attribute);
7743           goto continue_outer_loop;
7744         }
7745       al=(&argument_list[pp-rp->arguments]);
7746       switch (pp->type)
7747       {
7748         case ArrayReference:
7749         {
7750           if (SvTYPE(sv) != SVt_RV)
7751             {
7752               (void) FormatLocaleString(message,MagickPathExtent,
7753                 "invalid %.60s value",pp->method);
7754               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7755               goto continue_outer_loop;
7756             }
7757           al->array_reference=SvRV(sv);
7758           break;
7759         }
7760         case RealReference:
7761         {
7762           al->real_reference=SvNV(sv);
7763           break;
7764         }
7765         case FileReference:
7766         {
7767           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7768           break;
7769         }
7770         case ImageReference:
7771         {
7772           if (!sv_isobject(sv) ||
7773               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7774                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7775             {
7776               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7777                 PackageName);
7778               goto PerlException;
7779             }
7780           break;
7781         }
7782         case IntegerReference:
7783         {
7784           al->integer_reference=SvIV(sv);
7785           break;
7786         }
7787         case StringReference:
7788         {
7789           al->string_reference=(char *) SvPV(sv,al->length);
7790           if (sv_isobject(sv))
7791             al->image_reference=SetupList(aTHX_ SvRV(sv),
7792               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7793           break;
7794         }
7795         default:
7796         {
7797           /*
7798             Is a string; look up name.
7799           */
7800           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7801             {
7802               al->string_reference=(char *) SvPV(sv,al->length);
7803               al->integer_reference=(-1);
7804               break;
7805             }
7806           al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7807             MagickFalse,SvPV(sv,na));
7808           if (pp->type == MagickChannelOptions)
7809             al->integer_reference=ParseChannelOption(SvPV(sv,na));
7810           if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7811             {
7812               (void) FormatLocaleString(message,MagickPathExtent,
7813                 "invalid %.60s value",pp->method);
7814               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7815               goto continue_outer_loop;
7816             }
7817           break;
7818         }
7819       }
7820       attribute_flag[pp-rp->arguments]++;
7821       continue_outer_loop: ;
7822     }
7823     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7824     pv=reference_vector;
7825     SetGeometryInfo(&geometry_info);
7826     channel=DefaultChannels;
7827     for (next=image; next; next=next->next)
7828     {
7829       image=next;
7830       SetGeometry(image,&geometry);
7831       if ((region_info.width*region_info.height) != 0)
7832         {
7833           region_image=image;
7834           image=CropImage(image,&region_info,exception);
7835         }
7836       switch (ix)
7837       {
7838         default:
7839         {
7840           (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double) ix);
7841           ThrowPerlException(exception,OptionError,
7842             "UnrecognizedPerlMagickMethod",message);
7843           goto PerlException;
7844         }
7845         case 1:  /* Comment */
7846         {
7847           if (attribute_flag[0] == 0)
7848             argument_list[0].string_reference=(char *) NULL;
7849           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7850             info ? info->image_info : (ImageInfo *) NULL,image,
7851             argument_list[0].string_reference,exception),exception);
7852           break;
7853         }
7854         case 2:  /* Label */
7855         {
7856           if (attribute_flag[0] == 0)
7857             argument_list[0].string_reference=(char *) NULL;
7858           (void) SetImageProperty(image,"label",InterpretImageProperties(
7859             info ? info->image_info : (ImageInfo *) NULL,image,
7860             argument_list[0].string_reference,exception),exception);
7861           break;
7862         }
7863         case 3:  /* AddNoise */
7864         {
7865           double
7866             attenuate;
7867
7868           if (attribute_flag[0] == 0)
7869             argument_list[0].integer_reference=UniformNoise;
7870           attenuate=1.0;
7871           if (attribute_flag[1] != 0)
7872             attenuate=argument_list[1].real_reference;
7873           if (attribute_flag[2] != 0)
7874             channel=(ChannelType) argument_list[2].integer_reference;
7875           channel_mask=SetImageChannelMask(image,channel);
7876           image=AddNoiseImage(image,(NoiseType)
7877             argument_list[0].integer_reference,attenuate,exception);
7878           if (image != (Image *) NULL)
7879             (void) SetImageChannelMask(image,channel_mask);
7880           break;
7881         }
7882         case 4:  /* Colorize */
7883         {
7884           PixelInfo
7885             target;
7886
7887           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
7888             0,0,&target,exception);
7889           if (attribute_flag[0] != 0)
7890             (void) QueryColorCompliance(argument_list[0].string_reference,
7891               AllCompliance,&target,exception);
7892           if (attribute_flag[1] == 0)
7893             argument_list[1].string_reference="100%";
7894           image=ColorizeImage(image,argument_list[1].string_reference,&target,
7895             exception);
7896           break;
7897         }
7898         case 5:  /* Border */
7899         {
7900           CompositeOperator
7901             compose;
7902
7903           geometry.width=0;
7904           geometry.height=0;
7905           if (attribute_flag[0] != 0)
7906             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7907               &geometry,exception);
7908           if (attribute_flag[1] != 0)
7909             geometry.width=argument_list[1].integer_reference;
7910           if (attribute_flag[2] != 0)
7911             geometry.height=argument_list[2].integer_reference;
7912           if (attribute_flag[3] != 0)
7913             QueryColorCompliance(argument_list[3].string_reference,
7914               AllCompliance,&image->border_color,exception);
7915           if (attribute_flag[4] != 0)
7916             QueryColorCompliance(argument_list[4].string_reference,
7917               AllCompliance,&image->border_color,exception);
7918           if (attribute_flag[5] != 0)
7919             QueryColorCompliance(argument_list[5].string_reference,
7920               AllCompliance,&image->border_color,exception);
7921           compose=image->compose;
7922           if (attribute_flag[6] != 0)
7923             compose=(CompositeOperator) argument_list[6].integer_reference;
7924           image=BorderImage(image,&geometry,compose,exception);
7925           break;
7926         }
7927         case 6:  /* Blur */
7928         {
7929           if (attribute_flag[0] != 0)
7930             {
7931               flags=ParseGeometry(argument_list[0].string_reference,
7932                 &geometry_info);
7933               if ((flags & SigmaValue) == 0)
7934                 geometry_info.sigma=1.0;
7935             }
7936           if (attribute_flag[1] != 0)
7937             geometry_info.rho=argument_list[1].real_reference;
7938           if (attribute_flag[2] != 0)
7939             geometry_info.sigma=argument_list[2].real_reference;
7940           if (attribute_flag[3] != 0)
7941             channel=(ChannelType) argument_list[3].integer_reference;
7942           channel_mask=SetImageChannelMask(image,channel);
7943           image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
7944             exception);
7945           if (image != (Image *) NULL)
7946             (void) SetImageChannelMask(image,channel_mask);
7947           break;
7948         }
7949         case 7:  /* Chop */
7950         {
7951           if (attribute_flag[5] != 0)
7952             image->gravity=(GravityType) argument_list[5].integer_reference;
7953           if (attribute_flag[0] != 0)
7954             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7955               &geometry,exception);
7956           if (attribute_flag[1] != 0)
7957             geometry.width=argument_list[1].integer_reference;
7958           if (attribute_flag[2] != 0)
7959             geometry.height=argument_list[2].integer_reference;
7960           if (attribute_flag[3] != 0)
7961             geometry.x=argument_list[3].integer_reference;
7962           if (attribute_flag[4] != 0)
7963             geometry.y=argument_list[4].integer_reference;
7964           image=ChopImage(image,&geometry,exception);
7965           break;
7966         }
7967         case 8:  /* Crop */
7968         {
7969           if (attribute_flag[6] != 0)
7970             image->gravity=(GravityType) argument_list[6].integer_reference;
7971           if (attribute_flag[0] != 0)
7972             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7973               &geometry,exception);
7974           if (attribute_flag[1] != 0)
7975             geometry.width=argument_list[1].integer_reference;
7976           if (attribute_flag[2] != 0)
7977             geometry.height=argument_list[2].integer_reference;
7978           if (attribute_flag[3] != 0)
7979             geometry.x=argument_list[3].integer_reference;
7980           if (attribute_flag[4] != 0)
7981             geometry.y=argument_list[4].integer_reference;
7982           if (attribute_flag[5] != 0)
7983             image->fuzz=StringToDoubleInterval(
7984               argument_list[5].string_reference,(double) QuantumRange+1.0);
7985           image=CropImage(image,&geometry,exception);
7986           break;
7987         }
7988         case 9:  /* Despeckle */
7989         {
7990           image=DespeckleImage(image,exception);
7991           break;
7992         }
7993         case 10:  /* Edge */
7994         {
7995           if (attribute_flag[0] != 0)
7996             geometry_info.rho=argument_list[0].real_reference;
7997           image=EdgeImage(image,geometry_info.rho,exception);
7998           break;
7999         }
8000         case 11:  /* Emboss */
8001         {
8002           if (attribute_flag[0] != 0)
8003             {
8004               flags=ParseGeometry(argument_list[0].string_reference,
8005                 &geometry_info);
8006               if ((flags & SigmaValue) == 0)
8007                 geometry_info.sigma=1.0;
8008             }
8009           if (attribute_flag[1] != 0)
8010             geometry_info.rho=argument_list[1].real_reference;
8011           if (attribute_flag[2] != 0)
8012             geometry_info.sigma=argument_list[2].real_reference;
8013           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
8014             exception);
8015           break;
8016         }
8017         case 12:  /* Enhance */
8018         {
8019           image=EnhanceImage(image,exception);
8020           break;
8021         }
8022         case 13:  /* Flip */
8023         {
8024           image=FlipImage(image,exception);
8025           break;
8026         }
8027         case 14:  /* Flop */
8028         {
8029           image=FlopImage(image,exception);
8030           break;
8031         }
8032         case 15:  /* Frame */
8033         {
8034           CompositeOperator
8035             compose;
8036
8037           FrameInfo
8038             frame_info;
8039
8040           if (attribute_flag[0] != 0)
8041             {
8042               flags=ParsePageGeometry(image,argument_list[0].string_reference,
8043                 &geometry,exception);
8044               frame_info.width=geometry.width;
8045               frame_info.height=geometry.height;
8046               frame_info.outer_bevel=geometry.x;
8047               frame_info.inner_bevel=geometry.y;
8048             }
8049           if (attribute_flag[1] != 0)
8050             frame_info.width=argument_list[1].integer_reference;
8051           if (attribute_flag[2] != 0)
8052             frame_info.height=argument_list[2].integer_reference;
8053           if (attribute_flag[3] != 0)
8054             frame_info.inner_bevel=argument_list[3].integer_reference;
8055           if (attribute_flag[4] != 0)
8056             frame_info.outer_bevel=argument_list[4].integer_reference;
8057           if (attribute_flag[5] != 0)
8058             QueryColorCompliance(argument_list[5].string_reference,
8059               AllCompliance,&fill_color,exception);
8060           if (attribute_flag[6] != 0)
8061             QueryColorCompliance(argument_list[6].string_reference,
8062               AllCompliance,&fill_color,exception);
8063           frame_info.x=(ssize_t) frame_info.width;
8064           frame_info.y=(ssize_t) frame_info.height;
8065           frame_info.width=image->columns+2*frame_info.x;
8066           frame_info.height=image->rows+2*frame_info.y;
8067           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
8068             image->alpha_color=fill_color;
8069           compose=image->compose;
8070           if (attribute_flag[7] != 0)
8071             compose=(CompositeOperator) argument_list[7].integer_reference;
8072           image=FrameImage(image,&frame_info,compose,exception);
8073           break;
8074         }
8075         case 16:  /* Implode */
8076         {
8077           PixelInterpolateMethod
8078             method;
8079
8080           if (attribute_flag[0] == 0)
8081             argument_list[0].real_reference=0.5;
8082           method=UndefinedInterpolatePixel;
8083           if (attribute_flag[1] != 0)
8084             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8085           image=ImplodeImage(image,argument_list[0].real_reference,
8086             method,exception);
8087           break;
8088         }
8089         case 17:  /* Magnify */
8090         {
8091           image=MagnifyImage(image,exception);
8092           break;
8093         }
8094         case 18:  /* MedianFilter */
8095         {
8096           if (attribute_flag[0] != 0)
8097             {
8098               flags=ParseGeometry(argument_list[0].string_reference,
8099                 &geometry_info);
8100               if ((flags & SigmaValue) == 0)
8101                 geometry_info.sigma=geometry_info.rho;
8102             }
8103           if (attribute_flag[1] != 0)
8104             geometry_info.rho=argument_list[1].real_reference;
8105           if (attribute_flag[2] != 0)
8106             geometry_info.sigma=argument_list[2].real_reference;
8107           if (attribute_flag[3] != 0)
8108             channel=(ChannelType) argument_list[3].integer_reference;
8109           channel_mask=SetImageChannelMask(image,channel);
8110           image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
8111             (size_t) geometry_info.sigma,exception);
8112           if (image != (Image *) NULL)
8113             (void) SetImageChannelMask(image,channel_mask);
8114           break;
8115         }
8116         case 19:  /* Minify */
8117         {
8118           image=MinifyImage(image,exception);
8119           break;
8120         }
8121         case 20:  /* OilPaint */
8122         {
8123           if (attribute_flag[0] == 0)
8124             argument_list[0].real_reference=0.0;
8125           if (attribute_flag[1] == 0)
8126             argument_list[1].real_reference=1.0;
8127           image=OilPaintImage(image,argument_list[0].real_reference,
8128             argument_list[1].real_reference,exception);
8129           break;
8130         }
8131         case 21:  /* ReduceNoise */
8132         {
8133           if (attribute_flag[0] != 0)
8134             {
8135               flags=ParseGeometry(argument_list[0].string_reference,
8136                 &geometry_info);
8137               if ((flags & SigmaValue) == 0)
8138                 geometry_info.sigma=1.0;
8139             }
8140           if (attribute_flag[1] != 0)
8141             geometry_info.rho=argument_list[1].real_reference;
8142           if (attribute_flag[2] != 0)
8143             geometry_info.sigma=argument_list[2].real_reference;
8144           if (attribute_flag[3] != 0)
8145             channel=(ChannelType) argument_list[3].integer_reference;
8146           channel_mask=SetImageChannelMask(image,channel);
8147           image=StatisticImage(image,NonpeakStatistic,(size_t)
8148             geometry_info.rho,(size_t) geometry_info.sigma,exception);
8149           if (image != (Image *) NULL)
8150             (void) SetImageChannelMask(image,channel_mask);
8151           break;
8152         }
8153         case 22:  /* Roll */
8154         {
8155           if (attribute_flag[0] != 0)
8156             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8157               &geometry,exception);
8158           if (attribute_flag[1] != 0)
8159             geometry.x=argument_list[1].integer_reference;
8160           if (attribute_flag[2] != 0)
8161             geometry.y=argument_list[2].integer_reference;
8162           image=RollImage(image,geometry.x,geometry.y,exception);
8163           break;
8164         }
8165         case 23:  /* Rotate */
8166         {
8167           if (attribute_flag[0] == 0)
8168             argument_list[0].real_reference=90.0;
8169           if (attribute_flag[1] != 0)
8170             {
8171               QueryColorCompliance(argument_list[1].string_reference,
8172                 AllCompliance,&image->background_color,exception);
8173               if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
8174                   (image->alpha_trait == UndefinedPixelTrait))
8175                 (void) SetImageAlpha(image,OpaqueAlpha,exception);
8176             }
8177           image=RotateImage(image,argument_list[0].real_reference,exception);
8178           break;
8179         }
8180         case 24:  /* Sample */
8181         {
8182           if (attribute_flag[0] != 0)
8183             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8184               &geometry,exception);
8185           if (attribute_flag[1] != 0)
8186             geometry.width=argument_list[1].integer_reference;
8187           if (attribute_flag[2] != 0)
8188             geometry.height=argument_list[2].integer_reference;
8189           image=SampleImage(image,geometry.width,geometry.height,exception);
8190           break;
8191         }
8192         case 25:  /* Scale */
8193         {
8194           if (attribute_flag[0] != 0)
8195             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8196               &geometry,exception);
8197           if (attribute_flag[1] != 0)
8198             geometry.width=argument_list[1].integer_reference;
8199           if (attribute_flag[2] != 0)
8200             geometry.height=argument_list[2].integer_reference;
8201           image=ScaleImage(image,geometry.width,geometry.height,exception);
8202           break;
8203         }
8204         case 26:  /* Shade */
8205         {
8206           if (attribute_flag[0] != 0)
8207             {
8208               flags=ParseGeometry(argument_list[0].string_reference,
8209                 &geometry_info);
8210               if ((flags & SigmaValue) == 0)
8211                 geometry_info.sigma=0.0;
8212             }
8213           if (attribute_flag[1] != 0)
8214             geometry_info.rho=argument_list[1].real_reference;
8215           if (attribute_flag[2] != 0)
8216             geometry_info.sigma=argument_list[2].real_reference;
8217           image=ShadeImage(image,
8218             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8219             geometry_info.rho,geometry_info.sigma,exception);
8220           break;
8221         }
8222         case 27:  /* Sharpen */
8223         {
8224           if (attribute_flag[0] != 0)
8225             {
8226               flags=ParseGeometry(argument_list[0].string_reference,
8227                 &geometry_info);
8228               if ((flags & SigmaValue) == 0)
8229                 geometry_info.sigma=1.0;
8230             }
8231           if (attribute_flag[1] != 0)
8232             geometry_info.rho=argument_list[1].real_reference;
8233           if (attribute_flag[2] != 0)
8234             geometry_info.sigma=argument_list[2].real_reference;
8235           if (attribute_flag[3] != 0)
8236             channel=(ChannelType) argument_list[3].integer_reference;
8237           channel_mask=SetImageChannelMask(image,channel);
8238           image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
8239             exception);
8240           if (image != (Image *) NULL)
8241             (void) SetImageChannelMask(image,channel_mask);
8242           break;
8243         }
8244         case 28:  /* Shear */
8245         {
8246           if (attribute_flag[0] != 0)
8247             {
8248               flags=ParseGeometry(argument_list[0].string_reference,
8249                 &geometry_info);
8250               if ((flags & SigmaValue) == 0)
8251                 geometry_info.sigma=geometry_info.rho;
8252             }
8253           if (attribute_flag[1] != 0)
8254             geometry_info.rho=argument_list[1].real_reference;
8255           if (attribute_flag[2] != 0)
8256             geometry_info.sigma=argument_list[2].real_reference;
8257           if (attribute_flag[3] != 0)
8258             QueryColorCompliance(argument_list[3].string_reference,
8259               AllCompliance,&image->background_color,exception);
8260           if (attribute_flag[4] != 0)
8261             QueryColorCompliance(argument_list[4].string_reference,
8262               AllCompliance,&image->background_color,exception);
8263           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
8264             exception);
8265           break;
8266         }
8267         case 29:  /* Spread */
8268         {
8269           PixelInterpolateMethod
8270             method;
8271
8272           if (attribute_flag[0] == 0)
8273             argument_list[0].real_reference=1.0;
8274           method=UndefinedInterpolatePixel;
8275           if (attribute_flag[1] != 0)
8276             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8277           image=SpreadImage(image,method,argument_list[0].real_reference,
8278             exception);
8279           break;
8280         }
8281         case 30:  /* Swirl */
8282         {
8283           PixelInterpolateMethod
8284             method;
8285
8286           if (attribute_flag[0] == 0)
8287             argument_list[0].real_reference=50.0;
8288           method=UndefinedInterpolatePixel;
8289           if (attribute_flag[1] != 0)
8290             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8291           image=SwirlImage(image,argument_list[0].real_reference,
8292             method,exception);
8293           break;
8294         }
8295         case 31:  /* Resize */
8296         case 32:  /* Zoom */
8297         {
8298           if (attribute_flag[0] != 0)
8299             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8300               &geometry,exception);
8301           if (attribute_flag[1] != 0)
8302             geometry.width=argument_list[1].integer_reference;
8303           if (attribute_flag[2] != 0)
8304             geometry.height=argument_list[2].integer_reference;
8305           if (attribute_flag[3] == 0)
8306             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
8307           if (attribute_flag[4] != 0)
8308             SetImageArtifact(image,"filter:support",
8309               argument_list[4].string_reference);
8310           image=ResizeImage(image,geometry.width,geometry.height,
8311             (FilterType) argument_list[3].integer_reference,
8312             exception);
8313           break;
8314         }
8315         case 33:  /* Annotate */
8316         {
8317           DrawInfo
8318             *draw_info;
8319
8320           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8321             (DrawInfo *) NULL);
8322           if (attribute_flag[0] != 0)
8323             {
8324               char
8325                 *text;
8326
8327               text=InterpretImageProperties(info ? info->image_info :
8328                 (ImageInfo *) NULL,image,argument_list[0].string_reference,
8329                 exception);
8330               (void) CloneString(&draw_info->text,text);
8331               text=DestroyString(text);
8332             }
8333           if (attribute_flag[1] != 0)
8334             (void) CloneString(&draw_info->font,
8335               argument_list[1].string_reference);
8336           if (attribute_flag[2] != 0)
8337             draw_info->pointsize=argument_list[2].real_reference;
8338           if (attribute_flag[3] != 0)
8339             (void) CloneString(&draw_info->density,
8340               argument_list[3].string_reference);
8341           if (attribute_flag[4] != 0)
8342             (void) QueryColorCompliance(argument_list[4].string_reference,
8343               AllCompliance,&draw_info->undercolor,exception);
8344           if (attribute_flag[5] != 0)
8345             {
8346               (void) QueryColorCompliance(argument_list[5].string_reference,
8347                 AllCompliance,&draw_info->stroke,exception);
8348               if (argument_list[5].image_reference != (Image *) NULL)
8349                 draw_info->stroke_pattern=CloneImage(
8350                   argument_list[5].image_reference,0,0,MagickTrue,exception);
8351             }
8352           if (attribute_flag[6] != 0)
8353             {
8354               (void) QueryColorCompliance(argument_list[6].string_reference,
8355                 AllCompliance,&draw_info->fill,exception);
8356               if (argument_list[6].image_reference != (Image *) NULL)
8357                 draw_info->fill_pattern=CloneImage(
8358                   argument_list[6].image_reference,0,0,MagickTrue,exception);
8359             }
8360           if (attribute_flag[7] != 0)
8361             {
8362               (void) CloneString(&draw_info->geometry,
8363                 argument_list[7].string_reference);
8364               flags=ParsePageGeometry(image,argument_list[7].string_reference,
8365                 &geometry,exception);
8366               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8367                 geometry_info.sigma=geometry_info.xi;
8368             }
8369           if (attribute_flag[8] != 0)
8370             (void) QueryColorCompliance(argument_list[8].string_reference,
8371               AllCompliance,&draw_info->fill,exception);
8372           if (attribute_flag[11] != 0)
8373             draw_info->gravity=(GravityType)
8374               argument_list[11].integer_reference;
8375           if (attribute_flag[25] != 0)
8376             {
8377               AV
8378                 *av;
8379
8380               av=(AV *) argument_list[25].array_reference;
8381               if ((av_len(av) != 3) && (av_len(av) != 5))
8382                 {
8383                   ThrowPerlException(exception,OptionError,
8384                     "affine matrix must have 4 or 6 elements",PackageName);
8385                   goto PerlException;
8386                 }
8387               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8388               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8389               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8390               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8391               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8392                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8393                 {
8394                   ThrowPerlException(exception,OptionError,
8395                     "affine matrix is singular",PackageName);
8396                    goto PerlException;
8397                 }
8398               if (av_len(av) == 5)
8399                 {
8400                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8401                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8402                 }
8403             }
8404           for (j=12; j < 17; j++)
8405           {
8406             if (attribute_flag[j] == 0)
8407               continue;
8408             value=argument_list[j].string_reference;
8409             angle=argument_list[j].real_reference;
8410             current=draw_info->affine;
8411             GetAffineMatrix(&affine);
8412             switch (j)
8413             {
8414               case 12:
8415               {
8416                 /*
8417                   Translate.
8418                 */
8419                 flags=ParseGeometry(value,&geometry_info);
8420                 affine.tx=geometry_info.xi;
8421                 affine.ty=geometry_info.psi;
8422                 if ((flags & PsiValue) == 0)
8423                   affine.ty=affine.tx;
8424                 break;
8425               }
8426               case 13:
8427               {
8428                 /*
8429                   Scale.
8430                 */
8431                 flags=ParseGeometry(value,&geometry_info);
8432                 affine.sx=geometry_info.rho;
8433                 affine.sy=geometry_info.sigma;
8434                 if ((flags & SigmaValue) == 0)
8435                   affine.sy=affine.sx;
8436                 break;
8437               }
8438               case 14:
8439               {
8440                 /*
8441                   Rotate.
8442                 */
8443                 if (angle == 0.0)
8444                   break;
8445                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8446                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8447                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8448                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8449                 break;
8450               }
8451               case 15:
8452               {
8453                 /*
8454                   SkewX.
8455                 */
8456                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8457                 break;
8458               }
8459               case 16:
8460               {
8461                 /*
8462                   SkewY.
8463                 */
8464                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8465                 break;
8466               }
8467             }
8468             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8469             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8470             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8471             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8472             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8473               current.tx;
8474             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8475               current.ty;
8476           }
8477           if (attribute_flag[9] == 0)
8478             argument_list[9].real_reference=0.0;
8479           if (attribute_flag[10] == 0)
8480             argument_list[10].real_reference=0.0;
8481           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8482             {
8483               char
8484                 geometry[MagickPathExtent];
8485
8486               (void) FormatLocaleString(geometry,MagickPathExtent,"%+f%+f",
8487                 (double) argument_list[9].real_reference+draw_info->affine.tx,
8488                 (double) argument_list[10].real_reference+draw_info->affine.ty);
8489               (void) CloneString(&draw_info->geometry,geometry);
8490             }
8491           if (attribute_flag[17] != 0)
8492             draw_info->stroke_width=argument_list[17].real_reference;
8493           if (attribute_flag[18] != 0)
8494             {
8495               draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8496                 MagickTrue : MagickFalse;
8497               draw_info->stroke_antialias=draw_info->text_antialias;
8498             }
8499           if (attribute_flag[19] != 0)
8500             (void) CloneString(&draw_info->family,
8501               argument_list[19].string_reference);
8502           if (attribute_flag[20] != 0)
8503             draw_info->style=(StyleType) argument_list[20].integer_reference;
8504           if (attribute_flag[21] != 0)
8505             draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8506           if (attribute_flag[22] != 0)
8507             draw_info->weight=argument_list[22].integer_reference;
8508           if (attribute_flag[23] != 0)
8509             draw_info->align=(AlignType) argument_list[23].integer_reference;
8510           if (attribute_flag[24] != 0)
8511             (void) CloneString(&draw_info->encoding,
8512               argument_list[24].string_reference);
8513           if (attribute_flag[25] != 0)
8514             draw_info->fill_pattern=CloneImage(
8515               argument_list[25].image_reference,0,0,MagickTrue,exception);
8516           if (attribute_flag[26] != 0)
8517             draw_info->fill_pattern=CloneImage(
8518               argument_list[26].image_reference,0,0,MagickTrue,exception);
8519           if (attribute_flag[27] != 0)
8520             draw_info->stroke_pattern=CloneImage(
8521               argument_list[27].image_reference,0,0,MagickTrue,exception);
8522           if (attribute_flag[29] != 0)
8523             draw_info->kerning=argument_list[29].real_reference;
8524           if (attribute_flag[30] != 0)
8525             draw_info->interline_spacing=argument_list[30].real_reference;
8526           if (attribute_flag[31] != 0)
8527             draw_info->interword_spacing=argument_list[31].real_reference;
8528           if (attribute_flag[32] != 0)
8529             draw_info->direction=(DirectionType)
8530               argument_list[32].integer_reference;
8531           (void) AnnotateImage(image,draw_info,exception);
8532           draw_info=DestroyDrawInfo(draw_info);
8533           break;
8534         }
8535         case 34:  /* ColorFloodfill */
8536         {
8537           DrawInfo
8538             *draw_info;
8539
8540           MagickBooleanType
8541             invert;
8542
8543           PixelInfo
8544             target;
8545
8546           draw_info=CloneDrawInfo(info ? info->image_info :
8547             (ImageInfo *) NULL,(DrawInfo *) NULL);
8548           if (attribute_flag[0] != 0)
8549             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8550               &geometry,exception);
8551           if (attribute_flag[1] != 0)
8552             geometry.x=argument_list[1].integer_reference;
8553           if (attribute_flag[2] != 0)
8554             geometry.y=argument_list[2].integer_reference;
8555           if (attribute_flag[3] != 0)
8556             (void) QueryColorCompliance(argument_list[3].string_reference,
8557               AllCompliance,&draw_info->fill,exception);
8558           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
8559             geometry.x,geometry.y,&target,exception);
8560           invert=MagickFalse;
8561           if (attribute_flag[4] != 0)
8562             {
8563               QueryColorCompliance(argument_list[4].string_reference,
8564                 AllCompliance,&target,exception);
8565               invert=MagickTrue;
8566             }
8567           if (attribute_flag[5] != 0)
8568             image->fuzz=StringToDoubleInterval(
8569               argument_list[5].string_reference,(double) QuantumRange+1.0);
8570           if (attribute_flag[6] != 0)
8571             invert=(MagickBooleanType) argument_list[6].integer_reference;
8572           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8573             geometry.y,invert,exception);
8574           draw_info=DestroyDrawInfo(draw_info);
8575           break;
8576         }
8577         case 35:  /* Composite */
8578         {
8579           char
8580             composite_geometry[MagickPathExtent];
8581
8582           Image
8583             *composite_image,
8584             *rotate_image;
8585
8586           MagickBooleanType
8587             clip_to_self;
8588
8589           compose=OverCompositeOp;
8590           if (attribute_flag[0] != 0)
8591             composite_image=argument_list[0].image_reference;
8592           else
8593             {
8594               ThrowPerlException(exception,OptionError,
8595                 "CompositeImageRequired",PackageName);
8596               goto PerlException;
8597             }
8598           /*
8599             Parameter Handling used for BOTH normal and tiled composition.
8600           */
8601           if (attribute_flag[1] != 0) /* compose */
8602             compose=(CompositeOperator) argument_list[1].integer_reference;
8603           if (attribute_flag[6] != 0) /* opacity  */
8604             {
8605               if (compose != DissolveCompositeOp)
8606                 (void) SetImageAlpha(composite_image,(Quantum)
8607                   StringToDoubleInterval(argument_list[6].string_reference,
8608                   (double) QuantumRange+1.0),exception);
8609               else
8610                 {
8611                   CacheView
8612                     *composite_view;
8613
8614                   double
8615                     opacity;
8616
8617                   MagickBooleanType
8618                     sync;
8619
8620                   register ssize_t
8621                     x;
8622
8623                   register Quantum
8624                     *q;
8625
8626                   ssize_t
8627                     y;
8628
8629                   /*
8630                     Handle dissolve composite operator (patch by
8631                     Kevin A. McGrail).
8632                   */
8633                   (void) CloneString(&image->geometry,
8634                     argument_list[6].string_reference);
8635                   opacity=(Quantum) StringToDoubleInterval(
8636                     argument_list[6].string_reference,(double) QuantumRange+
8637                     1.0);
8638                   if (composite_image->alpha_trait != UndefinedPixelTrait)
8639                     (void) SetImageAlpha(composite_image,OpaqueAlpha,exception);
8640                   composite_view=AcquireAuthenticCacheView(composite_image,exception);
8641                   for (y=0; y < (ssize_t) composite_image->rows ; y++)
8642                   {
8643                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8644                       composite_image->columns,1,exception);
8645                     for (x=0; x < (ssize_t) composite_image->columns; x++)
8646                     {
8647                       if (GetPixelAlpha(image,q) == OpaqueAlpha)
8648                         SetPixelAlpha(composite_image,ClampToQuantum(opacity),
8649                           q);
8650                       q+=GetPixelChannels(composite_image);
8651                     }
8652                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8653                     if (sync == MagickFalse)
8654                       break;
8655                   }
8656                   composite_view=DestroyCacheView(composite_view);
8657                 }
8658             }
8659           if (attribute_flag[9] != 0)    /* "color=>" */
8660             QueryColorCompliance(argument_list[9].string_reference,
8661               AllCompliance,&composite_image->background_color,exception);
8662           if (attribute_flag[12] != 0) /* "interpolate=>" */
8663             image->interpolate=(PixelInterpolateMethod)
8664               argument_list[12].integer_reference;
8665           if (attribute_flag[13] != 0)   /* "args=>" */
8666             (void) SetImageArtifact(composite_image,"compose:args",
8667               argument_list[13].string_reference);
8668           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8669             (void) SetImageArtifact(composite_image,"compose:args",
8670               argument_list[14].string_reference);
8671           clip_to_self=MagickTrue;
8672           if (attribute_flag[15] != 0)
8673             clip_to_self=(MagickBooleanType)
8674               argument_list[15].integer_reference;
8675           /*
8676             Tiling Composition (with orthogonal rotate).
8677           */
8678           rotate_image=(Image *) NULL;
8679           if (attribute_flag[8] != 0)   /* "rotate=>" */
8680             {
8681                /*
8682                  Rotate image.
8683                */
8684                rotate_image=RotateImage(composite_image,
8685                  argument_list[8].real_reference,exception);
8686                if (rotate_image == (Image *) NULL)
8687                  break;
8688             }
8689           if ((attribute_flag[7] != 0) &&
8690               (argument_list[7].integer_reference != 0)) /* tile */
8691             {
8692               ssize_t
8693                 x,
8694                 y;
8695
8696               /*
8697                 Tile the composite image.
8698               */
8699              if (attribute_flag[8] != 0)   /* "tile=>" */
8700                (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8701                  "false");
8702              else
8703                (void) SetImageArtifact(composite_image,
8704                  "compose:outside-overlay","false");
8705              for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8706                 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8707                 {
8708                   if (attribute_flag[8] != 0) /* rotate */
8709                     (void) CompositeImage(image,rotate_image,compose,
8710                       MagickTrue,x,y,exception);
8711                   else
8712                     (void) CompositeImage(image,composite_image,compose,
8713                       MagickTrue,x,y,exception);
8714                 }
8715               if (attribute_flag[8] != 0) /* rotate */
8716                 rotate_image=DestroyImage(rotate_image);
8717               break;
8718             }
8719           /*
8720             Parameter Handling used used ONLY for normal composition.
8721           */
8722           if (attribute_flag[5] != 0) /* gravity */
8723             image->gravity=(GravityType) argument_list[5].integer_reference;
8724           if (attribute_flag[2] != 0) /* geometry offset */
8725             {
8726               SetGeometry(image,&geometry);
8727               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8728                 &geometry);
8729               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8730                 &geometry);
8731             }
8732           if (attribute_flag[3] != 0) /* x offset */
8733             geometry.x=argument_list[3].integer_reference;
8734           if (attribute_flag[4] != 0) /* y offset */
8735             geometry.y=argument_list[4].integer_reference;
8736           if (attribute_flag[10] != 0) /* mask */
8737             {
8738               if ((image->compose == DisplaceCompositeOp) ||
8739                   (image->compose == DistortCompositeOp))
8740                 {
8741                   /*
8742                     Merge Y displacement into X displacement image.
8743                   */
8744                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8745                     exception);
8746                   (void) CompositeImage(composite_image,
8747                     argument_list[10].image_reference,CopyGreenCompositeOp,
8748                     MagickTrue,0,0,exception);
8749                 }
8750               else
8751                 {
8752                   Image
8753                     *mask_image;
8754
8755                   /*
8756                     Set a blending mask for the composition.
8757                   */
8758                   mask_image=CloneImage(argument_list[10].image_reference,0,0,
8759                     MagickTrue,exception);
8760                   (void) SetImageMask(composite_image,ReadPixelMask,mask_image,
8761                     exception);
8762                   mask_image=DestroyImage(mask_image);
8763                 }
8764             }
8765           if (attribute_flag[11] != 0) /* channel */
8766             channel=(ChannelType) argument_list[11].integer_reference;
8767           /*
8768             Composite two images (normal composition).
8769           */
8770           (void) FormatLocaleString(composite_geometry,MagickPathExtent,
8771             "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8772             (double) composite_image->rows,(double) geometry.x,(double)
8773             geometry.y);
8774           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8775             exception);
8776           channel_mask=SetImageChannelMask(image,channel);
8777           if (attribute_flag[8] == 0) /* no rotate */
8778             CompositeImage(image,composite_image,compose,clip_to_self,
8779               geometry.x,geometry.y,exception);
8780           else
8781             {
8782               /*
8783                 Position adjust rotated image then composite.
8784               */
8785               geometry.x-=(ssize_t) (rotate_image->columns-
8786                 composite_image->columns)/2;
8787               geometry.y-=(ssize_t) (rotate_image->rows-
8788                 composite_image->rows)/2;
8789               CompositeImage(image,rotate_image,compose,clip_to_self,geometry.x,
8790                 geometry.y,exception);
8791               rotate_image=DestroyImage(rotate_image);
8792             }
8793           if (attribute_flag[10] != 0) /* mask */
8794             {
8795               if ((image->compose == DisplaceCompositeOp) ||
8796                   (image->compose == DistortCompositeOp))
8797                 composite_image=DestroyImage(composite_image);
8798               else
8799                 (void) SetImageMask(image,ReadPixelMask,(Image *) NULL,
8800                   exception);
8801             }
8802           (void) SetImageChannelMask(image,channel_mask);
8803           break;
8804         }
8805         case 36:  /* Contrast */
8806         {
8807           if (attribute_flag[0] == 0)
8808             argument_list[0].integer_reference=0;
8809           (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8810             MagickTrue : MagickFalse,exception);
8811           break;
8812         }
8813         case 37:  /* CycleColormap */
8814         {
8815           if (attribute_flag[0] == 0)
8816             argument_list[0].integer_reference=6;
8817           (void) CycleColormapImage(image,argument_list[0].integer_reference,
8818             exception);
8819           break;
8820         }
8821         case 38:  /* Draw */
8822         {
8823           DrawInfo
8824             *draw_info;
8825
8826           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8827             (DrawInfo *) NULL);
8828           (void) CloneString(&draw_info->primitive,"point");
8829           if (attribute_flag[0] != 0)
8830             {
8831               if (argument_list[0].integer_reference < 0)
8832                 (void) CloneString(&draw_info->primitive,
8833                   argument_list[0].string_reference);
8834               else
8835                 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8836                   MagickPrimitiveOptions,argument_list[0].integer_reference));
8837             }
8838           if (attribute_flag[1] != 0)
8839             {
8840               if (LocaleCompare(draw_info->primitive,"path") == 0)
8841                 {
8842                   (void) ConcatenateString(&draw_info->primitive," '");
8843                   ConcatenateString(&draw_info->primitive,
8844                     argument_list[1].string_reference);
8845                   (void) ConcatenateString(&draw_info->primitive,"'");
8846                 }
8847               else
8848                 {
8849                   (void) ConcatenateString(&draw_info->primitive," ");
8850                   ConcatenateString(&draw_info->primitive,
8851                     argument_list[1].string_reference);
8852                 }
8853             }
8854           if (attribute_flag[2] != 0)
8855             {
8856               (void) ConcatenateString(&draw_info->primitive," ");
8857               (void) ConcatenateString(&draw_info->primitive,
8858                 CommandOptionToMnemonic(MagickMethodOptions,
8859                 argument_list[2].integer_reference));
8860             }
8861           if (attribute_flag[3] != 0)
8862             {
8863               (void) QueryColorCompliance(argument_list[3].string_reference,
8864                 AllCompliance,&draw_info->stroke,exception);
8865               if (argument_list[3].image_reference != (Image *) NULL)
8866                 draw_info->stroke_pattern=CloneImage(
8867                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8868             }
8869           if (attribute_flag[4] != 0)
8870             {
8871               (void) QueryColorCompliance(argument_list[4].string_reference,
8872                 AllCompliance,&draw_info->fill,exception);
8873               if (argument_list[4].image_reference != (Image *) NULL)
8874                 draw_info->fill_pattern=CloneImage(
8875                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8876             }
8877           if (attribute_flag[5] != 0)
8878             draw_info->stroke_width=argument_list[5].real_reference;
8879           if (attribute_flag[6] != 0)
8880             (void) CloneString(&draw_info->font,
8881               argument_list[6].string_reference);
8882           if (attribute_flag[7] != 0)
8883             (void) QueryColorCompliance(argument_list[7].string_reference,
8884               AllCompliance,&draw_info->border_color,exception);
8885           if (attribute_flag[8] != 0)
8886             draw_info->affine.tx=argument_list[8].real_reference;
8887           if (attribute_flag[9] != 0)
8888             draw_info->affine.ty=argument_list[9].real_reference;
8889           if (attribute_flag[20] != 0)
8890             {
8891               AV
8892                 *av;
8893
8894               av=(AV *) argument_list[20].array_reference;
8895               if ((av_len(av) != 3) && (av_len(av) != 5))
8896                 {
8897                   ThrowPerlException(exception,OptionError,
8898                     "affine matrix must have 4 or 6 elements",PackageName);
8899                   goto PerlException;
8900                 }
8901               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8902               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8903               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8904               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8905               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8906                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8907                 {
8908                   ThrowPerlException(exception,OptionError,
8909                     "affine matrix is singular",PackageName);
8910                    goto PerlException;
8911                 }
8912               if (av_len(av) == 5)
8913                 {
8914                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8915                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8916                 }
8917             }
8918           for (j=10; j < 15; j++)
8919           {
8920             if (attribute_flag[j] == 0)
8921               continue;
8922             value=argument_list[j].string_reference;
8923             angle=argument_list[j].real_reference;
8924             current=draw_info->affine;
8925             GetAffineMatrix(&affine);
8926             switch (j)
8927             {
8928               case 10:
8929               {
8930                 /*
8931                   Translate.
8932                 */
8933                 flags=ParseGeometry(value,&geometry_info);
8934                 affine.tx=geometry_info.xi;
8935                 affine.ty=geometry_info.psi;
8936                 if ((flags & PsiValue) == 0)
8937                   affine.ty=affine.tx;
8938                 break;
8939               }
8940               case 11:
8941               {
8942                 /*
8943                   Scale.
8944                 */
8945                 flags=ParseGeometry(value,&geometry_info);
8946                 affine.sx=geometry_info.rho;
8947                 affine.sy=geometry_info.sigma;
8948                 if ((flags & SigmaValue) == 0)
8949                   affine.sy=affine.sx;
8950                 break;
8951               }
8952               case 12:
8953               {
8954                 /*
8955                   Rotate.
8956                 */
8957                 if (angle == 0.0)
8958                   break;
8959                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8960                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8961                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8962                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8963                 break;
8964               }
8965               case 13:
8966               {
8967                 /*
8968                   SkewX.
8969                 */
8970                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8971                 break;
8972               }
8973               case 14:
8974               {
8975                 /*
8976                   SkewY.
8977                 */
8978                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8979                 break;
8980               }
8981             }
8982             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8983             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8984             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8985             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8986             draw_info->affine.tx=
8987               current.sx*affine.tx+current.ry*affine.ty+current.tx;
8988             draw_info->affine.ty=
8989               current.rx*affine.tx+current.sy*affine.ty+current.ty;
8990           }
8991           if (attribute_flag[15] != 0)
8992             draw_info->fill_pattern=CloneImage(
8993               argument_list[15].image_reference,0,0,MagickTrue,exception);
8994           if (attribute_flag[16] != 0)
8995             draw_info->pointsize=argument_list[16].real_reference;
8996           if (attribute_flag[17] != 0)
8997             {
8998               draw_info->stroke_antialias=argument_list[17].integer_reference != 0
8999                 ? MagickTrue : MagickFalse;
9000               draw_info->text_antialias=draw_info->stroke_antialias;
9001             }
9002           if (attribute_flag[18] != 0)
9003             (void) CloneString(&draw_info->density,
9004               argument_list[18].string_reference);
9005           if (attribute_flag[19] != 0)
9006             draw_info->stroke_width=argument_list[19].real_reference;
9007           if (attribute_flag[21] != 0)
9008             draw_info->dash_offset=argument_list[21].real_reference;
9009           if (attribute_flag[22] != 0)
9010             {
9011               AV
9012                 *av;
9013
9014               av=(AV *) argument_list[22].array_reference;
9015               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
9016                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
9017               if (draw_info->dash_pattern != (double *) NULL)
9018                 {
9019                   for (i=0; i <= av_len(av); i++)
9020                     draw_info->dash_pattern[i]=(double)
9021                       SvNV(*(av_fetch(av,i,0)));
9022                   draw_info->dash_pattern[i]=0.0;
9023                 }
9024             }
9025           if (attribute_flag[23] != 0)
9026             image->interpolate=(PixelInterpolateMethod)
9027               argument_list[23].integer_reference;
9028           if ((attribute_flag[24] != 0) &&
9029               (draw_info->fill_pattern != (Image *) NULL))
9030             flags=ParsePageGeometry(draw_info->fill_pattern,
9031               argument_list[24].string_reference,
9032               &draw_info->fill_pattern->tile_offset,exception);
9033           if (attribute_flag[25] != 0)
9034             {
9035               (void) ConcatenateString(&draw_info->primitive," '");
9036               (void) ConcatenateString(&draw_info->primitive,
9037                 argument_list[25].string_reference);
9038               (void) ConcatenateString(&draw_info->primitive,"'");
9039             }
9040           if (attribute_flag[26] != 0)
9041             draw_info->fill_pattern=CloneImage(
9042               argument_list[26].image_reference,0,0,MagickTrue,exception);
9043           if (attribute_flag[27] != 0)
9044             draw_info->stroke_pattern=CloneImage(
9045               argument_list[27].image_reference,0,0,MagickTrue,exception);
9046           if (attribute_flag[28] != 0)
9047             (void) CloneString(&draw_info->primitive,
9048               argument_list[28].string_reference);
9049           if (attribute_flag[29] != 0)
9050             draw_info->kerning=argument_list[29].real_reference;
9051           if (attribute_flag[30] != 0)
9052             draw_info->interline_spacing=argument_list[30].real_reference;
9053           if (attribute_flag[31] != 0)
9054             draw_info->interword_spacing=argument_list[31].real_reference;
9055           if (attribute_flag[32] != 0)
9056             draw_info->direction=(DirectionType)
9057               argument_list[32].integer_reference;
9058           DrawImage(image,draw_info,exception);
9059           draw_info=DestroyDrawInfo(draw_info);
9060           break;
9061         }
9062         case 39:  /* Equalize */
9063         {
9064           if (attribute_flag[0] != 0)
9065             channel=(ChannelType) argument_list[0].integer_reference;
9066           channel_mask=SetImageChannelMask(image,channel);
9067           EqualizeImage(image,exception);
9068           (void) SetImageChannelMask(image,channel_mask);
9069           break;
9070         }
9071         case 40:  /* Gamma */
9072         {
9073           if (attribute_flag[1] != 0)
9074             channel=(ChannelType) argument_list[1].integer_reference;
9075           if (attribute_flag[2] == 0)
9076             argument_list[2].real_reference=1.0;
9077           if (attribute_flag[3] == 0)
9078             argument_list[3].real_reference=1.0;
9079           if (attribute_flag[4] == 0)
9080             argument_list[4].real_reference=1.0;
9081           if (attribute_flag[0] == 0)
9082             {
9083               (void) FormatLocaleString(message,MagickPathExtent,
9084                 "%.15g,%.15g,%.15g",(double) argument_list[2].real_reference,
9085                 (double) argument_list[3].real_reference,
9086                 (double) argument_list[4].real_reference);
9087               argument_list[0].string_reference=message;
9088             }
9089           (void) GammaImage(image,StringToDouble(
9090             argument_list[0].string_reference,(char **) NULL),exception);
9091           break;
9092         }
9093         case 41:  /* Map */
9094         {
9095           QuantizeInfo
9096             *quantize_info;
9097
9098           if (attribute_flag[0] == 0)
9099             {
9100               ThrowPerlException(exception,OptionError,"MapImageRequired",
9101                 PackageName);
9102               goto PerlException;
9103             }
9104           quantize_info=AcquireQuantizeInfo(info->image_info);
9105           if (attribute_flag[1] != 0)
9106             quantize_info->dither_method=(DitherMethod)
9107               argument_list[1].integer_reference;
9108           (void) RemapImages(quantize_info,image,
9109             argument_list[0].image_reference,exception);
9110           quantize_info=DestroyQuantizeInfo(quantize_info);
9111           break;
9112         }
9113         case 42:  /* MatteFloodfill */
9114         {
9115           DrawInfo
9116             *draw_info;
9117
9118           MagickBooleanType
9119             invert;
9120
9121           PixelInfo
9122             target;
9123
9124           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9125             (DrawInfo *) NULL);
9126           if (attribute_flag[0] != 0)
9127             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9128               &geometry,exception);
9129           if (attribute_flag[1] != 0)
9130             geometry.x=argument_list[1].integer_reference;
9131           if (attribute_flag[2] != 0)
9132             geometry.y=argument_list[2].integer_reference;
9133           if (image->alpha_trait == UndefinedPixelTrait)
9134             (void) SetImageAlpha(image,OpaqueAlpha,exception);
9135           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
9136             geometry.x,geometry.y,&target,exception);
9137           if (attribute_flag[4] != 0)
9138             QueryColorCompliance(argument_list[4].string_reference,
9139               AllCompliance,&target,exception);
9140           if (attribute_flag[3] != 0)
9141             target.alpha=StringToDoubleInterval(
9142               argument_list[3].string_reference,(double) (double) QuantumRange+
9143               1.0);
9144           if (attribute_flag[5] != 0)
9145             image->fuzz=StringToDoubleInterval(
9146               argument_list[5].string_reference,(double) QuantumRange+1.0);
9147           invert=MagickFalse;
9148           if (attribute_flag[6] != 0)
9149             invert=(MagickBooleanType) argument_list[6].integer_reference;
9150           channel_mask=SetImageChannelMask(image,AlphaChannel);
9151           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
9152             geometry.y,invert,exception);
9153           (void) SetImageChannelMask(image,channel_mask);
9154           draw_info=DestroyDrawInfo(draw_info);
9155           break;
9156         }
9157         case 43:  /* Modulate */
9158         {
9159           char
9160             modulate[MagickPathExtent];
9161
9162           geometry_info.rho=100.0;
9163           geometry_info.sigma=100.0;
9164           geometry_info.xi=100.0;
9165           if (attribute_flag[0] != 0)
9166             (void)ParseGeometry(argument_list[0].string_reference,
9167               &geometry_info);
9168           if (attribute_flag[1] != 0)
9169             geometry_info.xi=argument_list[1].real_reference;
9170           if (attribute_flag[2] != 0)
9171             geometry_info.sigma=argument_list[2].real_reference;
9172           if (attribute_flag[3] != 0)
9173             {
9174               geometry_info.sigma=argument_list[3].real_reference;
9175               SetImageArtifact(image,"modulate:colorspace","HWB");
9176             }
9177           if (attribute_flag[4] != 0)
9178             {
9179               geometry_info.rho=argument_list[4].real_reference;
9180               SetImageArtifact(image,"modulate:colorspace","HSB");
9181             }
9182           if (attribute_flag[5] != 0)
9183             {
9184               geometry_info.sigma=argument_list[5].real_reference;
9185               SetImageArtifact(image,"modulate:colorspace","HSL");
9186             }
9187           if (attribute_flag[6] != 0)
9188             {
9189               geometry_info.rho=argument_list[6].real_reference;
9190               SetImageArtifact(image,"modulate:colorspace","HWB");
9191             }
9192           (void) FormatLocaleString(modulate,MagickPathExtent,"%.15g,%.15g,%.15g",
9193             geometry_info.rho,geometry_info.sigma,geometry_info.xi);
9194           (void) ModulateImage(image,modulate,exception);
9195           break;
9196         }
9197         case 44:  /* Negate */
9198         {
9199           if (attribute_flag[0] == 0)
9200             argument_list[0].integer_reference=0;
9201           if (attribute_flag[1] != 0)
9202             channel=(ChannelType) argument_list[1].integer_reference;
9203           channel_mask=SetImageChannelMask(image,channel);
9204           (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
9205             MagickTrue : MagickFalse,exception);
9206           (void) SetImageChannelMask(image,channel_mask);
9207           break;
9208         }
9209         case 45:  /* Normalize */
9210         {
9211           if (attribute_flag[0] != 0)
9212             channel=(ChannelType) argument_list[0].integer_reference;
9213           channel_mask=SetImageChannelMask(image,channel);
9214           NormalizeImage(image,exception);
9215           (void) SetImageChannelMask(image,channel_mask);
9216           break;
9217         }
9218         case 46:  /* NumberColors */
9219           break;
9220         case 47:  /* Opaque */
9221         {
9222           MagickBooleanType
9223             invert;
9224
9225           PixelInfo
9226             fill_color,
9227             target;
9228
9229           (void) QueryColorCompliance("none",AllCompliance,&target,
9230              exception);
9231           (void) QueryColorCompliance("none",AllCompliance,&fill_color,
9232             exception);
9233           if (attribute_flag[0] != 0)
9234             (void) QueryColorCompliance(argument_list[0].string_reference,
9235               AllCompliance,&target,exception);
9236           if (attribute_flag[1] != 0)
9237             (void) QueryColorCompliance(argument_list[1].string_reference,
9238               AllCompliance,&fill_color,exception);
9239           if (attribute_flag[2] != 0)
9240             image->fuzz=StringToDoubleInterval(
9241               argument_list[2].string_reference,(double) QuantumRange+1.0);
9242           if (attribute_flag[3] != 0)
9243             channel=(ChannelType) argument_list[3].integer_reference;
9244           invert=MagickFalse;
9245           if (attribute_flag[4] != 0)
9246             invert=(MagickBooleanType) argument_list[4].integer_reference;
9247           channel_mask=SetImageChannelMask(image,channel);
9248           (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
9249           (void) SetImageChannelMask(image,channel_mask);
9250           break;
9251         }
9252         case 48:  /* Quantize */
9253         {
9254           QuantizeInfo
9255             *quantize_info;
9256
9257           quantize_info=AcquireQuantizeInfo(info->image_info);
9258           if (attribute_flag[0] != 0)
9259             quantize_info->number_colors=(size_t)
9260               argument_list[0].integer_reference;
9261           if (attribute_flag[1] != 0)
9262             quantize_info->tree_depth=(size_t)
9263               argument_list[1].integer_reference;
9264           if (attribute_flag[2] != 0)
9265             quantize_info->colorspace=(ColorspaceType)
9266               argument_list[2].integer_reference;
9267           if (attribute_flag[3] != 0)
9268             quantize_info->dither_method=(DitherMethod)
9269               argument_list[3].integer_reference;
9270           if (attribute_flag[4] != 0)
9271             quantize_info->measure_error=
9272               argument_list[4].integer_reference != 0 ? MagickTrue : MagickFalse;
9273           if (attribute_flag[6] != 0)
9274             (void) QueryColorCompliance(argument_list[6].string_reference,
9275               AllCompliance,&image->transparent_color,exception);
9276           if (attribute_flag[7] != 0)
9277             quantize_info->dither_method=(DitherMethod)
9278               argument_list[7].integer_reference;
9279           if (attribute_flag[5] && argument_list[5].integer_reference)
9280             (void) QuantizeImages(quantize_info,image,exception);
9281           else
9282             if ((image->storage_class == DirectClass) ||
9283                (image->colors > quantize_info->number_colors) ||
9284                (quantize_info->colorspace == GRAYColorspace))
9285              (void) QuantizeImage(quantize_info,image,exception);
9286            else
9287              CompressImageColormap(image,exception);
9288           quantize_info=DestroyQuantizeInfo(quantize_info);
9289           break;
9290         }
9291         case 49:  /* Raise */
9292         {
9293           if (attribute_flag[0] != 0)
9294             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9295               &geometry,exception);
9296           if (attribute_flag[1] != 0)
9297             geometry.width=argument_list[1].integer_reference;
9298           if (attribute_flag[2] != 0)
9299             geometry.height=argument_list[2].integer_reference;
9300           if (attribute_flag[3] == 0)
9301             argument_list[3].integer_reference=1;
9302           (void) RaiseImage(image,&geometry,
9303             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
9304             exception);
9305           break;
9306         }
9307         case 50:  /* Segment */
9308         {
9309           ColorspaceType
9310             colorspace;
9311
9312           double
9313             cluster_threshold,
9314             smoothing_threshold;
9315
9316           MagickBooleanType
9317             verbose;
9318
9319           cluster_threshold=1.0;
9320           smoothing_threshold=1.5;
9321           colorspace=sRGBColorspace;
9322           verbose=MagickFalse;
9323           if (attribute_flag[0] != 0)
9324             {
9325               flags=ParseGeometry(argument_list[0].string_reference,
9326                 &geometry_info);
9327               cluster_threshold=geometry_info.rho;
9328               if (flags & SigmaValue)
9329                 smoothing_threshold=geometry_info.sigma;
9330             }
9331           if (attribute_flag[1] != 0)
9332             cluster_threshold=argument_list[1].real_reference;
9333           if (attribute_flag[2] != 0)
9334             smoothing_threshold=argument_list[2].real_reference;
9335           if (attribute_flag[3] != 0)
9336             colorspace=(ColorspaceType) argument_list[3].integer_reference;
9337           if (attribute_flag[4] != 0)
9338             verbose=argument_list[4].integer_reference != 0 ?
9339               MagickTrue : MagickFalse;
9340           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
9341             smoothing_threshold,exception);
9342           break;
9343         }
9344         case 51:  /* Signature */
9345         {
9346           (void) SignatureImage(image,exception);
9347           break;
9348         }
9349         case 52:  /* Solarize */
9350         {
9351           geometry_info.rho=QuantumRange/2.0;
9352           if (attribute_flag[0] != 0)
9353             flags=ParseGeometry(argument_list[0].string_reference,
9354               &geometry_info);
9355           if (attribute_flag[1] != 0)
9356             geometry_info.rho=StringToDoubleInterval(
9357               argument_list[1].string_reference,(double) QuantumRange+1.0);
9358           (void) SolarizeImage(image,geometry_info.rho,exception);
9359           break;
9360         }
9361         case 53:  /* Sync */
9362         {
9363           (void) SyncImage(image,exception);
9364           break;
9365         }
9366         case 54:  /* Texture */
9367         {
9368           if (attribute_flag[0] == 0)
9369             break;
9370           TextureImage(image,argument_list[0].image_reference,exception);
9371           break;
9372         }
9373         case 55:  /* Evalute */
9374         {
9375           MagickEvaluateOperator
9376             op;
9377
9378           op=SetEvaluateOperator;
9379           if (attribute_flag[0] == MagickFalse)
9380             argument_list[0].real_reference=0.0;
9381           if (attribute_flag[1] != MagickFalse)
9382             op=(MagickEvaluateOperator) argument_list[1].integer_reference;
9383           if (attribute_flag[2] != MagickFalse)
9384             channel=(ChannelType) argument_list[2].integer_reference;
9385           channel_mask=SetImageChannelMask(image,channel);
9386           (void) EvaluateImage(image,op,argument_list[0].real_reference,
9387             exception);
9388           (void) SetImageChannelMask(image,channel_mask);
9389           break;
9390         }
9391         case 56:  /* Transparent */
9392         {
9393           double
9394             opacity;
9395
9396           MagickBooleanType
9397             invert;
9398
9399           PixelInfo
9400             target;
9401
9402           (void) QueryColorCompliance("none",AllCompliance,&target,
9403             exception);
9404           if (attribute_flag[0] != 0)
9405             (void) QueryColorCompliance(argument_list[0].string_reference,
9406               AllCompliance,&target,exception);
9407           opacity=TransparentAlpha;
9408           if (attribute_flag[1] != 0)
9409             opacity=StringToDoubleInterval(argument_list[1].string_reference,
9410               (double) QuantumRange+1.0);
9411           if (attribute_flag[2] != 0)
9412             image->fuzz=StringToDoubleInterval(
9413               argument_list[2].string_reference,(double) QuantumRange+1.0);
9414           if (attribute_flag[3] == 0)
9415             argument_list[3].integer_reference=0;
9416           invert=MagickFalse;
9417           if (attribute_flag[3] != 0)
9418             invert=(MagickBooleanType) argument_list[3].integer_reference;
9419           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9420             invert,exception);
9421           break;
9422         }
9423         case 57:  /* Threshold */
9424         {
9425           double
9426             threshold;
9427
9428           if (attribute_flag[0] == 0)
9429             argument_list[0].string_reference="50%";
9430           if (attribute_flag[1] != 0)
9431             channel=(ChannelType) argument_list[1].integer_reference;
9432           threshold=StringToDoubleInterval(argument_list[0].string_reference,
9433             (double) QuantumRange+1.0);
9434           channel_mask=SetImageChannelMask(image,channel);
9435           (void) BilevelImage(image,threshold,exception);
9436           (void) SetImageChannelMask(image,channel_mask);
9437           break;
9438         }
9439         case 58:  /* Charcoal */
9440         {
9441           if (attribute_flag[0] != 0)
9442             {
9443               flags=ParseGeometry(argument_list[0].string_reference,
9444                 &geometry_info);
9445               if ((flags & SigmaValue) == 0)
9446                 geometry_info.sigma=1.0;
9447             }
9448           if (attribute_flag[1] != 0)
9449             geometry_info.rho=argument_list[1].real_reference;
9450           if (attribute_flag[2] != 0)
9451             geometry_info.sigma=argument_list[2].real_reference;
9452           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9453             exception);
9454           break;
9455         }
9456         case 59:  /* Trim */
9457         {
9458           if (attribute_flag[0] != 0)
9459             image->fuzz=StringToDoubleInterval(
9460               argument_list[0].string_reference,(double) QuantumRange+1.0);
9461           image=TrimImage(image,exception);
9462           break;
9463         }
9464         case 60:  /* Wave */
9465         {
9466           PixelInterpolateMethod
9467             method;
9468
9469           if (attribute_flag[0] != 0)
9470             {
9471               flags=ParseGeometry(argument_list[0].string_reference,
9472                 &geometry_info);
9473               if ((flags & SigmaValue) == 0)
9474                 geometry_info.sigma=1.0;
9475             }
9476           if (attribute_flag[1] != 0)
9477             geometry_info.rho=argument_list[1].real_reference;
9478           if (attribute_flag[2] != 0)
9479             geometry_info.sigma=argument_list[2].real_reference;
9480           method=UndefinedInterpolatePixel;
9481           if (attribute_flag[3] != 0)
9482             method=(PixelInterpolateMethod) argument_list[3].integer_reference;
9483           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9484             method,exception);
9485           break;
9486         }
9487         case 61:  /* Separate */
9488         {
9489           if (attribute_flag[0] != 0)
9490             channel=(ChannelType) argument_list[0].integer_reference;
9491           image=SeparateImage(image,channel,exception);
9492           break;
9493         }
9494         case 63:  /* Stereo */
9495         {
9496           if (attribute_flag[0] == 0)
9497             {
9498               ThrowPerlException(exception,OptionError,"StereoImageRequired",
9499                 PackageName);
9500               goto PerlException;
9501             }
9502           if (attribute_flag[1] != 0)
9503             geometry.x=argument_list[1].integer_reference;
9504           if (attribute_flag[2] != 0)
9505             geometry.y=argument_list[2].integer_reference;
9506           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9507             geometry.x,geometry.y,exception);
9508           break;
9509         }
9510         case 64:  /* Stegano */
9511         {
9512           if (attribute_flag[0] == 0)
9513             {
9514               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9515                 PackageName);
9516               goto PerlException;
9517             }
9518           if (attribute_flag[1] == 0)
9519             argument_list[1].integer_reference=0;
9520           image->offset=argument_list[1].integer_reference;
9521           image=SteganoImage(image,argument_list[0].image_reference,exception);
9522           break;
9523         }
9524         case 65:  /* Deconstruct */
9525         {
9526           image=CompareImagesLayers(image,CompareAnyLayer,exception);
9527           break;
9528         }
9529         case 66:  /* GaussianBlur */
9530         {
9531           if (attribute_flag[0] != 0)
9532             {
9533               flags=ParseGeometry(argument_list[0].string_reference,
9534                 &geometry_info);
9535               if ((flags & SigmaValue) == 0)
9536                 geometry_info.sigma=1.0;
9537             }
9538           if (attribute_flag[1] != 0)
9539             geometry_info.rho=argument_list[1].real_reference;
9540           if (attribute_flag[2] != 0)
9541             geometry_info.sigma=argument_list[2].real_reference;
9542           if (attribute_flag[3] != 0)
9543             channel=(ChannelType) argument_list[3].integer_reference;
9544           channel_mask=SetImageChannelMask(image,channel);
9545           image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9546             exception);
9547           if (image != (Image *) NULL)
9548             (void) SetImageChannelMask(image,channel_mask);
9549           break;
9550         }
9551         case 67:  /* Convolve */
9552         {
9553           KernelInfo
9554             *kernel;
9555
9556           kernel=(KernelInfo *) NULL;
9557           if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9558             break;
9559           if (attribute_flag[0] != 0)
9560             {
9561               AV
9562                 *av;
9563
9564               size_t
9565                 order;
9566
9567               kernel=AcquireKernelInfo((const char *) NULL,exception);
9568               if (kernel == (KernelInfo *) NULL)
9569                 break;
9570               av=(AV *) argument_list[0].array_reference;
9571               order=(size_t) sqrt(av_len(av)+1);
9572               kernel->width=order;
9573               kernel->height=order;
9574               kernel->values=(MagickRealType *) AcquireAlignedMemory(order,
9575                 order*sizeof(*kernel->values));
9576               if (kernel->values == (MagickRealType *) NULL)
9577                 {
9578                   kernel=DestroyKernelInfo(kernel);
9579                   ThrowPerlException(exception,ResourceLimitFatalError,
9580                     "MemoryAllocationFailed",PackageName);
9581                   goto PerlException;
9582                 }
9583               for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9584                 kernel->values[j]=(MagickRealType) SvNV(*(av_fetch(av,j,0)));
9585               for ( ; j < (ssize_t) (order*order); j++)
9586                 kernel->values[j]=0.0;
9587             }
9588           if (attribute_flag[1] != 0)
9589             channel=(ChannelType) argument_list[1].integer_reference;
9590           if (attribute_flag[2] != 0)
9591             SetImageArtifact(image,"filter:blur",
9592               argument_list[2].string_reference);
9593           if (attribute_flag[3] != 0)
9594             {
9595               kernel=AcquireKernelInfo(argument_list[3].string_reference,
9596                 exception);
9597               if (kernel == (KernelInfo *) NULL)
9598                 break;
9599             }
9600           channel_mask=SetImageChannelMask(image,channel);
9601           image=ConvolveImage(image,kernel,exception);
9602           if (image != (Image *) NULL)
9603             (void) SetImageChannelMask(image,channel_mask);
9604           kernel=DestroyKernelInfo(kernel);
9605           break;
9606         }
9607         case 68:  /* Profile */
9608         {
9609           const char
9610             *name;
9611
9612           Image
9613             *profile_image;
9614
9615           ImageInfo
9616             *profile_info;
9617
9618           StringInfo
9619             *profile;
9620
9621           name="*";
9622           if (attribute_flag[0] != 0)
9623             name=argument_list[0].string_reference;
9624           if (attribute_flag[2] != 0)
9625             image->rendering_intent=(RenderingIntent)
9626               argument_list[2].integer_reference;
9627           if (attribute_flag[3] != 0)
9628             image->black_point_compensation=
9629               argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9630           if (attribute_flag[1] != 0)
9631             {
9632               if (argument_list[1].length == 0)
9633                 {
9634                   /*
9635                     Remove a profile from the image.
9636                   */
9637                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9638                     exception);
9639                   break;
9640                 }
9641               /*
9642                 Associate user supplied profile with the image.
9643               */
9644               profile=AcquireStringInfo(argument_list[1].length);
9645               SetStringInfoDatum(profile,(const unsigned char *)
9646                 argument_list[1].string_reference);
9647               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9648                 (size_t) GetStringInfoLength(profile),exception);
9649               profile=DestroyStringInfo(profile);
9650               break;
9651             }
9652           /*
9653             Associate a profile with the image.
9654           */
9655           profile_info=CloneImageInfo(info ? info->image_info :
9656             (ImageInfo *) NULL);
9657           profile_image=ReadImages(profile_info,name,exception);
9658           if (profile_image == (Image *) NULL)
9659             break;
9660           ResetImageProfileIterator(profile_image);
9661           name=GetNextImageProfile(profile_image);
9662           while (name != (const char *) NULL)
9663           {
9664             const StringInfo
9665               *profile;
9666
9667             profile=GetImageProfile(profile_image,name);
9668             if (profile != (const StringInfo *) NULL)
9669               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9670                 (size_t) GetStringInfoLength(profile),exception);
9671             name=GetNextImageProfile(profile_image);
9672           }
9673           profile_image=DestroyImage(profile_image);
9674           profile_info=DestroyImageInfo(profile_info);
9675           break;
9676         }
9677         case 69:  /* UnsharpMask */
9678         {
9679           if (attribute_flag[0] != 0)
9680             {
9681               flags=ParseGeometry(argument_list[0].string_reference,
9682                 &geometry_info);
9683               if ((flags & SigmaValue) == 0)
9684                 geometry_info.sigma=1.0;
9685               if ((flags & XiValue) == 0)
9686                 geometry_info.xi=1.0;
9687               if ((flags & PsiValue) == 0)
9688                 geometry_info.psi=0.5;
9689             }
9690           if (attribute_flag[1] != 0)
9691             geometry_info.rho=argument_list[1].real_reference;
9692           if (attribute_flag[2] != 0)
9693             geometry_info.sigma=argument_list[2].real_reference;
9694           if (attribute_flag[3] != 0)
9695             geometry_info.xi=argument_list[3].real_reference;
9696           if (attribute_flag[4] != 0)
9697             geometry_info.psi=argument_list[4].real_reference;
9698           if (attribute_flag[5] != 0)
9699             channel=(ChannelType) argument_list[5].integer_reference;
9700           channel_mask=SetImageChannelMask(image,channel);
9701           image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9702             geometry_info.xi,geometry_info.psi,exception);
9703           if (image != (Image *) NULL)
9704             (void) SetImageChannelMask(image,channel_mask);
9705           break;
9706         }
9707         case 70:  /* MotionBlur */
9708         {
9709           if (attribute_flag[0] != 0)
9710             {
9711               flags=ParseGeometry(argument_list[0].string_reference,
9712                 &geometry_info);
9713               if ((flags & SigmaValue) == 0)
9714                 geometry_info.sigma=1.0;
9715               if ((flags & XiValue) == 0)
9716                 geometry_info.xi=1.0;
9717             }
9718           if (attribute_flag[1] != 0)
9719             geometry_info.rho=argument_list[1].real_reference;
9720           if (attribute_flag[2] != 0)
9721             geometry_info.sigma=argument_list[2].real_reference;
9722           if (attribute_flag[3] != 0)
9723             geometry_info.xi=argument_list[3].real_reference;
9724           if (attribute_flag[4] != 0)
9725             channel=(ChannelType) argument_list[4].integer_reference;
9726           channel_mask=SetImageChannelMask(image,channel);
9727           image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9728             geometry_info.xi,exception);
9729           if (image != (Image *) NULL)
9730             (void) SetImageChannelMask(image,channel_mask);
9731           break;
9732         }
9733         case 71:  /* OrderedDither */
9734         {
9735           if (attribute_flag[0] == 0)
9736             argument_list[0].string_reference="o8x8";
9737           if (attribute_flag[1] != 0)
9738             channel=(ChannelType) argument_list[1].integer_reference;
9739           channel_mask=SetImageChannelMask(image,channel);
9740           (void) OrderedDitherImage(image,argument_list[0].string_reference,
9741             exception);
9742           (void) SetImageChannelMask(image,channel_mask);
9743           break;
9744         }
9745         case 72:  /* Shave */
9746         {
9747           if (attribute_flag[0] != 0)
9748             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9749               &geometry,exception);
9750           if (attribute_flag[1] != 0)
9751             geometry.width=argument_list[1].integer_reference;
9752           if (attribute_flag[2] != 0)
9753             geometry.height=argument_list[2].integer_reference;
9754           image=ShaveImage(image,&geometry,exception);
9755           break;
9756         }
9757         case 73:  /* Level */
9758         {
9759           double
9760             black_point,
9761             gamma,
9762             white_point;
9763
9764           black_point=0.0;
9765           white_point=(double) image->columns*image->rows;
9766           gamma=1.0;
9767           if (attribute_flag[0] != 0)
9768             {
9769               flags=ParseGeometry(argument_list[0].string_reference,
9770                 &geometry_info);
9771               black_point=geometry_info.rho;
9772               if ((flags & SigmaValue) != 0)
9773                 white_point=geometry_info.sigma;
9774               if ((flags & XiValue) != 0)
9775                 gamma=geometry_info.xi;
9776               if ((flags & PercentValue) != 0)
9777                 {
9778                   black_point*=(double) (QuantumRange/100.0);
9779                   white_point*=(double) (QuantumRange/100.0);
9780                 }
9781               if ((flags & SigmaValue) == 0)
9782                 white_point=(double) QuantumRange-black_point;
9783             }
9784           if (attribute_flag[1] != 0)
9785             black_point=argument_list[1].real_reference;
9786           if (attribute_flag[2] != 0)
9787             white_point=argument_list[2].real_reference;
9788           if (attribute_flag[3] != 0)
9789             gamma=argument_list[3].real_reference;
9790           if (attribute_flag[4] != 0)
9791             channel=(ChannelType) argument_list[4].integer_reference;
9792           if (attribute_flag[5] != 0)
9793             {
9794               argument_list[0].real_reference=argument_list[5].real_reference;
9795               attribute_flag[0]=attribute_flag[5];
9796             }
9797           channel_mask=SetImageChannelMask(image,channel);
9798           (void) LevelImage(image,black_point,white_point,gamma,exception);
9799           (void) SetImageChannelMask(image,channel_mask);
9800           break;
9801         }
9802         case 74:  /* Clip */
9803         {
9804           if (attribute_flag[0] == 0)
9805             argument_list[0].string_reference="#1";
9806           if (attribute_flag[1] == 0)
9807             argument_list[1].integer_reference=MagickTrue;
9808           (void) ClipImagePath(image,argument_list[0].string_reference,
9809             argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse,
9810             exception);
9811           break;
9812         }
9813         case 75:  /* AffineTransform */
9814         {
9815           DrawInfo
9816             *draw_info;
9817
9818           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9819             (DrawInfo *) NULL);
9820           if (attribute_flag[0] != 0)
9821             {
9822               AV
9823                 *av;
9824
9825               av=(AV *) argument_list[0].array_reference;
9826               if ((av_len(av) != 3) && (av_len(av) != 5))
9827                 {
9828                   ThrowPerlException(exception,OptionError,
9829                     "affine matrix must have 4 or 6 elements",PackageName);
9830                   goto PerlException;
9831                 }
9832               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9833               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9834               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9835               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9836               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9837                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9838                 {
9839                   ThrowPerlException(exception,OptionError,
9840                     "affine matrix is singular",PackageName);
9841                    goto PerlException;
9842                 }
9843               if (av_len(av) == 5)
9844                 {
9845                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9846                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9847                 }
9848             }
9849           for (j=1; j < 6; j++)
9850           {
9851             if (attribute_flag[j] == 0)
9852               continue;
9853             value=argument_list[j].string_reference;
9854             angle=argument_list[j].real_reference;
9855             current=draw_info->affine;
9856             GetAffineMatrix(&affine);
9857             switch (j)
9858             {
9859               case 1:
9860               {
9861                 /*
9862                   Translate.
9863                 */
9864                 flags=ParseGeometry(value,&geometry_info);
9865                 affine.tx=geometry_info.xi;
9866                 affine.ty=geometry_info.psi;
9867                 if ((flags & PsiValue) == 0)
9868                   affine.ty=affine.tx;
9869                 break;
9870               }
9871               case 2:
9872               {
9873                 /*
9874                   Scale.
9875                 */
9876                 flags=ParseGeometry(value,&geometry_info);
9877                 affine.sx=geometry_info.rho;
9878                 affine.sy=geometry_info.sigma;
9879                 if ((flags & SigmaValue) == 0)
9880                   affine.sy=affine.sx;
9881                 break;
9882               }
9883               case 3:
9884               {
9885                 /*
9886                   Rotate.
9887                 */
9888                 if (angle == 0.0)
9889                   break;
9890                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9891                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9892                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9893                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9894                 break;
9895               }
9896               case 4:
9897               {
9898                 /*
9899                   SkewX.
9900                 */
9901                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9902                 break;
9903               }
9904               case 5:
9905               {
9906                 /*
9907                   SkewY.
9908                 */
9909                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9910                 break;
9911               }
9912             }
9913             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9914             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9915             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9916             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9917             draw_info->affine.tx=
9918               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9919             draw_info->affine.ty=
9920               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9921           }
9922           if (attribute_flag[6] != 0)
9923             image->interpolate=(PixelInterpolateMethod)
9924               argument_list[6].integer_reference;
9925           if (attribute_flag[7] != 0)
9926             QueryColorCompliance(argument_list[7].string_reference,
9927               AllCompliance,&image->background_color,exception);
9928           image=AffineTransformImage(image,&draw_info->affine,exception);
9929           draw_info=DestroyDrawInfo(draw_info);
9930           break;
9931         }
9932         case 76:  /* Difference */
9933         {
9934           if (attribute_flag[0] == 0)
9935             {
9936               ThrowPerlException(exception,OptionError,
9937                 "ReferenceImageRequired",PackageName);
9938               goto PerlException;
9939             }
9940           if (attribute_flag[1] != 0)
9941             image->fuzz=StringToDoubleInterval(
9942               argument_list[1].string_reference,(double) QuantumRange+1.0);
9943           (void) SetImageColorMetric(image,argument_list[0].image_reference,
9944             exception);
9945           break;
9946         }
9947         case 77:  /* AdaptiveThreshold */
9948         {
9949           if (attribute_flag[0] != 0)
9950             {
9951               flags=ParseGeometry(argument_list[0].string_reference,
9952                 &geometry_info);
9953               if ((flags & PercentValue) != 0)
9954                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9955             }
9956           if (attribute_flag[1] != 0)
9957             geometry_info.rho=argument_list[1].integer_reference;
9958           if (attribute_flag[2] != 0)
9959             geometry_info.sigma=argument_list[2].integer_reference;
9960           if (attribute_flag[3] != 0)
9961             geometry_info.xi=argument_list[3].integer_reference;;
9962           image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
9963             (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
9964           break;
9965         }
9966         case 78:  /* Resample */
9967         {
9968           size_t
9969             height,
9970             width;
9971
9972           if (attribute_flag[0] != 0)
9973             {
9974               flags=ParseGeometry(argument_list[0].string_reference,
9975                 &geometry_info);
9976               if ((flags & SigmaValue) == 0)
9977                 geometry_info.sigma=geometry_info.rho;
9978             }
9979           if (attribute_flag[1] != 0)
9980             geometry_info.rho=argument_list[1].real_reference;
9981           if (attribute_flag[2] != 0)
9982             geometry_info.sigma=argument_list[2].real_reference;
9983           if (attribute_flag[3] == 0)
9984             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
9985           if (attribute_flag[4] == 0)
9986             SetImageArtifact(image,"filter:support",
9987               argument_list[4].string_reference);
9988           width=(size_t) (geometry_info.rho*image->columns/
9989             (image->resolution.x == 0.0 ? 72.0 : image->resolution.x)+0.5);
9990           height=(size_t) (geometry_info.sigma*image->rows/
9991             (image->resolution.y == 0.0 ? 72.0 : image->resolution.y)+0.5);
9992           image=ResizeImage(image,width,height,(FilterType)
9993             argument_list[3].integer_reference,exception);
9994           if (image != (Image *) NULL)
9995             {
9996               image->resolution.x=geometry_info.rho;
9997               image->resolution.y=geometry_info.sigma;
9998             }
9999           break;
10000         }
10001         case 79:  /* Describe */
10002         {
10003           if (attribute_flag[0] == 0)
10004             argument_list[0].file_reference=(FILE *) NULL;
10005           if (attribute_flag[1] != 0)
10006             (void) SetImageArtifact(image,"identify:features",
10007               argument_list[1].string_reference);
10008           (void) IdentifyImage(image,argument_list[0].file_reference,
10009             MagickTrue,exception);
10010           break;
10011         }
10012         case 80:  /* BlackThreshold */
10013         {
10014           if (attribute_flag[0] == 0)
10015             argument_list[0].string_reference="50%";
10016           if (attribute_flag[2] != 0)
10017             channel=(ChannelType) argument_list[2].integer_reference;
10018           channel_mask=SetImageChannelMask(image,channel);
10019           BlackThresholdImage(image,argument_list[0].string_reference,
10020             exception);
10021           (void) SetImageChannelMask(image,channel_mask);
10022           break;
10023         }
10024         case 81:  /* WhiteThreshold */
10025         {
10026           if (attribute_flag[0] == 0)
10027             argument_list[0].string_reference="50%";
10028           if (attribute_flag[2] != 0)
10029             channel=(ChannelType) argument_list[2].integer_reference;
10030           channel_mask=SetImageChannelMask(image,channel);
10031           WhiteThresholdImage(image,argument_list[0].string_reference,
10032             exception);
10033           (void) SetImageChannelMask(image,channel_mask);
10034           break;
10035         }
10036         case 82:  /* RotationalBlur */
10037         {
10038           if (attribute_flag[0] != 0)
10039             {
10040               flags=ParseGeometry(argument_list[0].string_reference,
10041                 &geometry_info);
10042             }
10043           if (attribute_flag[1] != 0)
10044             geometry_info.rho=argument_list[1].real_reference;
10045           if (attribute_flag[2] != 0)
10046             channel=(ChannelType) argument_list[2].integer_reference;
10047           channel_mask=SetImageChannelMask(image,channel);
10048           image=RotationalBlurImage(image,geometry_info.rho,exception);
10049           if (image != (Image *) NULL)
10050             (void) SetImageChannelMask(image,channel_mask);
10051           break;
10052         }
10053         case 83:  /* Thumbnail */
10054         {
10055           if (attribute_flag[0] != 0)
10056             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10057               &geometry,exception);
10058           if (attribute_flag[1] != 0)
10059             geometry.width=argument_list[1].integer_reference;
10060           if (attribute_flag[2] != 0)
10061             geometry.height=argument_list[2].integer_reference;
10062           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
10063           break;
10064         }
10065         case 84:  /* Strip */
10066         {
10067           (void) StripImage(image,exception);
10068           break;
10069         }
10070         case 85:  /* Tint */
10071         {
10072           PixelInfo
10073             tint;
10074
10075           GetPixelInfo(image,&tint);
10076           if (attribute_flag[0] != 0)
10077             (void) QueryColorCompliance(argument_list[0].string_reference,
10078               AllCompliance,&tint,exception);
10079           if (attribute_flag[1] == 0)
10080             argument_list[1].string_reference="100";
10081           image=TintImage(image,argument_list[1].string_reference,&tint,
10082             exception);
10083           break;
10084         }
10085         case 86:  /* Channel */
10086         {
10087           if (attribute_flag[0] != 0)
10088             channel=(ChannelType) argument_list[0].integer_reference;
10089           image=SeparateImage(image,channel,exception);
10090           break;
10091         }
10092         case 87:  /* Splice */
10093         {
10094           if (attribute_flag[7] != 0)
10095             image->gravity=(GravityType) argument_list[7].integer_reference;
10096           if (attribute_flag[0] != 0)
10097             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
10098               &geometry,exception);
10099           if (attribute_flag[1] != 0)
10100             geometry.width=argument_list[1].integer_reference;
10101           if (attribute_flag[2] != 0)
10102             geometry.height=argument_list[2].integer_reference;
10103           if (attribute_flag[3] != 0)
10104             geometry.x=argument_list[3].integer_reference;
10105           if (attribute_flag[4] != 0)
10106             geometry.y=argument_list[4].integer_reference;
10107           if (attribute_flag[5] != 0)
10108             image->fuzz=StringToDoubleInterval(
10109               argument_list[5].string_reference,(double) QuantumRange+1.0);
10110           if (attribute_flag[6] != 0)
10111             (void) QueryColorCompliance(argument_list[6].string_reference,
10112               AllCompliance,&image->background_color,exception);
10113           image=SpliceImage(image,&geometry,exception);
10114           break;
10115         }
10116         case 88:  /* Posterize */
10117         {
10118           if (attribute_flag[0] == 0)
10119             argument_list[0].integer_reference=3;
10120           if (attribute_flag[1] == 0)
10121             argument_list[1].integer_reference=0;
10122           (void) PosterizeImage(image,argument_list[0].integer_reference,
10123             argument_list[1].integer_reference ? RiemersmaDitherMethod :
10124             NoDitherMethod,exception);
10125           break;
10126         }
10127         case 89:  /* Shadow */
10128         {
10129           if (attribute_flag[0] != 0)
10130             {
10131               flags=ParseGeometry(argument_list[0].string_reference,
10132                 &geometry_info);
10133               if ((flags & SigmaValue) == 0)
10134                 geometry_info.sigma=1.0;
10135               if ((flags & XiValue) == 0)
10136                 geometry_info.xi=4.0;
10137               if ((flags & PsiValue) == 0)
10138                 geometry_info.psi=4.0;
10139             }
10140           if (attribute_flag[1] != 0)
10141             geometry_info.rho=argument_list[1].real_reference;
10142           if (attribute_flag[2] != 0)
10143             geometry_info.sigma=argument_list[2].real_reference;
10144           if (attribute_flag[3] != 0)
10145             geometry_info.xi=argument_list[3].integer_reference;
10146           if (attribute_flag[4] != 0)
10147             geometry_info.psi=argument_list[4].integer_reference;
10148           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
10149             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10150             ceil(geometry_info.psi-0.5),exception);
10151           break;
10152         }
10153         case 90:  /* Identify */
10154         {
10155           if (attribute_flag[0] == 0)
10156             argument_list[0].file_reference=(FILE *) NULL;
10157           if (attribute_flag[1] != 0)
10158             (void) SetImageArtifact(image,"identify:features",
10159               argument_list[1].string_reference);
10160           if ((attribute_flag[2] != 0) &&
10161               (argument_list[2].integer_reference != 0))
10162             (void) SetImageArtifact(image,"identify:unique","true");
10163           (void) IdentifyImage(image,argument_list[0].file_reference,
10164             MagickTrue,exception);
10165           break;
10166         }
10167         case 91:  /* SepiaTone */
10168         {
10169           if (attribute_flag[0] == 0)
10170             argument_list[0].real_reference=80.0*QuantumRange/100.0;
10171           image=SepiaToneImage(image,argument_list[0].real_reference,
10172             exception);
10173           break;
10174         }
10175         case 92:  /* SigmoidalContrast */
10176         {
10177           MagickBooleanType
10178             sharpen;
10179
10180           if (attribute_flag[0] != 0)
10181             {
10182               flags=ParseGeometry(argument_list[0].string_reference,
10183                 &geometry_info);
10184               if ((flags & SigmaValue) == 0)
10185                 geometry_info.sigma=QuantumRange/2.0;
10186               if ((flags & PercentValue) != 0)
10187                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
10188             }
10189           if (attribute_flag[1] != 0)
10190             geometry_info.rho=argument_list[1].real_reference;
10191           if (attribute_flag[2] != 0)
10192             geometry_info.sigma=argument_list[2].real_reference;
10193           if (attribute_flag[3] != 0)
10194             channel=(ChannelType) argument_list[3].integer_reference;
10195           sharpen=MagickTrue;
10196           if (attribute_flag[4] != 0)
10197             sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
10198               MagickFalse;
10199           channel_mask=SetImageChannelMask(image,channel);
10200           (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
10201             geometry_info.sigma,exception);
10202           (void) SetImageChannelMask(image,channel_mask);
10203           break;
10204         }
10205         case 93:  /* Extent */
10206         {
10207           if (attribute_flag[7] != 0)
10208             image->gravity=(GravityType) argument_list[7].integer_reference;
10209           if (attribute_flag[0] != 0)
10210             {
10211               int
10212                 flags;
10213
10214               flags=ParseGravityGeometry(image,
10215                 argument_list[0].string_reference,&geometry,exception);
10216               (void) flags;
10217               if (geometry.width == 0)
10218                 geometry.width=image->columns;
10219               if (geometry.height == 0)
10220                 geometry.height=image->rows;
10221             }
10222           if (attribute_flag[1] != 0)
10223             geometry.width=argument_list[1].integer_reference;
10224           if (attribute_flag[2] != 0)
10225             geometry.height=argument_list[2].integer_reference;
10226           if (attribute_flag[3] != 0)
10227             geometry.x=argument_list[3].integer_reference;
10228           if (attribute_flag[4] != 0)
10229             geometry.y=argument_list[4].integer_reference;
10230           if (attribute_flag[5] != 0)
10231             image->fuzz=StringToDoubleInterval(
10232               argument_list[5].string_reference,(double) QuantumRange+1.0);
10233           if (attribute_flag[6] != 0)
10234             (void) QueryColorCompliance(argument_list[6].string_reference,
10235               AllCompliance,&image->background_color,exception);
10236           image=ExtentImage(image,&geometry,exception);
10237           break;
10238         }
10239         case 94:  /* Vignette */
10240         {
10241           if (attribute_flag[0] != 0)
10242             {
10243               flags=ParseGeometry(argument_list[0].string_reference,
10244                 &geometry_info);
10245               if ((flags & SigmaValue) == 0)
10246                 geometry_info.sigma=1.0;
10247               if ((flags & XiValue) == 0)
10248                 geometry_info.xi=0.1*image->columns;
10249               if ((flags & PsiValue) == 0)
10250                 geometry_info.psi=0.1*image->rows;
10251             }
10252           if (attribute_flag[1] != 0)
10253             geometry_info.rho=argument_list[1].real_reference;
10254           if (attribute_flag[2] != 0)
10255             geometry_info.sigma=argument_list[2].real_reference;
10256           if (attribute_flag[3] != 0)
10257             geometry_info.xi=argument_list[3].integer_reference;
10258           if (attribute_flag[4] != 0)
10259             geometry_info.psi=argument_list[4].integer_reference;
10260           if (attribute_flag[5] != 0)
10261             (void) QueryColorCompliance(argument_list[5].string_reference,
10262               AllCompliance,&image->background_color,exception);
10263           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
10264             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10265             ceil(geometry_info.psi-0.5),exception);
10266           break;
10267         }
10268         case 95:  /* ContrastStretch */
10269         {
10270           double
10271             black_point,
10272             white_point;
10273
10274           black_point=0.0;
10275           white_point=(double) image->columns*image->rows;
10276           if (attribute_flag[0] != 0)
10277             {
10278               flags=ParseGeometry(argument_list[0].string_reference,
10279                 &geometry_info);
10280               black_point=geometry_info.rho;
10281               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
10282                 black_point;
10283               if ((flags & PercentValue) != 0)
10284                 {
10285                   black_point*=(double) image->columns*image->rows/100.0;
10286                   white_point*=(double) image->columns*image->rows/100.0;
10287                 }
10288               white_point=(double) image->columns*image->rows-
10289                 white_point;
10290             }
10291           if (attribute_flag[1] != 0)
10292             black_point=argument_list[1].real_reference;
10293           if (attribute_flag[2] != 0)
10294             white_point=argument_list[2].real_reference;
10295           if (attribute_flag[4] != 0)
10296             channel=(ChannelType) argument_list[4].integer_reference;
10297           channel_mask=SetImageChannelMask(image,channel);
10298           (void) ContrastStretchImage(image,black_point,white_point,exception);
10299           (void) SetImageChannelMask(image,channel_mask);
10300           break;
10301         }
10302         case 96:  /* Sans0 */
10303         {
10304           break;
10305         }
10306         case 97:  /* Sans1 */
10307         {
10308           break;
10309         }
10310         case 98:  /* AdaptiveSharpen */
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             geometry_info.xi=argument_list[3].real_reference;
10327           if (attribute_flag[4] != 0)
10328             channel=(ChannelType) argument_list[4].integer_reference;
10329           channel_mask=SetImageChannelMask(image,channel);
10330           image=AdaptiveSharpenImage(image,geometry_info.rho,
10331             geometry_info.sigma,exception);
10332           if (image != (Image *) NULL)
10333             (void) SetImageChannelMask(image,channel_mask);
10334           break;
10335         }
10336         case 99:  /* Transpose */
10337         {
10338           image=TransposeImage(image,exception);
10339           break;
10340         }
10341         case 100:  /* Tranverse */
10342         {
10343           image=TransverseImage(image,exception);
10344           break;
10345         }
10346         case 101:  /* AutoOrient */
10347         {
10348           image=AutoOrientImage(image,image->orientation,exception);
10349           break;
10350         }
10351         case 102:  /* AdaptiveBlur */
10352         {
10353           if (attribute_flag[0] != 0)
10354             {
10355               flags=ParseGeometry(argument_list[0].string_reference,
10356                 &geometry_info);
10357               if ((flags & SigmaValue) == 0)
10358                 geometry_info.sigma=1.0;
10359               if ((flags & XiValue) == 0)
10360                 geometry_info.xi=0.0;
10361             }
10362           if (attribute_flag[1] != 0)
10363             geometry_info.rho=argument_list[1].real_reference;
10364           if (attribute_flag[2] != 0)
10365             geometry_info.sigma=argument_list[2].real_reference;
10366           if (attribute_flag[3] != 0)
10367             channel=(ChannelType) argument_list[3].integer_reference;
10368           channel_mask=SetImageChannelMask(image,channel);
10369           image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10370             exception);
10371           if (image != (Image *) NULL)
10372             (void) SetImageChannelMask(image,channel_mask);
10373           break;
10374         }
10375         case 103:  /* Sketch */
10376         {
10377           if (attribute_flag[0] != 0)
10378             {
10379               flags=ParseGeometry(argument_list[0].string_reference,
10380                 &geometry_info);
10381               if ((flags & SigmaValue) == 0)
10382                 geometry_info.sigma=1.0;
10383               if ((flags & XiValue) == 0)
10384                 geometry_info.xi=1.0;
10385             }
10386           if (attribute_flag[1] != 0)
10387             geometry_info.rho=argument_list[1].real_reference;
10388           if (attribute_flag[2] != 0)
10389             geometry_info.sigma=argument_list[2].real_reference;
10390           if (attribute_flag[3] != 0)
10391             geometry_info.xi=argument_list[3].real_reference;
10392           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10393             geometry_info.xi,exception);
10394           break;
10395         }
10396         case 104:  /* UniqueColors */
10397         {
10398           image=UniqueImageColors(image,exception);
10399           break;
10400         }
10401         case 105:  /* AdaptiveResize */
10402         {
10403           if (attribute_flag[0] != 0)
10404             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10405               &geometry,exception);
10406           if (attribute_flag[1] != 0)
10407             geometry.width=argument_list[1].integer_reference;
10408           if (attribute_flag[2] != 0)
10409             geometry.height=argument_list[2].integer_reference;
10410           if (attribute_flag[3] != 0)
10411             image->filter=(FilterType) argument_list[4].integer_reference;
10412           if (attribute_flag[4] != 0)
10413             SetImageArtifact(image,"filter:support",
10414               argument_list[4].string_reference);
10415           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10416             exception);
10417           break;
10418         }
10419         case 106:  /* ClipMask */
10420         {
10421           Image
10422             *mask_image;
10423
10424           if (attribute_flag[0] == 0)
10425             {
10426               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10427                 PackageName);
10428               goto PerlException;
10429             }
10430           mask_image=CloneImage(argument_list[0].image_reference,0,0,MagickTrue,
10431             exception);
10432           (void) SetImageMask(image,ReadPixelMask,mask_image,exception);
10433           mask_image=DestroyImage(mask_image);
10434           break;
10435         }
10436         case 107:  /* LinearStretch */
10437         {
10438            double
10439              black_point,
10440              white_point;
10441
10442            black_point=0.0;
10443            white_point=(double) image->columns*image->rows;
10444            if (attribute_flag[0] != 0)
10445              {
10446                flags=ParseGeometry(argument_list[0].string_reference,
10447                  &geometry_info);
10448                if ((flags & SigmaValue) != 0)
10449                   white_point=geometry_info.sigma;
10450                if ((flags & PercentValue) != 0)
10451                  {
10452                    black_point*=(double) image->columns*image->rows/100.0;
10453                    white_point*=(double) image->columns*image->rows/100.0;
10454                  }
10455                if ((flags & SigmaValue) == 0)
10456                  white_point=(double) image->columns*image->rows-black_point;
10457              }
10458           if (attribute_flag[1] != 0)
10459             black_point=argument_list[1].real_reference;
10460           if (attribute_flag[2] != 0)
10461             white_point=argument_list[2].real_reference;
10462           (void) LinearStretchImage(image,black_point,white_point,exception);
10463           break;
10464         }
10465         case 108:  /* ColorMatrix */
10466         {
10467           AV
10468             *av;
10469
10470           double
10471             *color_matrix;
10472
10473           KernelInfo
10474             *kernel_info;
10475
10476           size_t
10477             order;
10478
10479           if (attribute_flag[0] == 0)
10480             break;
10481           av=(AV *) argument_list[0].array_reference;
10482           order=(size_t) sqrt(av_len(av)+1);
10483           color_matrix=(double *) AcquireQuantumMemory(order,order*
10484             sizeof(*color_matrix));
10485           if (color_matrix == (double *) NULL)
10486             {
10487               ThrowPerlException(exception,ResourceLimitFatalError,
10488                 "MemoryAllocationFailed",PackageName);
10489               goto PerlException;
10490            }
10491           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10492             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10493           for ( ; j < (ssize_t) (order*order); j++)
10494             color_matrix[j]=0.0;
10495           kernel_info=AcquireKernelInfo((const char *) NULL,exception);
10496           if (kernel_info == (KernelInfo *) NULL)
10497             break;
10498           kernel_info->width=order;
10499           kernel_info->height=order;
10500           kernel_info->values=(MagickRealType *) AcquireAlignedMemory(order,
10501             order*sizeof(*kernel_info->values));
10502           if (kernel_info->values != (MagickRealType *) NULL)
10503             {
10504               for (i=0; i < (ssize_t) (order*order); i++)
10505                 kernel_info->values[i]=(MagickRealType) color_matrix[i];
10506               image=ColorMatrixImage(image,kernel_info,exception);
10507             }
10508           kernel_info=DestroyKernelInfo(kernel_info);
10509           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10510           break;
10511         }
10512         case 109:  /* Mask */
10513         {
10514           Image
10515             *mask_image;
10516
10517           if (attribute_flag[0] == 0)
10518             {
10519               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10520                 PackageName);
10521               goto PerlException;
10522             }
10523           mask_image=CloneImage(argument_list[0].image_reference,0,0,
10524             MagickTrue,exception);
10525           (void) SetImageMask(image,ReadPixelMask,mask_image,exception);
10526           mask_image=DestroyImage(mask_image);
10527           break;
10528         }
10529         case 110:  /* Polaroid */
10530         {
10531           char
10532             *caption;
10533
10534           DrawInfo
10535             *draw_info;
10536
10537           double
10538             angle;
10539
10540           PixelInterpolateMethod
10541             method;
10542
10543           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10544             (DrawInfo *) NULL);
10545           caption=(char *) NULL;
10546           if (attribute_flag[0] != 0)
10547             caption=InterpretImageProperties(info ? info->image_info :
10548               (ImageInfo *) NULL,image,argument_list[0].string_reference,
10549               exception);
10550           angle=0.0;
10551           if (attribute_flag[1] != 0)
10552             angle=argument_list[1].real_reference;
10553           if (attribute_flag[2] != 0)
10554             (void) CloneString(&draw_info->font,
10555               argument_list[2].string_reference);
10556           if (attribute_flag[3] != 0)
10557             (void) QueryColorCompliance(argument_list[3].string_reference,
10558               AllCompliance,&draw_info->stroke,exception);
10559           if (attribute_flag[4] != 0)
10560             (void) QueryColorCompliance(argument_list[4].string_reference,
10561               AllCompliance,&draw_info->fill,exception);
10562           if (attribute_flag[5] != 0)
10563             draw_info->stroke_width=argument_list[5].real_reference;
10564           if (attribute_flag[6] != 0)
10565             draw_info->pointsize=argument_list[6].real_reference;
10566           if (attribute_flag[7] != 0)
10567             draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10568           if (attribute_flag[8] != 0)
10569             (void) QueryColorCompliance(argument_list[8].string_reference,
10570               AllCompliance,&image->background_color,exception);
10571           method=UndefinedInterpolatePixel;
10572           if (attribute_flag[9] != 0)
10573             method=(PixelInterpolateMethod) argument_list[9].integer_reference;
10574           image=PolaroidImage(image,draw_info,caption,angle,method,exception);
10575           draw_info=DestroyDrawInfo(draw_info);
10576           if (caption != (char *) NULL)
10577             caption=DestroyString(caption);
10578           break;
10579         }
10580         case 111:  /* FloodfillPaint */
10581         {
10582           DrawInfo
10583             *draw_info;
10584
10585           MagickBooleanType
10586             invert;
10587
10588           PixelInfo
10589             target;
10590
10591           draw_info=CloneDrawInfo(info ? info->image_info :
10592             (ImageInfo *) NULL,(DrawInfo *) NULL);
10593           if (attribute_flag[0] != 0)
10594             flags=ParsePageGeometry(image,argument_list[0].string_reference,
10595               &geometry,exception);
10596           if (attribute_flag[1] != 0)
10597             geometry.x=argument_list[1].integer_reference;
10598           if (attribute_flag[2] != 0)
10599             geometry.y=argument_list[2].integer_reference;
10600           if (attribute_flag[3] != 0)
10601             (void) QueryColorCompliance(argument_list[3].string_reference,
10602               AllCompliance,&draw_info->fill,exception);
10603           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
10604             geometry.x,geometry.y,&target,exception);
10605           if (attribute_flag[4] != 0)
10606             QueryColorCompliance(argument_list[4].string_reference,
10607               AllCompliance,&target,exception);
10608           if (attribute_flag[5] != 0)
10609             image->fuzz=StringToDoubleInterval(
10610               argument_list[5].string_reference,(double) QuantumRange+1.0);
10611           if (attribute_flag[6] != 0)
10612             channel=(ChannelType) argument_list[6].integer_reference;
10613           invert=MagickFalse;
10614           if (attribute_flag[7] != 0)
10615             invert=(MagickBooleanType) argument_list[7].integer_reference;
10616           channel_mask=SetImageChannelMask(image,channel);
10617           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10618             geometry.y,invert,exception);
10619           (void) SetImageChannelMask(image,channel_mask);
10620           draw_info=DestroyDrawInfo(draw_info);
10621           break;
10622         }
10623         case 112:  /* Distort */
10624         {
10625           AV
10626             *av;
10627
10628           double
10629             *coordinates;
10630
10631           DistortMethod
10632             method;
10633
10634           size_t
10635             number_coordinates;
10636
10637           VirtualPixelMethod
10638             virtual_pixel;
10639
10640           if (attribute_flag[0] == 0)
10641             break;
10642           method=UndefinedDistortion;
10643           if (attribute_flag[1] != 0)
10644             method=(DistortMethod) argument_list[1].integer_reference;
10645           av=(AV *) argument_list[0].array_reference;
10646           number_coordinates=(size_t) av_len(av)+1;
10647           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10648             sizeof(*coordinates));
10649           if (coordinates == (double *) NULL)
10650             {
10651               ThrowPerlException(exception,ResourceLimitFatalError,
10652                 "MemoryAllocationFailed",PackageName);
10653               goto PerlException;
10654             }
10655           for (j=0; j < (ssize_t) number_coordinates; j++)
10656             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10657           virtual_pixel=UndefinedVirtualPixelMethod;
10658           if (attribute_flag[2] != 0)
10659             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10660               argument_list[2].integer_reference,exception);
10661           image=DistortImage(image,method,number_coordinates,coordinates,
10662             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10663             exception);
10664           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10665             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10666               exception);
10667           coordinates=(double *) RelinquishMagickMemory(coordinates);
10668           break;
10669         }
10670         case 113:  /* Clut */
10671         {
10672           PixelInterpolateMethod
10673             method;
10674
10675           if (attribute_flag[0] == 0)
10676             {
10677               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10678                 PackageName);
10679               goto PerlException;
10680             }
10681           method=UndefinedInterpolatePixel;
10682           if (attribute_flag[1] != 0)
10683             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
10684           if (attribute_flag[2] != 0)
10685             channel=(ChannelType) argument_list[2].integer_reference;
10686           channel_mask=SetImageChannelMask(image,channel);
10687           (void) ClutImage(image,argument_list[0].image_reference,method,
10688             exception);
10689           (void) SetImageChannelMask(image,channel_mask);
10690           break;
10691         }
10692         case 114:  /* LiquidRescale */
10693         {
10694           if (attribute_flag[0] != 0)
10695             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10696               &geometry,exception);
10697           if (attribute_flag[1] != 0)
10698             geometry.width=argument_list[1].integer_reference;
10699           if (attribute_flag[2] != 0)
10700             geometry.height=argument_list[2].integer_reference;
10701           if (attribute_flag[3] == 0)
10702             argument_list[3].real_reference=1.0;
10703           if (attribute_flag[4] == 0)
10704             argument_list[4].real_reference=0.0;
10705           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10706             argument_list[3].real_reference,argument_list[4].real_reference,
10707             exception);
10708           break;
10709         }
10710         case 115:  /* EncipherImage */
10711         {
10712           (void) EncipherImage(image,argument_list[0].string_reference,
10713             exception);
10714           break;
10715         }
10716         case 116:  /* DecipherImage */
10717         {
10718           (void) DecipherImage(image,argument_list[0].string_reference,
10719             exception);
10720           break;
10721         }
10722         case 117:  /* Deskew */
10723         {
10724           geometry_info.rho=QuantumRange/2.0;
10725           if (attribute_flag[0] != 0)
10726             flags=ParseGeometry(argument_list[0].string_reference,
10727               &geometry_info);
10728           if (attribute_flag[1] != 0)
10729             geometry_info.rho=StringToDoubleInterval(
10730               argument_list[1].string_reference,(double) QuantumRange+1.0);
10731           image=DeskewImage(image,geometry_info.rho,exception);
10732           break;
10733         }
10734         case 118:  /* Remap */
10735         {
10736           QuantizeInfo
10737             *quantize_info;
10738
10739           if (attribute_flag[0] == 0)
10740             {
10741               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10742                 PackageName);
10743               goto PerlException;
10744             }
10745           quantize_info=AcquireQuantizeInfo(info->image_info);
10746           if (attribute_flag[1] != 0)
10747             quantize_info->dither_method=(DitherMethod)
10748               argument_list[1].integer_reference;
10749           (void) RemapImages(quantize_info,image,
10750             argument_list[0].image_reference,exception);
10751           quantize_info=DestroyQuantizeInfo(quantize_info);
10752           break;
10753         }
10754         case 119:  /* SparseColor */
10755         {
10756           AV
10757             *av;
10758
10759           double
10760             *coordinates;
10761
10762           SparseColorMethod
10763             method;
10764
10765           size_t
10766             number_coordinates;
10767
10768           VirtualPixelMethod
10769             virtual_pixel;
10770
10771           if (attribute_flag[0] == 0)
10772             break;
10773           method=UndefinedColorInterpolate;
10774           if (attribute_flag[1] != 0)
10775             method=(SparseColorMethod) argument_list[1].integer_reference;
10776           av=(AV *) argument_list[0].array_reference;
10777           number_coordinates=(size_t) av_len(av)+1;
10778           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10779             sizeof(*coordinates));
10780           if (coordinates == (double *) NULL)
10781             {
10782               ThrowPerlException(exception,ResourceLimitFatalError,
10783                 "MemoryAllocationFailed",PackageName);
10784               goto PerlException;
10785             }
10786           for (j=0; j < (ssize_t) number_coordinates; j++)
10787             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10788           virtual_pixel=UndefinedVirtualPixelMethod;
10789           if (attribute_flag[2] != 0)
10790             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10791               argument_list[2].integer_reference,exception);
10792           if (attribute_flag[3] != 0)
10793             channel=(ChannelType) argument_list[3].integer_reference;
10794           channel_mask=SetImageChannelMask(image,channel);
10795           image=SparseColorImage(image,method,number_coordinates,coordinates,
10796             exception);
10797           if (image != (Image *) NULL)
10798             (void) SetImageChannelMask(image,channel_mask);
10799           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10800             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10801               exception);
10802           coordinates=(double *) RelinquishMagickMemory(coordinates);
10803           break;
10804         }
10805         case 120:  /* Function */
10806         {
10807           AV
10808             *av;
10809
10810           double
10811             *parameters;
10812
10813           MagickFunction
10814             function;
10815
10816           size_t
10817             number_parameters;
10818
10819           VirtualPixelMethod
10820             virtual_pixel;
10821
10822           if (attribute_flag[0] == 0)
10823             break;
10824           function=UndefinedFunction;
10825           if (attribute_flag[1] != 0)
10826             function=(MagickFunction) argument_list[1].integer_reference;
10827           av=(AV *) argument_list[0].array_reference;
10828           number_parameters=(size_t) av_len(av)+1;
10829           parameters=(double *) AcquireQuantumMemory(number_parameters,
10830             sizeof(*parameters));
10831           if (parameters == (double *) NULL)
10832             {
10833               ThrowPerlException(exception,ResourceLimitFatalError,
10834                 "MemoryAllocationFailed",PackageName);
10835               goto PerlException;
10836             }
10837           for (j=0; j < (ssize_t) number_parameters; j++)
10838             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10839           virtual_pixel=UndefinedVirtualPixelMethod;
10840           if (attribute_flag[2] != 0)
10841             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10842               argument_list[2].integer_reference,exception);
10843           (void) FunctionImage(image,function,number_parameters,parameters,
10844             exception);
10845           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10846             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10847               exception);
10848           parameters=(double *) RelinquishMagickMemory(parameters);
10849           break;
10850         }
10851         case 121:  /* SelectiveBlur */
10852         {
10853           if (attribute_flag[0] != 0)
10854             {
10855               flags=ParseGeometry(argument_list[0].string_reference,
10856                 &geometry_info);
10857               if ((flags & SigmaValue) == 0)
10858                 geometry_info.sigma=1.0;
10859               if ((flags & PercentValue) != 0)
10860                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10861             }
10862           if (attribute_flag[1] != 0)
10863             geometry_info.rho=argument_list[1].real_reference;
10864           if (attribute_flag[2] != 0)
10865             geometry_info.sigma=argument_list[2].real_reference;
10866           if (attribute_flag[3] != 0)
10867             geometry_info.xi=argument_list[3].integer_reference;;
10868           if (attribute_flag[5] != 0)
10869             channel=(ChannelType) argument_list[5].integer_reference;
10870           channel_mask=SetImageChannelMask(image,channel);
10871           image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10872             geometry_info.xi,exception);
10873           if (image != (Image *) NULL)
10874             (void) SetImageChannelMask(image,channel_mask);
10875           break;
10876         }
10877         case 122:  /* HaldClut */
10878         {
10879           if (attribute_flag[0] == 0)
10880             {
10881               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10882                 PackageName);
10883               goto PerlException;
10884             }
10885           if (attribute_flag[1] != 0)
10886             channel=(ChannelType) argument_list[1].integer_reference;
10887           channel_mask=SetImageChannelMask(image,channel);
10888           (void) HaldClutImage(image,argument_list[0].image_reference,
10889             exception);
10890           (void) SetImageChannelMask(image,channel_mask);
10891           break;
10892         }
10893         case 123:  /* BlueShift */
10894         {
10895           if (attribute_flag[0] != 0)
10896             (void) ParseGeometry(argument_list[0].string_reference,
10897               &geometry_info);
10898           image=BlueShiftImage(image,geometry_info.rho,exception);
10899           break;
10900         }
10901         case 124:  /* ForwardFourierTransformImage */
10902         {
10903           image=ForwardFourierTransformImage(image,
10904             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10905             exception);
10906           break;
10907         }
10908         case 125:  /* InverseFourierTransformImage */
10909         {
10910           image=InverseFourierTransformImage(image,image->next,
10911             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10912             exception);
10913           break;
10914         }
10915         case 126:  /* ColorDecisionList */
10916         {
10917           if (attribute_flag[0] == 0)
10918             argument_list[0].string_reference=(char *) NULL;
10919           (void) ColorDecisionListImage(image,
10920             argument_list[0].string_reference,exception);
10921           break;
10922         }
10923         case 127:  /* AutoGamma */
10924         {
10925           if (attribute_flag[0] != 0)
10926             channel=(ChannelType) argument_list[0].integer_reference;
10927           channel_mask=SetImageChannelMask(image,channel);
10928           (void) AutoGammaImage(image,exception);
10929           (void) SetImageChannelMask(image,channel_mask);
10930           break;
10931         }
10932         case 128:  /* AutoLevel */
10933         {
10934           if (attribute_flag[0] != 0)
10935             channel=(ChannelType) argument_list[0].integer_reference;
10936           channel_mask=SetImageChannelMask(image,channel);
10937           (void) AutoLevelImage(image,exception);
10938           (void) SetImageChannelMask(image,channel_mask);
10939           break;
10940         }
10941         case 129:  /* LevelColors */
10942         {
10943           PixelInfo
10944             black_point,
10945             white_point;
10946
10947           (void) QueryColorCompliance("#000000",AllCompliance,&black_point,
10948             exception);
10949           (void) QueryColorCompliance("#ffffff",AllCompliance,&white_point,
10950             exception);
10951           if (attribute_flag[1] != 0)
10952              (void) QueryColorCompliance(
10953                argument_list[1].string_reference,AllCompliance,&black_point,
10954                exception);
10955           if (attribute_flag[2] != 0)
10956              (void) QueryColorCompliance(
10957                argument_list[2].string_reference,AllCompliance,&white_point,
10958                exception);
10959           if (attribute_flag[3] != 0)
10960             channel=(ChannelType) argument_list[3].integer_reference;
10961           channel_mask=SetImageChannelMask(image,channel);
10962           (void) LevelImageColors(image,&black_point,&white_point,
10963             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10964             exception);
10965           (void) SetImageChannelMask(image,channel_mask);
10966           break;
10967         }
10968         case 130:  /* Clamp */
10969         {
10970           if (attribute_flag[0] != 0)
10971             channel=(ChannelType) argument_list[0].integer_reference;
10972           channel_mask=SetImageChannelMask(image,channel);
10973           (void) ClampImage(image,exception);
10974           (void) SetImageChannelMask(image,channel_mask);
10975           break;
10976         }
10977         case 131:  /* BrightnessContrast */
10978         {
10979           double
10980             brightness,
10981             contrast;
10982
10983           brightness=0.0;
10984           contrast=0.0;
10985           if (attribute_flag[0] != 0)
10986             {
10987               flags=ParseGeometry(argument_list[0].string_reference,
10988                 &geometry_info);
10989               brightness=geometry_info.rho;
10990               if ((flags & SigmaValue) == 0)
10991                 contrast=geometry_info.sigma;
10992             }
10993           if (attribute_flag[1] != 0)
10994             brightness=argument_list[1].real_reference;
10995           if (attribute_flag[2] != 0)
10996             contrast=argument_list[2].real_reference;
10997           if (attribute_flag[4] != 0)
10998             channel=(ChannelType) argument_list[4].integer_reference;
10999           channel_mask=SetImageChannelMask(image,channel);
11000           (void) BrightnessContrastImage(image,brightness,contrast,exception);
11001           (void) SetImageChannelMask(image,channel_mask);
11002           break;
11003         }
11004         case 132:  /* Morphology */
11005         {
11006           KernelInfo
11007             *kernel;
11008
11009           MorphologyMethod
11010             method;
11011
11012           ssize_t
11013             iterations;
11014
11015           if (attribute_flag[0] == 0)
11016             break;
11017           kernel=AcquireKernelInfo(argument_list[0].string_reference,exception);
11018           if (kernel == (KernelInfo *) NULL)
11019             break;
11020           if (attribute_flag[1] != 0)
11021             channel=(ChannelType) argument_list[1].integer_reference;
11022           method=UndefinedMorphology;
11023           if (attribute_flag[2] != 0)
11024             method=argument_list[2].integer_reference;
11025           iterations=1;
11026           if (attribute_flag[3] != 0)
11027             iterations=argument_list[3].integer_reference;
11028           channel_mask=SetImageChannelMask(image,channel);
11029           image=MorphologyImage(image,method,iterations,kernel,exception);
11030           if (image != (Image *) NULL)
11031             (void) SetImageChannelMask(image,channel_mask);
11032           kernel=DestroyKernelInfo(kernel);
11033           break;
11034         }
11035         case 133:  /* Mode */
11036         {
11037           if (attribute_flag[0] != 0)
11038             {
11039               flags=ParseGeometry(argument_list[0].string_reference,
11040                 &geometry_info);
11041               if ((flags & SigmaValue) == 0)
11042                 geometry_info.sigma=1.0;
11043             }
11044           if (attribute_flag[1] != 0)
11045             geometry_info.rho=argument_list[1].real_reference;
11046           if (attribute_flag[2] != 0)
11047             geometry_info.sigma=argument_list[2].real_reference;
11048           if (attribute_flag[3] != 0)
11049             channel=(ChannelType) argument_list[3].integer_reference;
11050           channel_mask=SetImageChannelMask(image,channel);
11051           image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
11052             (size_t) geometry_info.sigma,exception);
11053           if (image != (Image *) NULL)
11054             (void) SetImageChannelMask(image,channel_mask);
11055           break;
11056         }
11057         case 134:  /* Statistic */
11058         {
11059           StatisticType
11060             statistic;
11061
11062           statistic=UndefinedStatistic;
11063           if (attribute_flag[0] != 0)
11064             {
11065               flags=ParseGeometry(argument_list[0].string_reference,
11066                 &geometry_info);
11067               if ((flags & SigmaValue) == 0)
11068                 geometry_info.sigma=1.0;
11069             }
11070           if (attribute_flag[1] != 0)
11071             geometry_info.rho=argument_list[1].real_reference;
11072           if (attribute_flag[2] != 0)
11073             geometry_info.sigma=argument_list[2].real_reference;
11074           if (attribute_flag[3] != 0)
11075             channel=(ChannelType) argument_list[3].integer_reference;
11076           if (attribute_flag[4] != 0)
11077             statistic=(StatisticType) argument_list[4].integer_reference;
11078           channel_mask=SetImageChannelMask(image,channel);
11079           image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
11080             (size_t) geometry_info.sigma,exception);
11081           if (image != (Image *) NULL)
11082             (void) SetImageChannelMask(image,channel_mask);
11083           break;
11084         }
11085         case 135:  /* Perceptible */
11086         {
11087           double
11088             epsilon;
11089
11090           epsilon=MagickEpsilon;
11091           if (attribute_flag[0] != 0)
11092             epsilon=argument_list[0].real_reference;
11093           if (attribute_flag[1] != 0)
11094             channel=(ChannelType) argument_list[1].integer_reference;
11095           channel_mask=SetImageChannelMask(image,channel);
11096           (void) PerceptibleImage(image,epsilon,exception);
11097           (void) SetImageChannelMask(image,channel_mask);
11098           break;
11099         }
11100         case 136:  /* Poly */
11101         {
11102           AV
11103             *av;
11104
11105           double
11106             *terms;
11107
11108           size_t
11109             number_terms;
11110
11111           if (attribute_flag[0] == 0)
11112             break;
11113           if (attribute_flag[1] != 0)
11114             channel=(ChannelType) argument_list[1].integer_reference;
11115           av=(AV *) argument_list[0].array_reference;
11116           number_terms=(size_t) av_len(av);
11117           terms=(double *) AcquireQuantumMemory(number_terms,sizeof(*terms));
11118           if (terms == (double *) NULL)
11119             {
11120               ThrowPerlException(exception,ResourceLimitFatalError,
11121                 "MemoryAllocationFailed",PackageName);
11122               goto PerlException;
11123             }
11124           for (j=0; j < av_len(av); j++)
11125             terms[j]=(double) SvNV(*(av_fetch(av,j,0)));
11126           image=PolynomialImage(image,number_terms >> 1,terms,exception);
11127           terms=(double *) RelinquishMagickMemory(terms);
11128           break;
11129         }
11130         case 137:  /* Grayscale */
11131         {
11132           PixelIntensityMethod
11133             method;
11134
11135           method=UndefinedPixelIntensityMethod;
11136           if (attribute_flag[0] != 0)
11137             method=(PixelIntensityMethod) argument_list[0].integer_reference;
11138           (void) GrayscaleImage(image,method,exception);
11139           break;
11140         }
11141         case 138:  /* Canny */
11142         {
11143           if (attribute_flag[0] != 0)
11144             {
11145               flags=ParseGeometry(argument_list[0].string_reference,
11146                 &geometry_info);
11147               if ((flags & SigmaValue) == 0)
11148                 geometry_info.sigma=1.0;
11149               if ((flags & XiValue) == 0)
11150                 geometry_info.xi=0.10;
11151               if ((flags & PsiValue) == 0)
11152                 geometry_info.psi=0.30;
11153               if ((flags & PercentValue) != 0)
11154                 {
11155                   geometry_info.xi/=100.0;
11156                   geometry_info.psi/=100.0;
11157                 }
11158             }
11159           if (attribute_flag[1] != 0)
11160             geometry_info.rho=argument_list[1].real_reference;
11161           if (attribute_flag[2] != 0)
11162             geometry_info.sigma=argument_list[2].real_reference;
11163           if (attribute_flag[3] != 0)
11164             geometry_info.xi=argument_list[3].real_reference;
11165           if (attribute_flag[4] != 0)
11166             geometry_info.psi=argument_list[4].real_reference;
11167           if (attribute_flag[5] != 0)
11168             channel=(ChannelType) argument_list[5].integer_reference;
11169           channel_mask=SetImageChannelMask(image,channel);
11170           image=CannyEdgeImage(image,geometry_info.rho,geometry_info.sigma,
11171             geometry_info.xi,geometry_info.psi,exception);
11172           if (image != (Image *) NULL)
11173             (void) SetImageChannelMask(image,channel_mask);
11174           break;
11175         }
11176         case 139:  /* HoughLine */
11177         {
11178           if (attribute_flag[0] != 0)
11179             {
11180               flags=ParseGeometry(argument_list[0].string_reference,
11181                 &geometry_info);
11182               if ((flags & SigmaValue) == 0)
11183                 geometry_info.sigma=geometry_info.rho;
11184               if ((flags & XiValue) == 0)
11185                 geometry_info.xi=40;
11186             }
11187           if (attribute_flag[1] != 0)
11188             geometry_info.rho=(double) argument_list[1].integer_reference;
11189           if (attribute_flag[2] != 0)
11190             geometry_info.sigma=(double) argument_list[2].integer_reference;
11191           if (attribute_flag[3] != 0)
11192             geometry_info.xi=(double) argument_list[3].integer_reference;
11193           image=HoughLineImage(image,(size_t) geometry_info.rho,(size_t)
11194             geometry_info.sigma,(size_t) geometry_info.xi,exception);
11195           break;
11196         }
11197         case 140:  /* MeanShift */
11198         {
11199           if (attribute_flag[0] != 0)
11200             {
11201               flags=ParseGeometry(argument_list[0].string_reference,
11202                 &geometry_info);
11203               if ((flags & SigmaValue) == 0)
11204                 geometry_info.sigma=geometry_info.rho;
11205               if ((flags & XiValue) == 0)
11206                 geometry_info.xi=0.10*QuantumRange;
11207               if ((flags & PercentValue) != 0)
11208                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
11209             }
11210           if (attribute_flag[1] != 0)
11211             geometry_info.rho=(double) argument_list[1].integer_reference;
11212           if (attribute_flag[2] != 0)
11213             geometry_info.sigma=(double) argument_list[2].integer_reference;
11214           if (attribute_flag[3] != 0)
11215             geometry_info.xi=(double) argument_list[3].integer_reference;
11216           image=MeanShiftImage(image,(size_t) geometry_info.rho,(size_t)
11217             geometry_info.sigma,geometry_info.xi,exception);
11218           break;
11219         }
11220         case 141:  /* Kuwahara */
11221         {
11222           if (attribute_flag[0] != 0)
11223             {
11224               flags=ParseGeometry(argument_list[0].string_reference,
11225                 &geometry_info);
11226               if ((flags & SigmaValue) == 0)
11227                 geometry_info.sigma=geometry_info.rho-0.5;
11228             }
11229           if (attribute_flag[1] != 0)
11230             geometry_info.rho=argument_list[1].real_reference;
11231           if (attribute_flag[2] != 0)
11232             geometry_info.sigma=argument_list[2].real_reference;
11233           if (attribute_flag[3] != 0)
11234             channel=(ChannelType) argument_list[3].integer_reference;
11235           channel_mask=SetImageChannelMask(image,channel);
11236           image=KuwaharaImage(image,geometry_info.rho,geometry_info.sigma,
11237             exception);
11238           if (image != (Image *) NULL)
11239             (void) SetImageChannelMask(image,channel_mask);
11240           break;
11241         }
11242         case 142:  /* ConnectedComponent */
11243         {
11244           size_t
11245             connectivity;
11246
11247           connectivity=4;
11248           if (attribute_flag[0] != 0)
11249             connectivity=argument_list[0].integer_reference;
11250           image=ConnectedComponentsImage(image,connectivity,
11251             (CCObjectInfo **) NULL,exception);
11252           break;
11253         }
11254         case 143:  /* Copy */
11255         {
11256           Image
11257             *source_image;
11258
11259           OffsetInfo
11260             offset;
11261
11262           RectangleInfo
11263             offset_geometry;
11264
11265           source_image=image;
11266           if (attribute_flag[0] != 0)
11267             source_image=argument_list[0].image_reference;
11268           SetGeometry(source_image,&geometry);
11269           if (attribute_flag[1] != 0)
11270             flags=ParseGravityGeometry(source_image,
11271               argument_list[1].string_reference,&geometry,exception);
11272           if (attribute_flag[2] != 0)
11273             geometry.width=argument_list[2].integer_reference;
11274           if (attribute_flag[3] != 0)
11275             geometry.height=argument_list[3].integer_reference;
11276           if (attribute_flag[4] != 0)
11277             geometry.x=argument_list[4].integer_reference;
11278           if (attribute_flag[5] != 0)
11279             geometry.y=argument_list[5].integer_reference;
11280           if (attribute_flag[6] != 0)
11281             image->gravity=(GravityType) argument_list[6].integer_reference;
11282           SetGeometry(image,&offset_geometry);
11283           if (attribute_flag[7] != 0)
11284             flags=ParseGravityGeometry(image,argument_list[7].string_reference,
11285               &offset_geometry,exception);
11286           offset.x=offset_geometry.x;
11287           offset.y=offset_geometry.y;
11288           if (attribute_flag[8] != 0)
11289             offset.x=argument_list[8].integer_reference;
11290           if (attribute_flag[9] != 0)
11291             offset.y=argument_list[9].integer_reference;
11292           (void) CopyImagePixels(image,source_image,&geometry,&offset,
11293             exception);
11294           break;
11295         }
11296         case 144:  /* Color */
11297         {
11298           PixelInfo
11299             color;
11300
11301           (void) QueryColorCompliance("none",AllCompliance,&color,exception);
11302           if (attribute_flag[0] != 0)
11303             (void) QueryColorCompliance(argument_list[0].string_reference,
11304               AllCompliance,&color,exception);
11305           (void) SetImageColor(image,&color,exception);
11306           break;
11307         }
11308         case 145:  /* WaveletDenoise */
11309         {
11310           if (attribute_flag[0] != 0)
11311             {
11312               flags=ParseGeometry(argument_list[0].string_reference,
11313                 &geometry_info);
11314               if ((flags & PercentValue) != 0)
11315                 {
11316                   geometry_info.rho=QuantumRange*geometry_info.rho/100.0;
11317                   geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
11318                 }
11319               if ((flags & SigmaValue) == 0)
11320                 geometry_info.sigma=0.0;
11321             }
11322           if (attribute_flag[1] != 0)
11323             geometry_info.rho=argument_list[1].real_reference;
11324           if (attribute_flag[2] != 0)
11325             geometry_info.sigma=argument_list[2].real_reference;
11326           if (attribute_flag[3] != 0)
11327             channel=(ChannelType) argument_list[3].integer_reference;
11328           channel_mask=SetImageChannelMask(image,channel);
11329           image=WaveletDenoiseImage(image,geometry_info.rho,geometry_info.sigma,
11330             exception);
11331           if (image != (Image *) NULL)
11332             (void) SetImageChannelMask(image,channel_mask);
11333           break;
11334         }
11335         case 146:  /* Colorspace */
11336         {
11337           ColorspaceType
11338             colorspace;
11339
11340           colorspace=sRGBColorspace;
11341           if (attribute_flag[0] != 0)
11342             colorspace=(ColorspaceType) argument_list[0].integer_reference;
11343           (void) TransformImageColorspace(image,colorspace,exception);
11344           break;
11345         }
11346       }
11347       if (next != (Image *) NULL)
11348         (void) CatchImageException(next);
11349       if (region_image != (Image *) NULL)
11350         {
11351           /*
11352             Composite region.
11353           */
11354           status=CompositeImage(region_image,image,CopyCompositeOp,MagickTrue,
11355             region_info.x,region_info.y,exception);
11356           (void) status;
11357           (void) CatchImageException(region_image);
11358           image=DestroyImage(image);
11359           image=region_image;
11360         }
11361       if (image != (Image *) NULL)
11362         {
11363           number_images++;
11364           if (next && (next != image))
11365             {
11366               image->next=next->next;
11367               if (image->next != (Image *) NULL)
11368                 image->next->previous=image;
11369               DeleteImageFromRegistry(*pv,next);
11370             }
11371           sv_setiv(*pv,PTR2IV(image));
11372           next=image;
11373         }
11374       if (*pv)
11375         pv++;
11376     }
11377
11378   PerlException:
11379     if (reference_vector)
11380       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
11381     InheritPerlException(exception,perl_exception);
11382     exception=DestroyExceptionInfo(exception);
11383     sv_setiv(perl_exception,(IV) number_images);
11384     SvPOK_on(perl_exception);
11385     ST(0)=sv_2mortal(perl_exception);
11386     XSRETURN(1);
11387   }
11388 \f
11389 #
11390 ###############################################################################
11391 #                                                                             #
11392 #                                                                             #
11393 #                                                                             #
11394 #   M o n t a g e                                                             #
11395 #                                                                             #
11396 #                                                                             #
11397 #                                                                             #
11398 ###############################################################################
11399 #
11400 #
11401 void
11402 Montage(ref,...)
11403   Image::Magick ref=NO_INIT
11404   ALIAS:
11405     MontageImage  = 1
11406     montage       = 2
11407     montageimage  = 3
11408   PPCODE:
11409   {
11410     AV
11411       *av;
11412
11413     char
11414       *attribute;
11415
11416     ExceptionInfo
11417       *exception;
11418
11419     HV
11420       *hv;
11421
11422     Image
11423       *image,
11424       *next;
11425
11426     PixelInfo
11427       transparent_color;
11428
11429     MontageInfo
11430       *montage_info;
11431
11432     register ssize_t
11433       i;
11434
11435     ssize_t
11436       sp;
11437
11438     struct PackageInfo
11439       *info;
11440
11441     SV
11442       *av_reference,
11443       *perl_exception,
11444       *reference,
11445       *rv,
11446       *sv;
11447
11448     PERL_UNUSED_VAR(ref);
11449     PERL_UNUSED_VAR(ix);
11450     exception=AcquireExceptionInfo();
11451     perl_exception=newSVpv("",0);
11452     sv=NULL;
11453     attribute=NULL;
11454     if (sv_isobject(ST(0)) == 0)
11455       {
11456         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11457           PackageName);
11458         goto PerlException;
11459       }
11460     reference=SvRV(ST(0));
11461     hv=SvSTASH(reference);
11462     av=newAV();
11463     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11464     SvREFCNT_dec(av);
11465     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11466     if (image == (Image *) NULL)
11467       {
11468         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11469           PackageName);
11470         goto PerlException;
11471       }
11472     /*
11473       Get options.
11474     */
11475     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11476     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
11477     (void) QueryColorCompliance("none",AllCompliance,&transparent_color,
11478       exception);
11479     for (i=2; i < items; i+=2)
11480     {
11481       attribute=(char *) SvPV(ST(i-1),na);
11482       switch (*attribute)
11483       {
11484         case 'B':
11485         case 'b':
11486         {
11487           if (LocaleCompare(attribute,"background") == 0)
11488             {
11489               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11490                 &montage_info->background_color,exception);
11491               for (next=image; next; next=next->next)
11492                 next->background_color=montage_info->background_color;
11493               break;
11494             }
11495           if (LocaleCompare(attribute,"border") == 0)
11496             {
11497               montage_info->border_width=SvIV(ST(i));
11498               break;
11499             }
11500           if (LocaleCompare(attribute,"bordercolor") == 0)
11501             {
11502               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11503                 &montage_info->border_color,exception);
11504               for (next=image; next; next=next->next)
11505                 next->border_color=montage_info->border_color;
11506               break;
11507             }
11508           if (LocaleCompare(attribute,"borderwidth") == 0)
11509             {
11510               montage_info->border_width=SvIV(ST(i));
11511               break;
11512             }
11513           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11514             attribute);
11515           break;
11516         }
11517         case 'C':
11518         case 'c':
11519         {
11520           if (LocaleCompare(attribute,"compose") == 0)
11521             {
11522               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11523                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
11524               if (sp < 0)
11525                 {
11526                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11527                     SvPV(ST(i),na));
11528                   break;
11529                 }
11530               for (next=image; next; next=next->next)
11531                 next->compose=(CompositeOperator) sp;
11532               break;
11533             }
11534           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11535             attribute);
11536           break;
11537         }
11538         case 'F':
11539         case 'f':
11540         {
11541           if (LocaleCompare(attribute,"fill") == 0)
11542             {
11543               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11544                 &montage_info->fill,exception);
11545               break;
11546             }
11547           if (LocaleCompare(attribute,"font") == 0)
11548             {
11549               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
11550               break;
11551             }
11552           if (LocaleCompare(attribute,"frame") == 0)
11553             {
11554               char
11555                 *p;
11556
11557               p=SvPV(ST(i),na);
11558               if (IsGeometry(p) == MagickFalse)
11559                 {
11560                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11561                     p);
11562                   break;
11563                 }
11564               (void) CloneString(&montage_info->frame,p);
11565               if (*p == '\0')
11566                 montage_info->frame=(char *) NULL;
11567               break;
11568             }
11569           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11570             attribute);
11571           break;
11572         }
11573         case 'G':
11574         case 'g':
11575         {
11576           if (LocaleCompare(attribute,"geometry") == 0)
11577             {
11578               char
11579                 *p;
11580
11581               p=SvPV(ST(i),na);
11582               if (IsGeometry(p) == MagickFalse)
11583                 {
11584                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11585                     p);
11586                   break;
11587                 }
11588              (void) CloneString(&montage_info->geometry,p);
11589              if (*p == '\0')
11590                montage_info->geometry=(char *) NULL;
11591              break;
11592            }
11593          if (LocaleCompare(attribute,"gravity") == 0)
11594            {
11595              ssize_t
11596                in;
11597
11598              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11599                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11600              if (in < 0)
11601                {
11602                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
11603                    SvPV(ST(i),na));
11604                  return;
11605                }
11606              montage_info->gravity=(GravityType) in;
11607              for (next=image; next; next=next->next)
11608                next->gravity=(GravityType) in;
11609              break;
11610            }
11611           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11612             attribute);
11613           break;
11614         }
11615         case 'L':
11616         case 'l':
11617         {
11618           if (LocaleCompare(attribute,"label") == 0)
11619             {
11620               for (next=image; next; next=next->next)
11621                 (void) SetImageProperty(next,"label",InterpretImageProperties(
11622                   info ? info->image_info : (ImageInfo *) NULL,next,
11623                   SvPV(ST(i),na),exception),exception);
11624               break;
11625             }
11626           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11627             attribute);
11628           break;
11629         }
11630         case 'M':
11631         case 'm':
11632         {
11633           if (LocaleCompare(attribute,"mattecolor") == 0)
11634             {
11635               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11636                 &montage_info->alpha_color,exception);
11637               for (next=image; next; next=next->next)
11638                 next->alpha_color=montage_info->alpha_color;
11639               break;
11640             }
11641           if (LocaleCompare(attribute,"mode") == 0)
11642             {
11643               ssize_t
11644                 in;
11645
11646               in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11647                 MagickModeOptions,MagickFalse,SvPV(ST(i),na));
11648               switch (in)
11649               {
11650                 default:
11651                 {
11652                   ThrowPerlException(exception,OptionError,
11653                     "UnrecognizedModeType",SvPV(ST(i),na));
11654                   break;
11655                 }
11656                 case FrameMode:
11657                 {
11658                   (void) CloneString(&montage_info->frame,"15x15+3+3");
11659                   montage_info->shadow=MagickTrue;
11660                   break;
11661                 }
11662                 case UnframeMode:
11663                 {
11664                   montage_info->frame=(char *) NULL;
11665                   montage_info->shadow=MagickFalse;
11666                   montage_info->border_width=0;
11667                   break;
11668                 }
11669                 case ConcatenateMode:
11670                 {
11671                   montage_info->frame=(char *) NULL;
11672                   montage_info->shadow=MagickFalse;
11673                   (void) CloneString(&montage_info->geometry,"+0+0");
11674                   montage_info->border_width=0;
11675                 }
11676               }
11677               break;
11678             }
11679           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11680             attribute);
11681           break;
11682         }
11683         case 'P':
11684         case 'p':
11685         {
11686           if (LocaleCompare(attribute,"pointsize") == 0)
11687             {
11688               montage_info->pointsize=SvIV(ST(i));
11689               break;
11690             }
11691           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11692             attribute);
11693           break;
11694         }
11695         case 'S':
11696         case 's':
11697         {
11698           if (LocaleCompare(attribute,"shadow") == 0)
11699             {
11700               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11701                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11702               if (sp < 0)
11703                 {
11704                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11705                     SvPV(ST(i),na));
11706                   break;
11707                 }
11708              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11709              break;
11710             }
11711           if (LocaleCompare(attribute,"stroke") == 0)
11712             {
11713               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11714                 &montage_info->stroke,exception);
11715               break;
11716             }
11717           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11718             attribute);
11719           break;
11720         }
11721         case 'T':
11722         case 't':
11723         {
11724           if (LocaleCompare(attribute,"texture") == 0)
11725             {
11726               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11727               break;
11728             }
11729           if (LocaleCompare(attribute,"tile") == 0)
11730             {
11731               char *p=SvPV(ST(i),na);
11732               if (IsGeometry(p) == MagickFalse)
11733                 {
11734                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11735                     p);
11736                   break;
11737                 }
11738               (void) CloneString(&montage_info->tile,p);
11739               if (*p == '\0')
11740                 montage_info->tile=(char *) NULL;
11741               break;
11742             }
11743           if (LocaleCompare(attribute,"title") == 0)
11744             {
11745               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11746               break;
11747             }
11748           if (LocaleCompare(attribute,"transparent") == 0)
11749             {
11750               PixelInfo
11751                 transparent_color;
11752
11753               QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11754                 &transparent_color,exception);
11755               for (next=image; next; next=next->next)
11756                 (void) TransparentPaintImage(next,&transparent_color,
11757                   TransparentAlpha,MagickFalse,exception);
11758               break;
11759             }
11760           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11761             attribute);
11762           break;
11763         }
11764         default:
11765         {
11766           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11767             attribute);
11768           break;
11769         }
11770       }
11771     }
11772     image=MontageImageList(info->image_info,montage_info,image,exception);
11773     montage_info=DestroyMontageInfo(montage_info);
11774     if (image == (Image *) NULL)
11775       goto PerlException;
11776     if (transparent_color.alpha != TransparentAlpha)
11777       for (next=image; next; next=next->next)
11778         (void) TransparentPaintImage(next,&transparent_color,
11779           TransparentAlpha,MagickFalse,exception);
11780     for (  ; image; image=image->next)
11781     {
11782       AddImageToRegistry(sv,image);
11783       rv=newRV(sv);
11784       av_push(av,sv_bless(rv,hv));
11785       SvREFCNT_dec(sv);
11786     }
11787     exception=DestroyExceptionInfo(exception);
11788     ST(0)=av_reference;
11789     SvREFCNT_dec(perl_exception);
11790     XSRETURN(1);
11791
11792   PerlException:
11793     InheritPerlException(exception,perl_exception);
11794     exception=DestroyExceptionInfo(exception);
11795     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11796     SvPOK_on(perl_exception);
11797     ST(0)=sv_2mortal(perl_exception);
11798     XSRETURN(1);
11799   }
11800 \f
11801 #
11802 ###############################################################################
11803 #                                                                             #
11804 #                                                                             #
11805 #                                                                             #
11806 #   M o r p h                                                                 #
11807 #                                                                             #
11808 #                                                                             #
11809 #                                                                             #
11810 ###############################################################################
11811 #
11812 #
11813 void
11814 Morph(ref,...)
11815   Image::Magick ref=NO_INIT
11816   ALIAS:
11817     MorphImage  = 1
11818     morph       = 2
11819     morphimage  = 3
11820   PPCODE:
11821   {
11822     AV
11823       *av;
11824
11825     char
11826       *attribute;
11827
11828     ExceptionInfo
11829       *exception;
11830
11831     HV
11832       *hv;
11833
11834     Image
11835       *image;
11836
11837     register ssize_t
11838       i;
11839
11840     ssize_t
11841       number_frames;
11842
11843     struct PackageInfo
11844       *info;
11845
11846     SV
11847       *av_reference,
11848       *perl_exception,
11849       *reference,
11850       *rv,
11851       *sv;
11852
11853     PERL_UNUSED_VAR(ref);
11854     PERL_UNUSED_VAR(ix);
11855     exception=AcquireExceptionInfo();
11856     perl_exception=newSVpv("",0);
11857     sv=NULL;
11858     av=NULL;
11859     attribute=NULL;
11860     if (sv_isobject(ST(0)) == 0)
11861       {
11862         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11863           PackageName);
11864         goto PerlException;
11865       }
11866     reference=SvRV(ST(0));
11867     hv=SvSTASH(reference);
11868     av=newAV();
11869     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11870     SvREFCNT_dec(av);
11871     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11872     if (image == (Image *) NULL)
11873       {
11874         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11875           PackageName);
11876         goto PerlException;
11877       }
11878     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11879     /*
11880       Get attribute.
11881     */
11882     number_frames=30;
11883     for (i=2; i < items; i+=2)
11884     {
11885       attribute=(char *) SvPV(ST(i-1),na);
11886       switch (*attribute)
11887       {
11888         case 'F':
11889         case 'f':
11890         {
11891           if (LocaleCompare(attribute,"frames") == 0)
11892             {
11893               number_frames=SvIV(ST(i));
11894               break;
11895             }
11896           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11897             attribute);
11898           break;
11899         }
11900         default:
11901         {
11902           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11903             attribute);
11904           break;
11905         }
11906       }
11907     }
11908     image=MorphImages(image,number_frames,exception);
11909     if (image == (Image *) NULL)
11910       goto PerlException;
11911     for ( ; image; image=image->next)
11912     {
11913       AddImageToRegistry(sv,image);
11914       rv=newRV(sv);
11915       av_push(av,sv_bless(rv,hv));
11916       SvREFCNT_dec(sv);
11917     }
11918     exception=DestroyExceptionInfo(exception);
11919     ST(0)=av_reference;
11920     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11921     XSRETURN(1);
11922
11923   PerlException:
11924     InheritPerlException(exception,perl_exception);
11925     exception=DestroyExceptionInfo(exception);
11926     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11927     SvPOK_on(perl_exception);
11928     ST(0)=sv_2mortal(perl_exception);
11929     XSRETURN(1);
11930   }
11931 \f
11932 #
11933 ###############################################################################
11934 #                                                                             #
11935 #                                                                             #
11936 #                                                                             #
11937 #   M o s a i c                                                               #
11938 #                                                                             #
11939 #                                                                             #
11940 #                                                                             #
11941 ###############################################################################
11942 #
11943 #
11944 void
11945 Mosaic(ref)
11946   Image::Magick ref=NO_INIT
11947   ALIAS:
11948     MosaicImage   = 1
11949     mosaic        = 2
11950     mosaicimage   = 3
11951   PPCODE:
11952   {
11953     AV
11954       *av;
11955
11956     ExceptionInfo
11957       *exception;
11958
11959     HV
11960       *hv;
11961
11962     Image
11963       *image;
11964
11965     struct PackageInfo
11966       *info;
11967
11968     SV
11969       *perl_exception,
11970       *reference,
11971       *rv,
11972       *sv;
11973
11974     PERL_UNUSED_VAR(ref);
11975     PERL_UNUSED_VAR(ix);
11976     exception=AcquireExceptionInfo();
11977     perl_exception=newSVpv("",0);
11978     sv=NULL;
11979     if (sv_isobject(ST(0)) == 0)
11980       {
11981         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11982           PackageName);
11983         goto PerlException;
11984       }
11985     reference=SvRV(ST(0));
11986     hv=SvSTASH(reference);
11987     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11988     if (image == (Image *) NULL)
11989       {
11990         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11991           PackageName);
11992         goto PerlException;
11993       }
11994     image=MergeImageLayers(image,MosaicLayer,exception);
11995     /*
11996       Create blessed Perl array for the returned image.
11997     */
11998     av=newAV();
11999     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12000     SvREFCNT_dec(av);
12001     AddImageToRegistry(sv,image);
12002     rv=newRV(sv);
12003     av_push(av,sv_bless(rv,hv));
12004     SvREFCNT_dec(sv);
12005     (void) CopyMagickString(info->image_info->filename,image->filename,
12006       MagickPathExtent);
12007     SetImageInfo(info->image_info,0,exception);
12008     exception=DestroyExceptionInfo(exception);
12009     SvREFCNT_dec(perl_exception);
12010     XSRETURN(1);
12011
12012   PerlException:
12013     InheritPerlException(exception,perl_exception);
12014     exception=DestroyExceptionInfo(exception);
12015     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12016     SvPOK_on(perl_exception);  /* return messages in string context */
12017     ST(0)=sv_2mortal(perl_exception);
12018     XSRETURN(1);
12019   }
12020 \f
12021 #
12022 ###############################################################################
12023 #                                                                             #
12024 #                                                                             #
12025 #                                                                             #
12026 #   P i n g                                                                   #
12027 #                                                                             #
12028 #                                                                             #
12029 #                                                                             #
12030 ###############################################################################
12031 #
12032 #
12033 void
12034 Ping(ref,...)
12035   Image::Magick ref=NO_INIT
12036   ALIAS:
12037     PingImage  = 1
12038     ping       = 2
12039     pingimage  = 3
12040   PPCODE:
12041   {
12042     AV
12043       *av;
12044
12045     char
12046       **keep,
12047       **list;
12048
12049     ExceptionInfo
12050       *exception;
12051
12052     Image
12053       *image,
12054       *next;
12055
12056     int
12057       n;
12058
12059     MagickBooleanType
12060       status;
12061
12062     register char
12063       **p;
12064
12065     register ssize_t
12066       i;
12067
12068     ssize_t
12069       ac;
12070
12071     STRLEN
12072       *length;
12073
12074     struct PackageInfo
12075       *info,
12076       *package_info;
12077
12078     SV
12079       *perl_exception,
12080       *reference;
12081
12082     size_t
12083       count;
12084
12085     PERL_UNUSED_VAR(ref);
12086     PERL_UNUSED_VAR(ix);
12087     exception=AcquireExceptionInfo();
12088     perl_exception=newSVpv("",0);
12089     package_info=(struct PackageInfo *) NULL;
12090     ac=(items < 2) ? 1 : items-1;
12091     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
12092     keep=list;
12093     length=(STRLEN *) NULL;
12094     if (list == (char **) NULL)
12095       {
12096         ThrowPerlException(exception,ResourceLimitError,
12097           "MemoryAllocationFailed",PackageName);
12098         goto PerlException;
12099       }
12100     keep=list;
12101     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
12102     if (length == (STRLEN *) NULL)
12103       {
12104         ThrowPerlException(exception,ResourceLimitError,
12105           "MemoryAllocationFailed",PackageName);
12106         goto PerlException;
12107       }
12108     if (sv_isobject(ST(0)) == 0)
12109       {
12110         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12111           PackageName);
12112         goto PerlException;
12113       }
12114     reference=SvRV(ST(0));
12115     if (SvTYPE(reference) != SVt_PVAV)
12116       {
12117         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12118           PackageName);
12119         goto PerlException;
12120       }
12121     av=(AV *) reference;
12122     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12123       exception);
12124     package_info=ClonePackageInfo(info,exception);
12125     n=1;
12126     if (items <= 1)
12127       *list=(char *) (*package_info->image_info->filename ?
12128         package_info->image_info->filename : "XC:black");
12129     else
12130       for (n=0, i=0; i < ac; i++)
12131       {
12132         list[n]=(char *) SvPV(ST(i+1),length[n]);
12133         if ((items >= 3) && strEQcase(list[n],"blob"))
12134           {
12135             void
12136               *blob;
12137
12138             i++;
12139             blob=(void *) (SvPV(ST(i+1),length[n]));
12140             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
12141           }
12142         if ((items >= 3) && strEQcase(list[n],"filename"))
12143           continue;
12144         if ((items >= 3) && strEQcase(list[n],"file"))
12145           {
12146             FILE
12147               *file;
12148
12149             PerlIO
12150               *io_info;
12151
12152             i++;
12153             io_info=IoIFP(sv_2io(ST(i+1)));
12154             if (io_info == (PerlIO *) NULL)
12155               {
12156                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12157                   PackageName);
12158                 continue;
12159               }
12160             file=PerlIO_findFILE(io_info);
12161             if (file == (FILE *) NULL)
12162               {
12163                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12164                   PackageName);
12165                 continue;
12166               }
12167             SetImageInfoFile(package_info->image_info,file);
12168           }
12169         if ((items >= 3) && strEQcase(list[n],"magick"))
12170           continue;
12171         n++;
12172       }
12173     list[n]=(char *) NULL;
12174     keep=list;
12175     status=ExpandFilenames(&n,&list);
12176     if (status == MagickFalse)
12177       {
12178         ThrowPerlException(exception,ResourceLimitError,
12179           "MemoryAllocationFailed",PackageName);
12180         goto PerlException;
12181       }
12182     count=0;
12183     for (i=0; i < n; i++)
12184     {
12185       (void) CopyMagickString(package_info->image_info->filename,list[i],
12186         MagickPathExtent);
12187       image=PingImage(package_info->image_info,exception);
12188       if (image == (Image *) NULL)
12189         break;
12190       if ((package_info->image_info->file != (FILE *) NULL) ||
12191           (package_info->image_info->blob != (void *) NULL))
12192         DisassociateImageStream(image);
12193       count+=GetImageListLength(image);
12194       EXTEND(sp,4*count);
12195       for (next=image; next; next=next->next)
12196       {
12197         PUSHs(sv_2mortal(newSViv(next->columns)));
12198         PUSHs(sv_2mortal(newSViv(next->rows)));
12199         PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
12200         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
12201       }
12202       image=DestroyImageList(image);
12203     }
12204     /*
12205       Free resources.
12206     */
12207     for (i=0; i < n; i++)
12208       if (list[i] != (char *) NULL)
12209         for (p=keep; list[i] != *p++; )
12210           if (*p == NULL)
12211             {
12212               list[i]=(char *) RelinquishMagickMemory(list[i]);
12213               break;
12214             }
12215
12216   PerlException:
12217     if (package_info != (struct PackageInfo *) NULL)
12218       DestroyPackageInfo(package_info);
12219     if (list && (list != keep))
12220       list=(char **) RelinquishMagickMemory(list);
12221     if (keep)
12222       keep=(char **) RelinquishMagickMemory(keep);
12223     if (length)
12224       length=(STRLEN *) RelinquishMagickMemory(length);
12225     InheritPerlException(exception,perl_exception);
12226     exception=DestroyExceptionInfo(exception);
12227     SvREFCNT_dec(perl_exception);  /* throw away all errors */
12228   }
12229 \f
12230 #
12231 ###############################################################################
12232 #                                                                             #
12233 #                                                                             #
12234 #                                                                             #
12235 #   P r e v i e w                                                             #
12236 #                                                                             #
12237 #                                                                             #
12238 #                                                                             #
12239 ###############################################################################
12240 #
12241 #
12242 void
12243 Preview(ref,...)
12244   Image::Magick ref=NO_INIT
12245   ALIAS:
12246     PreviewImage = 1
12247     preview      = 2
12248     previewimage = 3
12249   PPCODE:
12250   {
12251     AV
12252       *av;
12253
12254     ExceptionInfo
12255       *exception;
12256
12257     HV
12258       *hv;
12259
12260     Image
12261       *image,
12262       *preview_image;
12263
12264     PreviewType
12265       preview_type;
12266
12267     struct PackageInfo
12268       *info;
12269
12270     SV
12271       *av_reference,
12272       *perl_exception,
12273       *reference,
12274       *rv,
12275       *sv;
12276
12277     PERL_UNUSED_VAR(ref);
12278     PERL_UNUSED_VAR(ix);
12279     exception=AcquireExceptionInfo();
12280     perl_exception=newSVpv("",0);
12281     sv=NULL;
12282     av=NULL;
12283     if (sv_isobject(ST(0)) == 0)
12284       {
12285         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12286           PackageName);
12287         goto PerlException;
12288       }
12289     reference=SvRV(ST(0));
12290     hv=SvSTASH(reference);
12291     av=newAV();
12292     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12293     SvREFCNT_dec(av);
12294     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12295     if (image == (Image *) NULL)
12296       {
12297         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12298           PackageName);
12299         goto PerlException;
12300       }
12301     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
12302     preview_type=GammaPreview;
12303     if (items > 1)
12304       preview_type=(PreviewType)
12305         ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
12306     for ( ; image; image=image->next)
12307     {
12308       preview_image=PreviewImage(image,preview_type,exception);
12309       if (preview_image == (Image *) NULL)
12310         goto PerlException;
12311       AddImageToRegistry(sv,preview_image);
12312       rv=newRV(sv);
12313       av_push(av,sv_bless(rv,hv));
12314       SvREFCNT_dec(sv);
12315     }
12316     exception=DestroyExceptionInfo(exception);
12317     ST(0)=av_reference;
12318     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12319     XSRETURN(1);
12320
12321   PerlException:
12322     InheritPerlException(exception,perl_exception);
12323     exception=DestroyExceptionInfo(exception);
12324     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12325     SvPOK_on(perl_exception);
12326     ST(0)=sv_2mortal(perl_exception);
12327     XSRETURN(1);
12328   }
12329 \f
12330 #
12331 ###############################################################################
12332 #                                                                             #
12333 #                                                                             #
12334 #                                                                             #
12335 #   Q u e r y C o l o r                                                       #
12336 #                                                                             #
12337 #                                                                             #
12338 #                                                                             #
12339 ###############################################################################
12340 #
12341 #
12342 void
12343 QueryColor(ref,...)
12344   Image::Magick ref=NO_INIT
12345   ALIAS:
12346     querycolor = 1
12347   PPCODE:
12348   {
12349     char
12350       *name;
12351
12352     ExceptionInfo
12353       *exception;
12354
12355     PixelInfo
12356       color;
12357
12358     register ssize_t
12359       i;
12360
12361     SV
12362       *perl_exception;
12363
12364     PERL_UNUSED_VAR(ref);
12365     PERL_UNUSED_VAR(ix);
12366     exception=AcquireExceptionInfo();
12367     perl_exception=newSVpv("",0);
12368     if (items == 1)
12369       {
12370         const ColorInfo
12371           **colorlist;
12372
12373         size_t
12374           colors;
12375
12376         colorlist=GetColorInfoList("*",&colors,exception);
12377         EXTEND(sp,colors);
12378         for (i=0; i < (ssize_t) colors; i++)
12379         {
12380           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
12381         }
12382         colorlist=(const ColorInfo **)
12383           RelinquishMagickMemory((ColorInfo **) colorlist);
12384         goto PerlException;
12385       }
12386     EXTEND(sp,5*items);
12387     for (i=1; i < items; i++)
12388     {
12389       name=(char *) SvPV(ST(i),na);
12390       if (QueryColorCompliance(name,AllCompliance,&color,exception) == MagickFalse)
12391         {
12392           PUSHs(&sv_undef);
12393           continue;
12394         }
12395       PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
12396       PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
12397       PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
12398       if (color.colorspace == CMYKColorspace)
12399         PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
12400       if (color.alpha_trait != UndefinedPixelTrait)
12401         PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
12402     }
12403
12404   PerlException:
12405     InheritPerlException(exception,perl_exception);
12406     exception=DestroyExceptionInfo(exception);
12407     SvREFCNT_dec(perl_exception);
12408   }
12409 \f
12410 #
12411 ###############################################################################
12412 #                                                                             #
12413 #                                                                             #
12414 #                                                                             #
12415 #   Q u e r y C o l o r N a m e                                               #
12416 #                                                                             #
12417 #                                                                             #
12418 #                                                                             #
12419 ###############################################################################
12420 #
12421 #
12422 void
12423 QueryColorname(ref,...)
12424   Image::Magick ref=NO_INIT
12425   ALIAS:
12426     querycolorname = 1
12427   PPCODE:
12428   {
12429     AV
12430       *av;
12431
12432     char
12433       message[MagickPathExtent];
12434
12435     ExceptionInfo
12436       *exception;
12437
12438     Image
12439       *image;
12440
12441     PixelInfo
12442       target_color;
12443
12444     register ssize_t
12445       i;
12446
12447     struct PackageInfo
12448       *info;
12449
12450     SV
12451       *perl_exception,
12452       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12453
12454     PERL_UNUSED_VAR(ref);
12455     PERL_UNUSED_VAR(ix);
12456     exception=AcquireExceptionInfo();
12457     perl_exception=newSVpv("",0);
12458     reference=SvRV(ST(0));
12459     av=(AV *) reference;
12460     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12461       exception);
12462     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12463     if (image == (Image *) NULL)
12464       {
12465         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12466           PackageName);
12467         goto PerlException;
12468       }
12469     EXTEND(sp,items);
12470     for (i=1; i < items; i++)
12471     {
12472       (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,&target_color,
12473         exception);
12474       (void) QueryColorname(image,&target_color,SVGCompliance,message,
12475         exception);
12476       PUSHs(sv_2mortal(newSVpv(message,0)));
12477     }
12478
12479   PerlException:
12480     InheritPerlException(exception,perl_exception);
12481     exception=DestroyExceptionInfo(exception);
12482     SvREFCNT_dec(perl_exception);
12483   }
12484 \f
12485 #
12486 ###############################################################################
12487 #                                                                             #
12488 #                                                                             #
12489 #                                                                             #
12490 #   Q u e r y F o n t                                                         #
12491 #                                                                             #
12492 #                                                                             #
12493 #                                                                             #
12494 ###############################################################################
12495 #
12496 #
12497 void
12498 QueryFont(ref,...)
12499   Image::Magick ref=NO_INIT
12500   ALIAS:
12501     queryfont = 1
12502   PPCODE:
12503   {
12504     char
12505       *name,
12506       message[MagickPathExtent];
12507
12508     ExceptionInfo
12509       *exception;
12510
12511     register ssize_t
12512       i;
12513
12514     SV
12515       *perl_exception;
12516
12517     volatile const TypeInfo
12518       *type_info;
12519
12520     PERL_UNUSED_VAR(ref);
12521     PERL_UNUSED_VAR(ix);
12522     exception=AcquireExceptionInfo();
12523     perl_exception=newSVpv("",0);
12524     if (items == 1)
12525       {
12526         const TypeInfo
12527           **typelist;
12528
12529         size_t
12530           types;
12531
12532         typelist=GetTypeInfoList("*",&types,exception);
12533         EXTEND(sp,types);
12534         for (i=0; i < (ssize_t) types; i++)
12535         {
12536           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
12537         }
12538         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
12539           typelist);
12540         goto PerlException;
12541       }
12542     EXTEND(sp,10*items);
12543     for (i=1; i < items; i++)
12544     {
12545       name=(char *) SvPV(ST(i),na);
12546       type_info=GetTypeInfo(name,exception);
12547       if (type_info == (TypeInfo *) NULL)
12548         {
12549           PUSHs(&sv_undef);
12550           continue;
12551         }
12552       if (type_info->name == (char *) NULL)
12553         PUSHs(&sv_undef);
12554       else
12555         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
12556       if (type_info->description == (char *) NULL)
12557         PUSHs(&sv_undef);
12558       else
12559         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
12560       if (type_info->family == (char *) NULL)
12561         PUSHs(&sv_undef);
12562       else
12563         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
12564       if (type_info->style == UndefinedStyle)
12565         PUSHs(&sv_undef);
12566       else
12567         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
12568           type_info->style),0)));
12569       if (type_info->stretch == UndefinedStretch)
12570         PUSHs(&sv_undef);
12571       else
12572         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
12573           type_info->stretch),0)));
12574       (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
12575         type_info->weight);
12576       PUSHs(sv_2mortal(newSVpv(message,0)));
12577       if (type_info->encoding == (char *) NULL)
12578         PUSHs(&sv_undef);
12579       else
12580         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
12581       if (type_info->foundry == (char *) NULL)
12582         PUSHs(&sv_undef);
12583       else
12584         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
12585       if (type_info->format == (char *) NULL)
12586         PUSHs(&sv_undef);
12587       else
12588         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
12589       if (type_info->metrics == (char *) NULL)
12590         PUSHs(&sv_undef);
12591       else
12592         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
12593       if (type_info->glyphs == (char *) NULL)
12594         PUSHs(&sv_undef);
12595       else
12596         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
12597     }
12598
12599   PerlException:
12600     InheritPerlException(exception,perl_exception);
12601     exception=DestroyExceptionInfo(exception);
12602     SvREFCNT_dec(perl_exception);
12603   }
12604 \f
12605 #
12606 ###############################################################################
12607 #                                                                             #
12608 #                                                                             #
12609 #                                                                             #
12610 #   Q u e r y F o n t M e t r i c s                                           #
12611 #                                                                             #
12612 #                                                                             #
12613 #                                                                             #
12614 ###############################################################################
12615 #
12616 #
12617 void
12618 QueryFontMetrics(ref,...)
12619   Image::Magick ref=NO_INIT
12620   ALIAS:
12621     queryfontmetrics = 1
12622   PPCODE:
12623   {
12624     AffineMatrix
12625       affine,
12626       current;
12627
12628     AV
12629       *av;
12630
12631     char
12632       *attribute;
12633
12634     double
12635       x,
12636       y;
12637
12638     DrawInfo
12639       *draw_info;
12640
12641     ExceptionInfo
12642       *exception;
12643
12644     GeometryInfo
12645       geometry_info;
12646
12647     Image
12648       *image;
12649
12650     MagickBooleanType
12651       status;
12652
12653     MagickStatusType
12654       flags;
12655
12656     register ssize_t
12657       i;
12658
12659     ssize_t
12660       type;
12661
12662     struct PackageInfo
12663       *info,
12664       *package_info;
12665
12666     SV
12667       *perl_exception,
12668       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12669
12670     TypeMetric
12671       metrics;
12672
12673     PERL_UNUSED_VAR(ref);
12674     PERL_UNUSED_VAR(ix);
12675     exception=AcquireExceptionInfo();
12676     package_info=(struct PackageInfo *) NULL;
12677     perl_exception=newSVpv("",0);
12678     reference=SvRV(ST(0));
12679     av=(AV *) reference;
12680     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12681       exception);
12682     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12683     if (image == (Image *) NULL)
12684       {
12685         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12686           PackageName);
12687         goto PerlException;
12688       }
12689     package_info=ClonePackageInfo(info,exception);
12690     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12691     CloneString(&draw_info->text,"");
12692     current=draw_info->affine;
12693     GetAffineMatrix(&affine);
12694     x=0.0;
12695     y=0.0;
12696     EXTEND(sp,7*items);
12697     for (i=2; i < items; i+=2)
12698     {
12699       attribute=(char *) SvPV(ST(i-1),na);
12700       switch (*attribute)
12701       {
12702         case 'A':
12703         case 'a':
12704         {
12705           if (LocaleCompare(attribute,"antialias") == 0)
12706             {
12707               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12708                 SvPV(ST(i),na));
12709               if (type < 0)
12710                 {
12711                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12712                     SvPV(ST(i),na));
12713                   break;
12714                 }
12715               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12716               break;
12717             }
12718           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12719             attribute);
12720           break;
12721         }
12722         case 'd':
12723         case 'D':
12724         {
12725           if (LocaleCompare(attribute,"density") == 0)
12726             {
12727               CloneString(&draw_info->density,SvPV(ST(i),na));
12728               break;
12729             }
12730           if (LocaleCompare(attribute,"direction") == 0)
12731             {
12732               draw_info->direction=(DirectionType) ParseCommandOption(
12733                 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12734               break;
12735             }
12736           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12737             attribute);
12738           break;
12739         }
12740         case 'e':
12741         case 'E':
12742         {
12743           if (LocaleCompare(attribute,"encoding") == 0)
12744             {
12745               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12746               break;
12747             }
12748           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12749             attribute);
12750           break;
12751         }
12752         case 'f':
12753         case 'F':
12754         {
12755           if (LocaleCompare(attribute,"family") == 0)
12756             {
12757               CloneString(&draw_info->family,SvPV(ST(i),na));
12758               break;
12759             }
12760           if (LocaleCompare(attribute,"fill") == 0)
12761             {
12762               if (info)
12763                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12764                   &draw_info->fill,exception);
12765               break;
12766             }
12767           if (LocaleCompare(attribute,"font") == 0)
12768             {
12769               CloneString(&draw_info->font,SvPV(ST(i),na));
12770               break;
12771             }
12772           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12773             attribute);
12774           break;
12775         }
12776         case 'g':
12777         case 'G':
12778         {
12779           if (LocaleCompare(attribute,"geometry") == 0)
12780             {
12781               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12782               break;
12783             }
12784           if (LocaleCompare(attribute,"gravity") == 0)
12785             {
12786               draw_info->gravity=(GravityType) ParseCommandOption(
12787                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12788               break;
12789             }
12790           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12791             attribute);
12792           break;
12793         }
12794         case 'i':
12795         case 'I':
12796         {
12797           if (LocaleCompare(attribute,"interline-spacing") == 0)
12798             {
12799               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12800               draw_info->interline_spacing=geometry_info.rho;
12801               break;
12802             }
12803           if (LocaleCompare(attribute,"interword-spacing") == 0)
12804             {
12805               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12806               draw_info->interword_spacing=geometry_info.rho;
12807               break;
12808             }
12809           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12810             attribute);
12811           break;
12812         }
12813         case 'k':
12814         case 'K':
12815         {
12816           if (LocaleCompare(attribute,"kerning") == 0)
12817             {
12818               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12819               draw_info->kerning=geometry_info.rho;
12820               break;
12821             }
12822           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12823             attribute);
12824           break;
12825         }
12826         case 'p':
12827         case 'P':
12828         {
12829           if (LocaleCompare(attribute,"pointsize") == 0)
12830             {
12831               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12832               draw_info->pointsize=geometry_info.rho;
12833               break;
12834             }
12835           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12836             attribute);
12837           break;
12838         }
12839         case 'r':
12840         case 'R':
12841         {
12842           if (LocaleCompare(attribute,"rotate") == 0)
12843             {
12844               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12845               affine.rx=geometry_info.rho;
12846               affine.ry=geometry_info.sigma;
12847               if ((flags & SigmaValue) == 0)
12848                 affine.ry=affine.rx;
12849               break;
12850             }
12851           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12852             attribute);
12853           break;
12854         }
12855         case 's':
12856         case 'S':
12857         {
12858           if (LocaleCompare(attribute,"scale") == 0)
12859             {
12860               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12861               affine.sx=geometry_info.rho;
12862               affine.sy=geometry_info.sigma;
12863               if ((flags & SigmaValue) == 0)
12864                 affine.sy=affine.sx;
12865               break;
12866             }
12867           if (LocaleCompare(attribute,"skew") == 0)
12868             {
12869               double
12870                 x_angle,
12871                 y_angle;
12872
12873               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12874               x_angle=geometry_info.rho;
12875               y_angle=geometry_info.sigma;
12876               if ((flags & SigmaValue) == 0)
12877                 y_angle=x_angle;
12878               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12879               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12880               break;
12881             }
12882           if (LocaleCompare(attribute,"stroke") == 0)
12883             {
12884               if (info)
12885                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12886                   &draw_info->stroke,exception);
12887               break;
12888             }
12889           if (LocaleCompare(attribute,"style") == 0)
12890             {
12891               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12892                 SvPV(ST(i),na));
12893               if (type < 0)
12894                 {
12895                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12896                     SvPV(ST(i),na));
12897                   break;
12898                 }
12899               draw_info->style=(StyleType) type;
12900               break;
12901             }
12902           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12903             attribute);
12904           break;
12905         }
12906         case 't':
12907         case 'T':
12908         {
12909           if (LocaleCompare(attribute,"text") == 0)
12910             {
12911               CloneString(&draw_info->text,SvPV(ST(i),na));
12912               break;
12913             }
12914           if (LocaleCompare(attribute,"translate") == 0)
12915             {
12916               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12917               affine.tx=geometry_info.rho;
12918               affine.ty=geometry_info.sigma;
12919               if ((flags & SigmaValue) == 0)
12920                 affine.ty=affine.tx;
12921               break;
12922             }
12923           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12924             attribute);
12925           break;
12926         }
12927         case 'w':
12928         case 'W':
12929         {
12930           if (LocaleCompare(attribute,"weight") == 0)
12931             {
12932               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12933               draw_info->weight=(size_t) geometry_info.rho;
12934               break;
12935             }
12936           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12937             attribute);
12938           break;
12939         }
12940         case 'x':
12941         case 'X':
12942         {
12943           if (LocaleCompare(attribute,"x") == 0)
12944             {
12945               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12946               x=geometry_info.rho;
12947               break;
12948             }
12949           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12950             attribute);
12951           break;
12952         }
12953         case 'y':
12954         case 'Y':
12955         {
12956           if (LocaleCompare(attribute,"y") == 0)
12957             {
12958               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12959               y=geometry_info.rho;
12960               break;
12961             }
12962           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12963             attribute);
12964           break;
12965         }
12966         default:
12967         {
12968           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12969             attribute);
12970           break;
12971         }
12972       }
12973     }
12974     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12975     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12976     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12977     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12978     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12979     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12980     if (draw_info->geometry == (char *) NULL)
12981       {
12982         draw_info->geometry=AcquireString((char *) NULL);
12983         (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
12984           "%.15g,%.15g",x,y);
12985       }
12986     status=GetTypeMetrics(image,draw_info,&metrics,exception);
12987     (void) CatchImageException(image);
12988     if (status == MagickFalse)
12989       PUSHs(&sv_undef);
12990     else
12991       {
12992         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12993         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12994         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12995         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12996         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12997         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12998         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12999         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13000         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13001         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13002         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13003         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13004         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13005       }
13006     draw_info=DestroyDrawInfo(draw_info);
13007
13008   PerlException:
13009     if (package_info != (struct PackageInfo *) NULL)
13010       DestroyPackageInfo(package_info);
13011     InheritPerlException(exception,perl_exception);
13012     exception=DestroyExceptionInfo(exception);
13013     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13014   }
13015 \f
13016 #
13017 ###############################################################################
13018 #                                                                             #
13019 #                                                                             #
13020 #                                                                             #
13021 #   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                         #
13022 #                                                                             #
13023 #                                                                             #
13024 #                                                                             #
13025 ###############################################################################
13026 #
13027 #
13028 void
13029 QueryMultilineFontMetrics(ref,...)
13030   Image::Magick ref=NO_INIT
13031   ALIAS:
13032     querymultilinefontmetrics = 1
13033   PPCODE:
13034   {
13035     AffineMatrix
13036       affine,
13037       current;
13038
13039     AV
13040       *av;
13041
13042     char
13043       *attribute;
13044
13045     double
13046       x,
13047       y;
13048
13049     DrawInfo
13050       *draw_info;
13051
13052     ExceptionInfo
13053       *exception;
13054
13055     GeometryInfo
13056       geometry_info;
13057
13058     Image
13059       *image;
13060
13061     MagickBooleanType
13062       status;
13063
13064     MagickStatusType
13065       flags;
13066
13067     register ssize_t
13068       i;
13069
13070     ssize_t
13071       type;
13072
13073     struct PackageInfo
13074       *info,
13075       *package_info;
13076
13077     SV
13078       *perl_exception,
13079       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13080
13081     TypeMetric
13082       metrics;
13083
13084     PERL_UNUSED_VAR(ref);
13085     PERL_UNUSED_VAR(ix);
13086     exception=AcquireExceptionInfo();
13087     package_info=(struct PackageInfo *) NULL;
13088     perl_exception=newSVpv("",0);
13089     reference=SvRV(ST(0));
13090     av=(AV *) reference;
13091     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13092       exception);
13093     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13094     if (image == (Image *) NULL)
13095       {
13096         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13097           PackageName);
13098         goto PerlException;
13099       }
13100     package_info=ClonePackageInfo(info,exception);
13101     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
13102     CloneString(&draw_info->text,"");
13103     current=draw_info->affine;
13104     GetAffineMatrix(&affine);
13105     x=0.0;
13106     y=0.0;
13107     EXTEND(sp,7*items);
13108     for (i=2; i < items; i+=2)
13109     {
13110       attribute=(char *) SvPV(ST(i-1),na);
13111       switch (*attribute)
13112       {
13113         case 'A':
13114         case 'a':
13115         {
13116           if (LocaleCompare(attribute,"antialias") == 0)
13117             {
13118               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13119                 SvPV(ST(i),na));
13120               if (type < 0)
13121                 {
13122                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13123                     SvPV(ST(i),na));
13124                   break;
13125                 }
13126               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
13127               break;
13128             }
13129           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13130             attribute);
13131           break;
13132         }
13133         case 'd':
13134         case 'D':
13135         {
13136           if (LocaleCompare(attribute,"density") == 0)
13137             {
13138               CloneString(&draw_info->density,SvPV(ST(i),na));
13139               break;
13140             }
13141           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13142             attribute);
13143           break;
13144         }
13145         case 'e':
13146         case 'E':
13147         {
13148           if (LocaleCompare(attribute,"encoding") == 0)
13149             {
13150               CloneString(&draw_info->encoding,SvPV(ST(i),na));
13151               break;
13152             }
13153           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13154             attribute);
13155           break;
13156         }
13157         case 'f':
13158         case 'F':
13159         {
13160           if (LocaleCompare(attribute,"family") == 0)
13161             {
13162               CloneString(&draw_info->family,SvPV(ST(i),na));
13163               break;
13164             }
13165           if (LocaleCompare(attribute,"fill") == 0)
13166             {
13167               if (info)
13168                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13169                   &draw_info->fill,exception);
13170               break;
13171             }
13172           if (LocaleCompare(attribute,"font") == 0)
13173             {
13174               CloneString(&draw_info->font,SvPV(ST(i),na));
13175               break;
13176             }
13177           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13178             attribute);
13179           break;
13180         }
13181         case 'g':
13182         case 'G':
13183         {
13184           if (LocaleCompare(attribute,"geometry") == 0)
13185             {
13186               CloneString(&draw_info->geometry,SvPV(ST(i),na));
13187               break;
13188             }
13189           if (LocaleCompare(attribute,"gravity") == 0)
13190             {
13191               draw_info->gravity=(GravityType) ParseCommandOption(
13192                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13193               break;
13194             }
13195           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13196             attribute);
13197           break;
13198         }
13199         case 'p':
13200         case 'P':
13201         {
13202           if (LocaleCompare(attribute,"pointsize") == 0)
13203             {
13204               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13205               draw_info->pointsize=geometry_info.rho;
13206               break;
13207             }
13208           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13209             attribute);
13210           break;
13211         }
13212         case 'r':
13213         case 'R':
13214         {
13215           if (LocaleCompare(attribute,"rotate") == 0)
13216             {
13217               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13218               affine.rx=geometry_info.rho;
13219               affine.ry=geometry_info.sigma;
13220               if ((flags & SigmaValue) == 0)
13221                 affine.ry=affine.rx;
13222               break;
13223             }
13224           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13225             attribute);
13226           break;
13227         }
13228         case 's':
13229         case 'S':
13230         {
13231           if (LocaleCompare(attribute,"scale") == 0)
13232             {
13233               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13234               affine.sx=geometry_info.rho;
13235               affine.sy=geometry_info.sigma;
13236               if ((flags & SigmaValue) == 0)
13237                 affine.sy=affine.sx;
13238               break;
13239             }
13240           if (LocaleCompare(attribute,"skew") == 0)
13241             {
13242               double
13243                 x_angle,
13244                 y_angle;
13245
13246               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13247               x_angle=geometry_info.rho;
13248               y_angle=geometry_info.sigma;
13249               if ((flags & SigmaValue) == 0)
13250                 y_angle=x_angle;
13251               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
13252               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
13253               break;
13254             }
13255           if (LocaleCompare(attribute,"stroke") == 0)
13256             {
13257               if (info)
13258                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13259                   &draw_info->stroke,exception);
13260               break;
13261             }
13262           if (LocaleCompare(attribute,"style") == 0)
13263             {
13264               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
13265                 SvPV(ST(i),na));
13266               if (type < 0)
13267                 {
13268                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13269                     SvPV(ST(i),na));
13270                   break;
13271                 }
13272               draw_info->style=(StyleType) type;
13273               break;
13274             }
13275           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13276             attribute);
13277           break;
13278         }
13279         case 't':
13280         case 'T':
13281         {
13282           if (LocaleCompare(attribute,"text") == 0)
13283             {
13284               CloneString(&draw_info->text,SvPV(ST(i),na));
13285               break;
13286             }
13287           if (LocaleCompare(attribute,"translate") == 0)
13288             {
13289               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13290               affine.tx=geometry_info.rho;
13291               affine.ty=geometry_info.sigma;
13292               if ((flags & SigmaValue) == 0)
13293                 affine.ty=affine.tx;
13294               break;
13295             }
13296           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13297             attribute);
13298           break;
13299         }
13300         case 'w':
13301         case 'W':
13302         {
13303           if (LocaleCompare(attribute,"weight") == 0)
13304             {
13305               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13306               draw_info->weight=(size_t) geometry_info.rho;
13307               break;
13308             }
13309           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13310             attribute);
13311           break;
13312         }
13313         case 'x':
13314         case 'X':
13315         {
13316           if (LocaleCompare(attribute,"x") == 0)
13317             {
13318               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13319               x=geometry_info.rho;
13320               break;
13321             }
13322           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13323             attribute);
13324           break;
13325         }
13326         case 'y':
13327         case 'Y':
13328         {
13329           if (LocaleCompare(attribute,"y") == 0)
13330             {
13331               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13332               y=geometry_info.rho;
13333               break;
13334             }
13335           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13336             attribute);
13337           break;
13338         }
13339         default:
13340         {
13341           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13342             attribute);
13343           break;
13344         }
13345       }
13346     }
13347     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
13348     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
13349     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
13350     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
13351     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
13352     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
13353     if (draw_info->geometry == (char *) NULL)
13354       {
13355         draw_info->geometry=AcquireString((char *) NULL);
13356         (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
13357           "%.15g,%.15g",x,y);
13358       }
13359     status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
13360     (void) CatchException(exception);
13361     if (status == MagickFalse)
13362       PUSHs(&sv_undef);
13363     else
13364       {
13365         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
13366         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
13367         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
13368         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13369         PUSHs(sv_2mortal(newSVnv(metrics.width)));
13370         PUSHs(sv_2mortal(newSVnv(metrics.height)));
13371         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13372         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13373         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13374         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13375         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13376         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13377         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13378       }
13379     draw_info=DestroyDrawInfo(draw_info);
13380
13381   PerlException:
13382     if (package_info != (struct PackageInfo *) NULL)
13383       DestroyPackageInfo(package_info);
13384     InheritPerlException(exception,perl_exception);
13385     exception=DestroyExceptionInfo(exception);
13386     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13387   }
13388 \f
13389 #
13390 ###############################################################################
13391 #                                                                             #
13392 #                                                                             #
13393 #                                                                             #
13394 #   Q u e r y F o r m a t                                                     #
13395 #                                                                             #
13396 #                                                                             #
13397 #                                                                             #
13398 ###############################################################################
13399 #
13400 #
13401 void
13402 QueryFormat(ref,...)
13403   Image::Magick ref=NO_INIT
13404   ALIAS:
13405     queryformat = 1
13406   PPCODE:
13407   {
13408     char
13409       *name;
13410
13411     ExceptionInfo
13412       *exception;
13413
13414     register ssize_t
13415       i;
13416
13417     SV
13418       *perl_exception;
13419
13420     volatile const MagickInfo
13421       *magick_info;
13422
13423     PERL_UNUSED_VAR(ref);
13424     PERL_UNUSED_VAR(ix);
13425     exception=AcquireExceptionInfo();
13426     perl_exception=newSVpv("",0);
13427     if (items == 1)
13428       {
13429         char
13430           format[MagickPathExtent];
13431
13432         const MagickInfo
13433           **format_list;
13434
13435         size_t
13436           types;
13437
13438         format_list=GetMagickInfoList("*",&types,exception);
13439         EXTEND(sp,types);
13440         for (i=0; i < (ssize_t) types; i++)
13441         {
13442           (void) CopyMagickString(format,format_list[i]->name,MagickPathExtent);
13443           LocaleLower(format);
13444           PUSHs(sv_2mortal(newSVpv(format,0)));
13445         }
13446         format_list=(const MagickInfo **)
13447           RelinquishMagickMemory((MagickInfo *) format_list);
13448         goto PerlException;
13449       }
13450     EXTEND(sp,8*items);
13451     for (i=1; i < items; i++)
13452     {
13453       name=(char *) SvPV(ST(i),na);
13454       magick_info=GetMagickInfo(name,exception);
13455       if (magick_info == (const MagickInfo *) NULL)
13456         {
13457           PUSHs(&sv_undef);
13458           continue;
13459         }
13460       if (magick_info->description == (char *) NULL)
13461         PUSHs(&sv_undef);
13462       else
13463         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
13464       if (magick_info->module == (char *) NULL)
13465         PUSHs(&sv_undef);
13466       else
13467         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
13468     }
13469
13470   PerlException:
13471     InheritPerlException(exception,perl_exception);
13472     exception=DestroyExceptionInfo(exception);
13473     SvREFCNT_dec(perl_exception);
13474   }
13475 \f
13476 #
13477 ###############################################################################
13478 #                                                                             #
13479 #                                                                             #
13480 #                                                                             #
13481 #   Q u e r y O p t i o n                                                     #
13482 #                                                                             #
13483 #                                                                             #
13484 #                                                                             #
13485 ###############################################################################
13486 #
13487 #
13488 void
13489 QueryOption(ref,...)
13490   Image::Magick ref=NO_INIT
13491   ALIAS:
13492     queryoption = 1
13493   PPCODE:
13494   {
13495     char
13496       **options;
13497
13498     ExceptionInfo
13499       *exception;
13500
13501     register ssize_t
13502       i;
13503
13504     ssize_t
13505       j,
13506       option;
13507
13508     SV
13509       *perl_exception;
13510
13511     PERL_UNUSED_VAR(ref);
13512     PERL_UNUSED_VAR(ix);
13513     exception=AcquireExceptionInfo();
13514     perl_exception=newSVpv("",0);
13515     EXTEND(sp,8*items);
13516     for (i=1; i < items; i++)
13517     {
13518       option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
13519         SvPV(ST(i),na));
13520       options=GetCommandOptions((CommandOption) option);
13521       if (options == (char **) NULL)
13522         PUSHs(&sv_undef);
13523       else
13524         {
13525           for (j=0; options[j] != (char *) NULL; j++)
13526             PUSHs(sv_2mortal(newSVpv(options[j],0)));
13527           options=DestroyStringList(options);
13528         }
13529     }
13530
13531     InheritPerlException(exception,perl_exception);
13532     exception=DestroyExceptionInfo(exception);
13533     SvREFCNT_dec(perl_exception);
13534   }
13535 \f
13536 #
13537 ###############################################################################
13538 #                                                                             #
13539 #                                                                             #
13540 #                                                                             #
13541 #   R e a d                                                                   #
13542 #                                                                             #
13543 #                                                                             #
13544 #                                                                             #
13545 ###############################################################################
13546 #
13547 #
13548 void
13549 Read(ref,...)
13550   Image::Magick ref=NO_INIT
13551   ALIAS:
13552     ReadImage  = 1
13553     read       = 2
13554     readimage  = 3
13555   PPCODE:
13556   {
13557     AV
13558       *av;
13559
13560     char
13561       **keep,
13562       **list;
13563
13564     ExceptionInfo
13565       *exception;
13566
13567     HV
13568       *hv;
13569
13570     Image
13571       *image;
13572
13573     int
13574       n;
13575
13576     MagickBooleanType
13577       status;
13578
13579     register char
13580       **p;
13581
13582     register ssize_t
13583       i;
13584
13585     ssize_t
13586       ac,
13587       number_images;
13588
13589     STRLEN
13590       *length;
13591
13592     struct PackageInfo
13593       *info,
13594       *package_info;
13595
13596     SV
13597       *perl_exception,  /* Perl variable for storing messages */
13598       *reference,
13599       *rv,
13600       *sv;
13601
13602     PERL_UNUSED_VAR(ref);
13603     PERL_UNUSED_VAR(ix);
13604     exception=AcquireExceptionInfo();
13605     perl_exception=newSVpv("",0);
13606     sv=NULL;
13607     package_info=(struct PackageInfo *) NULL;
13608     number_images=0;
13609     ac=(items < 2) ? 1 : items-1;
13610     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
13611     keep=list;
13612     length=(STRLEN *) NULL;
13613     if (list == (char **) NULL)
13614       {
13615         ThrowPerlException(exception,ResourceLimitError,
13616           "MemoryAllocationFailed",PackageName);
13617         goto PerlException;
13618       }
13619     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
13620     if (length == (STRLEN *) NULL)
13621       {
13622         ThrowPerlException(exception,ResourceLimitError,
13623           "MemoryAllocationFailed",PackageName);
13624         goto PerlException;
13625       }
13626     if (sv_isobject(ST(0)) == 0)
13627       {
13628         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13629           PackageName);
13630         goto PerlException;
13631       }
13632     reference=SvRV(ST(0));
13633     hv=SvSTASH(reference);
13634     if (SvTYPE(reference) != SVt_PVAV)
13635       {
13636         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13637           PackageName);
13638         goto PerlException;
13639       }
13640     av=(AV *) reference;
13641     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13642       exception);
13643     package_info=ClonePackageInfo(info,exception);
13644     n=1;
13645     if (items <= 1)
13646       *list=(char *) (*package_info->image_info->filename ?
13647         package_info->image_info->filename : "XC:black");
13648     else
13649       for (n=0, i=0; i < ac; i++)
13650       {
13651         list[n]=(char *) SvPV(ST(i+1),length[n]);
13652         if ((items >= 3) && strEQcase(list[n],"blob"))
13653           {
13654             void
13655               *blob;
13656
13657             i++;
13658             blob=(void *) (SvPV(ST(i+1),length[n]));
13659             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13660           }
13661         if ((items >= 3) && strEQcase(list[n],"filename"))
13662           continue;
13663         if ((items >= 3) && strEQcase(list[n],"file"))
13664           {
13665             FILE
13666               *file;
13667
13668             PerlIO
13669               *io_info;
13670
13671             i++;
13672             io_info=IoIFP(sv_2io(ST(i+1)));
13673             if (io_info == (PerlIO *) NULL)
13674               {
13675                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13676                   PackageName);
13677                 continue;
13678               }
13679             file=PerlIO_findFILE(io_info);
13680             if (file == (FILE *) NULL)
13681               {
13682                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13683                   PackageName);
13684                 continue;
13685               }
13686             SetImageInfoFile(package_info->image_info,file);
13687           }
13688         if ((items >= 3) && strEQcase(list[n],"magick"))
13689           continue;
13690         n++;
13691       }
13692     list[n]=(char *) NULL;
13693     keep=list;
13694     status=ExpandFilenames(&n,&list);
13695     if (status == MagickFalse)
13696       {
13697         ThrowPerlException(exception,ResourceLimitError,
13698           "MemoryAllocationFailed",PackageName);
13699         goto PerlException;
13700       }
13701     number_images=0;
13702     for (i=0; i < n; i++)
13703     {
13704       if ((package_info->image_info->file == (FILE *) NULL) &&
13705           (package_info->image_info->blob == (void *) NULL))
13706         image=ReadImages(package_info->image_info,list[i],exception);
13707       else
13708         {
13709           image=ReadImages(package_info->image_info,
13710             package_info->image_info->filename,exception);
13711           if (image != (Image *) NULL)
13712             DisassociateImageStream(image);
13713         }
13714       if (image == (Image *) NULL)
13715         break;
13716       for ( ; image; image=image->next)
13717       {
13718         AddImageToRegistry(sv,image);
13719         rv=newRV(sv);
13720         av_push(av,sv_bless(rv,hv));
13721         SvREFCNT_dec(sv);
13722         number_images++;
13723       }
13724     }
13725     /*
13726       Free resources.
13727     */
13728     for (i=0; i < n; i++)
13729       if (list[i] != (char *) NULL)
13730         for (p=keep; list[i] != *p++; )
13731           if (*p == (char *) NULL)
13732             {
13733               list[i]=(char *) RelinquishMagickMemory(list[i]);
13734               break;
13735             }
13736
13737   PerlException:
13738     if (package_info != (struct PackageInfo *) NULL)
13739       DestroyPackageInfo(package_info);
13740     if (list && (list != keep))
13741       list=(char **) RelinquishMagickMemory(list);
13742     if (keep)
13743       keep=(char **) RelinquishMagickMemory(keep);
13744     if (length)
13745       length=(STRLEN *) RelinquishMagickMemory(length);
13746     InheritPerlException(exception,perl_exception);
13747     exception=DestroyExceptionInfo(exception);
13748     sv_setiv(perl_exception,(IV) number_images);
13749     SvPOK_on(perl_exception);
13750     ST(0)=sv_2mortal(perl_exception);
13751     XSRETURN(1);
13752   }
13753 \f
13754 #
13755 ###############################################################################
13756 #                                                                             #
13757 #                                                                             #
13758 #                                                                             #
13759 #   R e m o t e                                                               #
13760 #                                                                             #
13761 #                                                                             #
13762 #                                                                             #
13763 ###############################################################################
13764 #
13765 #
13766 void
13767 Remote(ref,...)
13768   Image::Magick ref=NO_INIT
13769   ALIAS:
13770     RemoteCommand  = 1
13771     remote         = 2
13772     remoteCommand  = 3
13773   PPCODE:
13774   {
13775     AV
13776       *av;
13777
13778     ExceptionInfo
13779       *exception;
13780
13781     register ssize_t
13782       i;
13783
13784     SV
13785       *perl_exception,
13786       *reference;
13787
13788     struct PackageInfo
13789       *info;
13790
13791     PERL_UNUSED_VAR(ref);
13792     PERL_UNUSED_VAR(ix);
13793     exception=AcquireExceptionInfo();
13794     perl_exception=newSVpv("",0);
13795     reference=SvRV(ST(0));
13796     av=(AV *) reference;
13797     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13798       exception);
13799     for (i=1; i < items; i++)
13800       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13801         SvPV(ST(i),na),exception);
13802     InheritPerlException(exception,perl_exception);
13803     exception=DestroyExceptionInfo(exception);
13804     SvREFCNT_dec(perl_exception);    /* throw away all errors */
13805   }
13806 \f
13807 #
13808 ###############################################################################
13809 #                                                                             #
13810 #                                                                             #
13811 #                                                                             #
13812 #   S e t                                                                     #
13813 #                                                                             #
13814 #                                                                             #
13815 #                                                                             #
13816 ###############################################################################
13817 #
13818 #
13819 void
13820 Set(ref,...)
13821   Image::Magick ref=NO_INIT
13822   ALIAS:
13823     SetAttributes  = 1
13824     SetAttribute   = 2
13825     set            = 3
13826     setattributes  = 4
13827     setattribute   = 5
13828   PPCODE:
13829   {
13830     ExceptionInfo
13831       *exception;
13832
13833     Image
13834       *image;
13835
13836     register ssize_t
13837       i;
13838
13839     struct PackageInfo
13840       *info;
13841
13842     SV
13843       *perl_exception,
13844       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13845
13846     PERL_UNUSED_VAR(ref);
13847     PERL_UNUSED_VAR(ix);
13848     exception=AcquireExceptionInfo();
13849     perl_exception=newSVpv("",0);
13850     if (sv_isobject(ST(0)) == 0)
13851       {
13852         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13853           PackageName);
13854         goto PerlException;
13855       }
13856     reference=SvRV(ST(0));
13857     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13858     if (items == 2)
13859       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13860     else
13861       for (i=2; i < items; i+=2)
13862         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13863
13864   PerlException:
13865     InheritPerlException(exception,perl_exception);
13866     exception=DestroyExceptionInfo(exception);
13867     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13868     SvPOK_on(perl_exception);
13869     ST(0)=sv_2mortal(perl_exception);
13870     XSRETURN(1);
13871   }
13872 \f
13873 #
13874 ###############################################################################
13875 #                                                                             #
13876 #                                                                             #
13877 #                                                                             #
13878 #   S e t P i x e l                                                           #
13879 #                                                                             #
13880 #                                                                             #
13881 #                                                                             #
13882 ###############################################################################
13883 #
13884 #
13885 void
13886 SetPixel(ref,...)
13887   Image::Magick ref=NO_INIT
13888   ALIAS:
13889     setpixel = 1
13890     setPixel = 2
13891   PPCODE:
13892   {
13893     AV
13894       *av;
13895
13896     char
13897       *attribute;
13898
13899     ChannelType
13900       channel,
13901       channel_mask;
13902
13903     ExceptionInfo
13904       *exception;
13905
13906     Image
13907       *image;
13908
13909     MagickBooleanType
13910       normalize;
13911
13912     RectangleInfo
13913       region;
13914
13915     register ssize_t
13916       i;
13917
13918     register Quantum
13919       *q;
13920
13921     ssize_t
13922       option;
13923
13924     struct PackageInfo
13925       *info;
13926
13927     SV
13928       *perl_exception,
13929       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13930
13931     PERL_UNUSED_VAR(ref);
13932     PERL_UNUSED_VAR(ix);
13933     exception=AcquireExceptionInfo();
13934     perl_exception=newSVpv("",0);
13935     reference=SvRV(ST(0));
13936     av=(AV *) reference;
13937     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13938       exception);
13939     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13940     if (image == (Image *) NULL)
13941       {
13942         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13943           PackageName);
13944         goto PerlException;
13945       }
13946     av=(AV *) NULL;
13947     normalize=MagickTrue;
13948     region.x=0;
13949     region.y=0;
13950     region.width=image->columns;
13951     region.height=1;
13952     if (items == 1)
13953       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13954     channel=DefaultChannels;
13955     for (i=2; i < items; i+=2)
13956     {
13957       attribute=(char *) SvPV(ST(i-1),na);
13958       switch (*attribute)
13959       {
13960         case 'C':
13961         case 'c':
13962         {
13963           if (LocaleCompare(attribute,"channel") == 0)
13964             {
13965               ssize_t
13966                 option;
13967
13968               option=ParseChannelOption(SvPV(ST(i),na));
13969               if (option < 0)
13970                 {
13971                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13972                     SvPV(ST(i),na));
13973                   return;
13974                 }
13975               channel=(ChannelType) option;
13976               break;
13977             }
13978           if (LocaleCompare(attribute,"color") == 0)
13979             {
13980               if (SvTYPE(ST(i)) != SVt_RV)
13981                 {
13982                   char
13983                     message[MagickPathExtent];
13984
13985                   (void) FormatLocaleString(message,MagickPathExtent,
13986                     "invalid %.60s value",attribute);
13987                   ThrowPerlException(exception,OptionError,message,
13988                     SvPV(ST(i),na));
13989                 }
13990               av=(AV *) SvRV(ST(i));
13991               break;
13992             }
13993           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13994             attribute);
13995           break;
13996         }
13997         case 'g':
13998         case 'G':
13999         {
14000           if (LocaleCompare(attribute,"geometry") == 0)
14001             {
14002               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
14003               break;
14004             }
14005           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14006             attribute);
14007           break;
14008         }
14009         case 'N':
14010         case 'n':
14011         {
14012           if (LocaleCompare(attribute,"normalize") == 0)
14013             {
14014               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14015                 SvPV(ST(i),na));
14016               if (option < 0)
14017                 {
14018                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
14019                     SvPV(ST(i),na));
14020                   break;
14021                 }
14022              normalize=option != 0 ? MagickTrue : MagickFalse;
14023              break;
14024             }
14025           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14026             attribute);
14027           break;
14028         }
14029         case 'x':
14030         case 'X':
14031         {
14032           if (LocaleCompare(attribute,"x") == 0)
14033             {
14034               region.x=SvIV(ST(i));
14035               break;
14036             }
14037           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14038             attribute);
14039           break;
14040         }
14041         case 'y':
14042         case 'Y':
14043         {
14044           if (LocaleCompare(attribute,"y") == 0)
14045             {
14046               region.y=SvIV(ST(i));
14047               break;
14048             }
14049           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14050             attribute);
14051           break;
14052         }
14053         default:
14054         {
14055           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14056             attribute);
14057           break;
14058         }
14059       }
14060     }
14061     (void) SetImageStorageClass(image,DirectClass,exception);
14062     channel_mask=SetImageChannelMask(image,channel);
14063     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
14064     if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
14065         (SvTYPE(av) != SVt_PVAV))
14066       PUSHs(&sv_undef);
14067     else
14068       {
14069         double
14070           scale;
14071
14072         register ssize_t
14073           i;
14074
14075         i=0;
14076         scale=1.0;
14077         if (normalize != MagickFalse)
14078           scale=QuantumRange;
14079         if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
14080             (i <= av_len(av)))
14081           {
14082             SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
14083               av_fetch(av,i,0)))),q);
14084             i++;
14085           }
14086         if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
14087             (i <= av_len(av)))
14088           {
14089             SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
14090               av_fetch(av,i,0)))),q);
14091             i++;
14092           }
14093         if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
14094             (i <= av_len(av)))
14095           {
14096             SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
14097               av_fetch(av,i,0)))),q);
14098             i++;
14099           }
14100         if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
14101             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
14102           {
14103             SetPixelBlack(image,ClampToQuantum(scale*
14104               SvNV(*(av_fetch(av,i,0)))),q);
14105             i++;
14106           }
14107         if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
14108             (i <= av_len(av)))
14109           {
14110             SetPixelAlpha(image,ClampToQuantum(scale*
14111               SvNV(*(av_fetch(av,i,0)))),q);
14112             i++;
14113           }
14114         (void) SyncAuthenticPixels(image,exception);
14115       }
14116     (void) SetImageChannelMask(image,channel_mask);
14117
14118   PerlException:
14119     InheritPerlException(exception,perl_exception);
14120     exception=DestroyExceptionInfo(exception);
14121     SvREFCNT_dec(perl_exception);
14122   }
14123 \f
14124 #
14125 ###############################################################################
14126 #                                                                             #
14127 #                                                                             #
14128 #                                                                             #
14129 #   S m u s h                                                                 #
14130 #                                                                             #
14131 #                                                                             #
14132 #                                                                             #
14133 ###############################################################################
14134 #
14135 #
14136 void
14137 Smush(ref,...)
14138   Image::Magick ref=NO_INIT
14139   ALIAS:
14140     SmushImage  = 1
14141     smush       = 2
14142     smushimage  = 3
14143   PPCODE:
14144   {
14145     AV
14146       *av;
14147
14148     char
14149       *attribute;
14150
14151     ExceptionInfo
14152       *exception;
14153
14154     HV
14155       *hv;
14156
14157     Image
14158       *image;
14159
14160     register ssize_t
14161       i;
14162
14163     ssize_t
14164       offset,
14165       stack;
14166
14167     struct PackageInfo
14168       *info;
14169
14170     SV
14171       *av_reference,
14172       *perl_exception,
14173       *reference,
14174       *rv,
14175       *sv;
14176
14177     PERL_UNUSED_VAR(ref);
14178     PERL_UNUSED_VAR(ix);
14179     exception=AcquireExceptionInfo();
14180     perl_exception=newSVpv("",0);
14181     sv=NULL;
14182     attribute=NULL;
14183     av=NULL;
14184     if (sv_isobject(ST(0)) == 0)
14185       {
14186         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14187           PackageName);
14188         goto PerlException;
14189       }
14190     reference=SvRV(ST(0));
14191     hv=SvSTASH(reference);
14192     av=newAV();
14193     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14194     SvREFCNT_dec(av);
14195     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14196     if (image == (Image *) NULL)
14197       {
14198         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14199           PackageName);
14200         goto PerlException;
14201       }
14202     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14203     /*
14204       Get options.
14205     */
14206     offset=0;
14207     stack=MagickTrue;
14208     for (i=2; i < items; i+=2)
14209     {
14210       attribute=(char *) SvPV(ST(i-1),na);
14211       switch (*attribute)
14212       {
14213         case 'O':
14214         case 'o':
14215         {
14216           if (LocaleCompare(attribute,"offset") == 0)
14217             {
14218               offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
14219               break;
14220             }
14221           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14222             attribute);
14223           break;
14224         }
14225         case 'S':
14226         case 's':
14227         {
14228           if (LocaleCompare(attribute,"stack") == 0)
14229             {
14230               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14231                 SvPV(ST(i),na));
14232               if (stack < 0)
14233                 {
14234                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
14235                     SvPV(ST(i),na));
14236                   return;
14237                 }
14238               break;
14239             }
14240           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14241             attribute);
14242           break;
14243         }
14244         default:
14245         {
14246           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14247             attribute);
14248           break;
14249         }
14250       }
14251     }
14252     image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
14253       exception);
14254     if (image == (Image *) NULL)
14255       goto PerlException;
14256     for ( ; image; image=image->next)
14257     {
14258       AddImageToRegistry(sv,image);
14259       rv=newRV(sv);
14260       av_push(av,sv_bless(rv,hv));
14261       SvREFCNT_dec(sv);
14262     }
14263     exception=DestroyExceptionInfo(exception);
14264     ST(0)=av_reference;
14265     SvREFCNT_dec(perl_exception);
14266     XSRETURN(1);
14267
14268   PerlException:
14269     InheritPerlException(exception,perl_exception);
14270     exception=DestroyExceptionInfo(exception);
14271     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14272     SvPOK_on(perl_exception);
14273     ST(0)=sv_2mortal(perl_exception);
14274     XSRETURN(1);
14275   }
14276 \f
14277 #
14278 ###############################################################################
14279 #                                                                             #
14280 #                                                                             #
14281 #                                                                             #
14282 #   S t a t i s t i c s                                                       #
14283 #                                                                             #
14284 #                                                                             #
14285 #                                                                             #
14286 ###############################################################################
14287 #
14288 #
14289 void
14290 Statistics(ref,...)
14291   Image::Magick ref=NO_INIT
14292   ALIAS:
14293     StatisticsImage = 1
14294     statistics      = 2
14295     statisticsimage = 3
14296   PPCODE:
14297   {
14298 #define ChannelStatistics(channel) \
14299 { \
14300   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14301     (double) channel_statistics[channel].depth); \
14302   PUSHs(sv_2mortal(newSVpv(message,0))); \
14303   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14304     channel_statistics[channel].minima/scale); \
14305   PUSHs(sv_2mortal(newSVpv(message,0))); \
14306   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14307     channel_statistics[channel].maxima/scale); \
14308   PUSHs(sv_2mortal(newSVpv(message,0))); \
14309   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14310     channel_statistics[channel].mean/scale); \
14311   PUSHs(sv_2mortal(newSVpv(message,0))); \
14312   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14313     channel_statistics[channel].standard_deviation/scale); \
14314   PUSHs(sv_2mortal(newSVpv(message,0))); \
14315   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14316     channel_statistics[channel].kurtosis); \
14317   PUSHs(sv_2mortal(newSVpv(message,0))); \
14318   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14319     channel_statistics[channel].skewness); \
14320   PUSHs(sv_2mortal(newSVpv(message,0))); \
14321   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14322     channel_statistics[channel].entropy); \
14323   PUSHs(sv_2mortal(newSVpv(message,0))); \
14324 }
14325
14326     AV
14327       *av;
14328
14329     char
14330       message[MagickPathExtent];
14331
14332     ChannelStatistics
14333       *channel_statistics;
14334
14335     double
14336       scale;
14337
14338     ExceptionInfo
14339       *exception;
14340
14341     Image
14342       *image;
14343
14344     ssize_t
14345       count;
14346
14347     struct PackageInfo
14348       *info;
14349
14350     SV
14351       *perl_exception,
14352       *reference;
14353
14354     PERL_UNUSED_VAR(ref);
14355     PERL_UNUSED_VAR(ix);
14356     exception=AcquireExceptionInfo();
14357     perl_exception=newSVpv("",0);
14358     av=NULL;
14359     if (sv_isobject(ST(0)) == 0)
14360       {
14361         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14362           PackageName);
14363         goto PerlException;
14364       }
14365     reference=SvRV(ST(0));
14366     av=newAV();
14367     SvREFCNT_dec(av);
14368     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14369     if (image == (Image *) NULL)
14370       {
14371         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14372           PackageName);
14373         goto PerlException;
14374       }
14375     count=0;
14376     for ( ; image; image=image->next)
14377     {
14378       channel_statistics=GetImageStatistics(image,exception);
14379       if (channel_statistics == (ChannelStatistics *) NULL)
14380         continue;
14381       count++;
14382       EXTEND(sp,35*count);
14383       scale=(double) QuantumRange;
14384       ChannelStatistics(RedChannel);
14385       ChannelStatistics(GreenChannel);
14386       ChannelStatistics(BlueChannel);
14387       if (image->colorspace == CMYKColorspace)
14388         ChannelStatistics(BlackChannel);
14389       if (image->alpha_trait != UndefinedPixelTrait)
14390         ChannelStatistics(AlphaChannel);
14391       channel_statistics=(ChannelStatistics *)
14392         RelinquishMagickMemory(channel_statistics);
14393     }
14394
14395   PerlException:
14396     InheritPerlException(exception,perl_exception);
14397     exception=DestroyExceptionInfo(exception);
14398     SvREFCNT_dec(perl_exception);
14399   }
14400 \f
14401 #
14402 ###############################################################################
14403 #                                                                             #
14404 #                                                                             #
14405 #                                                                             #
14406 #   S y n c A u t h e n t i c P i x e l s                                     #
14407 #                                                                             #
14408 #                                                                             #
14409 #                                                                             #
14410 ###############################################################################
14411 #
14412 #
14413 void
14414 SyncAuthenticPixels(ref,...)
14415   Image::Magick ref = NO_INIT
14416   ALIAS:
14417     Syncauthenticpixels = 1
14418     SyncImagePixels = 2
14419     syncimagepixels = 3
14420   CODE:
14421   {
14422     ExceptionInfo
14423       *exception;
14424
14425     Image
14426       *image;
14427
14428     MagickBooleanType
14429       status;
14430
14431     struct PackageInfo
14432       *info;
14433
14434     SV
14435       *perl_exception,
14436       *reference;
14437
14438     PERL_UNUSED_VAR(ref);
14439     PERL_UNUSED_VAR(ix);
14440     exception=AcquireExceptionInfo();
14441     perl_exception=newSVpv("",0);
14442     if (sv_isobject(ST(0)) == 0)
14443       {
14444         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14445           PackageName);
14446         goto PerlException;
14447       }
14448
14449     reference=SvRV(ST(0));
14450     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14451     if (image == (Image *) NULL)
14452       {
14453         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14454           PackageName);
14455         goto PerlException;
14456       }
14457
14458     status=SyncAuthenticPixels(image,exception);
14459     if (status != MagickFalse)
14460       return;
14461
14462   PerlException:
14463     InheritPerlException(exception,perl_exception);
14464     exception=DestroyExceptionInfo(exception);
14465     SvREFCNT_dec(perl_exception);  /* throw away all errors */
14466   }
14467 \f
14468 #
14469 ###############################################################################
14470 #                                                                             #
14471 #                                                                             #
14472 #                                                                             #
14473 #   W r i t e                                                                 #
14474 #                                                                             #
14475 #                                                                             #
14476 #                                                                             #
14477 ###############################################################################
14478 #
14479 #
14480 void
14481 Write(ref,...)
14482   Image::Magick ref=NO_INIT
14483   ALIAS:
14484     WriteImage    = 1
14485     write         = 2
14486     writeimage    = 3
14487   PPCODE:
14488   {
14489     char
14490       filename[MagickPathExtent];
14491
14492     ExceptionInfo
14493       *exception;
14494
14495     Image
14496       *image,
14497       *next;
14498
14499     register ssize_t
14500       i;
14501
14502     ssize_t
14503       number_images,
14504       scene;
14505
14506     struct PackageInfo
14507       *info,
14508       *package_info;
14509
14510     SV
14511       *perl_exception,
14512       *reference;
14513
14514     PERL_UNUSED_VAR(ref);
14515     PERL_UNUSED_VAR(ix);
14516     exception=AcquireExceptionInfo();
14517     perl_exception=newSVpv("",0);
14518     number_images=0;
14519     package_info=(struct PackageInfo *) NULL;
14520     if (sv_isobject(ST(0)) == 0)
14521       {
14522         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14523           PackageName);
14524         goto PerlException;
14525       }
14526     reference=SvRV(ST(0));
14527     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14528     if (image == (Image *) NULL)
14529       {
14530         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14531           PackageName);
14532         goto PerlException;
14533       }
14534     package_info=ClonePackageInfo(info,exception);
14535     if (items == 2)
14536       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14537     else
14538       if (items > 2)
14539         for (i=2; i < items; i+=2)
14540           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14541             exception);
14542     (void) CopyMagickString(filename,package_info->image_info->filename,
14543       MagickPathExtent);
14544     scene=0;
14545     for (next=image; next; next=next->next)
14546     {
14547       (void) CopyMagickString(next->filename,filename,MagickPathExtent);
14548       next->scene=scene++;
14549     }
14550     *package_info->image_info->magick='\0';
14551     SetImageInfo(package_info->image_info,(unsigned int)
14552       GetImageListLength(image),exception);
14553     for (next=image; next; next=next->next)
14554     {
14555       (void) WriteImage(package_info->image_info,next,exception);
14556       number_images++;
14557       if (package_info->image_info->adjoin)
14558         break;
14559     }
14560
14561   PerlException:
14562     if (package_info != (struct PackageInfo *) NULL)
14563       DestroyPackageInfo(package_info);
14564     InheritPerlException(exception,perl_exception);
14565     exception=DestroyExceptionInfo(exception);
14566     sv_setiv(perl_exception,(IV) number_images);
14567     SvPOK_on(perl_exception);
14568     ST(0)=sv_2mortal(perl_exception);
14569     XSRETURN(1);
14570   }