]> granicus.if.org Git - imagemagick/blob - PerlMagick/Magick.xs
Remove ColorImage() method from PerlMagick
[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-2016 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     { "Sans", { {"matrix", ArrayReference} } },
535     { "Color", { {"color", StringReference} } },
536     { "Mode", { {"geometry", StringReference},
537       {"width", IntegerReference},{"height", IntegerReference},
538       {"channel", MagickChannelOptions} } },
539     { "Statistic", { {"geometry", StringReference},
540       {"width", IntegerReference},{"height", IntegerReference},
541       {"channel", MagickChannelOptions}, {"type", MagickStatisticOptions} } },
542     { "Perceptible", { {"epsilon", RealReference},
543       {"channel", MagickChannelOptions} } },
544     { "Poly", { {"terms", ArrayReference},
545       {"channel", MagickChannelOptions} } },
546     { "Grayscale", { {"method", MagickNoiseOptions} } },
547     { "CannyEdge", { {"geometry", StringReference},
548       {"radius", RealReference}, {"sigma", RealReference},
549       {"lower-percent", RealReference}, {"upper-percent", RealReference} } },
550     { "HoughLine", { {"geometry", StringReference},
551       {"width", IntegerReference}, {"height", IntegerReference},
552       {"threshold", IntegerReference} } },
553     { "MeanShift", { {"geometry", StringReference},
554       {"width", IntegerReference}, {"height", IntegerReference},
555       {"distance", RealReference} } },
556     { "Kuwahara", { {"geometry", StringReference}, {"radius", RealReference},
557       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
558     { "ConnectedComponents", { {"connectivity", IntegerReference} } },
559     { "CopyPixels", { {"image", ImageReference}, {"geometry", StringReference},
560       {"width", IntegerReference}, {"height", IntegerReference},
561       {"x", IntegerReference}, {"y", IntegerReference},
562       {"gravity", MagickGravityOptions}, {"offset", StringReference}, 
563       {"dx", IntegerReference}, {"dy", IntegerReference} } },
564   };
565
566 static SplayTreeInfo
567   *magick_registry = (SplayTreeInfo *) NULL;
568 \f
569 /*
570   Forward declarations.
571 */
572 static Image
573   *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
574
575 static ssize_t
576   strEQcase(const char *,const char *);
577 \f
578 /*
579 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
580 %                                                                             %
581 %                                                                             %
582 %                                                                             %
583 %   C l o n e P a c k a g e I n f o                                           %
584 %                                                                             %
585 %                                                                             %
586 %                                                                             %
587 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
588 %
589 %  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
590 %  a new one.
591 %
592 %  The format of the ClonePackageInfo routine is:
593 %
594 %      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
595 %        exception)
596 %
597 %  A description of each parameter follows:
598 %
599 %    o info: a structure of type info.
600 %
601 %    o exception: Return any errors or warnings in this structure.
602 %
603 */
604 static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
605   ExceptionInfo *exception)
606 {
607   struct PackageInfo
608     *clone_info;
609
610   clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
611   if (clone_info == (struct PackageInfo *) NULL)
612     {
613       ThrowPerlException(exception,ResourceLimitError,
614         "UnableToClonePackageInfo",PackageName);
615       return((struct PackageInfo *) NULL);
616     }
617   if (info == (struct PackageInfo *) NULL)
618     {
619       clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
620       return(clone_info);
621     }
622   *clone_info=(*info);
623   clone_info->image_info=CloneImageInfo(info->image_info);
624   return(clone_info);
625 }
626 \f
627 /*
628 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
629 %                                                                             %
630 %                                                                             %
631 %                                                                             %
632 %   c o n s t a n t                                                           %
633 %                                                                             %
634 %                                                                             %
635 %                                                                             %
636 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
637 %
638 %  constant() returns a double value for the specified name.
639 %
640 %  The format of the constant routine is:
641 %
642 %      double constant(char *name,ssize_t sans)
643 %
644 %  A description of each parameter follows:
645 %
646 %    o value: Method constant returns a double value for the specified name.
647 %
648 %    o name: The name of the constant.
649 %
650 %    o sans: This integer value is not used.
651 %
652 */
653 static double constant(char *name,ssize_t sans)
654 {
655   (void) sans;
656   errno=0;
657   switch (*name)
658   {
659     case 'B':
660     {
661       if (strEQ(name,"BlobError"))
662         return(BlobError);
663       if (strEQ(name,"BlobWarning"))
664         return(BlobWarning);
665       break;
666     }
667     case 'C':
668     {
669       if (strEQ(name,"CacheError"))
670         return(CacheError);
671       if (strEQ(name,"CacheWarning"))
672         return(CacheWarning);
673       if (strEQ(name,"CoderError"))
674         return(CoderError);
675       if (strEQ(name,"CoderWarning"))
676         return(CoderWarning);
677       if (strEQ(name,"ConfigureError"))
678         return(ConfigureError);
679       if (strEQ(name,"ConfigureWarning"))
680         return(ConfigureWarning);
681       if (strEQ(name,"CorruptImageError"))
682         return(CorruptImageError);
683       if (strEQ(name,"CorruptImageWarning"))
684         return(CorruptImageWarning);
685       break;
686     }
687     case 'D':
688     {
689       if (strEQ(name,"DelegateError"))
690         return(DelegateError);
691       if (strEQ(name,"DelegateWarning"))
692         return(DelegateWarning);
693       if (strEQ(name,"DrawError"))
694         return(DrawError);
695       if (strEQ(name,"DrawWarning"))
696         return(DrawWarning);
697       break;
698     }
699     case 'E':
700     {
701       if (strEQ(name,"ErrorException"))
702         return(ErrorException);
703       if (strEQ(name,"ExceptionError"))
704         return(CoderError);
705       if (strEQ(name,"ExceptionWarning"))
706         return(CoderWarning);
707       break;
708     }
709     case 'F':
710     {
711       if (strEQ(name,"FatalErrorException"))
712         return(FatalErrorException);
713       if (strEQ(name,"FileOpenError"))
714         return(FileOpenError);
715       if (strEQ(name,"FileOpenWarning"))
716         return(FileOpenWarning);
717       break;
718     }
719     case 'I':
720     {
721       if (strEQ(name,"ImageError"))
722         return(ImageError);
723       if (strEQ(name,"ImageWarning"))
724         return(ImageWarning);
725       break;
726     }
727     case 'M':
728     {
729       if (strEQ(name,"MaxRGB"))
730         return(QuantumRange);
731       if (strEQ(name,"MissingDelegateError"))
732         return(MissingDelegateError);
733       if (strEQ(name,"MissingDelegateWarning"))
734         return(MissingDelegateWarning);
735       if (strEQ(name,"ModuleError"))
736         return(ModuleError);
737       if (strEQ(name,"ModuleWarning"))
738         return(ModuleWarning);
739       break;
740     }
741     case 'O':
742     {
743       if (strEQ(name,"Opaque"))
744         return(OpaqueAlpha);
745       if (strEQ(name,"OptionError"))
746         return(OptionError);
747       if (strEQ(name,"OptionWarning"))
748         return(OptionWarning);
749       break;
750     }
751     case 'Q':
752     {
753       if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
754         return(MAGICKCORE_QUANTUM_DEPTH);
755       if (strEQ(name,"QuantumDepth"))
756         return(MAGICKCORE_QUANTUM_DEPTH);
757       if (strEQ(name,"QuantumRange"))
758         return(QuantumRange);
759       break;
760     }
761     case 'R':
762     {
763       if (strEQ(name,"ResourceLimitError"))
764         return(ResourceLimitError);
765       if (strEQ(name,"ResourceLimitWarning"))
766         return(ResourceLimitWarning);
767       if (strEQ(name,"RegistryError"))
768         return(RegistryError);
769       if (strEQ(name,"RegistryWarning"))
770         return(RegistryWarning);
771       break;
772     }
773     case 'S':
774     {
775       if (strEQ(name,"StreamError"))
776         return(StreamError);
777       if (strEQ(name,"StreamWarning"))
778         return(StreamWarning);
779       if (strEQ(name,"Success"))
780         return(0);
781       break;
782     }
783     case 'T':
784     {
785       if (strEQ(name,"Transparent"))
786         return(TransparentAlpha);
787       if (strEQ(name,"TypeError"))
788         return(TypeError);
789       if (strEQ(name,"TypeWarning"))
790         return(TypeWarning);
791       break;
792     }
793     case 'W':
794     {
795       if (strEQ(name,"WarningException"))
796         return(WarningException);
797       break;
798     }
799     case 'X':
800     {
801       if (strEQ(name,"XServerError"))
802         return(XServerError);
803       if (strEQ(name,"XServerWarning"))
804         return(XServerWarning);
805       break;
806     }
807   }
808   errno=EINVAL;
809   return(0);
810 }
811 \f
812 /*
813 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
814 %                                                                             %
815 %                                                                             %
816 %                                                                             %
817 %   D e s t r o y P a c k a g e I n f o                                       %
818 %                                                                             %
819 %                                                                             %
820 %                                                                             %
821 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
822 %
823 %  Method DestroyPackageInfo frees a previously created info structure.
824 %
825 %  The format of the DestroyPackageInfo routine is:
826 %
827 %      DestroyPackageInfo(struct PackageInfo *info)
828 %
829 %  A description of each parameter follows:
830 %
831 %    o info: a structure of type info.
832 %
833 */
834 static void DestroyPackageInfo(struct PackageInfo *info)
835 {
836   info->image_info=DestroyImageInfo(info->image_info);
837   info=(struct PackageInfo *) RelinquishMagickMemory(info);
838 }
839 \f
840 /*
841 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
842 %                                                                             %
843 %                                                                             %
844 %                                                                             %
845 %   G e t L i s t                                                             %
846 %                                                                             %
847 %                                                                             %
848 %                                                                             %
849 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
850 %
851 %  Method GetList is recursively called by SetupList to traverse the
852 %  Image__Magick reference.  If building an reference_vector (see SetupList),
853 %  *current is the current position in *reference_vector and *last is the final
854 %  entry in *reference_vector.
855 %
856 %  The format of the GetList routine is:
857 %
858 %      GetList(info)
859 %
860 %  A description of each parameter follows:
861 %
862 %    o info: a structure of type info.
863 %
864 */
865 static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
866   ssize_t *current,ssize_t *last,ExceptionInfo *exception)
867 {
868   Image
869     *image;
870
871   if (reference == (SV *) NULL)
872     return(NULL);
873   switch (SvTYPE(reference))
874   {
875     case SVt_PVAV:
876     {
877       AV
878         *av;
879
880       Image
881         *head,
882         *previous;
883
884       register ssize_t
885         i;
886
887       ssize_t
888         n;
889
890       /*
891         Array of images.
892       */
893       previous=(Image *) NULL;
894       head=(Image *) NULL;
895       av=(AV *) reference;
896       n=av_len(av);
897       for (i=0; i <= n; i++)
898       {
899         SV
900           **rv;
901
902         rv=av_fetch(av,i,0);
903         if (rv && *rv && sv_isobject(*rv))
904           {
905             image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
906               exception);
907             if (image == (Image *) NULL)
908               continue;
909             if (image == previous)
910               {
911                 image=CloneImage(image,0,0,MagickTrue,exception);
912                 if (image == (Image *) NULL)
913                   return(NULL);
914               }
915             image->previous=previous;
916             *(previous ? &previous->next : &head)=image;
917             for (previous=image; previous->next; previous=previous->next) ;
918           }
919       }
920       return(head);
921     }
922     case SVt_PVMG:
923     {
924       /*
925         Blessed scalar, one image.
926       */
927       image=INT2PTR(Image *,SvIV(reference));
928       if (image == (Image *) NULL)
929         return(NULL);
930       image->previous=(Image *) NULL;
931       image->next=(Image *) NULL;
932       if (reference_vector)
933         {
934           if (*current == *last)
935             {
936               *last+=256;
937               if (*reference_vector == (SV **) NULL)
938                 *reference_vector=(SV **) AcquireQuantumMemory(*last,
939                   sizeof(*reference_vector));
940               else
941                 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
942                   *last,sizeof(*reference_vector));
943             }
944           if (*reference_vector == (SV **) NULL)
945             {
946               ThrowPerlException(exception,ResourceLimitError,
947                 "MemoryAllocationFailed",PackageName);
948               return((Image *) NULL);
949             }
950           (*reference_vector)[*current]=reference;
951           (*reference_vector)[++(*current)]=NULL;
952         }
953       return(image);
954     }
955     default:
956       break;
957   }
958   (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
959     (double) SvTYPE(reference));
960   return((Image *) NULL);
961 }
962 \f
963 /*
964 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
965 %                                                                             %
966 %                                                                             %
967 %                                                                             %
968 %   G e t P a c k a g e I n f o                                               %
969 %                                                                             %
970 %                                                                             %
971 %                                                                             %
972 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
973 %
974 %  Method GetPackageInfo looks up or creates an info structure for the given
975 %  Image__Magick reference.  If it does create a new one, the information in
976 %  package_info is used to initialize it.
977 %
978 %  The format of the GetPackageInfo routine is:
979 %
980 %      struct PackageInfo *GetPackageInfo(void *reference,
981 %        struct PackageInfo *package_info,ExceptionInfo *exception)
982 %
983 %  A description of each parameter follows:
984 %
985 %    o info: a structure of type info.
986 %
987 %    o exception: Return any errors or warnings in this structure.
988 %
989 */
990 static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
991   struct PackageInfo *package_info,ExceptionInfo *exception)
992 {
993   char
994     message[MagickPathExtent];
995
996   struct PackageInfo
997     *clone_info;
998
999   SV
1000     *sv;
1001
1002   (void) FormatLocaleString(message,MagickPathExtent,"%s::package%s%p",
1003     PackageName,XS_VERSION,reference);
1004   sv=perl_get_sv(message,(TRUE | 0x02));
1005   if (sv == (SV *) NULL)
1006     {
1007       ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
1008         message);
1009       return(package_info);
1010     }
1011   if (SvREFCNT(sv) == 0)
1012     (void) SvREFCNT_inc(sv);
1013   if (SvIOKp(sv) && (clone_info=INT2PTR(struct PackageInfo *,SvIV(sv))))
1014     return(clone_info);
1015   clone_info=ClonePackageInfo(package_info,exception);
1016   sv_setiv(sv,PTR2IV(clone_info));
1017   return(clone_info);
1018 }
1019 \f
1020 /*
1021 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1022 %                                                                             %
1023 %                                                                             %
1024 %                                                                             %
1025 %   S e t A t t r i b u t e                                                   %
1026 %                                                                             %
1027 %                                                                             %
1028 %                                                                             %
1029 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1030 %
1031 %  SetAttribute() sets the attribute to the value in sval.  This can change
1032 %  either or both of image or info.
1033 %
1034 %  The format of the SetAttribute routine is:
1035 %
1036 %      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1037 %        SV *sval,ExceptionInfo *exception)
1038 %
1039 %  A description of each parameter follows:
1040 %
1041 %    o list: a list of strings.
1042 %
1043 %    o string: a character string.
1044 %
1045 */
1046
1047 static double SiPrefixToDoubleInterval(const char *string,const double interval)
1048 {
1049   char
1050     *q;
1051
1052   double
1053     value;
1054
1055   value=InterpretSiPrefixValue(string,&q);
1056   if (*q == '%')
1057     value*=interval/100.0;
1058   return(value);
1059 }
1060
1061 static inline double StringToDouble(const char *string,char **sentinal)
1062 {
1063   return(InterpretLocaleValue(string,sentinal));
1064 }
1065
1066 static double StringToDoubleInterval(const char *string,const double interval)
1067 {
1068   char
1069     *q;
1070
1071   double
1072     value;
1073
1074   value=InterpretLocaleValue(string,&q);
1075   if (*q == '%')
1076     value*=interval/100.0;
1077   return(value);
1078 }
1079
1080 static inline ssize_t StringToLong(const char *value)
1081 {
1082   return(strtol(value,(char **) NULL,10));
1083 }
1084
1085 static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1086   const char *attribute,SV *sval,ExceptionInfo *exception)
1087 {
1088   GeometryInfo
1089     geometry_info;
1090
1091   long
1092     x,
1093     y;
1094
1095   PixelInfo
1096     pixel;
1097
1098   MagickStatusType
1099     flags;
1100
1101   PixelInfo
1102     *color,
1103     target_color;
1104
1105   ssize_t
1106     sp;
1107
1108   switch (*attribute)
1109   {
1110     case 'A':
1111     case 'a':
1112     {
1113       if (LocaleCompare(attribute,"adjoin") == 0)
1114         {
1115           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1116             SvPV(sval,na)) : SvIV(sval);
1117           if (sp < 0)
1118             {
1119               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1120                 SvPV(sval,na));
1121               break;
1122             }
1123           if (info)
1124             info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1125           break;
1126         }
1127       if (LocaleCompare(attribute,"alpha") == 0)
1128         {
1129           sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaChannelOptions,
1130             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1131           if (sp < 0)
1132             {
1133               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1134                 SvPV(sval,na));
1135               break;
1136             }
1137           for ( ; image; image=image->next)
1138             (void) SetImageAlphaChannel(image,(AlphaChannelOption) sp,
1139               exception);
1140           break;
1141         }
1142       if (LocaleCompare(attribute,"antialias") == 0)
1143         {
1144           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1145             SvPV(sval,na)) : SvIV(sval);
1146           if (sp < 0)
1147             {
1148               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1149                 SvPV(sval,na));
1150               break;
1151             }
1152           if (info)
1153             info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1154           break;
1155         }
1156       if (LocaleCompare(attribute,"area-limit") == 0)
1157         {
1158           MagickSizeType
1159             limit;
1160
1161           limit=MagickResourceInfinity;
1162           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1163             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1164               100.0);
1165           (void) SetMagickResourceLimit(AreaResource,limit);
1166           break;
1167         }
1168       if (LocaleCompare(attribute,"attenuate") == 0)
1169         {
1170           if (info)
1171             (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1172           break;
1173         }
1174       if (LocaleCompare(attribute,"authenticate") == 0)
1175         {
1176           if (info)
1177             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1178           break;
1179         }
1180       if (info)
1181         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1182       for ( ; image; image=image->next)
1183         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1184       break;
1185     }
1186     case 'B':
1187     case 'b':
1188     {
1189       if (LocaleCompare(attribute,"background") == 0)
1190         {
1191           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1192             exception);
1193           if (info)
1194             info->image_info->background_color=target_color;
1195           for ( ; image; image=image->next)
1196             image->background_color=target_color;
1197           break;
1198         }
1199       if (LocaleCompare(attribute,"blue-primary") == 0)
1200         {
1201           for ( ; image; image=image->next)
1202           {
1203             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1204             image->chromaticity.blue_primary.x=geometry_info.rho;
1205             image->chromaticity.blue_primary.y=geometry_info.sigma;
1206             if ((flags & SigmaValue) == 0)
1207               image->chromaticity.blue_primary.y=
1208                 image->chromaticity.blue_primary.x;
1209           }
1210           break;
1211         }
1212       if (LocaleCompare(attribute,"bordercolor") == 0)
1213         {
1214           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1215             exception);
1216           if (info)
1217             info->image_info->border_color=target_color;
1218           for ( ; image; image=image->next)
1219             image->border_color=target_color;
1220           break;
1221         }
1222       if (info)
1223         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1224       for ( ; image; image=image->next)
1225         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1226       break;
1227     }
1228     case 'C':
1229     case 'c':
1230     {
1231       if (LocaleCompare(attribute,"cache-threshold") == 0)
1232         {
1233           (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1234             SiPrefixToDoubleInterval(SvPV(sval,na),100.0));
1235           (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1236             (2.0*SiPrefixToDoubleInterval(SvPV(sval,na),100.0)));
1237           break;
1238         }
1239       if (LocaleCompare(attribute,"clip-mask") == 0)
1240         {
1241           Image
1242             *clip_mask;
1243
1244           clip_mask=(Image *) NULL;
1245           if (SvPOK(sval))
1246             clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1247           for ( ; image; image=image->next)
1248             SetImageMask(image,ReadPixelMask,clip_mask,exception);
1249           break;
1250         }
1251       if (LocaleNCompare(attribute,"colormap",8) == 0)
1252         {
1253           for ( ; image; image=image->next)
1254           {
1255             int
1256               items;
1257
1258             long
1259               i;
1260
1261             if (image->storage_class == DirectClass)
1262               continue;
1263             i=0;
1264             items=sscanf(attribute,"%*[^[][%ld",&i);
1265             (void) items;
1266             if (i > (ssize_t) image->colors)
1267               i%=image->colors;
1268             if ((strchr(SvPV(sval,na),',') == 0) ||
1269                 (strchr(SvPV(sval,na),')') != 0))
1270               QueryColorCompliance(SvPV(sval,na),AllCompliance,
1271                 image->colormap+i,exception);
1272             else
1273               {
1274                 color=image->colormap+i;
1275                 pixel.red=color->red;
1276                 pixel.green=color->green;
1277                 pixel.blue=color->blue;
1278                 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1279                 pixel.red=geometry_info.rho;
1280                 pixel.green=geometry_info.sigma;
1281                 pixel.blue=geometry_info.xi;
1282                 color->red=ClampToQuantum(pixel.red);
1283                 color->green=ClampToQuantum(pixel.green);
1284                 color->blue=ClampToQuantum(pixel.blue);
1285               }
1286           }
1287           break;
1288         }
1289       if (LocaleCompare(attribute,"colorspace") == 0)
1290         {
1291           sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1292             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1293           if (sp < 0)
1294             {
1295               ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1296                 SvPV(sval,na));
1297               break;
1298             }
1299           for ( ; image; image=image->next)
1300             (void) TransformImageColorspace(image,(ColorspaceType) sp,
1301               exception);
1302           break;
1303         }
1304       if (LocaleCompare(attribute,"comment") == 0)
1305         {
1306           for ( ; image; image=image->next)
1307             (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1308               info ? info->image_info : (ImageInfo *) NULL,image,
1309               SvPV(sval,na),exception),exception);
1310           break;
1311         }
1312       if (LocaleCompare(attribute,"compression") == 0)
1313         {
1314           sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1315             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1316           if (sp < 0)
1317             {
1318               ThrowPerlException(exception,OptionError,
1319                 "UnrecognizedImageCompression",SvPV(sval,na));
1320               break;
1321             }
1322           if (info)
1323             info->image_info->compression=(CompressionType) sp;
1324           for ( ; image; image=image->next)
1325             image->compression=(CompressionType) sp;
1326           break;
1327         }
1328       if (info)
1329         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1330       for ( ; image; image=image->next)
1331         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1332       break;
1333     }
1334     case 'D':
1335     case 'd':
1336     {
1337       if (LocaleCompare(attribute,"debug") == 0)
1338         {
1339           SetLogEventMask(SvPV(sval,na));
1340           break;
1341         }
1342       if (LocaleCompare(attribute,"delay") == 0)
1343         {
1344           flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1345           for ( ; image; image=image->next)
1346           {
1347             image->delay=(size_t) floor(geometry_info.rho+0.5);
1348             if ((flags & SigmaValue) != 0)
1349               image->ticks_per_second=(ssize_t)
1350                 floor(geometry_info.sigma+0.5);
1351           }
1352           break;
1353         }
1354       if (LocaleCompare(attribute,"disk-limit") == 0)
1355         {
1356           MagickSizeType
1357             limit;
1358
1359           limit=MagickResourceInfinity;
1360           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1361             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1362               100.0);
1363           (void) SetMagickResourceLimit(DiskResource,limit);
1364           break;
1365         }
1366       if (LocaleCompare(attribute,"density") == 0)
1367         {
1368           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1369             {
1370               ThrowPerlException(exception,OptionError,"MissingGeometry",
1371                 SvPV(sval,na));
1372               break;
1373             }
1374           if (info)
1375             (void) CloneString(&info->image_info->density,SvPV(sval,na));
1376           for ( ; image; image=image->next)
1377           {
1378             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1379             image->resolution.x=geometry_info.rho;
1380             image->resolution.y=geometry_info.sigma;
1381             if ((flags & SigmaValue) == 0)
1382               image->resolution.y=image->resolution.x;
1383           }
1384           break;
1385         }
1386       if (LocaleCompare(attribute,"depth") == 0)
1387         {
1388           if (info)
1389             info->image_info->depth=SvIV(sval);
1390           for ( ; image; image=image->next)
1391             (void) SetImageDepth(image,SvIV(sval),exception);
1392           break;
1393         }
1394       if (LocaleCompare(attribute,"dispose") == 0)
1395         {
1396           sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1397             SvPV(sval,na)) : SvIV(sval);
1398           if (sp < 0)
1399             {
1400               ThrowPerlException(exception,OptionError,
1401                 "UnrecognizedDisposeMethod",SvPV(sval,na));
1402               break;
1403             }
1404           for ( ; image; image=image->next)
1405             image->dispose=(DisposeType) sp;
1406           break;
1407         }
1408       if (LocaleCompare(attribute,"dither") == 0)
1409         {
1410           if (info)
1411             {
1412               sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1413                 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1414               if (sp < 0)
1415                 {
1416                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
1417                     SvPV(sval,na));
1418                   break;
1419                 }
1420               info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1421             }
1422           break;
1423         }
1424       if (LocaleCompare(attribute,"display") == 0)
1425         {
1426           display:
1427           if (info)
1428             (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1429           break;
1430         }
1431       if (info)
1432         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1433       for ( ; image; image=image->next)
1434         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1435       break;
1436     }
1437     case 'E':
1438     case 'e':
1439     {
1440       if (LocaleCompare(attribute,"endian") == 0)
1441         {
1442           sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1443             SvPV(sval,na)) : SvIV(sval);
1444           if (sp < 0)
1445             {
1446               ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1447                 SvPV(sval,na));
1448               break;
1449             }
1450           if (info)
1451             info->image_info->endian=(EndianType) sp;
1452           for ( ; image; image=image->next)
1453             image->endian=(EndianType) sp;
1454           break;
1455         }
1456       if (LocaleCompare(attribute,"extract") == 0)
1457         {
1458           /*
1459             Set image extract geometry.
1460           */
1461           (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1462           break;
1463         }
1464       if (info)
1465         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1466       for ( ; image; image=image->next)
1467         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1468       break;
1469     }
1470     case 'F':
1471     case 'f':
1472     {
1473       if (LocaleCompare(attribute,"filename") == 0)
1474         {
1475           if (info)
1476             (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1477               MagickPathExtent);
1478           for ( ; image; image=image->next)
1479             (void) CopyMagickString(image->filename,SvPV(sval,na),
1480               MagickPathExtent);
1481           break;
1482         }
1483       if (LocaleCompare(attribute,"file") == 0)
1484         {
1485           FILE
1486             *file;
1487
1488           PerlIO
1489             *io_info;
1490
1491           if (info == (struct PackageInfo *) NULL)
1492             break;
1493           io_info=IoIFP(sv_2io(sval));
1494           if (io_info == (PerlIO *) NULL)
1495             {
1496               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1497                 PackageName);
1498               break;
1499             }
1500           file=PerlIO_findFILE(io_info);
1501           if (file == (FILE *) NULL)
1502             {
1503               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1504                 PackageName);
1505               break;
1506             }
1507           SetImageInfoFile(info->image_info,file);
1508           break;
1509         }
1510       if (LocaleCompare(attribute,"fill") == 0)
1511         {
1512           if (info)
1513             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1514           break;
1515         }
1516       if (LocaleCompare(attribute,"font") == 0)
1517         {
1518           if (info)
1519             (void) CloneString(&info->image_info->font,SvPV(sval,na));
1520           break;
1521         }
1522       if (LocaleCompare(attribute,"foreground") == 0)
1523         break;
1524       if (LocaleCompare(attribute,"fuzz") == 0)
1525         {
1526           if (info)
1527             info->image_info->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1528               QuantumRange+1.0);
1529           for ( ; image; image=image->next)
1530             image->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1531               QuantumRange+1.0);
1532           break;
1533         }
1534       if (info)
1535         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1536       for ( ; image; image=image->next)
1537         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1538       break;
1539     }
1540     case 'G':
1541     case 'g':
1542     {
1543       if (LocaleCompare(attribute,"gamma") == 0)
1544         {
1545           for ( ; image; image=image->next)
1546             image->gamma=SvNV(sval);
1547           break;
1548         }
1549       if (LocaleCompare(attribute,"gravity") == 0)
1550         {
1551           sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1552             SvPV(sval,na)) : SvIV(sval);
1553           if (sp < 0)
1554             {
1555               ThrowPerlException(exception,OptionError,
1556                 "UnrecognizedGravityType",SvPV(sval,na));
1557               break;
1558             }
1559           if (info)
1560             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1561           for ( ; image; image=image->next)
1562             image->gravity=(GravityType) sp;
1563           break;
1564         }
1565       if (LocaleCompare(attribute,"green-primary") == 0)
1566         {
1567           for ( ; image; image=image->next)
1568           {
1569             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1570             image->chromaticity.green_primary.x=geometry_info.rho;
1571             image->chromaticity.green_primary.y=geometry_info.sigma;
1572             if ((flags & SigmaValue) == 0)
1573               image->chromaticity.green_primary.y=
1574                 image->chromaticity.green_primary.x;
1575           }
1576           break;
1577         }
1578       if (info)
1579         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1580       for ( ; image; image=image->next)
1581         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1582       break;
1583     }
1584     case 'I':
1585     case 'i':
1586     {
1587       if (LocaleNCompare(attribute,"index",5) == 0)
1588         {
1589           int
1590             items;
1591
1592           long
1593             index;
1594
1595           register Quantum
1596             *q;
1597
1598           CacheView
1599             *image_view;
1600
1601           for ( ; image; image=image->next)
1602           {
1603             if (image->storage_class != PseudoClass)
1604               continue;
1605             x=0;
1606             y=0;
1607             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1608             (void) items;
1609             image_view=AcquireAuthenticCacheView(image,exception);
1610             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1611             if (q != (Quantum *) NULL)
1612               {
1613                 items=sscanf(SvPV(sval,na),"%ld",&index);
1614                 if ((index >= 0) && (index < (ssize_t) image->colors))
1615                   SetPixelIndex(image,index,q);
1616                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1617               }
1618             image_view=DestroyCacheView(image_view);
1619           }
1620           break;
1621         }
1622       if (LocaleCompare(attribute,"iterations") == 0)
1623         {
1624   iterations:
1625           for ( ; image; image=image->next)
1626             image->iterations=SvIV(sval);
1627           break;
1628         }
1629       if (LocaleCompare(attribute,"interlace") == 0)
1630         {
1631           sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1632             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1633           if (sp < 0)
1634             {
1635               ThrowPerlException(exception,OptionError,
1636                 "UnrecognizedInterlaceType",SvPV(sval,na));
1637               break;
1638             }
1639           if (info)
1640             info->image_info->interlace=(InterlaceType) sp;
1641           for ( ; image; image=image->next)
1642             image->interlace=(InterlaceType) sp;
1643           break;
1644         }
1645       if (info)
1646         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1647       for ( ; image; image=image->next)
1648         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1649       break;
1650     }
1651     case 'L':
1652     case 'l':
1653     {
1654       if (LocaleCompare(attribute,"label") == 0)
1655         {
1656           for ( ; image; image=image->next)
1657             (void) SetImageProperty(image,"label",InterpretImageProperties(
1658               info ? info->image_info : (ImageInfo *) NULL,image,
1659               SvPV(sval,na),exception),exception);
1660           break;
1661         }
1662       if (LocaleCompare(attribute,"loop") == 0)
1663         goto iterations;
1664       if (info)
1665         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1666       for ( ; image; image=image->next)
1667         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1668       break;
1669     }
1670     case 'M':
1671     case 'm':
1672     {
1673       if (LocaleCompare(attribute,"magick") == 0)
1674         {
1675           if (info)
1676             (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
1677               "%s:",SvPV(sval,na));
1678           for ( ; image; image=image->next)
1679             (void) CopyMagickString(image->magick,SvPV(sval,na),MagickPathExtent);
1680           break;
1681         }
1682       if (LocaleCompare(attribute,"map-limit") == 0)
1683         {
1684           MagickSizeType
1685             limit;
1686
1687           limit=MagickResourceInfinity;
1688           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1689             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1690               100.0);
1691           (void) SetMagickResourceLimit(MapResource,limit);
1692           break;
1693         }
1694       if (LocaleCompare(attribute,"mask") == 0)
1695         {
1696           Image
1697             *mask;
1698
1699           mask=(Image *) NULL;
1700           if (SvPOK(sval))
1701             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1702           for ( ; image; image=image->next)
1703             SetImageMask(image,ReadPixelMask,mask,exception);
1704           break;
1705         }
1706       if (LocaleCompare(attribute,"mattecolor") == 0)
1707         {
1708           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1709             exception);
1710           if (info)
1711             info->image_info->alpha_color=target_color;
1712           for ( ; image; image=image->next)
1713             image->alpha_color=target_color;
1714           break;
1715         }
1716       if (LocaleCompare(attribute,"matte") == 0)
1717         {
1718           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1719             SvPV(sval,na)) : SvIV(sval);
1720           if (sp < 0)
1721             {
1722               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1723                 SvPV(sval,na));
1724               break;
1725             }
1726           for ( ; image; image=image->next)
1727             image->alpha_trait=sp != 0 ? BlendPixelTrait : UndefinedPixelTrait;
1728           break;
1729         }
1730       if (LocaleCompare(attribute,"memory-limit") == 0)
1731         {
1732           MagickSizeType
1733             limit;
1734
1735           limit=MagickResourceInfinity;
1736           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1737             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1738               100.0);
1739           (void) SetMagickResourceLimit(MemoryResource,limit);
1740           break;
1741         }
1742       if (LocaleCompare(attribute,"monochrome") == 0)
1743         {
1744           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1745             SvPV(sval,na)) : SvIV(sval);
1746           if (sp < 0)
1747             {
1748               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1749                 SvPV(sval,na));
1750               break;
1751             }
1752           if (info)
1753             info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1754           for ( ; image; image=image->next)
1755             (void) SetImageType(image,BilevelType,exception);
1756           break;
1757         }
1758       if (info)
1759         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1760       for ( ; image; image=image->next)
1761         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1762       break;
1763     }
1764     case 'O':
1765     case 'o':
1766     {
1767       if (LocaleCompare(attribute,"option") == 0)
1768         {
1769           if (info)
1770             DefineImageOption(info->image_info,SvPV(sval,na));
1771           break;
1772         }
1773       if (LocaleCompare(attribute,"orientation") == 0)
1774         {
1775           sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1776             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1777           if (sp < 0)
1778             {
1779               ThrowPerlException(exception,OptionError,
1780                 "UnrecognizedOrientationType",SvPV(sval,na));
1781               break;
1782             }
1783           if (info)
1784             info->image_info->orientation=(OrientationType) sp;
1785           for ( ; image; image=image->next)
1786             image->orientation=(OrientationType) sp;
1787           break;
1788         }
1789       if (info)
1790         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1791       for ( ; image; image=image->next)
1792         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1793       break;
1794     }
1795     case 'P':
1796     case 'p':
1797     {
1798       if (LocaleCompare(attribute,"page") == 0)
1799         {
1800           char
1801             *geometry;
1802
1803           geometry=GetPageGeometry(SvPV(sval,na));
1804           if (info)
1805             (void) CloneString(&info->image_info->page,geometry);
1806           for ( ; image; image=image->next)
1807             (void) ParsePageGeometry(image,geometry,&image->page,exception);
1808           geometry=(char *) RelinquishMagickMemory(geometry);
1809           break;
1810         }
1811       if (LocaleNCompare(attribute,"pixel",5) == 0)
1812         {
1813           int
1814             items;
1815
1816           PixelInfo
1817             pixel;
1818
1819           register Quantum
1820             *q;
1821
1822           CacheView
1823             *image_view;
1824
1825           for ( ; image; image=image->next)
1826           {
1827             if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1828               break;
1829             x=0;
1830             y=0;
1831             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1832             (void) items;
1833             image_view=AcquireVirtualCacheView(image,exception);
1834             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1835             if (q != (Quantum *) NULL)
1836               {
1837                 if ((strchr(SvPV(sval,na),',') == 0) ||
1838                     (strchr(SvPV(sval,na),')') != 0))
1839                   QueryColorCompliance(SvPV(sval,na),AllCompliance,
1840                     &pixel,exception);
1841                 else
1842                   {
1843                     GetPixelInfo(image,&pixel);
1844                     flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1845                     pixel.red=geometry_info.rho;
1846                     if ((flags & SigmaValue) != 0)
1847                       pixel.green=geometry_info.sigma;
1848                     if ((flags & XiValue) != 0)
1849                       pixel.blue=geometry_info.xi;
1850                     if ((flags & PsiValue) != 0)
1851                       pixel.alpha=geometry_info.psi;
1852                     if ((flags & ChiValue) != 0)
1853                       pixel.black=geometry_info.chi;
1854                   }
1855                 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1856                 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1857                 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1858                 if (image->colorspace == CMYKColorspace)
1859                   SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1860                 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1861                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1862               }
1863             image_view=DestroyCacheView(image_view);
1864           }
1865           break;
1866         }
1867       if (LocaleCompare(attribute,"pointsize") == 0)
1868         {
1869           if (info)
1870             {
1871               (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1872               info->image_info->pointsize=geometry_info.rho;
1873             }
1874           break;
1875         }
1876       if (LocaleCompare(attribute,"preview") == 0)
1877         {
1878           sp=SvPOK(sval) ? ParseCommandOption(MagickPreviewOptions,MagickFalse,
1879             SvPV(sval,na)) : SvIV(sval);
1880           if (sp < 0)
1881             {
1882               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1883                 SvPV(sval,na));
1884               break;
1885             }
1886           if (info)
1887             info->image_info->preview_type=(PreviewType) sp;
1888           break;
1889         }
1890       if (info)
1891         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1892       for ( ; image; image=image->next)
1893         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1894       break;
1895     }
1896     case 'Q':
1897     case 'q':
1898     {
1899       if (LocaleCompare(attribute,"quality") == 0)
1900         {
1901           if (info)
1902             info->image_info->quality=SvIV(sval);
1903           for ( ; image; image=image->next)
1904             image->quality=SvIV(sval);
1905           break;
1906         }
1907       if (info)
1908         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1909       for ( ; image; image=image->next)
1910         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1911       break;
1912     }
1913     case 'R':
1914     case 'r':
1915     {
1916       if (LocaleCompare(attribute,"read-mask") == 0)
1917         {
1918           Image
1919             *mask;
1920
1921           mask=(Image *) NULL;
1922           if (SvPOK(sval))
1923             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1924           for ( ; image; image=image->next)
1925             SetImageMask(image,ReadPixelMask,mask,exception);
1926           break;
1927         }
1928       if (LocaleCompare(attribute,"red-primary") == 0)
1929         {
1930           for ( ; image; image=image->next)
1931           {
1932             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1933             image->chromaticity.red_primary.x=geometry_info.rho;
1934             image->chromaticity.red_primary.y=geometry_info.sigma;
1935             if ((flags & SigmaValue) == 0)
1936               image->chromaticity.red_primary.y=
1937                 image->chromaticity.red_primary.x;
1938           }
1939           break;
1940         }
1941       if (LocaleCompare(attribute,"render") == 0)
1942         {
1943           sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1944             SvPV(sval,na)) : SvIV(sval);
1945           if (sp < 0)
1946             {
1947               ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1948                 SvPV(sval,na));
1949               break;
1950             }
1951          for ( ; image; image=image->next)
1952            image->rendering_intent=(RenderingIntent) sp;
1953          break;
1954        }
1955       if (LocaleCompare(attribute,"repage") == 0)
1956         {
1957           RectangleInfo
1958             geometry;
1959
1960           for ( ; image; image=image->next)
1961           {
1962             flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
1963             if ((flags & WidthValue) != 0)
1964               {
1965                 if ((flags & HeightValue) == 0)
1966                   geometry.height=geometry.width;
1967                 image->page.width=geometry.width;
1968                 image->page.height=geometry.height;
1969               }
1970             if ((flags & AspectValue) != 0)
1971               {
1972                 if ((flags & XValue) != 0)
1973                   image->page.x+=geometry.x;
1974                 if ((flags & YValue) != 0)
1975                   image->page.y+=geometry.y;
1976               }
1977             else
1978               {
1979                 if ((flags & XValue) != 0)
1980                   {
1981                     image->page.x=geometry.x;
1982                     if (((flags & WidthValue) != 0) && (geometry.x > 0))
1983                       image->page.width=image->columns+geometry.x;
1984                   }
1985                 if ((flags & YValue) != 0)
1986                   {
1987                     image->page.y=geometry.y;
1988                     if (((flags & HeightValue) != 0) && (geometry.y > 0))
1989                       image->page.height=image->rows+geometry.y;
1990                   }
1991               }
1992           }
1993           break;
1994         }
1995       if (info)
1996         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1997       for ( ; image; image=image->next)
1998         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1999       break;
2000     }
2001     case 'S':
2002     case 's':
2003     {
2004       if (LocaleCompare(attribute,"sampling-factor") == 0)
2005         {
2006           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2007             {
2008               ThrowPerlException(exception,OptionError,"MissingGeometry",
2009                 SvPV(sval,na));
2010               break;
2011             }
2012           if (info)
2013             (void) CloneString(&info->image_info->sampling_factor,
2014               SvPV(sval,na));
2015           break;
2016         }
2017       if (LocaleCompare(attribute,"scene") == 0)
2018         {
2019           for ( ; image; image=image->next)
2020             image->scene=SvIV(sval);
2021           break;
2022         }
2023       if (LocaleCompare(attribute,"server") == 0)
2024         goto display;
2025       if (LocaleCompare(attribute,"size") == 0)
2026         {
2027           if (info)
2028             {
2029               if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2030                 {
2031                   ThrowPerlException(exception,OptionError,"MissingGeometry",
2032                     SvPV(sval,na));
2033                   break;
2034                 }
2035               (void) CloneString(&info->image_info->size,SvPV(sval,na));
2036             }
2037           break;
2038         }
2039       if (LocaleCompare(attribute,"stroke") == 0)
2040         {
2041           if (info)
2042             (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2043           break;
2044         }
2045       if (info)
2046         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2047       for ( ; image; image=image->next)
2048         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2049       break;
2050     }
2051     case 'T':
2052     case 't':
2053     {
2054       if (LocaleCompare(attribute,"texture") == 0)
2055         {
2056           if (info)
2057             (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2058           break;
2059         }
2060       if (LocaleCompare(attribute,"thread-limit") == 0)
2061         {
2062           MagickSizeType
2063             limit;
2064
2065           limit=MagickResourceInfinity;
2066           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2067             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2068               100.0);
2069           (void) SetMagickResourceLimit(ThreadResource,limit);
2070           break;
2071         }
2072       if (LocaleCompare(attribute,"tile-offset") == 0)
2073         {
2074           char
2075             *geometry;
2076
2077           geometry=GetPageGeometry(SvPV(sval,na));
2078           if (info)
2079             (void) CloneString(&info->image_info->page,geometry);
2080           for ( ; image; image=image->next)
2081             (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2082               exception);
2083           geometry=(char *) RelinquishMagickMemory(geometry);
2084           break;
2085         }
2086       if (LocaleCompare(attribute,"time-limit") == 0)
2087         {
2088           MagickSizeType
2089             limit;
2090
2091           limit=MagickResourceInfinity;
2092           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2093             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2094               100.0);
2095           (void) SetMagickResourceLimit(TimeResource,limit);
2096           break;
2097         }
2098       if (LocaleCompare(attribute,"transparent-color") == 0)
2099         {
2100           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
2101             exception);
2102           if (info)
2103             info->image_info->transparent_color=target_color;
2104           for ( ; image; image=image->next)
2105             image->transparent_color=target_color;
2106           break;
2107         }
2108       if (LocaleCompare(attribute,"type") == 0)
2109         {
2110           sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2111             SvPV(sval,na)) : SvIV(sval);
2112           if (sp < 0)
2113             {
2114               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2115                 SvPV(sval,na));
2116               break;
2117             }
2118           if (info)
2119             info->image_info->type=(ImageType) sp;
2120           for ( ; image; image=image->next)
2121             SetImageType(image,(ImageType) sp,exception);
2122           break;
2123         }
2124       if (info)
2125         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2126       for ( ; image; image=image->next)
2127         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2128       break;
2129     }
2130     case 'U':
2131     case 'u':
2132     {
2133       if (LocaleCompare(attribute,"units") == 0)
2134         {
2135           sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2136             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2137           if (sp < 0)
2138             {
2139               ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2140                 SvPV(sval,na));
2141               break;
2142             }
2143           if (info)
2144             info->image_info->units=(ResolutionType) sp;
2145           for ( ; image; image=image->next)
2146           {
2147             ResolutionType
2148               units;
2149
2150             units=(ResolutionType) sp;
2151             if (image->units != units)
2152               switch (image->units)
2153               {
2154                 case UndefinedResolution:
2155                 case PixelsPerInchResolution:
2156                 {
2157                   if (units == PixelsPerCentimeterResolution)
2158                     {
2159                       image->resolution.x*=2.54;
2160                       image->resolution.y*=2.54;
2161                     }
2162                   break;
2163                 }
2164                 case PixelsPerCentimeterResolution:
2165                 {
2166                   if (units == PixelsPerInchResolution)
2167                     {
2168                       image->resolution.x/=2.54;
2169                       image->resolution.y/=2.54;
2170                     }
2171                   break;
2172                 }
2173               }
2174             image->units=units;
2175           }
2176           break;
2177         }
2178       if (info)
2179         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2180       for ( ; image; image=image->next)
2181         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2182       break;
2183     }
2184     case 'V':
2185     case 'v':
2186     {
2187       if (LocaleCompare(attribute,"verbose") == 0)
2188         {
2189           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2190             SvPV(sval,na)) : SvIV(sval);
2191           if (sp < 0)
2192             {
2193               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2194                 SvPV(sval,na));
2195               break;
2196             }
2197           if (info)
2198             info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2199           break;
2200         }
2201       if (LocaleCompare(attribute,"virtual-pixel") == 0)
2202         {
2203           sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2204             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2205           if (sp < 0)
2206             {
2207               ThrowPerlException(exception,OptionError,
2208                 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2209               break;
2210             }
2211           for ( ; image; image=image->next)
2212             SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp,exception);
2213           break;
2214         }
2215       if (info)
2216         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2217       for ( ; image; image=image->next)
2218         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2219       break;
2220     }
2221     case 'W':
2222     case 'w':
2223     {
2224       if (LocaleCompare(attribute,"white-point") == 0)
2225         {
2226           for ( ; image; image=image->next)
2227           {
2228             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2229             image->chromaticity.white_point.x=geometry_info.rho;
2230             image->chromaticity.white_point.y=geometry_info.sigma;
2231             if ((flags & SigmaValue) == 0)
2232               image->chromaticity.white_point.y=
2233                 image->chromaticity.white_point.x;
2234           }
2235           break;
2236         }
2237       if (LocaleCompare(attribute,"write-mask") == 0)
2238         {
2239           Image
2240             *mask;
2241
2242           mask=(Image *) NULL;
2243           if (SvPOK(sval))
2244             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
2245           for ( ; image; image=image->next)
2246             SetImageMask(image,WritePixelMask,mask,exception);
2247           break;
2248         }
2249       if (info)
2250         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2251       for ( ; image; image=image->next)
2252         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2253       break;
2254     }
2255     default:
2256     {
2257       if (info)
2258         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2259       for ( ; image; image=image->next)
2260         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2261       break;
2262     }
2263   }
2264 }
2265 \f
2266 /*
2267 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2268 %                                                                             %
2269 %                                                                             %
2270 %                                                                             %
2271 %   S e t u p L i s t                                                         %
2272 %                                                                             %
2273 %                                                                             %
2274 %                                                                             %
2275 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2276 %
2277 %  Method SetupList returns the list of all the images linked by their
2278 %  image->next and image->previous link lists for use with ImageMagick.  If
2279 %  info is non-NULL, an info structure is returned in *info.  If
2280 %  reference_vector is non-NULL,an array of SV* are returned in
2281 %  *reference_vector.  Reference_vector is used when the images are going to be
2282 %  replaced with new Image*'s.
2283 %
2284 %  The format of the SetupList routine is:
2285 %
2286 %      Image *SetupList(SV *reference,struct PackageInfo **info,
2287 %        SV ***reference_vector,ExceptionInfo *exception)
2288 %
2289 %  A description of each parameter follows:
2290 %
2291 %    o list: a list of strings.
2292 %
2293 %    o string: a character string.
2294 %
2295 %    o exception: Return any errors or warnings in this structure.
2296 %
2297 */
2298 static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2299   SV ***reference_vector,ExceptionInfo *exception)
2300 {
2301   Image
2302     *image;
2303
2304   ssize_t
2305     current,
2306     last;
2307
2308   if (reference_vector)
2309     *reference_vector=NULL;
2310   if (info)
2311     *info=NULL;
2312   current=0;
2313   last=0;
2314   image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2315   if (info && (SvTYPE(reference) == SVt_PVAV))
2316     *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2317       exception);
2318   return(image);
2319 }
2320 \f
2321 /*
2322 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2323 %                                                                             %
2324 %                                                                             %
2325 %                                                                             %
2326 %   s t r E Q c a s e                                                         %
2327 %                                                                             %
2328 %                                                                             %
2329 %                                                                             %
2330 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2331 %
2332 %  strEQcase() compares two strings and returns 0 if they are the
2333 %  same or if the second string runs out first.  The comparison is case
2334 %  insensitive.
2335 %
2336 %  The format of the strEQcase routine is:
2337 %
2338 %      ssize_t strEQcase(const char *p,const char *q)
2339 %
2340 %  A description of each parameter follows:
2341 %
2342 %    o p: a character string.
2343 %
2344 %    o q: a character string.
2345 %
2346 %
2347 */
2348 static ssize_t strEQcase(const char *p,const char *q)
2349 {
2350   char
2351     c;
2352
2353   register ssize_t
2354     i;
2355
2356   for (i=0 ; (c=(*q)) != 0; i++)
2357   {
2358     if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2359         (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2360       return(0);
2361     p++;
2362     q++;
2363   }
2364   return(((*q == 0) && (*p == 0)) ? i : 0);
2365 }
2366 \f
2367 /*
2368 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2369 %                                                                             %
2370 %                                                                             %
2371 %                                                                             %
2372 %   I m a g e : : M a g i c k                                                 %
2373 %                                                                             %
2374 %                                                                             %
2375 %                                                                             %
2376 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2377 %
2378 %
2379 */
2380 MODULE = Image::Magick PACKAGE = Image::Magick
2381
2382 PROTOTYPES: ENABLE
2383
2384 BOOT:
2385   MagickCoreGenesis("PerlMagick",MagickFalse);
2386   SetWarningHandler(NULL);
2387   SetErrorHandler(NULL);
2388   magick_registry=NewSplayTree((int (*)(const void *,const void *))
2389     NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2390
2391 void
2392 UNLOAD()
2393   PPCODE:
2394   {
2395     if (magick_registry != (SplayTreeInfo *) NULL)
2396       magick_registry=DestroySplayTree(magick_registry);
2397     MagickCoreTerminus();
2398   }
2399
2400 double
2401 constant(name,argument)
2402   char *name
2403   ssize_t argument
2404 \f
2405 #
2406 ###############################################################################
2407 #                                                                             #
2408 #                                                                             #
2409 #                                                                             #
2410 #   A n i m a t e                                                             #
2411 #                                                                             #
2412 #                                                                             #
2413 #                                                                             #
2414 ###############################################################################
2415 #
2416 #
2417 void
2418 Animate(ref,...)
2419   Image::Magick ref=NO_INIT
2420   ALIAS:
2421     AnimateImage  = 1
2422     animate       = 2
2423     animateimage  = 3
2424   PPCODE:
2425   {
2426     ExceptionInfo
2427       *exception;
2428
2429     Image
2430       *image;
2431
2432     register ssize_t
2433       i;
2434
2435     struct PackageInfo
2436       *info,
2437       *package_info;
2438
2439     SV
2440       *perl_exception,
2441       *reference;
2442
2443     PERL_UNUSED_VAR(ref);
2444     PERL_UNUSED_VAR(ix);
2445     exception=AcquireExceptionInfo();
2446     perl_exception=newSVpv("",0);
2447     package_info=(struct PackageInfo *) NULL;
2448     if (sv_isobject(ST(0)) == 0)
2449       {
2450         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2451           PackageName);
2452         goto PerlException;
2453       }
2454     reference=SvRV(ST(0));
2455     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2456     if (image == (Image *) NULL)
2457       {
2458         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2459           PackageName);
2460         goto PerlException;
2461       }
2462     package_info=ClonePackageInfo(info,exception);
2463     if (items == 2)
2464       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2465     else
2466       if (items > 2)
2467         for (i=2; i < items; i+=2)
2468           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2469             exception);
2470     (void) AnimateImages(package_info->image_info,image,exception);
2471     (void) CatchImageException(image);
2472
2473   PerlException:
2474     if (package_info != (struct PackageInfo *) NULL)
2475       DestroyPackageInfo(package_info);
2476     InheritPerlException(exception,perl_exception);
2477     exception=DestroyExceptionInfo(exception);
2478     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2479     SvPOK_on(perl_exception);
2480     ST(0)=sv_2mortal(perl_exception);
2481     XSRETURN(1);
2482   }
2483 \f
2484 #
2485 ###############################################################################
2486 #                                                                             #
2487 #                                                                             #
2488 #                                                                             #
2489 #   A p p e n d                                                               #
2490 #                                                                             #
2491 #                                                                             #
2492 #                                                                             #
2493 ###############################################################################
2494 #
2495 #
2496 void
2497 Append(ref,...)
2498   Image::Magick ref=NO_INIT
2499   ALIAS:
2500     AppendImage  = 1
2501     append       = 2
2502     appendimage  = 3
2503   PPCODE:
2504   {
2505     AV
2506       *av;
2507
2508     char
2509       *attribute;
2510
2511     ExceptionInfo
2512       *exception;
2513
2514     HV
2515       *hv;
2516
2517     Image
2518       *image;
2519
2520     register ssize_t
2521       i;
2522
2523     ssize_t
2524       stack;
2525
2526     struct PackageInfo
2527       *info;
2528
2529     SV
2530       *av_reference,
2531       *perl_exception,
2532       *reference,
2533       *rv,
2534       *sv;
2535
2536     PERL_UNUSED_VAR(ref);
2537     PERL_UNUSED_VAR(ix);
2538     exception=AcquireExceptionInfo();
2539     perl_exception=newSVpv("",0);
2540     sv=NULL;
2541     attribute=NULL;
2542     av=NULL;
2543     if (sv_isobject(ST(0)) == 0)
2544       {
2545         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2546           PackageName);
2547         goto PerlException;
2548       }
2549     reference=SvRV(ST(0));
2550     hv=SvSTASH(reference);
2551     av=newAV();
2552     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2553     SvREFCNT_dec(av);
2554     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2555     if (image == (Image *) NULL)
2556       {
2557         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2558           PackageName);
2559         goto PerlException;
2560       }
2561     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2562     /*
2563       Get options.
2564     */
2565     stack=MagickTrue;
2566     for (i=2; i < items; i+=2)
2567     {
2568       attribute=(char *) SvPV(ST(i-1),na);
2569       switch (*attribute)
2570       {
2571         case 'S':
2572         case 's':
2573         {
2574           if (LocaleCompare(attribute,"stack") == 0)
2575             {
2576               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2577                 SvPV(ST(i),na));
2578               if (stack < 0)
2579                 {
2580                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
2581                     SvPV(ST(i),na));
2582                   return;
2583                 }
2584               break;
2585             }
2586           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2587             attribute);
2588           break;
2589         }
2590         default:
2591         {
2592           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2593             attribute);
2594           break;
2595         }
2596       }
2597     }
2598     image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2599     if (image == (Image *) NULL)
2600       goto PerlException;
2601     for ( ; image; image=image->next)
2602     {
2603       AddImageToRegistry(sv,image);
2604       rv=newRV(sv);
2605       av_push(av,sv_bless(rv,hv));
2606       SvREFCNT_dec(sv);
2607     }
2608     exception=DestroyExceptionInfo(exception);
2609     ST(0)=av_reference;
2610     SvREFCNT_dec(perl_exception);
2611     XSRETURN(1);
2612
2613   PerlException:
2614     InheritPerlException(exception,perl_exception);
2615     exception=DestroyExceptionInfo(exception);
2616     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2617     SvPOK_on(perl_exception);
2618     ST(0)=sv_2mortal(perl_exception);
2619     XSRETURN(1);
2620   }
2621 \f
2622 #
2623 ###############################################################################
2624 #                                                                             #
2625 #                                                                             #
2626 #                                                                             #
2627 #   A v e r a g e                                                             #
2628 #                                                                             #
2629 #                                                                             #
2630 #                                                                             #
2631 ###############################################################################
2632 #
2633 #
2634 void
2635 Average(ref)
2636   Image::Magick ref=NO_INIT
2637   ALIAS:
2638     AverageImage   = 1
2639     average        = 2
2640     averageimage   = 3
2641   PPCODE:
2642   {
2643     AV
2644       *av;
2645
2646     char
2647       *p;
2648
2649     ExceptionInfo
2650       *exception;
2651
2652     HV
2653       *hv;
2654
2655     Image
2656       *image;
2657
2658     struct PackageInfo
2659       *info;
2660
2661     SV
2662       *perl_exception,
2663       *reference,
2664       *rv,
2665       *sv;
2666
2667     PERL_UNUSED_VAR(ref);
2668     PERL_UNUSED_VAR(ix);
2669     exception=AcquireExceptionInfo();
2670     perl_exception=newSVpv("",0);
2671     sv=NULL;
2672     if (sv_isobject(ST(0)) == 0)
2673       {
2674         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2675           PackageName);
2676         goto PerlException;
2677       }
2678     reference=SvRV(ST(0));
2679     hv=SvSTASH(reference);
2680     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2681     if (image == (Image *) NULL)
2682       {
2683         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2684           PackageName);
2685         goto PerlException;
2686       }
2687     image=EvaluateImages(image,MeanEvaluateOperator,exception);
2688     if (image == (Image *) NULL)
2689       goto PerlException;
2690     /*
2691       Create blessed Perl array for the returned image.
2692     */
2693     av=newAV();
2694     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2695     SvREFCNT_dec(av);
2696     AddImageToRegistry(sv,image);
2697     rv=newRV(sv);
2698     av_push(av,sv_bless(rv,hv));
2699     SvREFCNT_dec(sv);
2700     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2701     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
2702       "average-%.*s",(int) (MagickPathExtent-9),
2703       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2704     (void) CopyMagickString(image->filename,info->image_info->filename,
2705       MagickPathExtent);
2706     SetImageInfo(info->image_info,0,exception);
2707     exception=DestroyExceptionInfo(exception);
2708     SvREFCNT_dec(perl_exception);
2709     XSRETURN(1);
2710
2711   PerlException:
2712     InheritPerlException(exception,perl_exception);
2713     exception=DestroyExceptionInfo(exception);
2714     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2715     SvPOK_on(perl_exception);
2716     ST(0)=sv_2mortal(perl_exception);
2717     XSRETURN(1);
2718   }
2719 \f
2720 #
2721 ###############################################################################
2722 #                                                                             #
2723 #                                                                             #
2724 #                                                                             #
2725 #   B l o b T o I m a g e                                                     #
2726 #                                                                             #
2727 #                                                                             #
2728 #                                                                             #
2729 ###############################################################################
2730 #
2731 #
2732 void
2733 BlobToImage(ref,...)
2734   Image::Magick ref=NO_INIT
2735   ALIAS:
2736     BlobToImage  = 1
2737     blobtoimage  = 2
2738     blobto       = 3
2739   PPCODE:
2740   {
2741     AV
2742       *av;
2743
2744     char
2745       **keep,
2746       **list;
2747
2748     ExceptionInfo
2749       *exception;
2750
2751     HV
2752       *hv;
2753
2754     Image
2755       *image;
2756
2757     register char
2758       **p;
2759
2760     register ssize_t
2761       i;
2762
2763     ssize_t
2764       ac,
2765       n,
2766       number_images;
2767
2768     STRLEN
2769       *length;
2770
2771     struct PackageInfo
2772       *info;
2773
2774     SV
2775       *perl_exception,
2776       *reference,
2777       *rv,
2778       *sv;
2779
2780     PERL_UNUSED_VAR(ref);
2781     PERL_UNUSED_VAR(ix);
2782     exception=AcquireExceptionInfo();
2783     perl_exception=newSVpv("",0);
2784     sv=NULL;
2785     number_images=0;
2786     ac=(items < 2) ? 1 : items-1;
2787     length=(STRLEN *) NULL;
2788     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2789     if (list == (char **) NULL)
2790       {
2791         ThrowPerlException(exception,ResourceLimitError,
2792           "MemoryAllocationFailed",PackageName);
2793         goto PerlException;
2794       }
2795     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2796     if (length == (STRLEN *) NULL)
2797       {
2798         ThrowPerlException(exception,ResourceLimitError,
2799           "MemoryAllocationFailed",PackageName);
2800         goto PerlException;
2801       }
2802     if (sv_isobject(ST(0)) == 0)
2803       {
2804         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2805           PackageName);
2806         goto PerlException;
2807       }
2808     reference=SvRV(ST(0));
2809     hv=SvSTASH(reference);
2810     if (SvTYPE(reference) != SVt_PVAV)
2811       {
2812         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2813           PackageName);
2814         goto PerlException;
2815       }
2816     av=(AV *) reference;
2817     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2818       exception);
2819     n=1;
2820     if (items <= 1)
2821       {
2822         ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2823         goto PerlException;
2824       }
2825     for (n=0, i=0; i < ac; i++)
2826     {
2827       list[n]=(char *) (SvPV(ST(i+1),length[n]));
2828       if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2829         {
2830           list[n]=(char *) (SvPV(ST(i+2),length[n]));
2831           continue;
2832         }
2833       n++;
2834     }
2835     list[n]=(char *) NULL;
2836     keep=list;
2837     for (i=number_images=0; i < n; i++)
2838     {
2839       image=BlobToImage(info->image_info,list[i],length[i],exception);
2840       if (image == (Image *) NULL)
2841         break;
2842       for ( ; image; image=image->next)
2843       {
2844         AddImageToRegistry(sv,image);
2845         rv=newRV(sv);
2846         av_push(av,sv_bless(rv,hv));
2847         SvREFCNT_dec(sv);
2848         number_images++;
2849       }
2850     }
2851     /*
2852       Free resources.
2853     */
2854     for (i=0; i < n; i++)
2855       if (list[i] != (char *) NULL)
2856         for (p=keep; list[i] != *p++; )
2857           if (*p == (char *) NULL)
2858             {
2859               list[i]=(char *) RelinquishMagickMemory(list[i]);
2860               break;
2861             }
2862
2863   PerlException:
2864     if (list)
2865       list=(char **) RelinquishMagickMemory(list);
2866     if (length)
2867       length=(STRLEN *) RelinquishMagickMemory(length);
2868     InheritPerlException(exception,perl_exception);
2869     exception=DestroyExceptionInfo(exception);
2870     sv_setiv(perl_exception,(IV) number_images);
2871     SvPOK_on(perl_exception);
2872     ST(0)=sv_2mortal(perl_exception);
2873     XSRETURN(1);
2874   }
2875 \f
2876 #
2877 ###############################################################################
2878 #                                                                             #
2879 #                                                                             #
2880 #                                                                             #
2881 #   C h a n n e l F x                                                         #
2882 #                                                                             #
2883 #                                                                             #
2884 #                                                                             #
2885 ###############################################################################
2886 #
2887 #
2888 void
2889 ChannelFx(ref,...)
2890   Image::Magick ref=NO_INIT
2891   ALIAS:
2892     ChannelFxImage  = 1
2893     channelfx       = 2
2894     channelfximage  = 3
2895   PPCODE:
2896   {
2897     AV
2898       *av;
2899
2900     char
2901       *attribute,
2902       expression[MagickPathExtent];
2903
2904     ChannelType
2905       channel,
2906       channel_mask;
2907
2908     ExceptionInfo
2909       *exception;
2910
2911     HV
2912       *hv;
2913
2914     Image
2915       *image;
2916
2917     register ssize_t
2918       i;
2919
2920     struct PackageInfo
2921       *info;
2922
2923     SV
2924       *av_reference,
2925       *perl_exception,
2926       *reference,
2927       *rv,
2928       *sv;
2929
2930     PERL_UNUSED_VAR(ref);
2931     PERL_UNUSED_VAR(ix);
2932     exception=AcquireExceptionInfo();
2933     perl_exception=newSVpv("",0);
2934     sv=NULL;
2935     attribute=NULL;
2936     av=NULL;
2937     if (sv_isobject(ST(0)) == 0)
2938       {
2939         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2940           PackageName);
2941         goto PerlException;
2942       }
2943     reference=SvRV(ST(0));
2944     hv=SvSTASH(reference);
2945     av=newAV();
2946     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2947     SvREFCNT_dec(av);
2948     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2949     if (image == (Image *) NULL)
2950       {
2951         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2952           PackageName);
2953         goto PerlException;
2954       }
2955     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2956     /*
2957       Get options.
2958     */
2959     channel=DefaultChannels;
2960     (void) CopyMagickString(expression,"u",MagickPathExtent);
2961     if (items == 2)
2962       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
2963     else
2964       for (i=2; i < items; i+=2)
2965       {
2966         attribute=(char *) SvPV(ST(i-1),na);
2967         switch (*attribute)
2968         {
2969           case 'C':
2970           case 'c':
2971           {
2972             if (LocaleCompare(attribute,"channel") == 0)
2973               {
2974                 ssize_t
2975                   option;
2976
2977                 option=ParseChannelOption(SvPV(ST(i),na));
2978                 if (option < 0)
2979                   {
2980                     ThrowPerlException(exception,OptionError,
2981                       "UnrecognizedType",SvPV(ST(i),na));
2982                     return;
2983                   }
2984                 channel=(ChannelType) option;
2985                 break;
2986               }
2987             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2988               attribute);
2989             break;
2990           }
2991           case 'E':
2992           case 'e':
2993           {
2994             if (LocaleCompare(attribute,"expression") == 0)
2995               {
2996                 (void) CopyMagickString(expression,SvPV(ST(i),na),
2997                   MagickPathExtent);
2998                 break;
2999               }
3000             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3001               attribute);
3002             break;
3003           }
3004           default:
3005           {
3006             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3007               attribute);
3008             break;
3009           }
3010         }
3011       }
3012     channel_mask=SetImageChannelMask(image,channel);
3013     image=ChannelFxImage(image,expression,exception);
3014     if (image != (Image *) NULL)
3015       (void) SetImageChannelMask(image,channel_mask);
3016     if (image == (Image *) NULL)
3017       goto PerlException;
3018     for ( ; image; image=image->next)
3019     {
3020       AddImageToRegistry(sv,image);
3021       rv=newRV(sv);
3022       av_push(av,sv_bless(rv,hv));
3023       SvREFCNT_dec(sv);
3024     }
3025     exception=DestroyExceptionInfo(exception);
3026     ST(0)=av_reference;
3027     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3028     XSRETURN(1);
3029
3030   PerlException:
3031     InheritPerlException(exception,perl_exception);
3032     exception=DestroyExceptionInfo(exception);
3033     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3034     SvPOK_on(perl_exception);
3035     ST(0)=sv_2mortal(perl_exception);
3036     XSRETURN(1);
3037   }
3038 \f
3039 #
3040 ###############################################################################
3041 #                                                                             #
3042 #                                                                             #
3043 #                                                                             #
3044 #   C l o n e                                                                 #
3045 #                                                                             #
3046 #                                                                             #
3047 #                                                                             #
3048 ###############################################################################
3049 #
3050 #
3051 void
3052 Clone(ref)
3053   Image::Magick ref=NO_INIT
3054   ALIAS:
3055     CopyImage   = 1
3056     copy        = 2
3057     copyimage   = 3
3058     CloneImage  = 4
3059     clone       = 5
3060     cloneimage  = 6
3061     Clone       = 7
3062   PPCODE:
3063   {
3064     AV
3065       *av;
3066
3067     ExceptionInfo
3068       *exception;
3069
3070     HV
3071       *hv;
3072
3073     Image
3074       *clone,
3075       *image;
3076
3077     struct PackageInfo
3078       *info;
3079
3080     SV
3081       *perl_exception,
3082       *reference,
3083       *rv,
3084       *sv;
3085
3086     PERL_UNUSED_VAR(ref);
3087     PERL_UNUSED_VAR(ix);
3088     exception=AcquireExceptionInfo();
3089     perl_exception=newSVpv("",0);
3090     sv=NULL;
3091     if (sv_isobject(ST(0)) == 0)
3092       {
3093         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3094           PackageName);
3095         goto PerlException;
3096       }
3097     reference=SvRV(ST(0));
3098     hv=SvSTASH(reference);
3099     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3100     if (image == (Image *) NULL)
3101       {
3102         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3103           PackageName);
3104         goto PerlException;
3105       }
3106     /*
3107       Create blessed Perl array for the returned image.
3108     */
3109     av=newAV();
3110     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3111     SvREFCNT_dec(av);
3112     for ( ; image; image=image->next)
3113     {
3114       clone=CloneImage(image,0,0,MagickTrue,exception);
3115       if (clone == (Image *) NULL)
3116         break;
3117       AddImageToRegistry(sv,clone);
3118       rv=newRV(sv);
3119       av_push(av,sv_bless(rv,hv));
3120       SvREFCNT_dec(sv);
3121     }
3122     exception=DestroyExceptionInfo(exception);
3123     SvREFCNT_dec(perl_exception);
3124     XSRETURN(1);
3125
3126   PerlException:
3127     InheritPerlException(exception,perl_exception);
3128     exception=DestroyExceptionInfo(exception);
3129     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3130     SvPOK_on(perl_exception);
3131     ST(0)=sv_2mortal(perl_exception);
3132     XSRETURN(1);
3133   }
3134 \f
3135 #
3136 ###############################################################################
3137 #                                                                             #
3138 #                                                                             #
3139 #                                                                             #
3140 #   C L O N E                                                                 #
3141 #                                                                             #
3142 #                                                                             #
3143 #                                                                             #
3144 ###############################################################################
3145 #
3146 #
3147 void
3148 CLONE(ref,...)
3149   SV *ref;
3150   CODE:
3151   {
3152     PERL_UNUSED_VAR(ref);
3153     if (magick_registry != (SplayTreeInfo *) NULL)
3154       {
3155         register Image
3156           *p;
3157
3158         ResetSplayTreeIterator(magick_registry);
3159         p=(Image *) GetNextKeyInSplayTree(magick_registry);
3160         while (p != (Image *) NULL)
3161         {
3162           ReferenceImage(p);
3163           p=(Image *) GetNextKeyInSplayTree(magick_registry);
3164         }
3165       }
3166   }
3167 \f
3168 #
3169 ###############################################################################
3170 #                                                                             #
3171 #                                                                             #
3172 #                                                                             #
3173 #   C o a l e s c e                                                           #
3174 #                                                                             #
3175 #                                                                             #
3176 #                                                                             #
3177 ###############################################################################
3178 #
3179 #
3180 void
3181 Coalesce(ref)
3182   Image::Magick ref=NO_INIT
3183   ALIAS:
3184     CoalesceImage   = 1
3185     coalesce        = 2
3186     coalesceimage   = 3
3187   PPCODE:
3188   {
3189     AV
3190       *av;
3191
3192     ExceptionInfo
3193       *exception;
3194
3195     HV
3196       *hv;
3197
3198     Image
3199       *image;
3200
3201     struct PackageInfo
3202       *info;
3203
3204     SV
3205       *av_reference,
3206       *perl_exception,
3207       *reference,
3208       *rv,
3209       *sv;
3210
3211     PERL_UNUSED_VAR(ref);
3212     PERL_UNUSED_VAR(ix);
3213     exception=AcquireExceptionInfo();
3214     perl_exception=newSVpv("",0);
3215     sv=NULL;
3216     if (sv_isobject(ST(0)) == 0)
3217       {
3218         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3219           PackageName);
3220         goto PerlException;
3221       }
3222     reference=SvRV(ST(0));
3223     hv=SvSTASH(reference);
3224     av=newAV();
3225     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3226     SvREFCNT_dec(av);
3227     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3228     if (image == (Image *) NULL)
3229       {
3230         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3231           PackageName);
3232         goto PerlException;
3233       }
3234     image=CoalesceImages(image,exception);
3235     if (image == (Image *) NULL)
3236       goto PerlException;
3237     for ( ; image; image=image->next)
3238     {
3239       AddImageToRegistry(sv,image);
3240       rv=newRV(sv);
3241       av_push(av,sv_bless(rv,hv));
3242       SvREFCNT_dec(sv);
3243     }
3244     exception=DestroyExceptionInfo(exception);
3245     ST(0)=av_reference;
3246     SvREFCNT_dec(perl_exception);
3247     XSRETURN(1);
3248
3249   PerlException:
3250     InheritPerlException(exception,perl_exception);
3251     exception=DestroyExceptionInfo(exception);
3252     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3253     SvPOK_on(perl_exception);
3254     ST(0)=sv_2mortal(perl_exception);
3255     XSRETURN(1);
3256   }
3257 \f
3258 #
3259 ###############################################################################
3260 #                                                                             #
3261 #                                                                             #
3262 #                                                                             #
3263 #   C o m p a r e                                                             #
3264 #                                                                             #
3265 #                                                                             #
3266 #                                                                             #
3267 ###############################################################################
3268 #
3269 #
3270 void
3271 Compare(ref,...)
3272   Image::Magick ref=NO_INIT
3273   ALIAS:
3274     CompareImages = 1
3275     compare      = 2
3276     compareimage = 3
3277   PPCODE:
3278   {
3279     AV
3280       *av;
3281
3282     char
3283       *attribute;
3284
3285     double
3286       distortion;
3287
3288     ExceptionInfo
3289       *exception;
3290
3291     HV
3292       *hv;
3293
3294     Image
3295       *difference_image,
3296       *image,
3297       *reconstruct_image;
3298
3299     MetricType
3300       metric;
3301
3302     register ssize_t
3303       i;
3304
3305     ssize_t
3306       option;
3307
3308     struct PackageInfo
3309       *info;
3310
3311     SV
3312       *av_reference,
3313       *perl_exception,
3314       *reference,
3315       *rv,
3316       *sv;
3317
3318     PERL_UNUSED_VAR(ref);
3319     PERL_UNUSED_VAR(ix);
3320     exception=AcquireExceptionInfo();
3321     perl_exception=newSVpv("",0);
3322     sv=NULL;
3323     av=NULL;
3324     attribute=NULL;
3325     if (sv_isobject(ST(0)) == 0)
3326       {
3327         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3328           PackageName);
3329         goto PerlException;
3330       }
3331     reference=SvRV(ST(0));
3332     hv=SvSTASH(reference);
3333     av=newAV();
3334     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3335     SvREFCNT_dec(av);
3336     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3337     if (image == (Image *) NULL)
3338       {
3339         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3340           PackageName);
3341         goto PerlException;
3342       }
3343     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3344     /*
3345       Get attribute.
3346     */
3347     reconstruct_image=image;
3348     metric=RootMeanSquaredErrorMetric;
3349     for (i=2; i < items; i+=2)
3350     {
3351       attribute=(char *) SvPV(ST(i-1),na);
3352       switch (*attribute)
3353       {
3354         case 'C':
3355         case 'c':
3356         {
3357           if (LocaleCompare(attribute,"channel") == 0)
3358             {
3359               ssize_t
3360                 option;
3361
3362               option=ParseChannelOption(SvPV(ST(i),na));
3363               if (option < 0)
3364                 {
3365                   ThrowPerlException(exception,OptionError,
3366                     "UnrecognizedType",SvPV(ST(i),na));
3367                   return;
3368                 }
3369               (void) SetPixelChannelMask(image,(ChannelType) option);
3370               break;
3371             }
3372           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3373             attribute);
3374           break;
3375         }
3376         case 'F':
3377         case 'f':
3378         {
3379           if (LocaleCompare(attribute,"fuzz") == 0)
3380             {
3381               image->fuzz=StringToDoubleInterval(SvPV(ST(i),na),100.0);
3382               break;
3383             }
3384           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3385             attribute);
3386           break;
3387         }
3388         case 'I':
3389         case 'i':
3390         {
3391           if (LocaleCompare(attribute,"image") == 0)
3392             {
3393               reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3394                 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3395               break;
3396             }
3397           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3398             attribute);
3399           break;
3400         }
3401         case 'M':
3402         case 'm':
3403         {
3404           if (LocaleCompare(attribute,"metric") == 0)
3405             {
3406               option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3407                 SvPV(ST(i),na));
3408               if (option < 0)
3409                 {
3410                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3411                     SvPV(ST(i),na));
3412                   break;
3413                 }
3414               metric=(MetricType) option;
3415               break;
3416             }
3417           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3418             attribute);
3419           break;
3420         }
3421         default:
3422         {
3423           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3424             attribute);
3425           break;
3426         }
3427       }
3428     }
3429     difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3430       exception);
3431     if (difference_image != (Image *) NULL)
3432       {
3433         difference_image->error.mean_error_per_pixel=distortion;
3434         AddImageToRegistry(sv,difference_image);
3435         rv=newRV(sv);
3436         av_push(av,sv_bless(rv,hv));
3437         SvREFCNT_dec(sv);
3438       }
3439     exception=DestroyExceptionInfo(exception);
3440     ST(0)=av_reference;
3441     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3442     XSRETURN(1);
3443
3444   PerlException:
3445     InheritPerlException(exception,perl_exception);
3446     exception=DestroyExceptionInfo(exception);
3447     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3448     SvPOK_on(perl_exception);
3449     ST(0)=sv_2mortal(perl_exception);
3450     XSRETURN(1);
3451   }
3452 \f
3453 #
3454 ###############################################################################
3455 #                                                                             #
3456 #                                                                             #
3457 #                                                                             #
3458 #   C o m p l e x I m a g e s                                                 #
3459 #                                                                             #
3460 #                                                                             #
3461 #                                                                             #
3462 ###############################################################################
3463 #
3464 #
3465 void
3466 ComplexImages(ref)
3467   Image::Magick ref=NO_INIT
3468   ALIAS:
3469     ComplexImages   = 1
3470     compleximages   = 2
3471   PPCODE:
3472   {
3473     AV
3474       *av;
3475
3476     char
3477       *attribute,
3478       *p;
3479
3480     ComplexOperator
3481       op;
3482
3483     ExceptionInfo
3484       *exception;
3485
3486     HV
3487       *hv;
3488
3489     Image
3490       *image;
3491
3492     register ssize_t
3493       i;
3494
3495     struct PackageInfo
3496       *info;
3497
3498     SV
3499       *perl_exception,
3500       *reference,
3501       *rv,
3502       *sv;
3503
3504     PERL_UNUSED_VAR(ref);
3505     PERL_UNUSED_VAR(ix);
3506     exception=AcquireExceptionInfo();
3507     perl_exception=newSVpv("",0);
3508     sv=NULL;
3509     if (sv_isobject(ST(0)) == 0)
3510       {
3511         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3512           PackageName);
3513         goto PerlException;
3514       }
3515     reference=SvRV(ST(0));
3516     hv=SvSTASH(reference);
3517     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3518     if (image == (Image *) NULL)
3519       {
3520         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3521           PackageName);
3522         goto PerlException;
3523       }
3524     op=UndefinedComplexOperator;
3525     if (items == 2)
3526       {
3527         ssize_t
3528           in;
3529
3530         in=ParseCommandOption(MagickComplexOptions,MagickFalse,(char *)
3531           SvPV(ST(1),na));
3532         if (in < 0)
3533           {
3534             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3535               SvPV(ST(1),na));
3536             return;
3537           }
3538         op=(ComplexOperator) in;
3539       }
3540     else
3541       for (i=2; i < items; i+=2)
3542       {
3543         attribute=(char *) SvPV(ST(i-1),na);
3544         switch (*attribute)
3545         {
3546           case 'O':
3547           case 'o':
3548           {
3549             if (LocaleCompare(attribute,"operator") == 0)
3550               {
3551                 ssize_t
3552                   in;
3553
3554                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3555                   MagickComplexOptions,MagickFalse,SvPV(ST(i),na));
3556                 if (in < 0)
3557                   {
3558                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3559                       SvPV(ST(i),na));
3560                     return;
3561                   }
3562                 op=(ComplexOperator) in;
3563                 break;
3564               }
3565             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3566               attribute);
3567             break;
3568           }
3569           default:
3570           {
3571             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3572               attribute);
3573             break;
3574           }
3575         }
3576       }
3577     image=ComplexImages(image,op,exception);
3578     if (image == (Image *) NULL)
3579       goto PerlException;
3580     /*
3581       Create blessed Perl array for the returned image.
3582     */
3583     av=newAV();
3584     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3585     SvREFCNT_dec(av);
3586     AddImageToRegistry(sv,image);
3587     rv=newRV(sv);
3588     av_push(av,sv_bless(rv,hv));
3589     SvREFCNT_dec(sv);
3590     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3591     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
3592       "complex-%.*s",(int) (MagickPathExtent-9),
3593       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3594     (void) CopyMagickString(image->filename,info->image_info->filename,
3595       MagickPathExtent);
3596     SetImageInfo(info->image_info,0,exception);
3597     exception=DestroyExceptionInfo(exception);
3598     SvREFCNT_dec(perl_exception);
3599     XSRETURN(1);
3600
3601   PerlException:
3602     InheritPerlException(exception,perl_exception);
3603     exception=DestroyExceptionInfo(exception);
3604     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3605     SvPOK_on(perl_exception);
3606     ST(0)=sv_2mortal(perl_exception);
3607     XSRETURN(1);
3608   }
3609 \f
3610 #
3611 ###############################################################################
3612 #                                                                             #
3613 #                                                                             #
3614 #                                                                             #
3615 #   C o m p a r e L a y e r s                                                 #
3616 #                                                                             #
3617 #                                                                             #
3618 #                                                                             #
3619 ###############################################################################
3620 #
3621 #
3622 void
3623 CompareLayers(ref)
3624   Image::Magick ref=NO_INIT
3625   ALIAS:
3626     CompareImagesLayers   = 1
3627     comparelayers        = 2
3628     compareimagelayers   = 3
3629   PPCODE:
3630   {
3631     AV
3632       *av;
3633
3634     char
3635       *attribute;
3636
3637     ExceptionInfo
3638       *exception;
3639
3640     HV
3641       *hv;
3642
3643     Image
3644       *image;
3645
3646     LayerMethod
3647       method;
3648
3649     register ssize_t
3650       i;
3651
3652     ssize_t
3653       option;
3654
3655     struct PackageInfo
3656       *info;
3657
3658     SV
3659       *av_reference,
3660       *perl_exception,
3661       *reference,
3662       *rv,
3663       *sv;
3664
3665     PERL_UNUSED_VAR(ref);
3666     PERL_UNUSED_VAR(ix);
3667     exception=AcquireExceptionInfo();
3668     perl_exception=newSVpv("",0);
3669     sv=NULL;
3670     if (sv_isobject(ST(0)) == 0)
3671       {
3672         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3673           PackageName);
3674         goto PerlException;
3675       }
3676     reference=SvRV(ST(0));
3677     hv=SvSTASH(reference);
3678     av=newAV();
3679     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3680     SvREFCNT_dec(av);
3681     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3682     if (image == (Image *) NULL)
3683       {
3684         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3685           PackageName);
3686         goto PerlException;
3687       }
3688     method=CompareAnyLayer;
3689     for (i=2; i < items; i+=2)
3690     {
3691       attribute=(char *) SvPV(ST(i-1),na);
3692       switch (*attribute)
3693       {
3694         case 'M':
3695         case 'm':
3696         {
3697           if (LocaleCompare(attribute,"method") == 0)
3698             {
3699               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3700                 SvPV(ST(i),na));
3701               if (option < 0)
3702                 {
3703                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3704                     SvPV(ST(i),na));
3705                   break;
3706                 }
3707                method=(LayerMethod) option;
3708               break;
3709             }
3710           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3711             attribute);
3712           break;
3713         }
3714         default:
3715         {
3716           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3717             attribute);
3718           break;
3719         }
3720       }
3721     }
3722     image=CompareImagesLayers(image,method,exception);
3723     if (image == (Image *) NULL)
3724       goto PerlException;
3725     for ( ; image; image=image->next)
3726     {
3727       AddImageToRegistry(sv,image);
3728       rv=newRV(sv);
3729       av_push(av,sv_bless(rv,hv));
3730       SvREFCNT_dec(sv);
3731     }
3732     exception=DestroyExceptionInfo(exception);
3733     ST(0)=av_reference;
3734     SvREFCNT_dec(perl_exception);
3735     XSRETURN(1);
3736
3737   PerlException:
3738     InheritPerlException(exception,perl_exception);
3739     exception=DestroyExceptionInfo(exception);
3740     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3741     SvPOK_on(perl_exception);
3742     ST(0)=sv_2mortal(perl_exception);
3743     XSRETURN(1);
3744   }
3745 \f
3746 #
3747 ###############################################################################
3748 #                                                                             #
3749 #                                                                             #
3750 #                                                                             #
3751 #   D e s t r o y                                                             #
3752 #                                                                             #
3753 #                                                                             #
3754 #                                                                             #
3755 ###############################################################################
3756 #
3757 #
3758 void
3759 DESTROY(ref)
3760   Image::Magick ref=NO_INIT
3761   PPCODE:
3762   {
3763     SV
3764       *reference;
3765
3766     PERL_UNUSED_VAR(ref);
3767     if (sv_isobject(ST(0)) == 0)
3768       croak("ReferenceIsNotMyType");
3769     reference=SvRV(ST(0));
3770     switch (SvTYPE(reference))
3771     {
3772       case SVt_PVAV:
3773       {
3774         char
3775           message[MagickPathExtent];
3776
3777         const SV
3778           *key;
3779
3780         HV
3781           *hv;
3782
3783         GV
3784           **gvp;
3785
3786         struct PackageInfo
3787           *info;
3788
3789         SV
3790           *sv;
3791
3792         /*
3793           Array (AV *) reference
3794         */
3795         (void) FormatLocaleString(message,MagickPathExtent,"package%s%p",
3796           XS_VERSION,reference);
3797         hv=gv_stashpv(PackageName, FALSE);
3798         if (!hv)
3799           break;
3800         gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3801         if (!gvp)
3802           break;
3803         sv=GvSV(*gvp);
3804         if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3805           {
3806             info=INT2PTR(struct PackageInfo *,SvIV(sv));
3807             DestroyPackageInfo(info);
3808           }
3809         key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3810         (void) key;
3811         break;
3812       }
3813       case SVt_PVMG:
3814       {
3815         Image
3816           *image;
3817
3818         /*
3819           Blessed scalar = (Image *) SvIV(reference)
3820         */
3821         image=INT2PTR(Image *,SvIV(reference));
3822         if (image != (Image *) NULL)
3823           DeleteImageFromRegistry(reference,image);
3824         break;
3825       }
3826       default:
3827         break;
3828     }
3829   }
3830 \f
3831 #
3832 ###############################################################################
3833 #                                                                             #
3834 #                                                                             #
3835 #                                                                             #
3836 #   D i s p l a y                                                             #
3837 #                                                                             #
3838 #                                                                             #
3839 #                                                                             #
3840 ###############################################################################
3841 #
3842 #
3843 void
3844 Display(ref,...)
3845   Image::Magick ref=NO_INIT
3846   ALIAS:
3847     DisplayImage  = 1
3848     display       = 2
3849     displayimage  = 3
3850   PPCODE:
3851   {
3852     ExceptionInfo
3853       *exception;
3854
3855     Image
3856       *image;
3857
3858     register ssize_t
3859       i;
3860
3861     struct PackageInfo
3862       *info,
3863       *package_info;
3864
3865     SV
3866       *perl_exception,
3867       *reference;
3868
3869     PERL_UNUSED_VAR(ref);
3870     PERL_UNUSED_VAR(ix);
3871     exception=AcquireExceptionInfo();
3872     perl_exception=newSVpv("",0);
3873     package_info=(struct PackageInfo *) NULL;
3874     if (sv_isobject(ST(0)) == 0)
3875       {
3876         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3877           PackageName);
3878         goto PerlException;
3879       }
3880     reference=SvRV(ST(0));
3881     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3882     if (image == (Image *) NULL)
3883       {
3884         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3885           PackageName);
3886         goto PerlException;
3887       }
3888     package_info=ClonePackageInfo(info,exception);
3889     if (items == 2)
3890       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3891     else
3892       if (items > 2)
3893         for (i=2; i < items; i+=2)
3894           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3895             exception);
3896     (void) DisplayImages(package_info->image_info,image,exception);
3897     (void) CatchImageException(image);
3898
3899   PerlException:
3900     if (package_info != (struct PackageInfo *) NULL)
3901       DestroyPackageInfo(package_info);
3902     InheritPerlException(exception,perl_exception);
3903     exception=DestroyExceptionInfo(exception);
3904     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3905     SvPOK_on(perl_exception);
3906     ST(0)=sv_2mortal(perl_exception);
3907     XSRETURN(1);
3908   }
3909 \f
3910 #
3911 ###############################################################################
3912 #                                                                             #
3913 #                                                                             #
3914 #                                                                             #
3915 #   E v a l u a t e I m a g e s                                               #
3916 #                                                                             #
3917 #                                                                             #
3918 #                                                                             #
3919 ###############################################################################
3920 #
3921 #
3922 void
3923 EvaluateImages(ref)
3924   Image::Magick ref=NO_INIT
3925   ALIAS:
3926     EvaluateImages   = 1
3927     evaluateimages   = 2
3928   PPCODE:
3929   {
3930     AV
3931       *av;
3932
3933     char
3934       *attribute,
3935       *p;
3936
3937     ExceptionInfo
3938       *exception;
3939
3940     HV
3941       *hv;
3942
3943     Image
3944       *image;
3945
3946     MagickEvaluateOperator
3947       op;
3948
3949     register ssize_t
3950       i;
3951
3952     struct PackageInfo
3953       *info;
3954
3955     SV
3956       *perl_exception,
3957       *reference,
3958       *rv,
3959       *sv;
3960
3961     PERL_UNUSED_VAR(ref);
3962     PERL_UNUSED_VAR(ix);
3963     exception=AcquireExceptionInfo();
3964     perl_exception=newSVpv("",0);
3965     sv=NULL;
3966     if (sv_isobject(ST(0)) == 0)
3967       {
3968         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3969           PackageName);
3970         goto PerlException;
3971       }
3972     reference=SvRV(ST(0));
3973     hv=SvSTASH(reference);
3974     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3975     if (image == (Image *) NULL)
3976       {
3977         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3978           PackageName);
3979         goto PerlException;
3980       }
3981     op=MeanEvaluateOperator;
3982     if (items == 2)
3983       {
3984         ssize_t
3985           in;
3986
3987         in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
3988           SvPV(ST(1),na));
3989         if (in < 0)
3990           {
3991             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3992               SvPV(ST(1),na));
3993             return;
3994           }
3995         op=(MagickEvaluateOperator) in;
3996       }
3997     else
3998       for (i=2; i < items; i+=2)
3999       {
4000         attribute=(char *) SvPV(ST(i-1),na);
4001         switch (*attribute)
4002         {
4003           case 'O':
4004           case 'o':
4005           {
4006             if (LocaleCompare(attribute,"operator") == 0)
4007               {
4008                 ssize_t
4009                   in;
4010
4011                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
4012                   MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
4013                 if (in < 0)
4014                   {
4015                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
4016                       SvPV(ST(i),na));
4017                     return;
4018                   }
4019                 op=(MagickEvaluateOperator) in;
4020                 break;
4021               }
4022             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4023               attribute);
4024             break;
4025           }
4026           default:
4027           {
4028             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4029               attribute);
4030             break;
4031           }
4032         }
4033       }
4034     image=EvaluateImages(image,op,exception);
4035     if (image == (Image *) NULL)
4036       goto PerlException;
4037     /*
4038       Create blessed Perl array for the returned image.
4039     */
4040     av=newAV();
4041     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4042     SvREFCNT_dec(av);
4043     AddImageToRegistry(sv,image);
4044     rv=newRV(sv);
4045     av_push(av,sv_bless(rv,hv));
4046     SvREFCNT_dec(sv);
4047     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4048     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4049       "evaluate-%.*s",(int) (MagickPathExtent-9),
4050       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4051     (void) CopyMagickString(image->filename,info->image_info->filename,
4052       MagickPathExtent);
4053     SetImageInfo(info->image_info,0,exception);
4054     exception=DestroyExceptionInfo(exception);
4055     SvREFCNT_dec(perl_exception);
4056     XSRETURN(1);
4057
4058   PerlException:
4059     InheritPerlException(exception,perl_exception);
4060     exception=DestroyExceptionInfo(exception);
4061     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4062     SvPOK_on(perl_exception);
4063     ST(0)=sv_2mortal(perl_exception);
4064     XSRETURN(1);
4065   }
4066 \f
4067 #
4068 ###############################################################################
4069 #                                                                             #
4070 #                                                                             #
4071 #                                                                             #
4072 #   F e a t u r e s                                                           #
4073 #                                                                             #
4074 #                                                                             #
4075 #                                                                             #
4076 ###############################################################################
4077 #
4078 #
4079 void
4080 Features(ref,...)
4081   Image::Magick ref=NO_INIT
4082   ALIAS:
4083     FeaturesImage = 1
4084     features      = 2
4085     featuresimage = 3
4086   PPCODE:
4087   {
4088 #define ChannelFeatures(channel,direction) \
4089 { \
4090   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4091     channel_features[channel].angular_second_moment[direction]); \
4092   PUSHs(sv_2mortal(newSVpv(message,0))); \
4093   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4094     channel_features[channel].contrast[direction]); \
4095   PUSHs(sv_2mortal(newSVpv(message,0))); \
4096   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4097     channel_features[channel].contrast[direction]); \
4098   PUSHs(sv_2mortal(newSVpv(message,0))); \
4099   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4100     channel_features[channel].variance_sum_of_squares[direction]); \
4101   PUSHs(sv_2mortal(newSVpv(message,0))); \
4102   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4103     channel_features[channel].inverse_difference_moment[direction]); \
4104   PUSHs(sv_2mortal(newSVpv(message,0))); \
4105   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4106     channel_features[channel].sum_average[direction]); \
4107   PUSHs(sv_2mortal(newSVpv(message,0))); \
4108   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4109     channel_features[channel].sum_variance[direction]); \
4110   PUSHs(sv_2mortal(newSVpv(message,0))); \
4111   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4112     channel_features[channel].sum_entropy[direction]); \
4113   PUSHs(sv_2mortal(newSVpv(message,0))); \
4114   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4115     channel_features[channel].entropy[direction]); \
4116   PUSHs(sv_2mortal(newSVpv(message,0))); \
4117   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4118     channel_features[channel].difference_variance[direction]); \
4119   PUSHs(sv_2mortal(newSVpv(message,0))); \
4120   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4121     channel_features[channel].difference_entropy[direction]); \
4122   PUSHs(sv_2mortal(newSVpv(message,0))); \
4123   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4124     channel_features[channel].measure_of_correlation_1[direction]); \
4125   PUSHs(sv_2mortal(newSVpv(message,0))); \
4126   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4127     channel_features[channel].measure_of_correlation_2[direction]); \
4128   PUSHs(sv_2mortal(newSVpv(message,0))); \
4129   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4130     channel_features[channel].maximum_correlation_coefficient[direction]); \
4131   PUSHs(sv_2mortal(newSVpv(message,0))); \
4132 }
4133
4134     AV
4135       *av;
4136
4137     char
4138       *attribute,
4139       message[MagickPathExtent];
4140
4141     ChannelFeatures
4142       *channel_features;
4143
4144     double
4145       distance;
4146
4147     ExceptionInfo
4148       *exception;
4149
4150     Image
4151       *image;
4152
4153     register ssize_t
4154       i;
4155
4156     ssize_t
4157       count;
4158
4159     struct PackageInfo
4160       *info;
4161
4162     SV
4163       *perl_exception,
4164       *reference;
4165
4166     PERL_UNUSED_VAR(ref);
4167     PERL_UNUSED_VAR(ix);
4168     exception=AcquireExceptionInfo();
4169     perl_exception=newSVpv("",0);
4170     av=NULL;
4171     if (sv_isobject(ST(0)) == 0)
4172       {
4173         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4174           PackageName);
4175         goto PerlException;
4176       }
4177     reference=SvRV(ST(0));
4178     av=newAV();
4179     SvREFCNT_dec(av);
4180     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4181     if (image == (Image *) NULL)
4182       {
4183         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4184           PackageName);
4185         goto PerlException;
4186       }
4187     distance=1.0;
4188     for (i=2; i < items; i+=2)
4189     {
4190       attribute=(char *) SvPV(ST(i-1),na);
4191       switch (*attribute)
4192       {
4193         case 'D':
4194         case 'd':
4195         {
4196           if (LocaleCompare(attribute,"distance") == 0)
4197             {
4198               distance=StringToLong((char *) SvPV(ST(1),na));
4199               break;
4200             }
4201           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4202             attribute);
4203           break;
4204         }
4205         default:
4206         {
4207           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4208             attribute);
4209           break;
4210         }
4211       }
4212     }
4213     count=0;
4214     for ( ; image; image=image->next)
4215     {
4216       channel_features=GetImageFeatures(image,distance,exception);
4217       if (channel_features == (ChannelFeatures *) NULL)
4218         continue;
4219       count++;
4220       EXTEND(sp,280*count);
4221       for (i=0; i < 4; i++)
4222       {
4223         ChannelFeatures(RedChannel,i);
4224         ChannelFeatures(GreenChannel,i);
4225         ChannelFeatures(BlueChannel,i);
4226         if (image->colorspace == CMYKColorspace)
4227           ChannelFeatures(BlackChannel,i);
4228         if (image->alpha_trait != UndefinedPixelTrait)
4229           ChannelFeatures(AlphaChannel,i);
4230       }
4231       channel_features=(ChannelFeatures *)
4232         RelinquishMagickMemory(channel_features);
4233     }
4234
4235   PerlException:
4236     InheritPerlException(exception,perl_exception);
4237     exception=DestroyExceptionInfo(exception);
4238     SvREFCNT_dec(perl_exception);
4239   }
4240 \f
4241 #
4242 ###############################################################################
4243 #                                                                             #
4244 #                                                                             #
4245 #                                                                             #
4246 #   F l a t t e n                                                             #
4247 #                                                                             #
4248 #                                                                             #
4249 #                                                                             #
4250 ###############################################################################
4251 #
4252 #
4253 void
4254 Flatten(ref)
4255   Image::Magick ref=NO_INIT
4256   ALIAS:
4257     FlattenImage   = 1
4258     flatten        = 2
4259     flattenimage   = 3
4260   PPCODE:
4261   {
4262     AV
4263       *av;
4264
4265     char
4266       *attribute,
4267       *p;
4268
4269     ExceptionInfo
4270       *exception;
4271
4272     HV
4273       *hv;
4274
4275     Image
4276       *image;
4277
4278     PixelInfo
4279       background_color;
4280
4281     register ssize_t
4282       i;
4283
4284     struct PackageInfo
4285       *info;
4286
4287     SV
4288       *perl_exception,
4289       *reference,
4290       *rv,
4291       *sv;
4292
4293     PERL_UNUSED_VAR(ref);
4294     PERL_UNUSED_VAR(ix);
4295     exception=AcquireExceptionInfo();
4296     perl_exception=newSVpv("",0);
4297     sv=NULL;
4298     if (sv_isobject(ST(0)) == 0)
4299       {
4300         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4301           PackageName);
4302         goto PerlException;
4303       }
4304     reference=SvRV(ST(0));
4305     hv=SvSTASH(reference);
4306     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4307     if (image == (Image *) NULL)
4308       {
4309         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4310           PackageName);
4311         goto PerlException;
4312       }
4313     background_color=image->background_color;
4314     if (items == 2)
4315       (void) QueryColorCompliance((char *) SvPV(ST(1),na),AllCompliance,
4316         &background_color,exception);
4317     else
4318       for (i=2; i < items; i+=2)
4319       {
4320         attribute=(char *) SvPV(ST(i-1),na);
4321         switch (*attribute)
4322         {
4323           case 'B':
4324           case 'b':
4325           {
4326             if (LocaleCompare(attribute,"background") == 0)
4327               {
4328                 (void) QueryColorCompliance((char *) SvPV(ST(1),na),
4329                   AllCompliance,&background_color,exception);
4330                 break;
4331               }
4332             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4333               attribute);
4334             break;
4335           }
4336           default:
4337           {
4338             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4339               attribute);
4340             break;
4341           }
4342         }
4343       }
4344     image->background_color=background_color;
4345     image=MergeImageLayers(image,FlattenLayer,exception);
4346     if (image == (Image *) NULL)
4347       goto PerlException;
4348     /*
4349       Create blessed Perl array for the returned image.
4350     */
4351     av=newAV();
4352     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4353     SvREFCNT_dec(av);
4354     AddImageToRegistry(sv,image);
4355     rv=newRV(sv);
4356     av_push(av,sv_bless(rv,hv));
4357     SvREFCNT_dec(sv);
4358     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4359     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4360       "flatten-%.*s",(int) (MagickPathExtent-9),
4361       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4362     (void) CopyMagickString(image->filename,info->image_info->filename,
4363       MagickPathExtent);
4364     SetImageInfo(info->image_info,0,exception);
4365     exception=DestroyExceptionInfo(exception);
4366     SvREFCNT_dec(perl_exception);
4367     XSRETURN(1);
4368
4369   PerlException:
4370     InheritPerlException(exception,perl_exception);
4371     exception=DestroyExceptionInfo(exception);
4372     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4373     SvPOK_on(perl_exception);  /* return messages in string context */
4374     ST(0)=sv_2mortal(perl_exception);
4375     XSRETURN(1);
4376   }
4377 \f
4378 #
4379 ###############################################################################
4380 #                                                                             #
4381 #                                                                             #
4382 #                                                                             #
4383 #   F x                                                                       #
4384 #                                                                             #
4385 #                                                                             #
4386 #                                                                             #
4387 ###############################################################################
4388 #
4389 #
4390 void
4391 Fx(ref,...)
4392   Image::Magick ref=NO_INIT
4393   ALIAS:
4394     FxImage  = 1
4395     fx       = 2
4396     fximage  = 3
4397   PPCODE:
4398   {
4399     AV
4400       *av;
4401
4402     char
4403       *attribute,
4404       expression[MagickPathExtent];
4405
4406     ChannelType
4407       channel,
4408       channel_mask;
4409
4410     ExceptionInfo
4411       *exception;
4412
4413     HV
4414       *hv;
4415
4416     Image
4417       *image;
4418
4419     register ssize_t
4420       i;
4421
4422     struct PackageInfo
4423       *info;
4424
4425     SV
4426       *av_reference,
4427       *perl_exception,
4428       *reference,
4429       *rv,
4430       *sv;
4431
4432     PERL_UNUSED_VAR(ref);
4433     PERL_UNUSED_VAR(ix);
4434     exception=AcquireExceptionInfo();
4435     perl_exception=newSVpv("",0);
4436     sv=NULL;
4437     attribute=NULL;
4438     av=NULL;
4439     if (sv_isobject(ST(0)) == 0)
4440       {
4441         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4442           PackageName);
4443         goto PerlException;
4444       }
4445     reference=SvRV(ST(0));
4446     hv=SvSTASH(reference);
4447     av=newAV();
4448     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4449     SvREFCNT_dec(av);
4450     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4451     if (image == (Image *) NULL)
4452       {
4453         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4454           PackageName);
4455         goto PerlException;
4456       }
4457     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4458     /*
4459       Get options.
4460     */
4461     channel=DefaultChannels;
4462     (void) CopyMagickString(expression,"u",MagickPathExtent);
4463     if (items == 2)
4464       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
4465     else
4466       for (i=2; i < items; i+=2)
4467       {
4468         attribute=(char *) SvPV(ST(i-1),na);
4469         switch (*attribute)
4470         {
4471           case 'C':
4472           case 'c':
4473           {
4474             if (LocaleCompare(attribute,"channel") == 0)
4475               {
4476                 ssize_t
4477                   option;
4478
4479                 option=ParseChannelOption(SvPV(ST(i),na));
4480                 if (option < 0)
4481                   {
4482                     ThrowPerlException(exception,OptionError,
4483                       "UnrecognizedType",SvPV(ST(i),na));
4484                     return;
4485                   }
4486                 channel=(ChannelType) option;
4487                 break;
4488               }
4489             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4490               attribute);
4491             break;
4492           }
4493           case 'E':
4494           case 'e':
4495           {
4496             if (LocaleCompare(attribute,"expression") == 0)
4497               {
4498                 (void) CopyMagickString(expression,SvPV(ST(i),na),
4499                   MagickPathExtent);
4500                 break;
4501               }
4502             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4503               attribute);
4504             break;
4505           }
4506           default:
4507           {
4508             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4509               attribute);
4510             break;
4511           }
4512         }
4513       }
4514     channel_mask=SetImageChannelMask(image,channel);
4515     image=FxImage(image,expression,exception);
4516     if (image != (Image *) NULL)
4517       (void) SetImageChannelMask(image,channel_mask);
4518     if (image == (Image *) NULL)
4519       goto PerlException;
4520     for ( ; image; image=image->next)
4521     {
4522       AddImageToRegistry(sv,image);
4523       rv=newRV(sv);
4524       av_push(av,sv_bless(rv,hv));
4525       SvREFCNT_dec(sv);
4526     }
4527     exception=DestroyExceptionInfo(exception);
4528     ST(0)=av_reference;
4529     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4530     XSRETURN(1);
4531
4532   PerlException:
4533     InheritPerlException(exception,perl_exception);
4534     exception=DestroyExceptionInfo(exception);
4535     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4536     SvPOK_on(perl_exception);
4537     ST(0)=sv_2mortal(perl_exception);
4538     XSRETURN(1);
4539   }
4540 \f
4541 #
4542 ###############################################################################
4543 #                                                                             #
4544 #                                                                             #
4545 #                                                                             #
4546 #   G e t                                                                     #
4547 #                                                                             #
4548 #                                                                             #
4549 #                                                                             #
4550 ###############################################################################
4551 #
4552 #
4553 void
4554 Get(ref,...)
4555   Image::Magick ref=NO_INIT
4556   ALIAS:
4557     GetAttributes = 1
4558     GetAttribute  = 2
4559     get           = 3
4560     getattributes = 4
4561     getattribute  = 5
4562   PPCODE:
4563   {
4564     char
4565       *attribute,
4566       color[MagickPathExtent];
4567
4568     const char
4569       *value;
4570
4571     ExceptionInfo
4572       *exception;
4573
4574     Image
4575       *image;
4576
4577     long
4578       j;
4579
4580     register ssize_t
4581       i;
4582
4583     struct PackageInfo
4584       *info;
4585
4586     SV
4587       *perl_exception,
4588       *reference,
4589       *s;
4590
4591     PERL_UNUSED_VAR(ref);
4592     PERL_UNUSED_VAR(ix);
4593     exception=AcquireExceptionInfo();
4594     perl_exception=newSVpv("",0);
4595     if (sv_isobject(ST(0)) == 0)
4596       {
4597         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4598           PackageName);
4599         XSRETURN_EMPTY;
4600       }
4601     reference=SvRV(ST(0));
4602     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4603     if (image == (Image *) NULL && !info)
4604       XSRETURN_EMPTY;
4605     EXTEND(sp,items);
4606     for (i=1; i < items; i++)
4607     {
4608       attribute=(char *) SvPV(ST(i),na);
4609       s=NULL;
4610       switch (*attribute)
4611       {
4612         case 'A':
4613         case 'a':
4614         {
4615           if (LocaleCompare(attribute,"adjoin") == 0)
4616             {
4617               if (info)
4618                 s=newSViv((ssize_t) info->image_info->adjoin);
4619               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4620               continue;
4621             }
4622           if (LocaleCompare(attribute,"antialias") == 0)
4623             {
4624               if (info)
4625                 s=newSViv((ssize_t) info->image_info->antialias);
4626               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4627               continue;
4628             }
4629           if (LocaleCompare(attribute,"area") == 0)
4630             {
4631               s=newSViv(GetMagickResource(AreaResource));
4632               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4633               continue;
4634             }
4635           if (LocaleCompare(attribute,"attenuate") == 0)
4636             {
4637               const char
4638                 *value;
4639
4640               value=GetImageProperty(image,attribute,exception);
4641               if (value != (const char *) NULL)
4642                 s=newSVpv(value,0);
4643               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4644               continue;
4645             }
4646           if (LocaleCompare(attribute,"authenticate") == 0)
4647             {
4648               if (info)
4649                 {
4650                   const char
4651                     *option;
4652
4653                   option=GetImageOption(info->image_info,attribute);
4654                   if (option != (const char *) NULL)
4655                     s=newSVpv(option,0);
4656                 }
4657               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4658               continue;
4659             }
4660           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4661             attribute);
4662           break;
4663         }
4664         case 'B':
4665         case 'b':
4666         {
4667           if (LocaleCompare(attribute,"background") == 0)
4668             {
4669               if (image == (Image *) NULL)
4670                 break;
4671               (void) FormatLocaleString(color,MagickPathExtent,
4672                 "%.20g,%.20g,%.20g,%.20g",(double) image->background_color.red,
4673                 (double) image->background_color.green,
4674                 (double) image->background_color.blue,
4675                 (double) image->background_color.alpha);
4676               s=newSVpv(color,0);
4677               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4678               continue;
4679             }
4680           if (LocaleCompare(attribute,"base-columns") == 0)
4681             {
4682               if (image != (Image *) NULL)
4683                 s=newSViv((ssize_t) image->magick_columns);
4684               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4685               continue;
4686             }
4687           if (LocaleCompare(attribute,"base-filename") == 0)
4688             {
4689               if (image != (Image *) NULL)
4690                 s=newSVpv(image->magick_filename,0);
4691               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4692               continue;
4693             }
4694           if (LocaleCompare(attribute,"base-height") == 0)
4695             {
4696               if (image != (Image *) NULL)
4697                 s=newSViv((ssize_t) image->magick_rows);
4698               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4699               continue;
4700             }
4701           if (LocaleCompare(attribute,"base-rows") == 0)
4702             {
4703               if (image != (Image *) NULL)
4704                 s=newSViv((ssize_t) image->magick_rows);
4705               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4706               continue;
4707             }
4708           if (LocaleCompare(attribute,"base-width") == 0)
4709             {
4710               if (image != (Image *) NULL)
4711                 s=newSViv((ssize_t) image->magick_columns);
4712               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4713               continue;
4714             }
4715           if (LocaleCompare(attribute,"blue-primary") == 0)
4716             {
4717               if (image == (Image *) NULL)
4718                 break;
4719               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
4720                 image->chromaticity.blue_primary.x,
4721                 image->chromaticity.blue_primary.y);
4722               s=newSVpv(color,0);
4723               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4724               continue;
4725             }
4726           if (LocaleCompare(attribute,"bordercolor") == 0)
4727             {
4728               if (image == (Image *) NULL)
4729                 break;
4730               (void) FormatLocaleString(color,MagickPathExtent,
4731                 "%.20g,%.20g,%.20g,%.20g",(double) image->border_color.red,
4732                 (double) image->border_color.green,
4733                 (double) image->border_color.blue,
4734                 (double) image->border_color.alpha);
4735               s=newSVpv(color,0);
4736               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4737               continue;
4738             }
4739           if (LocaleCompare(attribute,"bounding-box") == 0)
4740             {
4741               char
4742                 geometry[MagickPathExtent];
4743
4744               RectangleInfo
4745                 page;
4746
4747               if (image == (Image *) NULL)
4748                 break;
4749               page=GetImageBoundingBox(image,exception);
4750               (void) FormatLocaleString(geometry,MagickPathExtent,
4751                 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4752                 page.height,(double) page.x,(double) page.y);
4753               s=newSVpv(geometry,0);
4754               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4755               continue;
4756             }
4757           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4758             attribute);
4759           break;
4760         }
4761         case 'C':
4762         case 'c':
4763         {
4764           if (LocaleCompare(attribute,"class") == 0)
4765             {
4766               if (image == (Image *) NULL)
4767                 break;
4768               s=newSViv(image->storage_class);
4769               (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4770                 image->storage_class));
4771               SvIOK_on(s);
4772               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4773               continue;
4774             }
4775           if (LocaleCompare(attribute,"clip-mask") == 0)
4776             {
4777               if (image != (Image *) NULL)
4778                 {
4779                   Image
4780                     *mask_image;
4781
4782                   SV
4783                     *sv;
4784
4785                   sv=NULL;
4786                   if (image->read_mask == MagickFalse)
4787                     ClipImage(image,exception);
4788                   mask_image=GetImageMask(image,ReadPixelMask,exception);
4789                   if (mask_image != (Image *) NULL)
4790                     {
4791                       AddImageToRegistry(sv,mask_image);
4792                       s=sv_bless(newRV(sv),SvSTASH(reference));
4793                     }
4794                 }
4795               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4796               continue;
4797             }
4798           if (LocaleCompare(attribute,"clip-path") == 0)
4799             {
4800               if (image != (Image *) NULL)
4801                 {
4802                   Image
4803                     *mask_image;
4804
4805                   SV
4806                     *sv;
4807
4808                   sv=NULL;
4809                   if (image->read_mask != MagickFalse)
4810                     ClipImage(image,exception);
4811                   mask_image=GetImageMask(image,ReadPixelMask,exception);
4812                   if (mask_image != (Image *) NULL)
4813                     {
4814                       AddImageToRegistry(sv,mask_image);
4815                       s=sv_bless(newRV(sv),SvSTASH(reference));
4816                     }
4817                 }
4818               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4819               continue;
4820             }
4821           if (LocaleCompare(attribute,"compression") == 0)
4822             {
4823               j=info ? info->image_info->compression : image ?
4824                 image->compression : UndefinedCompression;
4825               if (info)
4826                 if (info->image_info->compression == UndefinedCompression)
4827                   j=image->compression;
4828               s=newSViv(j);
4829               (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4830                 j));
4831               SvIOK_on(s);
4832               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4833               continue;
4834             }
4835           if (LocaleCompare(attribute,"colorspace") == 0)
4836             {
4837               j=image ? image->colorspace : RGBColorspace;
4838               s=newSViv(j);
4839               (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4840                 j));
4841               SvIOK_on(s);
4842               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4843               continue;
4844             }
4845           if (LocaleCompare(attribute,"colors") == 0)
4846             {
4847               if (image != (Image *) NULL)
4848                 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4849                   exception));
4850               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4851               continue;
4852             }
4853           if (LocaleNCompare(attribute,"colormap",8) == 0)
4854             {
4855               int
4856                 items;
4857
4858               if (image == (Image *) NULL || !image->colormap)
4859                 break;
4860               j=0;
4861               items=sscanf(attribute,"%*[^[][%ld",&j);
4862               (void) items;
4863               if (j > (ssize_t) image->colors)
4864                 j%=image->colors;
4865               (void) FormatLocaleString(color,MagickPathExtent,
4866                 "%.20g,%.20g,%.20g,%.20g",(double) image->colormap[j].red,
4867                 (double) image->colormap[j].green,
4868                 (double) image->colormap[j].blue,
4869                 (double) image->colormap[j].alpha);
4870               s=newSVpv(color,0);
4871               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4872               continue;
4873             }
4874           if (LocaleCompare(attribute,"columns") == 0)
4875             {
4876               if (image != (Image *) NULL)
4877                 s=newSViv((ssize_t) image->columns);
4878               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4879               continue;
4880             }
4881           if (LocaleCompare(attribute,"comment") == 0)
4882             {
4883               const char
4884                 *value;
4885
4886               value=GetImageProperty(image,attribute,exception);
4887               if (value != (const char *) NULL)
4888                 s=newSVpv(value,0);
4889               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4890               continue;
4891             }
4892           if (LocaleCompare(attribute,"copyright") == 0)
4893             {
4894               s=newSVpv(GetMagickCopyright(),0);
4895               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4896               continue;
4897             }
4898           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4899             attribute);
4900           break;
4901         }
4902         case 'D':
4903         case 'd':
4904         {
4905           if (LocaleCompare(attribute,"density") == 0)
4906             {
4907               char
4908                 geometry[MagickPathExtent];
4909
4910               if (image == (Image *) NULL)
4911                 break;
4912               (void) FormatLocaleString(geometry,MagickPathExtent,"%.15gx%.15g",
4913                 image->resolution.x,image->resolution.y);
4914               s=newSVpv(geometry,0);
4915               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4916               continue;
4917             }
4918           if (LocaleCompare(attribute,"delay") == 0)
4919             {
4920               if (image != (Image *) NULL)
4921                 s=newSViv((ssize_t) image->delay);
4922               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4923               continue;
4924             }
4925           if (LocaleCompare(attribute,"depth") == 0)
4926             {
4927               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4928               if (image != (Image *) NULL)
4929                 s=newSViv((ssize_t) GetImageDepth(image,exception));
4930               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4931               continue;
4932             }
4933           if (LocaleCompare(attribute,"directory") == 0)
4934             {
4935               if (image && image->directory)
4936                 s=newSVpv(image->directory,0);
4937               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4938               continue;
4939             }
4940           if (LocaleCompare(attribute,"dispose") == 0)
4941             {
4942               if (image == (Image *) NULL)
4943                 break;
4944
4945               s=newSViv(image->dispose);
4946               (void) sv_setpv(s,
4947                 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
4948               SvIOK_on(s);
4949               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4950               continue;
4951             }
4952           if (LocaleCompare(attribute,"disk") == 0)
4953             {
4954               s=newSViv(GetMagickResource(DiskResource));
4955               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4956               continue;
4957             }
4958           if (LocaleCompare(attribute,"dither") == 0)
4959             {
4960               if (info)
4961                 s=newSViv((ssize_t) info->image_info->dither);
4962               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4963               continue;
4964             }
4965           if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4966             {
4967               if (info && info->image_info->server_name)
4968                 s=newSVpv(info->image_info->server_name,0);
4969               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4970               continue;
4971             }
4972           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4973             attribute);
4974           break;
4975         }
4976         case 'E':
4977         case 'e':
4978         {
4979           if (LocaleCompare(attribute,"elapsed-time") == 0)
4980             {
4981               if (image != (Image *) NULL)
4982                 s=newSVnv(GetElapsedTime(&image->timer));
4983               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4984               continue;
4985             }
4986           if (LocaleCompare(attribute,"endian") == 0)
4987             {
4988               j=info ? info->image_info->endian : image ? image->endian :
4989                 UndefinedEndian;
4990               s=newSViv(j);
4991               (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
4992               SvIOK_on(s);
4993               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4994               continue;
4995             }
4996           if (LocaleCompare(attribute,"error") == 0)
4997             {
4998               if (image != (Image *) NULL)
4999                 s=newSVnv(image->error.mean_error_per_pixel);
5000               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5001               continue;
5002             }
5003           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5004             attribute);
5005           break;
5006         }
5007         case 'F':
5008         case 'f':
5009         {
5010           if (LocaleCompare(attribute,"filesize") == 0)
5011             {
5012               if (image != (Image *) NULL)
5013                 s=newSViv((ssize_t) GetBlobSize(image));
5014               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5015               continue;
5016             }
5017           if (LocaleCompare(attribute,"filename") == 0)
5018             {
5019               if (info && info->image_info->filename &&
5020                   *info->image_info->filename)
5021                 s=newSVpv(info->image_info->filename,0);
5022               if (image != (Image *) NULL)
5023                 s=newSVpv(image->filename,0);
5024               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5025               continue;
5026             }
5027           if (LocaleCompare(attribute,"filter") == 0)
5028             {
5029               s=image ? newSViv(image->filter) : newSViv(0);
5030               (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
5031                 image->filter));
5032               SvIOK_on(s);
5033               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5034               continue;
5035             }
5036           if (LocaleCompare(attribute,"font") == 0)
5037             {
5038               if (info && info->image_info->font)
5039                 s=newSVpv(info->image_info->font,0);
5040               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5041               continue;
5042             }
5043           if (LocaleCompare(attribute,"foreground") == 0)
5044             continue;
5045           if (LocaleCompare(attribute,"format") == 0)
5046             {
5047               const MagickInfo
5048                 *magick_info;
5049
5050               magick_info=(const MagickInfo *) NULL;
5051               if (info && (*info->image_info->magick != '\0'))
5052                 magick_info=GetMagickInfo(info->image_info->magick,exception);
5053               if (image != (Image *) NULL)
5054                 magick_info=GetMagickInfo(image->magick,exception);
5055               if ((magick_info != (const MagickInfo *) NULL) &&
5056                   (*magick_info->description != '\0'))
5057                 s=newSVpv((char *) magick_info->description,0);
5058               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5059               continue;
5060             }
5061           if (LocaleCompare(attribute,"fuzz") == 0)
5062             {
5063               if (info)
5064                 s=newSVnv(info->image_info->fuzz);
5065               if (image != (Image *) NULL)
5066                 s=newSVnv(image->fuzz);
5067               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5068               continue;
5069             }
5070           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5071             attribute);
5072           break;
5073         }
5074         case 'G':
5075         case 'g':
5076         {
5077           if (LocaleCompare(attribute,"gamma") == 0)
5078             {
5079               if (image != (Image *) NULL)
5080                 s=newSVnv(image->gamma);
5081               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5082               continue;
5083             }
5084           if (LocaleCompare(attribute,"geometry") == 0)
5085             {
5086               if (image && image->geometry)
5087                 s=newSVpv(image->geometry,0);
5088               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5089               continue;
5090             }
5091           if (LocaleCompare(attribute,"gravity") == 0)
5092             {
5093               s=image ? newSViv(image->gravity) : newSViv(0);
5094               (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
5095                 image->gravity));
5096               SvIOK_on(s);
5097               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5098               continue;
5099             }
5100           if (LocaleCompare(attribute,"green-primary") == 0)
5101             {
5102               if (image == (Image *) NULL)
5103                 break;
5104               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
5105                 image->chromaticity.green_primary.x,
5106                 image->chromaticity.green_primary.y);
5107               s=newSVpv(color,0);
5108               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5109               continue;
5110             }
5111           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5112             attribute);
5113           break;
5114         }
5115         case 'H':
5116         case 'h':
5117         {
5118           if (LocaleCompare(attribute,"height") == 0)
5119             {
5120               if (image != (Image *) NULL)
5121                 s=newSViv((ssize_t) image->rows);
5122               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5123               continue;
5124             }
5125           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5126             attribute);
5127           break;
5128         }
5129         case 'I':
5130         case 'i':
5131         {
5132           if (LocaleCompare(attribute,"icc") == 0)
5133             {
5134               if (image != (Image *) NULL)
5135                 {
5136                   const StringInfo
5137                     *profile;
5138
5139                   profile=GetImageProfile(image,"icc");
5140                   if (profile != (StringInfo *) NULL)
5141                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5142                       GetStringInfoLength(profile));
5143                 }
5144               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5145               continue;
5146             }
5147           if (LocaleCompare(attribute,"icm") == 0)
5148             {
5149               if (image != (Image *) NULL)
5150                 {
5151                   const StringInfo
5152                     *profile;
5153
5154                   profile=GetImageProfile(image,"icm");
5155                   if (profile != (const StringInfo *) NULL)
5156                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5157                       GetStringInfoLength(profile));
5158                 }
5159               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5160               continue;
5161             }
5162           if (LocaleCompare(attribute,"id") == 0)
5163             {
5164               if (image != (Image *) NULL)
5165                 {
5166                   char
5167                     key[MagickPathExtent];
5168
5169                   MagickBooleanType
5170                     status;
5171
5172                   static ssize_t
5173                     id = 0;
5174
5175                   (void) FormatLocaleString(key,MagickPathExtent,"%.20g\n",(double)
5176                     id);
5177                   status=SetImageRegistry(ImageRegistryType,key,image,
5178                     exception);
5179                   (void) status;
5180                   s=newSViv(id++);
5181                 }
5182               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5183               continue;
5184             }
5185           if (LocaleNCompare(attribute,"index",5) == 0)
5186             {
5187               char
5188                 name[MagickPathExtent];
5189
5190               int
5191                 items;
5192
5193               long
5194                 x,
5195                 y;
5196
5197               register const Quantum
5198                 *p;
5199
5200               CacheView
5201                 *image_view;
5202
5203               if (image == (Image *) NULL)
5204                 break;
5205               if (image->storage_class != PseudoClass)
5206                 break;
5207               x=0;
5208               y=0;
5209               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5210               (void) items;
5211               image_view=AcquireVirtualCacheView(image,exception);
5212               p=GetCacheViewVirtualPixels(image_view,x,y,1,1,exception);
5213               if (p != (const Quantum *) NULL)
5214                 {
5215                   (void) FormatLocaleString(name,MagickPathExtent,QuantumFormat,
5216                     GetPixelIndex(image,p));
5217                   s=newSVpv(name,0);
5218                   PUSHs(s ? sv_2mortal(s) : &sv_undef);
5219                 }
5220               image_view=DestroyCacheView(image_view);
5221               continue;
5222             }
5223           if (LocaleCompare(attribute,"iptc") == 0)
5224             {
5225               if (image != (Image *) NULL)
5226                 {
5227                   const StringInfo
5228                     *profile;
5229
5230                   profile=GetImageProfile(image,"iptc");
5231                   if (profile != (const StringInfo *) NULL)
5232                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5233                       GetStringInfoLength(profile));
5234                 }
5235               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5236               continue;
5237             }
5238           if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
5239             {
5240               if (image != (Image *) NULL)
5241                 s=newSViv((ssize_t) image->iterations);
5242               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5243               continue;
5244             }
5245           if (LocaleCompare(attribute,"interlace") == 0)
5246             {
5247               j=info ? info->image_info->interlace : image ? image->interlace :
5248                 UndefinedInterlace;
5249               s=newSViv(j);
5250               (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
5251                 j));
5252               SvIOK_on(s);
5253               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5254               continue;
5255             }
5256           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5257             attribute);
5258           break;
5259         }
5260         case 'L':
5261         case 'l':
5262         {
5263           if (LocaleCompare(attribute,"label") == 0)
5264             {
5265               const char
5266                 *value;
5267
5268               if (image == (Image *) NULL)
5269                 break;
5270               value=GetImageProperty(image,"Label",exception);
5271               if (value != (const char *) NULL)
5272                 s=newSVpv(value,0);
5273               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5274               continue;
5275             }
5276           if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
5277             {
5278               if (image != (Image *) NULL)
5279                 s=newSViv((ssize_t) image->iterations);
5280               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5281               continue;
5282             }
5283           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5284             attribute);
5285           break;
5286         }
5287         case 'M':
5288         case 'm':
5289         {
5290           if (LocaleCompare(attribute,"magick") == 0)
5291             {
5292               if (info && *info->image_info->magick)
5293                 s=newSVpv(info->image_info->magick,0);
5294               if (image != (Image *) NULL)
5295                 s=newSVpv(image->magick,0);
5296               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5297               continue;
5298             }
5299           if (LocaleCompare(attribute,"map") == 0)
5300             {
5301               s=newSViv(GetMagickResource(MapResource));
5302               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5303               continue;
5304             }
5305           if (LocaleCompare(attribute,"maximum-error") == 0)
5306             {
5307               if (image != (Image *) NULL)
5308                 s=newSVnv(image->error.normalized_maximum_error);
5309               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5310               continue;
5311             }
5312           if (LocaleCompare(attribute,"memory") == 0)
5313             {
5314               s=newSViv(GetMagickResource(MemoryResource));
5315               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5316               continue;
5317             }
5318           if (LocaleCompare(attribute,"mean-error") == 0)
5319             {
5320               if (image != (Image *) NULL)
5321                 s=newSVnv(image->error.normalized_mean_error);
5322               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5323               continue;
5324             }
5325           if (LocaleCompare(attribute,"mime") == 0)
5326             {
5327               if (info && *info->image_info->magick)
5328                 s=newSVpv(MagickToMime(info->image_info->magick),0);
5329               if (image != (Image *) NULL)
5330                 s=newSVpv(MagickToMime(image->magick),0);
5331               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5332               continue;
5333             }
5334           if (LocaleCompare(attribute,"mattecolor") == 0)
5335             {
5336               if (image == (Image *) NULL)
5337                 break;
5338               (void) FormatLocaleString(color,MagickPathExtent,
5339                 "%.20g,%.20g,%.20g,%.20g",(double) image->alpha_color.red,
5340                 (double) image->alpha_color.green,
5341                 (double) image->alpha_color.blue,
5342                 (double) image->alpha_color.alpha);
5343               s=newSVpv(color,0);
5344               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5345               continue;
5346             }
5347           if (LocaleCompare(attribute,"matte") == 0)
5348             {
5349               if (image != (Image *) NULL)
5350                 s=newSViv((ssize_t) image->alpha_trait != UndefinedPixelTrait ?
5351                   1 : 0);
5352               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5353               continue;
5354             }
5355           if (LocaleCompare(attribute,"mime") == 0)
5356             {
5357               const char
5358                 *magick;
5359
5360               magick=NULL;
5361               if (info && *info->image_info->magick)
5362                 magick=info->image_info->magick;
5363               if (image != (Image *) NULL)
5364                 magick=image->magick;
5365               if (magick)
5366                 {
5367                   char
5368                     *mime;
5369
5370                   mime=MagickToMime(magick);
5371                   s=newSVpv(mime,0);
5372                   mime=(char *) RelinquishMagickMemory(mime);
5373                 }
5374               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5375               continue;
5376             }
5377           if (LocaleCompare(attribute,"monochrome") == 0)
5378             {
5379               if (image == (Image *) NULL)
5380                 continue;
5381               j=info ? info->image_info->monochrome :
5382                 SetImageMonochrome(image,exception);
5383               s=newSViv(j);
5384               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5385               continue;
5386             }
5387           if (LocaleCompare(attribute,"montage") == 0)
5388             {
5389               if (image && image->montage)
5390                 s=newSVpv(image->montage,0);
5391               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5392               continue;
5393             }
5394           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5395             attribute);
5396           break;
5397         }
5398         case 'O':
5399         case 'o':
5400         {
5401           if (LocaleCompare(attribute,"orientation") == 0)
5402             {
5403               j=info ? info->image_info->orientation : image ?
5404                 image->orientation : UndefinedOrientation;
5405               s=newSViv(j);
5406               (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5407                 j));
5408               SvIOK_on(s);
5409               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5410               continue;
5411             }
5412           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5413             attribute);
5414           break;
5415         }
5416         case 'P':
5417         case 'p':
5418         {
5419           if (LocaleCompare(attribute,"page") == 0)
5420             {
5421               if (info && info->image_info->page)
5422                 s=newSVpv(info->image_info->page,0);
5423               if (image != (Image *) NULL)
5424                 {
5425                   char
5426                     geometry[MagickPathExtent];
5427
5428                   (void) FormatLocaleString(geometry,MagickPathExtent,
5429                     "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5430                     (double) image->page.height,(double) image->page.x,(double)
5431                     image->page.y);
5432                   s=newSVpv(geometry,0);
5433                 }
5434               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5435               continue;
5436             }
5437           if (LocaleCompare(attribute,"page.x") == 0)
5438             {
5439               if (image != (Image *) NULL)
5440                 s=newSViv((ssize_t) image->page.x);
5441               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5442               continue;
5443             }
5444           if (LocaleCompare(attribute,"page.y") == 0)
5445             {
5446               if (image != (Image *) NULL)
5447                 s=newSViv((ssize_t) image->page.y);
5448               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5449               continue;
5450             }
5451           if (LocaleNCompare(attribute,"pixel",5) == 0)
5452             {
5453               char
5454                 tuple[MagickPathExtent];
5455
5456               int
5457                 items;
5458
5459               long
5460                 x,
5461                 y;
5462
5463               register const Quantum
5464                 *p;
5465
5466               if (image == (Image *) NULL)
5467                 break;
5468               x=0;
5469               y=0;
5470               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5471               (void) items;
5472               p=GetVirtualPixels(image,x,y,1,1,exception);
5473               if (image->colorspace != CMYKColorspace)
5474                 (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
5475                   QuantumFormat "," QuantumFormat "," QuantumFormat,
5476                   GetPixelRed(image,p),GetPixelGreen(image,p),
5477                   GetPixelBlue(image,p),GetPixelAlpha(image,p));
5478               else
5479                 (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
5480                   QuantumFormat "," QuantumFormat "," QuantumFormat ","
5481                   QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5482                   GetPixelBlue(image,p),GetPixelBlack(image,p),
5483                   GetPixelAlpha(image,p));
5484               s=newSVpv(tuple,0);
5485               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5486               continue;
5487             }
5488           if (LocaleCompare(attribute,"pointsize") == 0)
5489             {
5490               if (info)
5491                 s=newSViv((ssize_t) info->image_info->pointsize);
5492               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5493               continue;
5494             }
5495           if (LocaleCompare(attribute,"preview") == 0)
5496             {
5497               s=newSViv(info->image_info->preview_type);
5498               (void) sv_setpv(s,CommandOptionToMnemonic(MagickPreviewOptions,
5499                 info->image_info->preview_type));
5500               SvIOK_on(s);
5501               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5502               continue;
5503             }
5504           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5505             attribute);
5506           break;
5507         }
5508         case 'Q':
5509         case 'q':
5510         {
5511           if (LocaleCompare(attribute,"quality") == 0)
5512             {
5513               if (info)
5514                 s=newSViv((ssize_t) info->image_info->quality);
5515               if (image != (Image *) NULL)
5516                 s=newSViv((ssize_t) image->quality);
5517               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5518               continue;
5519             }
5520           if (LocaleCompare(attribute,"quantum") == 0)
5521             {
5522               if (info)
5523                 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5524               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5525               continue;
5526             }
5527           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5528             attribute);
5529           break;
5530         }
5531         case 'R':
5532         case 'r':
5533         {
5534           if (LocaleCompare(attribute,"rendering-intent") == 0)
5535             {
5536               s=newSViv(image->rendering_intent);
5537               (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5538                 image->rendering_intent));
5539               SvIOK_on(s);
5540               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5541               continue;
5542             }
5543           if (LocaleCompare(attribute,"red-primary") == 0)
5544             {
5545               if (image == (Image *) NULL)
5546                 break;
5547               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
5548                 image->chromaticity.red_primary.x,
5549                 image->chromaticity.red_primary.y);
5550               s=newSVpv(color,0);
5551               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5552               continue;
5553             }
5554           if (LocaleCompare(attribute,"rows") == 0)
5555             {
5556               if (image != (Image *) NULL)
5557                 s=newSViv((ssize_t) image->rows);
5558               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5559               continue;
5560             }
5561           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5562             attribute);
5563           break;
5564         }
5565         case 'S':
5566         case 's':
5567         {
5568           if (LocaleCompare(attribute,"sampling-factor") == 0)
5569             {
5570               if (info && info->image_info->sampling_factor)
5571                 s=newSVpv(info->image_info->sampling_factor,0);
5572               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5573               continue;
5574             }
5575           if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5576             {
5577               if (info && info->image_info->server_name)
5578                 s=newSVpv(info->image_info->server_name,0);
5579               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5580               continue;
5581             }
5582           if (LocaleCompare(attribute,"size") == 0)
5583             {
5584               if (info && info->image_info->size)
5585                 s=newSVpv(info->image_info->size,0);
5586               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5587               continue;
5588             }
5589           if (LocaleCompare(attribute,"scene") == 0)
5590             {
5591               if (image != (Image *) NULL)
5592                 s=newSViv((ssize_t) image->scene);
5593               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5594               continue;
5595             }
5596           if (LocaleCompare(attribute,"scenes") == 0)
5597             {
5598               if (image != (Image *) NULL)
5599                 s=newSViv((ssize_t) info->image_info->number_scenes);
5600               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5601               continue;
5602             }
5603           if (LocaleCompare(attribute,"signature") == 0)
5604             {
5605               const char
5606                 *value;
5607
5608               if (image == (Image *) NULL)
5609                 break;
5610               (void) SignatureImage(image,exception);
5611               value=GetImageProperty(image,"Signature",exception);
5612               if (value != (const char *) NULL)
5613                 s=newSVpv(value,0);
5614               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5615               continue;
5616             }
5617           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5618             attribute);
5619           break;
5620         }
5621         case 'T':
5622         case 't':
5623         {
5624           if (LocaleCompare(attribute,"taint") == 0)
5625             {
5626               if (image != (Image *) NULL)
5627                 s=newSViv((ssize_t) IsTaintImage(image));
5628               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5629               continue;
5630             }
5631           if (LocaleCompare(attribute,"texture") == 0)
5632             {
5633               if (info && info->image_info->texture)
5634                 s=newSVpv(info->image_info->texture,0);
5635               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5636               continue;
5637             }
5638           if (LocaleCompare(attribute,"total-ink-density") == 0)
5639             {
5640               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5641               if (image != (Image *) NULL)
5642                 s=newSVnv(GetImageTotalInkDensity(image,exception));
5643               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5644               continue;
5645             }
5646           if (LocaleCompare(attribute,"transparent-color") == 0)
5647             {
5648               if (image == (Image *) NULL)
5649                 break;
5650               (void) FormatLocaleString(color,MagickPathExtent,
5651                 "%.20g,%.20g,%.20g,%.20g",(double) image->transparent_color.red,
5652                 (double) image->transparent_color.green,
5653                 (double) image->transparent_color.blue,
5654                 (double) image->transparent_color.alpha);
5655               s=newSVpv(color,0);
5656               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5657               continue;
5658             }
5659           if (LocaleCompare(attribute,"type") == 0)
5660             {
5661               if (image == (Image *) NULL)
5662                 break;
5663               j=(ssize_t) GetImageType(image);
5664               s=newSViv(j);
5665               (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5666               SvIOK_on(s);
5667               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5668               continue;
5669             }
5670           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5671             attribute);
5672           break;
5673         }
5674         case 'U':
5675         case 'u':
5676         {
5677           if (LocaleCompare(attribute,"units") == 0)
5678             {
5679               j=info ? info->image_info->units : image ? image->units :
5680                 UndefinedResolution;
5681               if (info && (info->image_info->units == UndefinedResolution))
5682                 if (image)
5683                   j=image->units;
5684               if (j == UndefinedResolution)
5685                 s=newSVpv("undefined units",0);
5686               else
5687                 if (j == PixelsPerInchResolution)
5688                   s=newSVpv("pixels / inch",0);
5689                 else
5690                   s=newSVpv("pixels / centimeter",0);
5691               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5692               continue;
5693             }
5694           if (LocaleCompare(attribute,"user-time") == 0)
5695             {
5696               if (image != (Image *) NULL)
5697                 s=newSVnv(GetUserTime(&image->timer));
5698               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5699               continue;
5700             }
5701           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5702             attribute);
5703           break;
5704         }
5705         case 'V':
5706         case 'v':
5707         {
5708           if (LocaleCompare(attribute,"verbose") == 0)
5709             {
5710               if (info)
5711                 s=newSViv((ssize_t) info->image_info->verbose);
5712               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5713               continue;
5714             }
5715           if (LocaleCompare(attribute,"version") == 0)
5716             {
5717               s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5718               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5719               continue;
5720             }
5721           if (LocaleCompare(attribute,"virtual-pixel") == 0)
5722             {
5723               if (image == (Image *) NULL)
5724                 break;
5725               j=(ssize_t) GetImageVirtualPixelMethod(image);
5726               s=newSViv(j);
5727               (void) sv_setpv(s,CommandOptionToMnemonic(
5728                 MagickVirtualPixelOptions,j));
5729               SvIOK_on(s);
5730               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5731               continue;
5732             }
5733           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5734             attribute);
5735           break;
5736         }
5737         case 'W':
5738         case 'w':
5739         {
5740           if (LocaleCompare(attribute,"white-point") == 0)
5741             {
5742               if (image == (Image *) NULL)
5743                 break;
5744               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
5745                 image->chromaticity.white_point.x,
5746                 image->chromaticity.white_point.y);
5747               s=newSVpv(color,0);
5748               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5749               continue;
5750             }
5751           if (LocaleCompare(attribute,"width") == 0)
5752             {
5753               if (image != (Image *) NULL)
5754                 s=newSViv((ssize_t) image->columns);
5755               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5756               continue;
5757             }
5758           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5759              attribute);
5760           break;
5761         }
5762         case 'X':
5763         case 'x':
5764         {
5765           if (LocaleCompare(attribute,"xmp") == 0)
5766             {
5767               if (image != (Image *) NULL)
5768                 {
5769                   const StringInfo
5770                     *profile;
5771
5772                   profile=GetImageProfile(image,"xmp");
5773                   if (profile != (StringInfo *) NULL)
5774                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5775                       GetStringInfoLength(profile));
5776                 }
5777               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5778               continue;
5779             }
5780           if (LocaleCompare(attribute,"x-resolution") == 0)
5781             {
5782               if (image != (Image *) NULL)
5783                 s=newSVnv(image->resolution.x);
5784               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5785               continue;
5786             }
5787           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5788             attribute);
5789           break;
5790         }
5791         case 'Y':
5792         case 'y':
5793         {
5794           if (LocaleCompare(attribute,"y-resolution") == 0)
5795             {
5796               if (image != (Image *) NULL)
5797                 s=newSVnv(image->resolution.y);
5798               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5799               continue;
5800             }
5801           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5802             attribute);
5803           break;
5804         }
5805         default:
5806           break;
5807       }
5808       if (image == (Image *) NULL)
5809         ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5810           attribute)
5811       else
5812         {
5813           value=GetImageProperty(image,attribute,exception);
5814           if (value != (const char *) NULL)
5815             {
5816               s=newSVpv(value,0);
5817               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5818             }
5819           else
5820             if (*attribute != '%')
5821               ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5822                 attribute)
5823             else
5824               {
5825                  char
5826                    *meta;
5827
5828                  meta=InterpretImageProperties(info ? info->image_info :
5829                    (ImageInfo *) NULL,image,attribute,exception);
5830                  s=newSVpv(meta,0);
5831                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5832                  meta=(char *) RelinquishMagickMemory(meta);
5833               }
5834         }
5835     }
5836     exception=DestroyExceptionInfo(exception);
5837     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5838   }
5839 \f
5840 #
5841 ###############################################################################
5842 #                                                                             #
5843 #                                                                             #
5844 #                                                                             #
5845 #   G e t A u t h e n t i c P i x e l s                                       #
5846 #                                                                             #
5847 #                                                                             #
5848 #                                                                             #
5849 ###############################################################################
5850 #
5851 #
5852 void *
5853 GetAuthenticPixels(ref,...)
5854   Image::Magick ref = NO_INIT
5855   ALIAS:
5856     getauthenticpixels = 1
5857     GetImagePixels = 2
5858     getimagepixels = 3
5859   CODE:
5860   {
5861     char
5862       *attribute;
5863
5864     ExceptionInfo
5865       *exception;
5866
5867     Image
5868       *image;
5869
5870     RectangleInfo
5871       region;
5872
5873     ssize_t
5874       i;
5875
5876     struct PackageInfo
5877       *info;
5878
5879     SV
5880       *perl_exception,
5881       *reference;
5882
5883     void
5884       *blob = NULL;
5885
5886     PERL_UNUSED_VAR(ref);
5887     PERL_UNUSED_VAR(ix);
5888     exception=AcquireExceptionInfo();
5889     perl_exception=newSVpv("",0);
5890     if (sv_isobject(ST(0)) == 0)
5891       {
5892         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5893           PackageName);
5894         goto PerlException;
5895       }
5896     reference=SvRV(ST(0));
5897
5898     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5899     if (image == (Image *) NULL)
5900       {
5901         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5902           PackageName);
5903         goto PerlException;
5904       }
5905
5906     region.x=0;
5907     region.y=0;
5908     region.width=image->columns;
5909     region.height=1;
5910     if (items == 1)
5911       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5912     for (i=2; i < items; i+=2)
5913     {
5914       attribute=(char *) SvPV(ST(i-1),na);
5915       switch (*attribute)
5916       {
5917         case 'g':
5918         case 'G':
5919         {
5920           if (LocaleCompare(attribute,"geometry") == 0)
5921             {
5922               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5923               break;
5924             }
5925           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5926             attribute);
5927           break;
5928         }
5929         case 'H':
5930         case 'h':
5931         {
5932           if (LocaleCompare(attribute,"height") == 0)
5933             {
5934               region.height=SvIV(ST(i));
5935               continue;
5936             }
5937           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5938             attribute);
5939           break;
5940         }
5941         case 'X':
5942         case 'x':
5943         {
5944           if (LocaleCompare(attribute,"x") == 0)
5945             {
5946               region.x=SvIV(ST(i));
5947               continue;
5948             }
5949           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5950             attribute);
5951           break;
5952         }
5953         case 'Y':
5954         case 'y':
5955         {
5956           if (LocaleCompare(attribute,"y") == 0)
5957             {
5958               region.y=SvIV(ST(i));
5959               continue;
5960             }
5961           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5962             attribute);
5963           break;
5964         }
5965         case 'W':
5966         case 'w':
5967         {
5968           if (LocaleCompare(attribute,"width") == 0)
5969             {
5970               region.width=SvIV(ST(i));
5971               continue;
5972             }
5973           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5974             attribute);
5975           break;
5976         }
5977       }
5978     }
5979     blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5980       region.height,exception);
5981     if (blob != (void *) NULL)
5982       goto PerlEnd;
5983
5984   PerlException:
5985     InheritPerlException(exception,perl_exception);
5986     exception=DestroyExceptionInfo(exception);
5987     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5988
5989   PerlEnd:
5990     RETVAL = blob;
5991   }
5992   OUTPUT:
5993     RETVAL
5994 \f
5995 #
5996 ###############################################################################
5997 #                                                                             #
5998 #                                                                             #
5999 #                                                                             #
6000 #   G e t V i r t u a l P i x e l s                                           #
6001 #                                                                             #
6002 #                                                                             #
6003 #                                                                             #
6004 ###############################################################################
6005 #
6006 #
6007 void *
6008 GetVirtualPixels(ref,...)
6009   Image::Magick ref = NO_INIT
6010   ALIAS:
6011     getvirtualpixels = 1
6012     AcquireImagePixels = 2
6013     acquireimagepixels = 3
6014   CODE:
6015   {
6016     char
6017       *attribute;
6018
6019     const void
6020       *blob = NULL;
6021
6022     ExceptionInfo
6023       *exception;
6024
6025     Image
6026       *image;
6027
6028     RectangleInfo
6029       region;
6030
6031     ssize_t
6032       i;
6033
6034     struct PackageInfo
6035       *info;
6036
6037     SV
6038       *perl_exception,
6039       *reference;
6040
6041     PERL_UNUSED_VAR(ref);
6042     PERL_UNUSED_VAR(ix);
6043     exception=AcquireExceptionInfo();
6044     perl_exception=newSVpv("",0);
6045     if (sv_isobject(ST(0)) == 0)
6046       {
6047         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6048           PackageName);
6049         goto PerlException;
6050       }
6051     reference=SvRV(ST(0));
6052
6053     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6054     if (image == (Image *) NULL)
6055       {
6056         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6057           PackageName);
6058         goto PerlException;
6059       }
6060
6061     region.x=0;
6062     region.y=0;
6063     region.width=image->columns;
6064     region.height=1;
6065     if (items == 1)
6066       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6067     for (i=2; i < items; i+=2)
6068     {
6069       attribute=(char *) SvPV(ST(i-1),na);
6070       switch (*attribute)
6071       {
6072         case 'g':
6073         case 'G':
6074         {
6075           if (LocaleCompare(attribute,"geometry") == 0)
6076             {
6077               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6078               break;
6079             }
6080           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6081             attribute);
6082           break;
6083         }
6084         case 'H':
6085         case 'h':
6086         {
6087           if (LocaleCompare(attribute,"height") == 0)
6088             {
6089               region.height=SvIV(ST(i));
6090               continue;
6091             }
6092           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6093             attribute);
6094           break;
6095         }
6096         case 'X':
6097         case 'x':
6098         {
6099           if (LocaleCompare(attribute,"x") == 0)
6100             {
6101               region.x=SvIV(ST(i));
6102               continue;
6103             }
6104           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6105             attribute);
6106           break;
6107         }
6108         case 'Y':
6109         case 'y':
6110         {
6111           if (LocaleCompare(attribute,"y") == 0)
6112             {
6113               region.y=SvIV(ST(i));
6114               continue;
6115             }
6116           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6117             attribute);
6118           break;
6119         }
6120         case 'W':
6121         case 'w':
6122         {
6123           if (LocaleCompare(attribute,"width") == 0)
6124             {
6125               region.width=SvIV(ST(i));
6126               continue;
6127             }
6128           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6129             attribute);
6130           break;
6131         }
6132       }
6133     }
6134     blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
6135       region.height,exception);
6136     if (blob != (void *) NULL)
6137       goto PerlEnd;
6138
6139   PerlException:
6140     InheritPerlException(exception,perl_exception);
6141     exception=DestroyExceptionInfo(exception);
6142     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6143
6144   PerlEnd:
6145     RETVAL = (void *) blob;
6146   }
6147   OUTPUT:
6148     RETVAL
6149 \f
6150 #
6151 ###############################################################################
6152 #                                                                             #
6153 #                                                                             #
6154 #                                                                             #
6155 #   G e t A u t h e n t i c M e t a c o n t e n t                             #
6156 #                                                                             #
6157 #                                                                             #
6158 #                                                                             #
6159 ###############################################################################
6160 #
6161 #
6162 void *
6163 GetAuthenticMetacontent(ref,...)
6164   Image::Magick ref = NO_INIT
6165   ALIAS:
6166     getauthenticmetacontent = 1
6167     GetMetacontent = 2
6168     getmetacontent = 3
6169   CODE:
6170   {
6171     ExceptionInfo
6172       *exception;
6173
6174     Image
6175       *image;
6176
6177     struct PackageInfo
6178       *info;
6179
6180     SV
6181       *perl_exception,
6182       *reference;
6183
6184     void
6185       *blob = NULL;
6186
6187     PERL_UNUSED_VAR(ref);
6188     PERL_UNUSED_VAR(ix);
6189     exception=AcquireExceptionInfo();
6190     perl_exception=newSVpv("",0);
6191     if (sv_isobject(ST(0)) == 0)
6192       {
6193         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6194           PackageName);
6195         goto PerlException;
6196       }
6197     reference=SvRV(ST(0));
6198
6199     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6200     if (image == (Image *) NULL)
6201       {
6202         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6203           PackageName);
6204         goto PerlException;
6205       }
6206
6207     blob=(void *) GetAuthenticMetacontent(image);
6208     if (blob != (void *) NULL)
6209       goto PerlEnd;
6210
6211   PerlException:
6212     InheritPerlException(exception,perl_exception);
6213     exception=DestroyExceptionInfo(exception);
6214     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6215
6216   PerlEnd:
6217     RETVAL = blob;
6218   }
6219   OUTPUT:
6220     RETVAL
6221 \f
6222 #
6223 ###############################################################################
6224 #                                                                             #
6225 #                                                                             #
6226 #                                                                             #
6227 #   G e t V i r t u a l M e t a c o n t e n t                                 #
6228 #                                                                             #
6229 #                                                                             #
6230 #                                                                             #
6231 ###############################################################################
6232 #
6233 #
6234 void *
6235 GetVirtualMetacontent(ref,...)
6236   Image::Magick ref = NO_INIT
6237   ALIAS:
6238     getvirtualmetacontent = 1
6239   CODE:
6240   {
6241     ExceptionInfo
6242       *exception;
6243
6244     Image
6245       *image;
6246
6247     struct PackageInfo
6248       *info;
6249
6250     SV
6251       *perl_exception,
6252       *reference;
6253
6254     void
6255       *blob = NULL;
6256
6257     PERL_UNUSED_VAR(ref);
6258     PERL_UNUSED_VAR(ix);
6259     exception=AcquireExceptionInfo();
6260     perl_exception=newSVpv("",0);
6261     if (sv_isobject(ST(0)) == 0)
6262       {
6263         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6264           PackageName);
6265         goto PerlException;
6266       }
6267     reference=SvRV(ST(0));
6268
6269     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6270     if (image == (Image *) NULL)
6271       {
6272         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6273           PackageName);
6274         goto PerlException;
6275       }
6276
6277     blob=(void *) GetVirtualMetacontent(image);
6278     if (blob != (void *) NULL)
6279       goto PerlEnd;
6280
6281   PerlException:
6282     InheritPerlException(exception,perl_exception);
6283     exception=DestroyExceptionInfo(exception);
6284     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6285
6286   PerlEnd:
6287     RETVAL = blob;
6288   }
6289   OUTPUT:
6290     RETVAL
6291 \f
6292 #
6293 ###############################################################################
6294 #                                                                             #
6295 #                                                                             #
6296 #                                                                             #
6297 #   H i s t o g r a m                                                         #
6298 #                                                                             #
6299 #                                                                             #
6300 #                                                                             #
6301 ###############################################################################
6302 #
6303 #
6304 void
6305 Histogram(ref,...)
6306   Image::Magick ref=NO_INIT
6307   ALIAS:
6308     HistogramImage = 1
6309     histogram      = 2
6310     histogramimage = 3
6311   PPCODE:
6312   {
6313     AV
6314       *av;
6315
6316     char
6317       message[MagickPathExtent];
6318
6319     PixelInfo
6320       *histogram;
6321
6322     ExceptionInfo
6323       *exception;
6324
6325     Image
6326       *image;
6327
6328     register ssize_t
6329       i;
6330
6331     ssize_t
6332       count;
6333
6334     struct PackageInfo
6335       *info;
6336
6337     SV
6338       *perl_exception,
6339       *reference;
6340
6341     size_t
6342       number_colors;
6343
6344     PERL_UNUSED_VAR(ref);
6345     PERL_UNUSED_VAR(ix);
6346     exception=AcquireExceptionInfo();
6347     perl_exception=newSVpv("",0);
6348     av=NULL;
6349     if (sv_isobject(ST(0)) == 0)
6350       {
6351         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6352           PackageName);
6353         goto PerlException;
6354       }
6355     reference=SvRV(ST(0));
6356     av=newAV();
6357     SvREFCNT_dec(av);
6358     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6359     if (image == (Image *) NULL)
6360       {
6361         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6362           PackageName);
6363         goto PerlException;
6364       }
6365     count=0;
6366     for ( ; image; image=image->next)
6367     {
6368       histogram=GetImageHistogram(image,&number_colors,exception);
6369       if (histogram == (PixelInfo *) NULL)
6370         continue;
6371       count+=(ssize_t) number_colors;
6372       EXTEND(sp,6*count);
6373       for (i=0; i < (ssize_t) number_colors; i++)
6374       {
6375         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6376           histogram[i].red);
6377         PUSHs(sv_2mortal(newSVpv(message,0)));
6378         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6379           histogram[i].green);
6380         PUSHs(sv_2mortal(newSVpv(message,0)));
6381         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6382           histogram[i].blue);
6383         PUSHs(sv_2mortal(newSVpv(message,0)));
6384         if (image->colorspace == CMYKColorspace)
6385           {
6386             (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6387               histogram[i].black);
6388             PUSHs(sv_2mortal(newSVpv(message,0)));
6389           }
6390         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6391           histogram[i].alpha);
6392         PUSHs(sv_2mortal(newSVpv(message,0)));
6393         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
6394           histogram[i].count);
6395         PUSHs(sv_2mortal(newSVpv(message,0)));
6396       }
6397       histogram=(PixelInfo *) RelinquishMagickMemory(histogram);
6398     }
6399
6400   PerlException:
6401     InheritPerlException(exception,perl_exception);
6402     exception=DestroyExceptionInfo(exception);
6403     SvREFCNT_dec(perl_exception);
6404   }
6405 \f
6406 #
6407 ###############################################################################
6408 #                                                                             #
6409 #                                                                             #
6410 #                                                                             #
6411 #   G e t P i x e l                                                           #
6412 #                                                                             #
6413 #                                                                             #
6414 #                                                                             #
6415 ###############################################################################
6416 #
6417 #
6418 void
6419 GetPixel(ref,...)
6420   Image::Magick ref=NO_INIT
6421   ALIAS:
6422     getpixel = 1
6423     getPixel = 2
6424   PPCODE:
6425   {
6426     AV
6427       *av;
6428
6429     char
6430       *attribute;
6431
6432     ExceptionInfo
6433       *exception;
6434
6435     Image
6436       *image;
6437
6438     MagickBooleanType
6439       normalize;
6440
6441     RectangleInfo
6442       region;
6443
6444     register const Quantum
6445       *p;
6446
6447     register ssize_t
6448       i;
6449
6450     ssize_t
6451       option;
6452
6453     struct PackageInfo
6454       *info;
6455
6456     SV
6457       *perl_exception,
6458       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6459
6460     PERL_UNUSED_VAR(ref);
6461     PERL_UNUSED_VAR(ix);
6462     exception=AcquireExceptionInfo();
6463     perl_exception=newSVpv("",0);
6464     reference=SvRV(ST(0));
6465     av=(AV *) reference;
6466     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6467       exception);
6468     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6469     if (image == (Image *) NULL)
6470       {
6471         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6472           PackageName);
6473         goto PerlException;
6474       }
6475     normalize=MagickTrue;
6476     region.x=0;
6477     region.y=0;
6478     region.width=image->columns;
6479     region.height=1;
6480     if (items == 1)
6481       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6482     for (i=2; i < items; i+=2)
6483     {
6484       attribute=(char *) SvPV(ST(i-1),na);
6485       switch (*attribute)
6486       {
6487         case 'C':
6488         case 'c':
6489         {
6490           if (LocaleCompare(attribute,"channel") == 0)
6491             {
6492               ssize_t
6493                 option;
6494
6495               option=ParseChannelOption(SvPV(ST(i),na));
6496               if (option < 0)
6497                 {
6498                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6499                     SvPV(ST(i),na));
6500                   return;
6501                 }
6502               (void) SetPixelChannelMask(image,(ChannelType) option);
6503               break;
6504             }
6505           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6506             attribute);
6507           break;
6508         }
6509         case 'g':
6510         case 'G':
6511         {
6512           if (LocaleCompare(attribute,"geometry") == 0)
6513             {
6514               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6515               break;
6516             }
6517           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6518             attribute);
6519           break;
6520         }
6521         case 'N':
6522         case 'n':
6523         {
6524           if (LocaleCompare(attribute,"normalize") == 0)
6525             {
6526               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6527                 SvPV(ST(i),na));
6528               if (option < 0)
6529                 {
6530                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6531                     SvPV(ST(i),na));
6532                   break;
6533                 }
6534              normalize=option != 0 ? MagickTrue : MagickFalse;
6535              break;
6536             }
6537           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6538             attribute);
6539           break;
6540         }
6541         case 'x':
6542         case 'X':
6543         {
6544           if (LocaleCompare(attribute,"x") == 0)
6545             {
6546               region.x=SvIV(ST(i));
6547               break;
6548             }
6549           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6550             attribute);
6551           break;
6552         }
6553         case 'y':
6554         case 'Y':
6555         {
6556           if (LocaleCompare(attribute,"y") == 0)
6557             {
6558               region.y=SvIV(ST(i));
6559               break;
6560             }
6561           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6562             attribute);
6563           break;
6564         }
6565         default:
6566         {
6567           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6568             attribute);
6569           break;
6570         }
6571       }
6572     }
6573     p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6574     if (p == (const Quantum *) NULL)
6575       PUSHs(&sv_undef);
6576     else
6577       {
6578         double
6579           scale;
6580
6581         scale=1.0;
6582         if (normalize != MagickFalse)
6583           scale=1.0/QuantumRange;
6584         if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
6585           PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6586         if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6587           PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6588         if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6589           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6590         if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6591             (image->colorspace == CMYKColorspace))
6592           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6593         if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
6594           PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6595       }
6596
6597   PerlException:
6598     InheritPerlException(exception,perl_exception);
6599     exception=DestroyExceptionInfo(exception);
6600     SvREFCNT_dec(perl_exception);
6601   }
6602 \f
6603 #
6604 ###############################################################################
6605 #                                                                             #
6606 #                                                                             #
6607 #                                                                             #
6608 #   G e t P i x e l s                                                         #
6609 #                                                                             #
6610 #                                                                             #
6611 #                                                                             #
6612 ###############################################################################
6613 #
6614 #
6615 void
6616 GetPixels(ref,...)
6617   Image::Magick ref=NO_INIT
6618   ALIAS:
6619     getpixels = 1
6620     getPixels = 2
6621   PPCODE:
6622   {
6623     AV
6624       *av;
6625
6626     char
6627       *attribute;
6628
6629     const char
6630       *map;
6631
6632     ExceptionInfo
6633       *exception;
6634
6635     Image
6636       *image;
6637
6638     MagickBooleanType
6639       normalize,
6640       status;
6641
6642     RectangleInfo
6643       region;
6644
6645     register ssize_t
6646       i;
6647
6648     ssize_t
6649       option;
6650
6651     struct PackageInfo
6652       *info;
6653
6654     SV
6655       *perl_exception,
6656       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6657
6658     PERL_UNUSED_VAR(ref);
6659     PERL_UNUSED_VAR(ix);
6660     exception=AcquireExceptionInfo();
6661     perl_exception=newSVpv("",0);
6662     reference=SvRV(ST(0));
6663     av=(AV *) reference;
6664     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6665       exception);
6666     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6667     if (image == (Image *) NULL)
6668       {
6669         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6670           PackageName);
6671         goto PerlException;
6672       }
6673     map="RGB";
6674     if (image->alpha_trait != UndefinedPixelTrait)
6675       map="RGBA";
6676     if (image->colorspace == CMYKColorspace)
6677       {
6678         map="CMYK";
6679         if (image->alpha_trait != UndefinedPixelTrait)
6680           map="CMYKA";
6681       }
6682     normalize=MagickFalse;
6683     region.x=0;
6684     region.y=0;
6685     region.width=image->columns;
6686     region.height=1;
6687     if (items == 1)
6688       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6689     for (i=2; i < items; i+=2)
6690     {
6691       attribute=(char *) SvPV(ST(i-1),na);
6692       switch (*attribute)
6693       {
6694         case 'g':
6695         case 'G':
6696         {
6697           if (LocaleCompare(attribute,"geometry") == 0)
6698             {
6699               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6700               break;
6701             }
6702           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6703             attribute);
6704           break;
6705         }
6706         case 'H':
6707         case 'h':
6708         {
6709           if (LocaleCompare(attribute,"height") == 0)
6710             {
6711               region.height=SvIV(ST(i));
6712               break;
6713             }
6714           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6715             attribute);
6716           break;
6717         }
6718         case 'M':
6719         case 'm':
6720         {
6721           if (LocaleCompare(attribute,"map") == 0)
6722             {
6723               map=SvPV(ST(i),na);
6724               break;
6725             }
6726           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6727             attribute);
6728           break;
6729         }
6730         case 'N':
6731         case 'n':
6732         {
6733           if (LocaleCompare(attribute,"normalize") == 0)
6734             {
6735               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6736                 SvPV(ST(i),na));
6737               if (option < 0)
6738                 {
6739                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6740                     SvPV(ST(i),na));
6741                   break;
6742                 }
6743              normalize=option != 0 ? MagickTrue : MagickFalse;
6744              break;
6745             }
6746           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6747             attribute);
6748           break;
6749         }
6750         case 'W':
6751         case 'w':
6752         {
6753           if (LocaleCompare(attribute,"width") == 0)
6754             {
6755               region.width=SvIV(ST(i));
6756               break;
6757             }
6758           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6759             attribute);
6760           break;
6761         }
6762         case 'x':
6763         case 'X':
6764         {
6765           if (LocaleCompare(attribute,"x") == 0)
6766             {
6767               region.x=SvIV(ST(i));
6768               break;
6769             }
6770           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6771             attribute);
6772           break;
6773         }
6774         case 'y':
6775         case 'Y':
6776         {
6777           if (LocaleCompare(attribute,"y") == 0)
6778             {
6779               region.y=SvIV(ST(i));
6780               break;
6781             }
6782           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6783             attribute);
6784           break;
6785         }
6786         default:
6787         {
6788           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6789             attribute);
6790           break;
6791         }
6792       }
6793     }
6794     if (normalize != MagickFalse)
6795       {
6796         float
6797           *pixels;
6798
6799         pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6800           region.height*sizeof(*pixels));
6801         if (pixels == (float *) NULL)
6802           {
6803             ThrowPerlException(exception,ResourceLimitError,
6804               "MemoryAllocationFailed",PackageName);
6805             goto PerlException;
6806           }
6807         status=ExportImagePixels(image,region.x,region.y,region.width,
6808           region.height,map,FloatPixel,pixels,exception);
6809         if (status == MagickFalse)
6810           PUSHs(&sv_undef);
6811         else
6812           {
6813             EXTEND(sp,strlen(map)*region.width*region.height);
6814             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6815               PUSHs(sv_2mortal(newSVnv(pixels[i])));
6816           }
6817         pixels=(float *) RelinquishMagickMemory(pixels);
6818       }
6819     else
6820       {
6821         Quantum
6822           *pixels;
6823
6824         pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6825           region.height*sizeof(*pixels));
6826         if (pixels == (Quantum *) NULL)
6827           {
6828             ThrowPerlException(exception,ResourceLimitError,
6829               "MemoryAllocationFailed",PackageName);
6830             goto PerlException;
6831           }
6832         status=ExportImagePixels(image,region.x,region.y,region.width,
6833           region.height,map,QuantumPixel,pixels,exception);
6834         if (status == MagickFalse)
6835           PUSHs(&sv_undef);
6836         else
6837           {
6838             EXTEND(sp,strlen(map)*region.width*region.height);
6839             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6840               PUSHs(sv_2mortal(newSViv(pixels[i])));
6841           }
6842         pixels=(Quantum *) RelinquishMagickMemory(pixels);
6843       }
6844
6845   PerlException:
6846     InheritPerlException(exception,perl_exception);
6847     exception=DestroyExceptionInfo(exception);
6848     SvREFCNT_dec(perl_exception);
6849   }
6850 \f
6851 #
6852 ###############################################################################
6853 #                                                                             #
6854 #                                                                             #
6855 #                                                                             #
6856 #   I m a g e T o B l o b                                                     #
6857 #                                                                             #
6858 #                                                                             #
6859 #                                                                             #
6860 ###############################################################################
6861 #
6862 #
6863 void
6864 ImageToBlob(ref,...)
6865   Image::Magick ref=NO_INIT
6866   ALIAS:
6867     ImageToBlob  = 1
6868     imagetoblob  = 2
6869     toblob       = 3
6870     blob         = 4
6871   PPCODE:
6872   {
6873     char
6874       filename[MagickPathExtent];
6875
6876     ExceptionInfo
6877       *exception;
6878
6879     Image
6880       *image,
6881       *next;
6882
6883     register ssize_t
6884       i;
6885
6886     struct PackageInfo
6887       *info,
6888       *package_info;
6889
6890     size_t
6891       length;
6892
6893     ssize_t
6894       scene;
6895
6896     SV
6897       *perl_exception,
6898       *reference;
6899
6900     void
6901       *blob;
6902
6903     PERL_UNUSED_VAR(ref);
6904     PERL_UNUSED_VAR(ix);
6905     exception=AcquireExceptionInfo();
6906     perl_exception=newSVpv("",0);
6907     package_info=(struct PackageInfo *) NULL;
6908     if (sv_isobject(ST(0)) == 0)
6909       {
6910         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6911           PackageName);
6912         goto PerlException;
6913       }
6914     reference=SvRV(ST(0));
6915     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6916     if (image == (Image *) NULL)
6917       {
6918         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6919           PackageName);
6920         goto PerlException;
6921       }
6922     package_info=ClonePackageInfo(info,exception);
6923     for (i=2; i < items; i+=2)
6924       SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6925     (void) CopyMagickString(filename,package_info->image_info->filename,
6926       MagickPathExtent);
6927     scene=0;
6928     for (next=image; next; next=next->next)
6929     {
6930       (void) CopyMagickString(next->filename,filename,MagickPathExtent);
6931       next->scene=scene++;
6932     }
6933     SetImageInfo(package_info->image_info,(unsigned int)
6934       GetImageListLength(image),exception);
6935     EXTEND(sp,(ssize_t) GetImageListLength(image));
6936     for ( ; image; image=image->next)
6937     {
6938       length=0;
6939       blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6940       if (blob != (char *) NULL)
6941         {
6942           PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6943           blob=(unsigned char *) RelinquishMagickMemory(blob);
6944         }
6945       if (package_info->image_info->adjoin)
6946         break;
6947     }
6948
6949   PerlException:
6950     if (package_info != (struct PackageInfo *) NULL)
6951       DestroyPackageInfo(package_info);
6952     InheritPerlException(exception,perl_exception);
6953     exception=DestroyExceptionInfo(exception);
6954     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6955   }
6956 \f
6957 #
6958 ###############################################################################
6959 #                                                                             #
6960 #                                                                             #
6961 #                                                                             #
6962 #   L a y e r s                                                               #
6963 #                                                                             #
6964 #                                                                             #
6965 #                                                                             #
6966 ###############################################################################
6967 #
6968 #
6969 void
6970 Layers(ref,...)
6971   Image::Magick ref=NO_INIT
6972   ALIAS:
6973     Layers                = 1
6974     layers           = 2
6975     OptimizeImageLayers   = 3
6976     optimizelayers        = 4
6977     optimizeimagelayers   = 5
6978   PPCODE:
6979   {
6980     AV
6981       *av;
6982
6983     char
6984       *attribute;
6985
6986     CompositeOperator
6987       compose;
6988
6989     ExceptionInfo
6990       *exception;
6991
6992     HV
6993       *hv;
6994
6995     Image
6996       *image,
6997       *layers;
6998
6999     LayerMethod
7000       method;
7001
7002     register ssize_t
7003       i;
7004
7005     ssize_t
7006       option,
7007       sp;
7008
7009     struct PackageInfo
7010       *info;
7011
7012     SV
7013       *av_reference,
7014       *perl_exception,
7015       *reference,
7016       *rv,
7017       *sv;
7018
7019     PERL_UNUSED_VAR(ref);
7020     PERL_UNUSED_VAR(ix);
7021     exception=AcquireExceptionInfo();
7022     perl_exception=newSVpv("",0);
7023     sv=NULL;
7024     if (sv_isobject(ST(0)) == 0)
7025       {
7026         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7027           PackageName);
7028         goto PerlException;
7029       }
7030     reference=SvRV(ST(0));
7031     hv=SvSTASH(reference);
7032     av=newAV();
7033     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
7034     SvREFCNT_dec(av);
7035     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
7036     if (image == (Image *) NULL)
7037       {
7038         ThrowPerlException(exception,OptionError,"NoImagesDefined",
7039           PackageName);
7040         goto PerlException;
7041       }
7042     compose=image->compose;
7043     method=OptimizeLayer;
7044     for (i=2; i < items; i+=2)
7045     {
7046       attribute=(char *) SvPV(ST(i-1),na);
7047       switch (*attribute)
7048       {
7049         case 'C':
7050         case 'c':
7051         {
7052           if (LocaleCompare(attribute,"compose") == 0)
7053             {
7054               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
7055                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
7056               if (sp < 0)
7057                 {
7058                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
7059                     SvPV(ST(i),na));
7060                   break;
7061                 }
7062               compose=(CompositeOperator) sp;
7063               break;
7064             }
7065           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7066             attribute);
7067           break;
7068         }
7069         case 'M':
7070         case 'm':
7071         {
7072           if (LocaleCompare(attribute,"method") == 0)
7073             {
7074               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
7075                 SvPV(ST(i),na));
7076               if (option < 0)
7077                 {
7078                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
7079                     SvPV(ST(i),na));
7080                   break;
7081                 }
7082               method=(LayerMethod) option;
7083               break;
7084             }
7085           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7086             attribute);
7087           break;
7088         }
7089         default:
7090         {
7091           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7092             attribute);
7093           break;
7094         }
7095       }
7096     }
7097     layers=(Image *) NULL;
7098     switch (method)
7099     {
7100       case CompareAnyLayer:
7101       case CompareClearLayer:
7102       case CompareOverlayLayer:
7103       default:
7104       {
7105         layers=CompareImagesLayers(image,method,exception);
7106         break;
7107       }
7108       case MergeLayer:
7109       case FlattenLayer:
7110       case MosaicLayer:
7111       {
7112         layers=MergeImageLayers(image,method,exception);
7113         break;
7114       }
7115       case DisposeLayer:
7116       {
7117         layers=DisposeImages(image,exception);
7118         break;
7119       }
7120       case OptimizeImageLayer:
7121       {
7122         layers=OptimizeImageLayers(image,exception);
7123         break;
7124       }
7125       case OptimizePlusLayer:
7126       {
7127         layers=OptimizePlusImageLayers(image,exception);
7128         break;
7129       }
7130       case OptimizeTransLayer:
7131       {
7132         OptimizeImageTransparency(image,exception);
7133         break;
7134       }
7135       case RemoveDupsLayer:
7136       {
7137         RemoveDuplicateLayers(&image,exception);
7138         break;
7139       }
7140       case RemoveZeroLayer:
7141       {
7142         RemoveZeroDelayLayers(&image,exception);
7143         break;
7144       }
7145       case OptimizeLayer:
7146       {
7147         QuantizeInfo
7148           *quantize_info;
7149
7150         /*
7151           General Purpose, GIF Animation Optimizer.
7152         */
7153         layers=CoalesceImages(image,exception);
7154         if (layers == (Image *) NULL)
7155           break;
7156         image=layers;
7157         layers=OptimizeImageLayers(image,exception);
7158         if (layers == (Image *) NULL)
7159           break;
7160         image=DestroyImageList(image);
7161         image=layers;
7162         layers=(Image *) NULL;
7163         OptimizeImageTransparency(image,exception);
7164         quantize_info=AcquireQuantizeInfo(info->image_info);
7165         (void) RemapImages(quantize_info,image,(Image *) NULL,exception);
7166         quantize_info=DestroyQuantizeInfo(quantize_info);
7167         break;
7168       }
7169       case CompositeLayer:
7170       {
7171         Image
7172           *source;
7173
7174         RectangleInfo
7175           geometry;
7176
7177         /*
7178           Split image sequence at the first 'NULL:' image.
7179         */
7180         source=image;
7181         while (source != (Image *) NULL)
7182         {
7183           source=GetNextImageInList(source);
7184           if ((source != (Image *) NULL) &&
7185               (LocaleCompare(source->magick,"NULL") == 0))
7186             break;
7187         }
7188         if (source != (Image *) NULL)
7189           {
7190             if ((GetPreviousImageInList(source) == (Image *) NULL) ||
7191                 (GetNextImageInList(source) == (Image *) NULL))
7192               source=(Image *) NULL;
7193             else
7194               {
7195                 /*
7196                   Separate the two lists, junk the null: image.
7197                 */
7198                 source=SplitImageList(source->previous);
7199                 DeleteImageFromList(&source);
7200               }
7201           }
7202         if (source == (Image *) NULL)
7203           {
7204             (void) ThrowMagickException(exception,GetMagickModule(),
7205               OptionError,"MissingNullSeparator","layers Composite");
7206             break;
7207           }
7208         /*
7209           Adjust offset with gravity and virtual canvas.
7210         */
7211         SetGeometry(image,&geometry);
7212         (void) ParseAbsoluteGeometry(image->geometry,&geometry);
7213         geometry.width=source->page.width != 0 ? source->page.width :
7214           source->columns;
7215         geometry.height=source->page.height != 0 ? source->page.height :
7216           source->rows;
7217         GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
7218           image->columns,image->page.height != 0 ? image->page.height :
7219           image->rows,image->gravity,&geometry);
7220         CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
7221         source=DestroyImageList(source);
7222         break;
7223       }
7224     }
7225     if (layers != (Image *) NULL)
7226       image=layers;
7227     else
7228       image=CloneImage(image,0,0,MagickTrue,exception);
7229     if (image == (Image *) NULL)
7230       goto PerlException;
7231     for ( ; image; image=image->next)
7232     {
7233       AddImageToRegistry(sv,image);
7234       rv=newRV(sv);
7235       av_push(av,sv_bless(rv,hv));
7236       SvREFCNT_dec(sv);
7237     }
7238     exception=DestroyExceptionInfo(exception);
7239     ST(0)=av_reference;
7240     SvREFCNT_dec(perl_exception);
7241     XSRETURN(1);
7242
7243   PerlException:
7244     InheritPerlException(exception,perl_exception);
7245     exception=DestroyExceptionInfo(exception);
7246     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
7247     SvPOK_on(perl_exception);
7248     ST(0)=sv_2mortal(perl_exception);
7249     XSRETURN(1);
7250   }
7251 \f
7252 #
7253 ###############################################################################
7254 #                                                                             #
7255 #                                                                             #
7256 #                                                                             #
7257 #   M a g i c k T o M i m e                                                   #
7258 #                                                                             #
7259 #                                                                             #
7260 #                                                                             #
7261 ###############################################################################
7262 #
7263 #
7264 SV *
7265 MagickToMime(ref,name)
7266   Image::Magick ref=NO_INIT
7267   char *name
7268   ALIAS:
7269     magicktomime = 1
7270   CODE:
7271   {
7272     char
7273       *mime;
7274
7275     PERL_UNUSED_VAR(ref);
7276     PERL_UNUSED_VAR(ix);
7277     mime=MagickToMime(name);
7278     RETVAL=newSVpv(mime,0);
7279     mime=(char *) RelinquishMagickMemory(mime);
7280   }
7281   OUTPUT:
7282     RETVAL
7283 \f
7284 #
7285 ###############################################################################
7286 #                                                                             #
7287 #                                                                             #
7288 #                                                                             #
7289 #   M o g r i f y                                                             #
7290 #                                                                             #
7291 #                                                                             #
7292 #                                                                             #
7293 ###############################################################################
7294 #
7295 #
7296 void
7297 Mogrify(ref,...)
7298   Image::Magick ref=NO_INIT
7299   ALIAS:
7300     Comment            =   1
7301     CommentImage       =   2
7302     Label              =   3
7303     LabelImage         =   4
7304     AddNoise           =   5
7305     AddNoiseImage      =   6
7306     Colorize           =   7
7307     ColorizeImage      =   8
7308     Border             =   9
7309     BorderImage        =  10
7310     Blur               =  11
7311     BlurImage          =  12
7312     Chop               =  13
7313     ChopImage          =  14
7314     Crop               =  15
7315     CropImage          =  16
7316     Despeckle          =  17
7317     DespeckleImage     =  18
7318     Edge               =  19
7319     EdgeImage          =  20
7320     Emboss             =  21
7321     EmbossImage        =  22
7322     Enhance            =  23
7323     EnhanceImage       =  24
7324     Flip               =  25
7325     FlipImage          =  26
7326     Flop               =  27
7327     FlopImage          =  28
7328     Frame              =  29
7329     FrameImage         =  30
7330     Implode            =  31
7331     ImplodeImage       =  32
7332     Magnify            =  33
7333     MagnifyImage       =  34
7334     MedianFilter       =  35
7335     MedianConvolveImage  =  36
7336     Minify             =  37
7337     MinifyImage        =  38
7338     OilPaint           =  39
7339     OilPaintImage      =  40
7340     ReduceNoise        =  41
7341     ReduceNoiseImage   =  42
7342     Roll               =  43
7343     RollImage          =  44
7344     Rotate             =  45
7345     RotateImage        =  46
7346     Sample             =  47
7347     SampleImage        =  48
7348     Scale              =  49
7349     ScaleImage         =  50
7350     Shade              =  51
7351     ShadeImage         =  52
7352     Sharpen            =  53
7353     SharpenImage       =  54
7354     Shear              =  55
7355     ShearImage         =  56
7356     Spread             =  57
7357     SpreadImage        =  58
7358     Swirl              =  59
7359     SwirlImage         =  60
7360     Resize             =  61
7361     ResizeImage        =  62
7362     Zoom               =  63
7363     ZoomImage          =  64
7364     Annotate           =  65
7365     AnnotateImage      =  66
7366     ColorFloodfill     =  67
7367     ColorFloodfillImage=  68
7368     Composite          =  69
7369     CompositeImage     =  70
7370     Contrast           =  71
7371     ContrastImage      =  72
7372     CycleColormap      =  73
7373     CycleColormapImage =  74
7374     Draw               =  75
7375     DrawImage          =  76
7376     Equalize           =  77
7377     EqualizeImage      =  78
7378     Gamma              =  79
7379     GammaImage         =  80
7380     Map                =  81
7381     MapImage           =  82
7382     MatteFloodfill     =  83
7383     MatteFloodfillImage=  84
7384     Modulate           =  85
7385     ModulateImage      =  86
7386     Negate             =  87
7387     NegateImage        =  88
7388     Normalize          =  89
7389     NormalizeImage     =  90
7390     NumberColors       =  91
7391     NumberColorsImage  =  92
7392     Opaque             =  93
7393     OpaqueImage        =  94
7394     Quantize           =  95
7395     QuantizeImage      =  96
7396     Raise              =  97
7397     RaiseImage         =  98
7398     Segment            =  99
7399     SegmentImage       = 100
7400     Signature          = 101
7401     SignatureImage     = 102
7402     Solarize           = 103
7403     SolarizeImage      = 104
7404     Sync               = 105
7405     SyncImage          = 106
7406     Texture            = 107
7407     TextureImage       = 108
7408     Evaluate           = 109
7409     EvaluateImage      = 110
7410     Transparent        = 111
7411     TransparentImage   = 112
7412     Threshold          = 113
7413     ThresholdImage     = 114
7414     Charcoal           = 115
7415     CharcoalImage      = 116
7416     Trim               = 117
7417     TrimImage          = 118
7418     Wave               = 119
7419     WaveImage          = 120
7420     Separate           = 121
7421     SeparateImage      = 122
7422     Stereo             = 125
7423     StereoImage        = 126
7424     Stegano            = 127
7425     SteganoImage       = 128
7426     Deconstruct        = 129
7427     DeconstructImage   = 130
7428     GaussianBlur       = 131
7429     GaussianBlurImage  = 132
7430     Convolve           = 133
7431     ConvolveImage      = 134
7432     Profile            = 135
7433     ProfileImage       = 136
7434     UnsharpMask        = 137
7435     UnsharpMaskImage   = 138
7436     MotionBlur         = 139
7437     MotionBlurImage    = 140
7438     OrderedDither      = 141
7439     OrderedDitherImage = 142
7440     Shave              = 143
7441     ShaveImage         = 144
7442     Level              = 145
7443     LevelImage         = 146
7444     Clip               = 147
7445     ClipImage          = 148
7446     AffineTransform    = 149
7447     AffineTransformImage = 150
7448     Difference         = 151
7449     DifferenceImage    = 152
7450     AdaptiveThreshold  = 153
7451     AdaptiveThresholdImage = 154
7452     Resample           = 155
7453     ResampleImage      = 156
7454     Describe           = 157
7455     DescribeImage      = 158
7456     BlackThreshold     = 159
7457     BlackThresholdImage= 160
7458     WhiteThreshold     = 161
7459     WhiteThresholdImage= 162
7460     RotationalBlur     = 163
7461     RotationalBlurImage= 164
7462     Thumbnail          = 165
7463     ThumbnailImage     = 166
7464     Strip              = 167
7465     StripImage         = 168
7466     Tint               = 169
7467     TintImage          = 170
7468     Channel            = 171
7469     ChannelImage       = 172
7470     Splice             = 173
7471     SpliceImage        = 174
7472     Posterize          = 175
7473     PosterizeImage     = 176
7474     Shadow             = 177
7475     ShadowImage        = 178
7476     Identify           = 179
7477     IdentifyImage      = 180
7478     SepiaTone          = 181
7479     SepiaToneImage     = 182
7480     SigmoidalContrast  = 183
7481     SigmoidalContrastImage = 184
7482     Extent             = 185
7483     ExtentImage        = 186
7484     Vignette           = 187
7485     VignetteImage      = 188
7486     ContrastStretch    = 189
7487     ContrastStretchImage = 190
7488     Sans0              = 191
7489     Sans0Image         = 192
7490     Sans1              = 193
7491     Sans1Image         = 194
7492     AdaptiveSharpen    = 195
7493     AdaptiveSharpenImage = 196
7494     Transpose          = 197
7495     TransposeImage     = 198
7496     Transverse         = 199
7497     TransverseImage    = 200
7498     AutoOrient         = 201
7499     AutoOrientImage    = 202
7500     AdaptiveBlur       = 203
7501     AdaptiveBlurImage  = 204
7502     Sketch             = 205
7503     SketchImage        = 206
7504     UniqueColors       = 207
7505     UniqueColorsImage  = 208
7506     AdaptiveResize     = 209
7507     AdaptiveResizeImage= 210
7508     ClipMask           = 211
7509     ClipMaskImage      = 212
7510     LinearStretch      = 213
7511     LinearStretchImage = 214
7512     ColorMatrix        = 215
7513     ColorMatrixImage   = 216
7514     Mask               = 217
7515     MaskImage          = 218
7516     Polaroid           = 219
7517     PolaroidImage      = 220
7518     FloodfillPaint     = 221
7519     FloodfillPaintImage= 222
7520     Distort            = 223
7521     DistortImage       = 224
7522     Clut               = 225
7523     ClutImage          = 226
7524     LiquidRescale      = 227
7525     LiquidRescaleImage = 228
7526     Encipher           = 229
7527     EncipherImage      = 230
7528     Decipher           = 231
7529     DecipherImage      = 232
7530     Deskew             = 233
7531     DeskewImage        = 234
7532     Remap              = 235
7533     RemapImage         = 236
7534     SparseColor        = 237
7535     SparseColorImage   = 238
7536     Function           = 239
7537     FunctionImage      = 240
7538     SelectiveBlur      = 241
7539     SelectiveBlurImage = 242
7540     HaldClut           = 243
7541     HaldClutImage      = 244
7542     BlueShift          = 245
7543     BlueShiftImage     = 246
7544     ForwardFourierTransform  = 247
7545     ForwardFourierTransformImage = 248
7546     InverseFourierTransform = 249
7547     InverseFourierTransformImage = 250
7548     ColorDecisionList  = 251
7549     ColorDecisionListImage = 252
7550     AutoGamma          = 253
7551     AutoGammaImage     = 254
7552     AutoLevel          = 255
7553     AutoLevelImage     = 256
7554     LevelColors        = 257
7555     LevelImageColors   = 258
7556     Clamp              = 259
7557     ClampImage         = 260
7558     BrightnessContrast = 261
7559     BrightnessContrastImage = 262
7560     Morphology         = 263
7561     MorphologyImage    = 264
7562     Mode               = 265
7563     ModeImage          = 266
7564     Statistic          = 267
7565     StatisticImage     = 268
7566     Perceptible        = 269
7567     PerceptibleImage   = 270
7568     Poly               = 271
7569     PolyImage          = 272
7570     Grayscale          = 273
7571     GrayscaleImage     = 274
7572     CannyEdge          = 275
7573     CannyEdgeImage     = 276
7574     HoughLine          = 277
7575     HoughLineImage     = 278
7576     MeanShift          = 279
7577     MeanShiftImage     = 280
7578     Kuwahara           = 281
7579     KuwaharaImage      = 282
7580     ConnectedComponent = 283
7581     ConnectedComponentImage = 284
7582     CopyPixels         = 285
7583     CopyImagePixels    = 286
7584     MogrifyRegion      = 666
7585   PPCODE:
7586   {
7587     AffineMatrix
7588       affine,
7589       current;
7590
7591     char
7592       attribute_flag[MaxArguments],
7593       message[MagickPathExtent];
7594
7595     ChannelType
7596       channel,
7597       channel_mask;
7598
7599     CompositeOperator
7600       compose;
7601
7602     const char
7603       *attribute,
7604       *value;
7605
7606     double
7607       angle;
7608
7609     ExceptionInfo
7610       *exception;
7611
7612     GeometryInfo
7613       geometry_info;
7614
7615     Image
7616       *image,
7617       *next,
7618       *region_image;
7619
7620     MagickBooleanType
7621       status;
7622
7623     MagickStatusType
7624       flags;
7625
7626     PixelInfo
7627       fill_color;
7628
7629     RectangleInfo
7630       geometry,
7631       region_info;
7632
7633     register ssize_t
7634       i;
7635
7636     ssize_t
7637       base,
7638       j,
7639       number_images;
7640
7641     struct Methods
7642       *rp;
7643
7644     struct PackageInfo
7645       *info;
7646
7647     SV
7648       *perl_exception,
7649       **pv,
7650       *reference,
7651       **reference_vector;
7652
7653     struct ArgumentList
7654       argument_list[MaxArguments];
7655
7656     PERL_UNUSED_VAR(ref);
7657     PERL_UNUSED_VAR(ix);
7658     exception=AcquireExceptionInfo();
7659     perl_exception=newSVpv("",0);
7660     reference_vector=NULL;
7661     region_image=NULL;
7662     number_images=0;
7663     base=2;
7664     if (sv_isobject(ST(0)) == 0)
7665       {
7666         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7667           PackageName);
7668         goto PerlException;
7669       }
7670     reference=SvRV(ST(0));
7671     region_info.width=0;
7672     region_info.height=0;
7673     region_info.x=0;
7674     region_info.y=0;
7675     region_image=(Image *) NULL;
7676     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7677     if (ix && (ix != 666))
7678       {
7679         /*
7680           Called as Method(...)
7681         */
7682         ix=(ix+1)/2;
7683         rp=(&Methods[ix-1]);
7684         attribute=rp->name;
7685       }
7686     else
7687       {
7688         /*
7689           Called as Mogrify("Method",...)
7690         */
7691         attribute=(char *) SvPV(ST(1),na);
7692         if (ix)
7693           {
7694             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7695             attribute=(char *) SvPV(ST(2),na);
7696             base++;
7697           }
7698         for (rp=Methods; ; rp++)
7699         {
7700           if (rp >= EndOf(Methods))
7701             {
7702               ThrowPerlException(exception,OptionError,
7703                 "UnrecognizedPerlMagickMethod",attribute);
7704               goto PerlException;
7705             }
7706           if (strEQcase(attribute,rp->name))
7707             break;
7708         }
7709         ix=rp-Methods+1;
7710         base++;
7711       }
7712     if (image == (Image *) NULL)
7713       {
7714         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7715         goto PerlException;
7716       }
7717     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7718     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7719     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7720     {
7721       Arguments
7722         *pp,
7723         *qq;
7724
7725       ssize_t
7726         ssize_test;
7727
7728       struct ArgumentList
7729         *al;
7730
7731       SV
7732         *sv;
7733
7734       sv=NULL;
7735       ssize_test=0;
7736       pp=(Arguments *) NULL;
7737       qq=rp->arguments;
7738       if (i == items)
7739         {
7740           pp=rp->arguments,
7741           sv=ST(i-1);
7742         }
7743       else
7744         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7745         {
7746           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7747             break;
7748           if (strEQcase(attribute,qq->method) > ssize_test)
7749             {
7750               pp=qq;
7751               ssize_test=strEQcase(attribute,qq->method);
7752             }
7753         }
7754       if (pp == (Arguments *) NULL)
7755         {
7756           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7757             attribute);
7758           goto continue_outer_loop;
7759         }
7760       al=(&argument_list[pp-rp->arguments]);
7761       switch (pp->type)
7762       {
7763         case ArrayReference:
7764         {
7765           if (SvTYPE(sv) != SVt_RV)
7766             {
7767               (void) FormatLocaleString(message,MagickPathExtent,
7768                 "invalid %.60s value",pp->method);
7769               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7770               goto continue_outer_loop;
7771             }
7772           al->array_reference=SvRV(sv);
7773           break;
7774         }
7775         case RealReference:
7776         {
7777           al->real_reference=SvNV(sv);
7778           break;
7779         }
7780         case FileReference:
7781         {
7782           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7783           break;
7784         }
7785         case ImageReference:
7786         {
7787           if (!sv_isobject(sv) ||
7788               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7789                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7790             {
7791               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7792                 PackageName);
7793               goto PerlException;
7794             }
7795           break;
7796         }
7797         case IntegerReference:
7798         {
7799           al->integer_reference=SvIV(sv);
7800           break;
7801         }
7802         case StringReference:
7803         {
7804           al->string_reference=(char *) SvPV(sv,al->length);
7805           if (sv_isobject(sv))
7806             al->image_reference=SetupList(aTHX_ SvRV(sv),
7807               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7808           break;
7809         }
7810         default:
7811         {
7812           /*
7813             Is a string; look up name.
7814           */
7815           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7816             {
7817               al->string_reference=(char *) SvPV(sv,al->length);
7818               al->integer_reference=(-1);
7819               break;
7820             }
7821           al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7822             MagickFalse,SvPV(sv,na));
7823           if (pp->type == MagickChannelOptions)
7824             al->integer_reference=ParseChannelOption(SvPV(sv,na));
7825           if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7826             {
7827               (void) FormatLocaleString(message,MagickPathExtent,
7828                 "invalid %.60s value",pp->method);
7829               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7830               goto continue_outer_loop;
7831             }
7832           break;
7833         }
7834       }
7835       attribute_flag[pp-rp->arguments]++;
7836       continue_outer_loop: ;
7837     }
7838     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7839     pv=reference_vector;
7840     SetGeometryInfo(&geometry_info);
7841     channel=DefaultChannels;
7842     for (next=image; next; next=next->next)
7843     {
7844       image=next;
7845       SetGeometry(image,&geometry);
7846       if ((region_info.width*region_info.height) != 0)
7847         {
7848           region_image=image;
7849           image=CropImage(image,&region_info,exception);
7850         }
7851       switch (ix)
7852       {
7853         default:
7854         {
7855           (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double) ix);
7856           ThrowPerlException(exception,OptionError,
7857             "UnrecognizedPerlMagickMethod",message);
7858           goto PerlException;
7859         }
7860         case 1:  /* Comment */
7861         {
7862           if (attribute_flag[0] == 0)
7863             argument_list[0].string_reference=(char *) NULL;
7864           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7865             info ? info->image_info : (ImageInfo *) NULL,image,
7866             argument_list[0].string_reference,exception),exception);
7867           break;
7868         }
7869         case 2:  /* Label */
7870         {
7871           if (attribute_flag[0] == 0)
7872             argument_list[0].string_reference=(char *) NULL;
7873           (void) SetImageProperty(image,"label",InterpretImageProperties(
7874             info ? info->image_info : (ImageInfo *) NULL,image,
7875             argument_list[0].string_reference,exception),exception);
7876           break;
7877         }
7878         case 3:  /* AddNoise */
7879         {
7880           double
7881             attenuate;
7882
7883           if (attribute_flag[0] == 0)
7884             argument_list[0].integer_reference=UniformNoise;
7885           attenuate=1.0;
7886           if (attribute_flag[1] != 0)
7887             attenuate=argument_list[1].real_reference;
7888           if (attribute_flag[2] != 0)
7889             channel=(ChannelType) argument_list[2].integer_reference;
7890           channel_mask=SetImageChannelMask(image,channel);
7891           image=AddNoiseImage(image,(NoiseType)
7892             argument_list[0].integer_reference,attenuate,exception);
7893           if (image != (Image *) NULL)
7894             (void) SetImageChannelMask(image,channel_mask);
7895           break;
7896         }
7897         case 4:  /* Colorize */
7898         {
7899           PixelInfo
7900             target;
7901
7902           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
7903             0,0,&target,exception);
7904           if (attribute_flag[0] != 0)
7905             (void) QueryColorCompliance(argument_list[0].string_reference,
7906               AllCompliance,&target,exception);
7907           if (attribute_flag[1] == 0)
7908             argument_list[1].string_reference="100%";
7909           image=ColorizeImage(image,argument_list[1].string_reference,&target,
7910             exception);
7911           break;
7912         }
7913         case 5:  /* Border */
7914         {
7915           CompositeOperator
7916             compose;
7917
7918           geometry.width=0;
7919           geometry.height=0;
7920           if (attribute_flag[0] != 0)
7921             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7922               &geometry,exception);
7923           if (attribute_flag[1] != 0)
7924             geometry.width=argument_list[1].integer_reference;
7925           if (attribute_flag[2] != 0)
7926             geometry.height=argument_list[2].integer_reference;
7927           if (attribute_flag[3] != 0)
7928             QueryColorCompliance(argument_list[3].string_reference,
7929               AllCompliance,&image->border_color,exception);
7930           if (attribute_flag[4] != 0)
7931             QueryColorCompliance(argument_list[4].string_reference,
7932               AllCompliance,&image->border_color,exception);
7933           if (attribute_flag[5] != 0)
7934             QueryColorCompliance(argument_list[5].string_reference,
7935               AllCompliance,&image->border_color,exception);
7936           compose=image->compose;
7937           if (attribute_flag[6] != 0)
7938             compose=(CompositeOperator) argument_list[6].integer_reference;
7939           image=BorderImage(image,&geometry,compose,exception);
7940           break;
7941         }
7942         case 6:  /* Blur */
7943         {
7944           if (attribute_flag[0] != 0)
7945             {
7946               flags=ParseGeometry(argument_list[0].string_reference,
7947                 &geometry_info);
7948               if ((flags & SigmaValue) == 0)
7949                 geometry_info.sigma=1.0;
7950             }
7951           if (attribute_flag[1] != 0)
7952             geometry_info.rho=argument_list[1].real_reference;
7953           if (attribute_flag[2] != 0)
7954             geometry_info.sigma=argument_list[2].real_reference;
7955           if (attribute_flag[3] != 0)
7956             channel=(ChannelType) argument_list[3].integer_reference;
7957           channel_mask=SetImageChannelMask(image,channel);
7958           image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
7959             exception);
7960           if (image != (Image *) NULL)
7961             (void) SetImageChannelMask(image,channel_mask);
7962           break;
7963         }
7964         case 7:  /* Chop */
7965         {
7966           if (attribute_flag[5] != 0)
7967             image->gravity=(GravityType) argument_list[5].integer_reference;
7968           if (attribute_flag[0] != 0)
7969             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7970               &geometry,exception);
7971           if (attribute_flag[1] != 0)
7972             geometry.width=argument_list[1].integer_reference;
7973           if (attribute_flag[2] != 0)
7974             geometry.height=argument_list[2].integer_reference;
7975           if (attribute_flag[3] != 0)
7976             geometry.x=argument_list[3].integer_reference;
7977           if (attribute_flag[4] != 0)
7978             geometry.y=argument_list[4].integer_reference;
7979           image=ChopImage(image,&geometry,exception);
7980           break;
7981         }
7982         case 8:  /* Crop */
7983         {
7984           if (attribute_flag[6] != 0)
7985             image->gravity=(GravityType) argument_list[6].integer_reference;
7986           if (attribute_flag[0] != 0)
7987             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7988               &geometry,exception);
7989           if (attribute_flag[1] != 0)
7990             geometry.width=argument_list[1].integer_reference;
7991           if (attribute_flag[2] != 0)
7992             geometry.height=argument_list[2].integer_reference;
7993           if (attribute_flag[3] != 0)
7994             geometry.x=argument_list[3].integer_reference;
7995           if (attribute_flag[4] != 0)
7996             geometry.y=argument_list[4].integer_reference;
7997           if (attribute_flag[5] != 0)
7998             image->fuzz=StringToDoubleInterval(
7999               argument_list[5].string_reference,(double) QuantumRange+1.0);
8000           image=CropImage(image,&geometry,exception);
8001           break;
8002         }
8003         case 9:  /* Despeckle */
8004         {
8005           image=DespeckleImage(image,exception);
8006           break;
8007         }
8008         case 10:  /* Edge */
8009         {
8010           if (attribute_flag[0] != 0)
8011             geometry_info.rho=argument_list[0].real_reference;
8012           image=EdgeImage(image,geometry_info.rho,exception);
8013           break;
8014         }
8015         case 11:  /* Emboss */
8016         {
8017           if (attribute_flag[0] != 0)
8018             {
8019               flags=ParseGeometry(argument_list[0].string_reference,
8020                 &geometry_info);
8021               if ((flags & SigmaValue) == 0)
8022                 geometry_info.sigma=1.0;
8023             }
8024           if (attribute_flag[1] != 0)
8025             geometry_info.rho=argument_list[1].real_reference;
8026           if (attribute_flag[2] != 0)
8027             geometry_info.sigma=argument_list[2].real_reference;
8028           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
8029             exception);
8030           break;
8031         }
8032         case 12:  /* Enhance */
8033         {
8034           image=EnhanceImage(image,exception);
8035           break;
8036         }
8037         case 13:  /* Flip */
8038         {
8039           image=FlipImage(image,exception);
8040           break;
8041         }
8042         case 14:  /* Flop */
8043         {
8044           image=FlopImage(image,exception);
8045           break;
8046         }
8047         case 15:  /* Frame */
8048         {
8049           CompositeOperator
8050             compose;
8051
8052           FrameInfo
8053             frame_info;
8054
8055           if (attribute_flag[0] != 0)
8056             {
8057               flags=ParsePageGeometry(image,argument_list[0].string_reference,
8058                 &geometry,exception);
8059               frame_info.width=geometry.width;
8060               frame_info.height=geometry.height;
8061               frame_info.outer_bevel=geometry.x;
8062               frame_info.inner_bevel=geometry.y;
8063             }
8064           if (attribute_flag[1] != 0)
8065             frame_info.width=argument_list[1].integer_reference;
8066           if (attribute_flag[2] != 0)
8067             frame_info.height=argument_list[2].integer_reference;
8068           if (attribute_flag[3] != 0)
8069             frame_info.inner_bevel=argument_list[3].integer_reference;
8070           if (attribute_flag[4] != 0)
8071             frame_info.outer_bevel=argument_list[4].integer_reference;
8072           if (attribute_flag[5] != 0)
8073             QueryColorCompliance(argument_list[5].string_reference,
8074               AllCompliance,&fill_color,exception);
8075           if (attribute_flag[6] != 0)
8076             QueryColorCompliance(argument_list[6].string_reference,
8077               AllCompliance,&fill_color,exception);
8078           frame_info.x=(ssize_t) frame_info.width;
8079           frame_info.y=(ssize_t) frame_info.height;
8080           frame_info.width=image->columns+2*frame_info.x;
8081           frame_info.height=image->rows+2*frame_info.y;
8082           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
8083             image->alpha_color=fill_color;
8084           compose=image->compose;
8085           if (attribute_flag[7] != 0)
8086             compose=(CompositeOperator) argument_list[7].integer_reference;
8087           image=FrameImage(image,&frame_info,compose,exception);
8088           break;
8089         }
8090         case 16:  /* Implode */
8091         {
8092           PixelInterpolateMethod
8093             method;
8094
8095           if (attribute_flag[0] == 0)
8096             argument_list[0].real_reference=0.5;
8097           method=UndefinedInterpolatePixel;
8098           if (attribute_flag[1] != 0)
8099             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8100           image=ImplodeImage(image,argument_list[0].real_reference,
8101             method,exception);
8102           break;
8103         }
8104         case 17:  /* Magnify */
8105         {
8106           image=MagnifyImage(image,exception);
8107           break;
8108         }
8109         case 18:  /* MedianFilter */
8110         {
8111           if (attribute_flag[0] != 0)
8112             {
8113               flags=ParseGeometry(argument_list[0].string_reference,
8114                 &geometry_info);
8115               if ((flags & SigmaValue) == 0)
8116                 geometry_info.sigma=geometry_info.rho;
8117             }
8118           if (attribute_flag[1] != 0)
8119             geometry_info.rho=argument_list[1].real_reference;
8120           if (attribute_flag[2] != 0)
8121             geometry_info.sigma=argument_list[2].real_reference;
8122           if (attribute_flag[3] != 0)
8123             channel=(ChannelType) argument_list[3].integer_reference;
8124           channel_mask=SetImageChannelMask(image,channel);
8125           image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
8126             (size_t) geometry_info.sigma,exception);
8127           if (image != (Image *) NULL)
8128             (void) SetImageChannelMask(image,channel_mask);
8129           break;
8130         }
8131         case 19:  /* Minify */
8132         {
8133           image=MinifyImage(image,exception);
8134           break;
8135         }
8136         case 20:  /* OilPaint */
8137         {
8138           if (attribute_flag[0] == 0)
8139             argument_list[0].real_reference=0.0;
8140           if (attribute_flag[1] == 0)
8141             argument_list[1].real_reference=1.0;
8142           image=OilPaintImage(image,argument_list[0].real_reference,
8143             argument_list[1].real_reference,exception);
8144           break;
8145         }
8146         case 21:  /* ReduceNoise */
8147         {
8148           if (attribute_flag[0] != 0)
8149             {
8150               flags=ParseGeometry(argument_list[0].string_reference,
8151                 &geometry_info);
8152               if ((flags & SigmaValue) == 0)
8153                 geometry_info.sigma=1.0;
8154             }
8155           if (attribute_flag[1] != 0)
8156             geometry_info.rho=argument_list[1].real_reference;
8157           if (attribute_flag[2] != 0)
8158             geometry_info.sigma=argument_list[2].real_reference;
8159           if (attribute_flag[3] != 0)
8160             channel=(ChannelType) argument_list[3].integer_reference;
8161           channel_mask=SetImageChannelMask(image,channel);
8162           image=StatisticImage(image,NonpeakStatistic,(size_t)
8163             geometry_info.rho,(size_t) geometry_info.sigma,exception);
8164           if (image != (Image *) NULL)
8165             (void) SetImageChannelMask(image,channel_mask);
8166           break;
8167         }
8168         case 22:  /* Roll */
8169         {
8170           if (attribute_flag[0] != 0)
8171             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8172               &geometry,exception);
8173           if (attribute_flag[1] != 0)
8174             geometry.x=argument_list[1].integer_reference;
8175           if (attribute_flag[2] != 0)
8176             geometry.y=argument_list[2].integer_reference;
8177           image=RollImage(image,geometry.x,geometry.y,exception);
8178           break;
8179         }
8180         case 23:  /* Rotate */
8181         {
8182           if (attribute_flag[0] == 0)
8183             argument_list[0].real_reference=90.0;
8184           if (attribute_flag[1] != 0)
8185             {
8186               QueryColorCompliance(argument_list[1].string_reference,
8187                 AllCompliance,&image->background_color,exception);
8188               if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
8189                   (image->alpha_trait == UndefinedPixelTrait))
8190                 (void) SetImageAlpha(image,OpaqueAlpha,exception);
8191             }
8192           image=RotateImage(image,argument_list[0].real_reference,exception);
8193           break;
8194         }
8195         case 24:  /* Sample */
8196         {
8197           if (attribute_flag[0] != 0)
8198             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8199               &geometry,exception);
8200           if (attribute_flag[1] != 0)
8201             geometry.width=argument_list[1].integer_reference;
8202           if (attribute_flag[2] != 0)
8203             geometry.height=argument_list[2].integer_reference;
8204           image=SampleImage(image,geometry.width,geometry.height,exception);
8205           break;
8206         }
8207         case 25:  /* Scale */
8208         {
8209           if (attribute_flag[0] != 0)
8210             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8211               &geometry,exception);
8212           if (attribute_flag[1] != 0)
8213             geometry.width=argument_list[1].integer_reference;
8214           if (attribute_flag[2] != 0)
8215             geometry.height=argument_list[2].integer_reference;
8216           image=ScaleImage(image,geometry.width,geometry.height,exception);
8217           break;
8218         }
8219         case 26:  /* Shade */
8220         {
8221           if (attribute_flag[0] != 0)
8222             {
8223               flags=ParseGeometry(argument_list[0].string_reference,
8224                 &geometry_info);
8225               if ((flags & SigmaValue) == 0)
8226                 geometry_info.sigma=0.0;
8227             }
8228           if (attribute_flag[1] != 0)
8229             geometry_info.rho=argument_list[1].real_reference;
8230           if (attribute_flag[2] != 0)
8231             geometry_info.sigma=argument_list[2].real_reference;
8232           image=ShadeImage(image,
8233             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8234             geometry_info.rho,geometry_info.sigma,exception);
8235           break;
8236         }
8237         case 27:  /* Sharpen */
8238         {
8239           if (attribute_flag[0] != 0)
8240             {
8241               flags=ParseGeometry(argument_list[0].string_reference,
8242                 &geometry_info);
8243               if ((flags & SigmaValue) == 0)
8244                 geometry_info.sigma=1.0;
8245             }
8246           if (attribute_flag[1] != 0)
8247             geometry_info.rho=argument_list[1].real_reference;
8248           if (attribute_flag[2] != 0)
8249             geometry_info.sigma=argument_list[2].real_reference;
8250           if (attribute_flag[3] != 0)
8251             channel=(ChannelType) argument_list[3].integer_reference;
8252           channel_mask=SetImageChannelMask(image,channel);
8253           image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
8254             exception);
8255           if (image != (Image *) NULL)
8256             (void) SetImageChannelMask(image,channel_mask);
8257           break;
8258         }
8259         case 28:  /* Shear */
8260         {
8261           if (attribute_flag[0] != 0)
8262             {
8263               flags=ParseGeometry(argument_list[0].string_reference,
8264                 &geometry_info);
8265               if ((flags & SigmaValue) == 0)
8266                 geometry_info.sigma=geometry_info.rho;
8267             }
8268           if (attribute_flag[1] != 0)
8269             geometry_info.rho=argument_list[1].real_reference;
8270           if (attribute_flag[2] != 0)
8271             geometry_info.sigma=argument_list[2].real_reference;
8272           if (attribute_flag[3] != 0)
8273             QueryColorCompliance(argument_list[3].string_reference,
8274               AllCompliance,&image->background_color,exception);
8275           if (attribute_flag[4] != 0)
8276             QueryColorCompliance(argument_list[4].string_reference,
8277               AllCompliance,&image->background_color,exception);
8278           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
8279             exception);
8280           break;
8281         }
8282         case 29:  /* Spread */
8283         {
8284           PixelInterpolateMethod
8285             method;
8286
8287           if (attribute_flag[0] == 0)
8288             argument_list[0].real_reference=1.0;
8289           method=UndefinedInterpolatePixel;
8290           if (attribute_flag[1] != 0)
8291             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8292           image=SpreadImage(image,method,argument_list[0].real_reference,
8293             exception);
8294           break;
8295         }
8296         case 30:  /* Swirl */
8297         {
8298           PixelInterpolateMethod
8299             method;
8300
8301           if (attribute_flag[0] == 0)
8302             argument_list[0].real_reference=50.0;
8303           method=UndefinedInterpolatePixel;
8304           if (attribute_flag[1] != 0)
8305             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8306           image=SwirlImage(image,argument_list[0].real_reference,
8307             method,exception);
8308           break;
8309         }
8310         case 31:  /* Resize */
8311         case 32:  /* Zoom */
8312         {
8313           if (attribute_flag[0] != 0)
8314             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8315               &geometry,exception);
8316           if (attribute_flag[1] != 0)
8317             geometry.width=argument_list[1].integer_reference;
8318           if (attribute_flag[2] != 0)
8319             geometry.height=argument_list[2].integer_reference;
8320           if (attribute_flag[3] == 0)
8321             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
8322           if (attribute_flag[4] != 0)
8323             SetImageArtifact(image,"filter:support",
8324               argument_list[4].string_reference);
8325           image=ResizeImage(image,geometry.width,geometry.height,
8326             (FilterType) argument_list[3].integer_reference,
8327             exception);
8328           break;
8329         }
8330         case 33:  /* Annotate */
8331         {
8332           DrawInfo
8333             *draw_info;
8334
8335           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8336             (DrawInfo *) NULL);
8337           if (attribute_flag[0] != 0)
8338             {
8339               char
8340                 *text;
8341
8342               text=InterpretImageProperties(info ? info->image_info :
8343                 (ImageInfo *) NULL,image,argument_list[0].string_reference,
8344                 exception);
8345               (void) CloneString(&draw_info->text,text);
8346               text=DestroyString(text);
8347             }
8348           if (attribute_flag[1] != 0)
8349             (void) CloneString(&draw_info->font,
8350               argument_list[1].string_reference);
8351           if (attribute_flag[2] != 0)
8352             draw_info->pointsize=argument_list[2].real_reference;
8353           if (attribute_flag[3] != 0)
8354             (void) CloneString(&draw_info->density,
8355               argument_list[3].string_reference);
8356           if (attribute_flag[4] != 0)
8357             (void) QueryColorCompliance(argument_list[4].string_reference,
8358               AllCompliance,&draw_info->undercolor,exception);
8359           if (attribute_flag[5] != 0)
8360             {
8361               (void) QueryColorCompliance(argument_list[5].string_reference,
8362                 AllCompliance,&draw_info->stroke,exception);
8363               if (argument_list[5].image_reference != (Image *) NULL)
8364                 draw_info->stroke_pattern=CloneImage(
8365                   argument_list[5].image_reference,0,0,MagickTrue,exception);
8366             }
8367           if (attribute_flag[6] != 0)
8368             {
8369               (void) QueryColorCompliance(argument_list[6].string_reference,
8370                 AllCompliance,&draw_info->fill,exception);
8371               if (argument_list[6].image_reference != (Image *) NULL)
8372                 draw_info->fill_pattern=CloneImage(
8373                   argument_list[6].image_reference,0,0,MagickTrue,exception);
8374             }
8375           if (attribute_flag[7] != 0)
8376             {
8377               (void) CloneString(&draw_info->geometry,
8378                 argument_list[7].string_reference);
8379               flags=ParsePageGeometry(image,argument_list[7].string_reference,
8380                 &geometry,exception);
8381               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8382                 geometry_info.sigma=geometry_info.xi;
8383             }
8384           if (attribute_flag[8] != 0)
8385             (void) QueryColorCompliance(argument_list[8].string_reference,
8386               AllCompliance,&draw_info->fill,exception);
8387           if (attribute_flag[11] != 0)
8388             draw_info->gravity=(GravityType)
8389               argument_list[11].integer_reference;
8390           if (attribute_flag[25] != 0)
8391             {
8392               AV
8393                 *av;
8394
8395               av=(AV *) argument_list[25].array_reference;
8396               if ((av_len(av) != 3) && (av_len(av) != 5))
8397                 {
8398                   ThrowPerlException(exception,OptionError,
8399                     "affine matrix must have 4 or 6 elements",PackageName);
8400                   goto PerlException;
8401                 }
8402               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8403               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8404               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8405               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8406               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8407                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8408                 {
8409                   ThrowPerlException(exception,OptionError,
8410                     "affine matrix is singular",PackageName);
8411                    goto PerlException;
8412                 }
8413               if (av_len(av) == 5)
8414                 {
8415                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8416                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8417                 }
8418             }
8419           for (j=12; j < 17; j++)
8420           {
8421             if (attribute_flag[j] == 0)
8422               continue;
8423             value=argument_list[j].string_reference;
8424             angle=argument_list[j].real_reference;
8425             current=draw_info->affine;
8426             GetAffineMatrix(&affine);
8427             switch (j)
8428             {
8429               case 12:
8430               {
8431                 /*
8432                   Translate.
8433                 */
8434                 flags=ParseGeometry(value,&geometry_info);
8435                 affine.tx=geometry_info.xi;
8436                 affine.ty=geometry_info.psi;
8437                 if ((flags & PsiValue) == 0)
8438                   affine.ty=affine.tx;
8439                 break;
8440               }
8441               case 13:
8442               {
8443                 /*
8444                   Scale.
8445                 */
8446                 flags=ParseGeometry(value,&geometry_info);
8447                 affine.sx=geometry_info.rho;
8448                 affine.sy=geometry_info.sigma;
8449                 if ((flags & SigmaValue) == 0)
8450                   affine.sy=affine.sx;
8451                 break;
8452               }
8453               case 14:
8454               {
8455                 /*
8456                   Rotate.
8457                 */
8458                 if (angle == 0.0)
8459                   break;
8460                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8461                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8462                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8463                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8464                 break;
8465               }
8466               case 15:
8467               {
8468                 /*
8469                   SkewX.
8470                 */
8471                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8472                 break;
8473               }
8474               case 16:
8475               {
8476                 /*
8477                   SkewY.
8478                 */
8479                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8480                 break;
8481               }
8482             }
8483             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8484             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8485             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8486             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8487             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8488               current.tx;
8489             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8490               current.ty;
8491           }
8492           if (attribute_flag[9] == 0)
8493             argument_list[9].real_reference=0.0;
8494           if (attribute_flag[10] == 0)
8495             argument_list[10].real_reference=0.0;
8496           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8497             {
8498               char
8499                 geometry[MagickPathExtent];
8500
8501               (void) FormatLocaleString(geometry,MagickPathExtent,"%+f%+f",
8502                 (double) argument_list[9].real_reference+draw_info->affine.tx,
8503                 (double) argument_list[10].real_reference+draw_info->affine.ty);
8504               (void) CloneString(&draw_info->geometry,geometry);
8505             }
8506           if (attribute_flag[17] != 0)
8507             draw_info->stroke_width=argument_list[17].real_reference;
8508           if (attribute_flag[18] != 0)
8509             {
8510               draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8511                 MagickTrue : MagickFalse;
8512               draw_info->stroke_antialias=draw_info->text_antialias;
8513             }
8514           if (attribute_flag[19] != 0)
8515             (void) CloneString(&draw_info->family,
8516               argument_list[19].string_reference);
8517           if (attribute_flag[20] != 0)
8518             draw_info->style=(StyleType) argument_list[20].integer_reference;
8519           if (attribute_flag[21] != 0)
8520             draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8521           if (attribute_flag[22] != 0)
8522             draw_info->weight=argument_list[22].integer_reference;
8523           if (attribute_flag[23] != 0)
8524             draw_info->align=(AlignType) argument_list[23].integer_reference;
8525           if (attribute_flag[24] != 0)
8526             (void) CloneString(&draw_info->encoding,
8527               argument_list[24].string_reference);
8528           if (attribute_flag[25] != 0)
8529             draw_info->fill_pattern=CloneImage(
8530               argument_list[25].image_reference,0,0,MagickTrue,exception);
8531           if (attribute_flag[26] != 0)
8532             draw_info->fill_pattern=CloneImage(
8533               argument_list[26].image_reference,0,0,MagickTrue,exception);
8534           if (attribute_flag[27] != 0)
8535             draw_info->stroke_pattern=CloneImage(
8536               argument_list[27].image_reference,0,0,MagickTrue,exception);
8537           if (attribute_flag[29] != 0)
8538             draw_info->kerning=argument_list[29].real_reference;
8539           if (attribute_flag[30] != 0)
8540             draw_info->interline_spacing=argument_list[30].real_reference;
8541           if (attribute_flag[31] != 0)
8542             draw_info->interword_spacing=argument_list[31].real_reference;
8543           if (attribute_flag[32] != 0)
8544             draw_info->direction=(DirectionType)
8545               argument_list[32].integer_reference;
8546           (void) AnnotateImage(image,draw_info,exception);
8547           draw_info=DestroyDrawInfo(draw_info);
8548           break;
8549         }
8550         case 34:  /* ColorFloodfill */
8551         {
8552           DrawInfo
8553             *draw_info;
8554
8555           MagickBooleanType
8556             invert;
8557
8558           PixelInfo
8559             target;
8560
8561           draw_info=CloneDrawInfo(info ? info->image_info :
8562             (ImageInfo *) NULL,(DrawInfo *) NULL);
8563           if (attribute_flag[0] != 0)
8564             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8565               &geometry,exception);
8566           if (attribute_flag[1] != 0)
8567             geometry.x=argument_list[1].integer_reference;
8568           if (attribute_flag[2] != 0)
8569             geometry.y=argument_list[2].integer_reference;
8570           if (attribute_flag[3] != 0)
8571             (void) QueryColorCompliance(argument_list[3].string_reference,
8572               AllCompliance,&draw_info->fill,exception);
8573           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
8574             geometry.x,geometry.y,&target,exception);
8575           invert=MagickFalse;
8576           if (attribute_flag[4] != 0)
8577             {
8578               QueryColorCompliance(argument_list[4].string_reference,
8579                 AllCompliance,&target,exception);
8580               invert=MagickTrue;
8581             }
8582           if (attribute_flag[5] != 0)
8583             image->fuzz=StringToDoubleInterval(
8584               argument_list[5].string_reference,(double) QuantumRange+1.0);
8585           if (attribute_flag[6] != 0)
8586             invert=(MagickBooleanType) argument_list[6].integer_reference;
8587           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8588             geometry.y,invert,exception);
8589           draw_info=DestroyDrawInfo(draw_info);
8590           break;
8591         }
8592         case 35:  /* Composite */
8593         {
8594           char
8595             composite_geometry[MagickPathExtent];
8596
8597           Image
8598             *composite_image,
8599             *rotate_image;
8600
8601           MagickBooleanType
8602             clip_to_self;
8603
8604           compose=OverCompositeOp;
8605           if (attribute_flag[0] != 0)
8606             composite_image=argument_list[0].image_reference;
8607           else
8608             {
8609               ThrowPerlException(exception,OptionError,
8610                 "CompositeImageRequired",PackageName);
8611               goto PerlException;
8612             }
8613           /*
8614             Parameter Handling used for BOTH normal and tiled composition.
8615           */
8616           if (attribute_flag[1] != 0) /* compose */
8617             compose=(CompositeOperator) argument_list[1].integer_reference;
8618           if (attribute_flag[6] != 0) /* opacity  */
8619             {
8620               if (compose != DissolveCompositeOp)
8621                 (void) SetImageAlpha(composite_image,(Quantum)
8622                   StringToDoubleInterval(argument_list[6].string_reference,
8623                   (double) QuantumRange+1.0),exception);
8624               else
8625                 {
8626                   CacheView
8627                     *composite_view;
8628
8629                   double
8630                     opacity;
8631
8632                   MagickBooleanType
8633                     sync;
8634
8635                   register ssize_t
8636                     x;
8637
8638                   register Quantum
8639                     *q;
8640
8641                   ssize_t
8642                     y;
8643
8644                   /*
8645                     Handle dissolve composite operator (patch by
8646                     Kevin A. McGrail).
8647                   */
8648                   (void) CloneString(&image->geometry,
8649                     argument_list[6].string_reference);
8650                   opacity=(Quantum) StringToDoubleInterval(
8651                     argument_list[6].string_reference,(double) QuantumRange+
8652                     1.0);
8653                   if (composite_image->alpha_trait != UndefinedPixelTrait)
8654                     (void) SetImageAlpha(composite_image,OpaqueAlpha,exception);
8655                   composite_view=AcquireAuthenticCacheView(composite_image,exception);
8656                   for (y=0; y < (ssize_t) composite_image->rows ; y++)
8657                   {
8658                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8659                       composite_image->columns,1,exception);
8660                     for (x=0; x < (ssize_t) composite_image->columns; x++)
8661                     {
8662                       if (GetPixelAlpha(image,q) == OpaqueAlpha)
8663                         SetPixelAlpha(composite_image,ClampToQuantum(opacity),
8664                           q);
8665                       q+=GetPixelChannels(composite_image);
8666                     }
8667                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8668                     if (sync == MagickFalse)
8669                       break;
8670                   }
8671                   composite_view=DestroyCacheView(composite_view);
8672                 }
8673             }
8674           if (attribute_flag[9] != 0)    /* "color=>" */
8675             QueryColorCompliance(argument_list[9].string_reference,
8676               AllCompliance,&composite_image->background_color,exception);
8677           if (attribute_flag[12] != 0) /* "interpolate=>" */
8678             image->interpolate=(PixelInterpolateMethod)
8679               argument_list[12].integer_reference;
8680           if (attribute_flag[13] != 0)   /* "args=>" */
8681             (void) SetImageArtifact(composite_image,"compose:args",
8682               argument_list[13].string_reference);
8683           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8684             (void) SetImageArtifact(composite_image,"compose:args",
8685               argument_list[14].string_reference);
8686           clip_to_self=MagickTrue;
8687           if (attribute_flag[15] != 0)
8688             clip_to_self=(MagickBooleanType)
8689               argument_list[15].integer_reference;
8690           /*
8691             Tiling Composition (with orthogonal rotate).
8692           */
8693           rotate_image=(Image *) NULL;
8694           if (attribute_flag[8] != 0)   /* "rotate=>" */
8695             {
8696                /*
8697                  Rotate image.
8698                */
8699                rotate_image=RotateImage(composite_image,
8700                  argument_list[8].real_reference,exception);
8701                if (rotate_image == (Image *) NULL)
8702                  break;
8703             }
8704           if ((attribute_flag[7] != 0) &&
8705               (argument_list[7].integer_reference != 0)) /* tile */
8706             {
8707               ssize_t
8708                 x,
8709                 y;
8710
8711               /*
8712                 Tile the composite image.
8713               */
8714              if (attribute_flag[8] != 0)   /* "tile=>" */
8715                (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8716                  "false");
8717              else
8718                (void) SetImageArtifact(composite_image,
8719                  "compose:outside-overlay","false");
8720              for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8721                 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8722                 {
8723                   if (attribute_flag[8] != 0) /* rotate */
8724                     (void) CompositeImage(image,rotate_image,compose,
8725                       MagickTrue,x,y,exception);
8726                   else
8727                     (void) CompositeImage(image,composite_image,compose,
8728                       MagickTrue,x,y,exception);
8729                 }
8730               if (attribute_flag[8] != 0) /* rotate */
8731                 rotate_image=DestroyImage(rotate_image);
8732               break;
8733             }
8734           /*
8735             Parameter Handling used used ONLY for normal composition.
8736           */
8737           if (attribute_flag[5] != 0) /* gravity */
8738             image->gravity=(GravityType) argument_list[5].integer_reference;
8739           if (attribute_flag[2] != 0) /* geometry offset */
8740             {
8741               SetGeometry(image,&geometry);
8742               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8743                 &geometry);
8744               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8745                 &geometry);
8746             }
8747           if (attribute_flag[3] != 0) /* x offset */
8748             geometry.x=argument_list[3].integer_reference;
8749           if (attribute_flag[4] != 0) /* y offset */
8750             geometry.y=argument_list[4].integer_reference;
8751           if (attribute_flag[10] != 0) /* mask */
8752             {
8753               if ((image->compose == DisplaceCompositeOp) ||
8754                   (image->compose == DistortCompositeOp))
8755                 {
8756                   /*
8757                     Merge Y displacement into X displacement image.
8758                   */
8759                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8760                     exception);
8761                   (void) CompositeImage(composite_image,
8762                     argument_list[10].image_reference,CopyGreenCompositeOp,
8763                     MagickTrue,0,0,exception);
8764                 }
8765               else
8766                 {
8767                   Image
8768                     *mask_image;
8769
8770                   /*
8771                     Set a blending mask for the composition.
8772                   */
8773                   mask_image=CloneImage(argument_list[10].image_reference,0,0,
8774                     MagickTrue,exception);
8775                   (void) SetImageMask(composite_image,ReadPixelMask,mask_image,
8776                     exception);
8777                   mask_image=DestroyImage(mask_image);
8778                 }
8779             }
8780           if (attribute_flag[11] != 0) /* channel */
8781             channel=(ChannelType) argument_list[11].integer_reference;
8782           /*
8783             Composite two images (normal composition).
8784           */
8785           (void) FormatLocaleString(composite_geometry,MagickPathExtent,
8786             "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8787             (double) composite_image->rows,(double) geometry.x,(double)
8788             geometry.y);
8789           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8790             exception);
8791           channel_mask=SetImageChannelMask(image,channel);
8792           if (attribute_flag[8] == 0) /* no rotate */
8793             CompositeImage(image,composite_image,compose,clip_to_self,
8794               geometry.x,geometry.y,exception);
8795           else
8796             {
8797               /*
8798                 Position adjust rotated image then composite.
8799               */
8800               geometry.x-=(ssize_t) (rotate_image->columns-
8801                 composite_image->columns)/2;
8802               geometry.y-=(ssize_t) (rotate_image->rows-
8803                 composite_image->rows)/2;
8804               CompositeImage(image,rotate_image,compose,clip_to_self,geometry.x,
8805                 geometry.y,exception);
8806               rotate_image=DestroyImage(rotate_image);
8807             }
8808           if (attribute_flag[10] != 0) /* mask */
8809             {
8810               if ((image->compose == DisplaceCompositeOp) ||
8811                   (image->compose == DistortCompositeOp))
8812                 composite_image=DestroyImage(composite_image);
8813               else
8814                 (void) SetImageMask(image,ReadPixelMask,(Image *) NULL,
8815                   exception);
8816             }
8817           (void) SetImageChannelMask(image,channel_mask);
8818           break;
8819         }
8820         case 36:  /* Contrast */
8821         {
8822           if (attribute_flag[0] == 0)
8823             argument_list[0].integer_reference=0;
8824           (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8825             MagickTrue : MagickFalse,exception);
8826           break;
8827         }
8828         case 37:  /* CycleColormap */
8829         {
8830           if (attribute_flag[0] == 0)
8831             argument_list[0].integer_reference=6;
8832           (void) CycleColormapImage(image,argument_list[0].integer_reference,
8833             exception);
8834           break;
8835         }
8836         case 38:  /* Draw */
8837         {
8838           DrawInfo
8839             *draw_info;
8840
8841           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8842             (DrawInfo *) NULL);
8843           (void) CloneString(&draw_info->primitive,"point");
8844           if (attribute_flag[0] != 0)
8845             {
8846               if (argument_list[0].integer_reference < 0)
8847                 (void) CloneString(&draw_info->primitive,
8848                   argument_list[0].string_reference);
8849               else
8850                 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8851                   MagickPrimitiveOptions,argument_list[0].integer_reference));
8852             }
8853           if (attribute_flag[1] != 0)
8854             {
8855               if (LocaleCompare(draw_info->primitive,"path") == 0)
8856                 {
8857                   (void) ConcatenateString(&draw_info->primitive," '");
8858                   ConcatenateString(&draw_info->primitive,
8859                     argument_list[1].string_reference);
8860                   (void) ConcatenateString(&draw_info->primitive,"'");
8861                 }
8862               else
8863                 {
8864                   (void) ConcatenateString(&draw_info->primitive," ");
8865                   ConcatenateString(&draw_info->primitive,
8866                     argument_list[1].string_reference);
8867                 }
8868             }
8869           if (attribute_flag[2] != 0)
8870             {
8871               (void) ConcatenateString(&draw_info->primitive," ");
8872               (void) ConcatenateString(&draw_info->primitive,
8873                 CommandOptionToMnemonic(MagickMethodOptions,
8874                 argument_list[2].integer_reference));
8875             }
8876           if (attribute_flag[3] != 0)
8877             {
8878               (void) QueryColorCompliance(argument_list[3].string_reference,
8879                 AllCompliance,&draw_info->stroke,exception);
8880               if (argument_list[3].image_reference != (Image *) NULL)
8881                 draw_info->stroke_pattern=CloneImage(
8882                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8883             }
8884           if (attribute_flag[4] != 0)
8885             {
8886               (void) QueryColorCompliance(argument_list[4].string_reference,
8887                 AllCompliance,&draw_info->fill,exception);
8888               if (argument_list[4].image_reference != (Image *) NULL)
8889                 draw_info->fill_pattern=CloneImage(
8890                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8891             }
8892           if (attribute_flag[5] != 0)
8893             draw_info->stroke_width=argument_list[5].real_reference;
8894           if (attribute_flag[6] != 0)
8895             (void) CloneString(&draw_info->font,
8896               argument_list[6].string_reference);
8897           if (attribute_flag[7] != 0)
8898             (void) QueryColorCompliance(argument_list[7].string_reference,
8899               AllCompliance,&draw_info->border_color,exception);
8900           if (attribute_flag[8] != 0)
8901             draw_info->affine.tx=argument_list[8].real_reference;
8902           if (attribute_flag[9] != 0)
8903             draw_info->affine.ty=argument_list[9].real_reference;
8904           if (attribute_flag[20] != 0)
8905             {
8906               AV
8907                 *av;
8908
8909               av=(AV *) argument_list[20].array_reference;
8910               if ((av_len(av) != 3) && (av_len(av) != 5))
8911                 {
8912                   ThrowPerlException(exception,OptionError,
8913                     "affine matrix must have 4 or 6 elements",PackageName);
8914                   goto PerlException;
8915                 }
8916               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8917               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8918               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8919               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8920               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8921                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8922                 {
8923                   ThrowPerlException(exception,OptionError,
8924                     "affine matrix is singular",PackageName);
8925                    goto PerlException;
8926                 }
8927               if (av_len(av) == 5)
8928                 {
8929                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8930                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8931                 }
8932             }
8933           for (j=10; j < 15; j++)
8934           {
8935             if (attribute_flag[j] == 0)
8936               continue;
8937             value=argument_list[j].string_reference;
8938             angle=argument_list[j].real_reference;
8939             current=draw_info->affine;
8940             GetAffineMatrix(&affine);
8941             switch (j)
8942             {
8943               case 10:
8944               {
8945                 /*
8946                   Translate.
8947                 */
8948                 flags=ParseGeometry(value,&geometry_info);
8949                 affine.tx=geometry_info.xi;
8950                 affine.ty=geometry_info.psi;
8951                 if ((flags & PsiValue) == 0)
8952                   affine.ty=affine.tx;
8953                 break;
8954               }
8955               case 11:
8956               {
8957                 /*
8958                   Scale.
8959                 */
8960                 flags=ParseGeometry(value,&geometry_info);
8961                 affine.sx=geometry_info.rho;
8962                 affine.sy=geometry_info.sigma;
8963                 if ((flags & SigmaValue) == 0)
8964                   affine.sy=affine.sx;
8965                 break;
8966               }
8967               case 12:
8968               {
8969                 /*
8970                   Rotate.
8971                 */
8972                 if (angle == 0.0)
8973                   break;
8974                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8975                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8976                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8977                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8978                 break;
8979               }
8980               case 13:
8981               {
8982                 /*
8983                   SkewX.
8984                 */
8985                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8986                 break;
8987               }
8988               case 14:
8989               {
8990                 /*
8991                   SkewY.
8992                 */
8993                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8994                 break;
8995               }
8996             }
8997             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8998             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8999             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9000             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9001             draw_info->affine.tx=
9002               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9003             draw_info->affine.ty=
9004               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9005           }
9006           if (attribute_flag[15] != 0)
9007             draw_info->fill_pattern=CloneImage(
9008               argument_list[15].image_reference,0,0,MagickTrue,exception);
9009           if (attribute_flag[16] != 0)
9010             draw_info->pointsize=argument_list[16].real_reference;
9011           if (attribute_flag[17] != 0)
9012             {
9013               draw_info->stroke_antialias=argument_list[17].integer_reference != 0
9014                 ? MagickTrue : MagickFalse;
9015               draw_info->text_antialias=draw_info->stroke_antialias;
9016             }
9017           if (attribute_flag[18] != 0)
9018             (void) CloneString(&draw_info->density,
9019               argument_list[18].string_reference);
9020           if (attribute_flag[19] != 0)
9021             draw_info->stroke_width=argument_list[19].real_reference;
9022           if (attribute_flag[21] != 0)
9023             draw_info->dash_offset=argument_list[21].real_reference;
9024           if (attribute_flag[22] != 0)
9025             {
9026               AV
9027                 *av;
9028
9029               av=(AV *) argument_list[22].array_reference;
9030               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
9031                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
9032               if (draw_info->dash_pattern != (double *) NULL)
9033                 {
9034                   for (i=0; i <= av_len(av); i++)
9035                     draw_info->dash_pattern[i]=(double)
9036                       SvNV(*(av_fetch(av,i,0)));
9037                   draw_info->dash_pattern[i]=0.0;
9038                 }
9039             }
9040           if (attribute_flag[23] != 0)
9041             image->interpolate=(PixelInterpolateMethod)
9042               argument_list[23].integer_reference;
9043           if ((attribute_flag[24] != 0) &&
9044               (draw_info->fill_pattern != (Image *) NULL))
9045             flags=ParsePageGeometry(draw_info->fill_pattern,
9046               argument_list[24].string_reference,
9047               &draw_info->fill_pattern->tile_offset,exception);
9048           if (attribute_flag[25] != 0)
9049             {
9050               (void) ConcatenateString(&draw_info->primitive," '");
9051               (void) ConcatenateString(&draw_info->primitive,
9052                 argument_list[25].string_reference);
9053               (void) ConcatenateString(&draw_info->primitive,"'");
9054             }
9055           if (attribute_flag[26] != 0)
9056             draw_info->fill_pattern=CloneImage(
9057               argument_list[26].image_reference,0,0,MagickTrue,exception);
9058           if (attribute_flag[27] != 0)
9059             draw_info->stroke_pattern=CloneImage(
9060               argument_list[27].image_reference,0,0,MagickTrue,exception);
9061           if (attribute_flag[28] != 0)
9062             (void) CloneString(&draw_info->primitive,
9063               argument_list[28].string_reference);
9064           if (attribute_flag[29] != 0)
9065             draw_info->kerning=argument_list[29].real_reference;
9066           if (attribute_flag[30] != 0)
9067             draw_info->interline_spacing=argument_list[30].real_reference;
9068           if (attribute_flag[31] != 0)
9069             draw_info->interword_spacing=argument_list[31].real_reference;
9070           if (attribute_flag[32] != 0)
9071             draw_info->direction=(DirectionType)
9072               argument_list[32].integer_reference;
9073           DrawImage(image,draw_info,exception);
9074           draw_info=DestroyDrawInfo(draw_info);
9075           break;
9076         }
9077         case 39:  /* Equalize */
9078         {
9079           if (attribute_flag[0] != 0)
9080             channel=(ChannelType) argument_list[0].integer_reference;
9081           channel_mask=SetImageChannelMask(image,channel);
9082           EqualizeImage(image,exception);
9083           (void) SetImageChannelMask(image,channel_mask);
9084           break;
9085         }
9086         case 40:  /* Gamma */
9087         {
9088           if (attribute_flag[1] != 0)
9089             channel=(ChannelType) argument_list[1].integer_reference;
9090           if (attribute_flag[2] == 0)
9091             argument_list[2].real_reference=1.0;
9092           if (attribute_flag[3] == 0)
9093             argument_list[3].real_reference=1.0;
9094           if (attribute_flag[4] == 0)
9095             argument_list[4].real_reference=1.0;
9096           if (attribute_flag[0] == 0)
9097             {
9098               (void) FormatLocaleString(message,MagickPathExtent,
9099                 "%.15g,%.15g,%.15g",(double) argument_list[2].real_reference,
9100                 (double) argument_list[3].real_reference,
9101                 (double) argument_list[4].real_reference);
9102               argument_list[0].string_reference=message;
9103             }
9104           (void) GammaImage(image,StringToDouble(
9105             argument_list[0].string_reference,(char **) NULL),exception);
9106           break;
9107         }
9108         case 41:  /* Map */
9109         {
9110           QuantizeInfo
9111             *quantize_info;
9112
9113           if (attribute_flag[0] == 0)
9114             {
9115               ThrowPerlException(exception,OptionError,"MapImageRequired",
9116                 PackageName);
9117               goto PerlException;
9118             }
9119           quantize_info=AcquireQuantizeInfo(info->image_info);
9120           if (attribute_flag[1] != 0)
9121             quantize_info->dither_method=(DitherMethod)
9122               argument_list[1].integer_reference;
9123           (void) RemapImages(quantize_info,image,
9124             argument_list[0].image_reference,exception);
9125           quantize_info=DestroyQuantizeInfo(quantize_info);
9126           break;
9127         }
9128         case 42:  /* MatteFloodfill */
9129         {
9130           DrawInfo
9131             *draw_info;
9132
9133           MagickBooleanType
9134             invert;
9135
9136           PixelInfo
9137             target;
9138
9139           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9140             (DrawInfo *) NULL);
9141           if (attribute_flag[0] != 0)
9142             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9143               &geometry,exception);
9144           if (attribute_flag[1] != 0)
9145             geometry.x=argument_list[1].integer_reference;
9146           if (attribute_flag[2] != 0)
9147             geometry.y=argument_list[2].integer_reference;
9148           if (image->alpha_trait == UndefinedPixelTrait)
9149             (void) SetImageAlpha(image,OpaqueAlpha,exception);
9150           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
9151             geometry.x,geometry.y,&target,exception);
9152           if (attribute_flag[4] != 0)
9153             QueryColorCompliance(argument_list[4].string_reference,
9154               AllCompliance,&target,exception);
9155           if (attribute_flag[3] != 0)
9156             target.alpha=StringToDoubleInterval(
9157               argument_list[3].string_reference,(double) (double) QuantumRange+
9158               1.0);
9159           if (attribute_flag[5] != 0)
9160             image->fuzz=StringToDoubleInterval(
9161               argument_list[5].string_reference,(double) QuantumRange+1.0);
9162           invert=MagickFalse;
9163           if (attribute_flag[6] != 0)
9164             invert=(MagickBooleanType) argument_list[6].integer_reference;
9165           channel_mask=SetImageChannelMask(image,AlphaChannel);
9166           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
9167             geometry.y,invert,exception);
9168           (void) SetImageChannelMask(image,channel_mask);
9169           draw_info=DestroyDrawInfo(draw_info);
9170           break;
9171         }
9172         case 43:  /* Modulate */
9173         {
9174           char
9175             modulate[MagickPathExtent];
9176
9177           geometry_info.rho=100.0;
9178           geometry_info.sigma=100.0;
9179           geometry_info.xi=100.0;
9180           if (attribute_flag[0] != 0)
9181             (void)ParseGeometry(argument_list[0].string_reference,
9182               &geometry_info);
9183           if (attribute_flag[1] != 0)
9184             geometry_info.xi=argument_list[1].real_reference;
9185           if (attribute_flag[2] != 0)
9186             geometry_info.sigma=argument_list[2].real_reference;
9187           if (attribute_flag[3] != 0)
9188             {
9189               geometry_info.sigma=argument_list[3].real_reference;
9190               SetImageArtifact(image,"modulate:colorspace","HWB");
9191             }
9192           if (attribute_flag[4] != 0)
9193             {
9194               geometry_info.rho=argument_list[4].real_reference;
9195               SetImageArtifact(image,"modulate:colorspace","HSB");
9196             }
9197           if (attribute_flag[5] != 0)
9198             {
9199               geometry_info.sigma=argument_list[5].real_reference;
9200               SetImageArtifact(image,"modulate:colorspace","HSL");
9201             }
9202           if (attribute_flag[6] != 0)
9203             {
9204               geometry_info.rho=argument_list[6].real_reference;
9205               SetImageArtifact(image,"modulate:colorspace","HWB");
9206             }
9207           (void) FormatLocaleString(modulate,MagickPathExtent,"%.15g,%.15g,%.15g",
9208             geometry_info.rho,geometry_info.sigma,geometry_info.xi);
9209           (void) ModulateImage(image,modulate,exception);
9210           break;
9211         }
9212         case 44:  /* Negate */
9213         {
9214           if (attribute_flag[0] == 0)
9215             argument_list[0].integer_reference=0;
9216           if (attribute_flag[1] != 0)
9217             channel=(ChannelType) argument_list[1].integer_reference;
9218           channel_mask=SetImageChannelMask(image,channel);
9219           (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
9220             MagickTrue : MagickFalse,exception);
9221           (void) SetImageChannelMask(image,channel_mask);
9222           break;
9223         }
9224         case 45:  /* Normalize */
9225         {
9226           if (attribute_flag[0] != 0)
9227             channel=(ChannelType) argument_list[0].integer_reference;
9228           channel_mask=SetImageChannelMask(image,channel);
9229           NormalizeImage(image,exception);
9230           (void) SetImageChannelMask(image,channel_mask);
9231           break;
9232         }
9233         case 46:  /* NumberColors */
9234           break;
9235         case 47:  /* Opaque */
9236         {
9237           MagickBooleanType
9238             invert;
9239
9240           PixelInfo
9241             fill_color,
9242             target;
9243
9244           (void) QueryColorCompliance("none",AllCompliance,&target,
9245              exception);
9246           (void) QueryColorCompliance("none",AllCompliance,&fill_color,
9247             exception);
9248           if (attribute_flag[0] != 0)
9249             (void) QueryColorCompliance(argument_list[0].string_reference,
9250               AllCompliance,&target,exception);
9251           if (attribute_flag[1] != 0)
9252             (void) QueryColorCompliance(argument_list[1].string_reference,
9253               AllCompliance,&fill_color,exception);
9254           if (attribute_flag[2] != 0)
9255             image->fuzz=StringToDoubleInterval(
9256               argument_list[2].string_reference,(double) QuantumRange+1.0);
9257           if (attribute_flag[3] != 0)
9258             channel=(ChannelType) argument_list[3].integer_reference;
9259           invert=MagickFalse;
9260           if (attribute_flag[4] != 0)
9261             invert=(MagickBooleanType) argument_list[4].integer_reference;
9262           channel_mask=SetImageChannelMask(image,channel);
9263           (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
9264           (void) SetImageChannelMask(image,channel_mask);
9265           break;
9266         }
9267         case 48:  /* Quantize */
9268         {
9269           QuantizeInfo
9270             *quantize_info;
9271
9272           quantize_info=AcquireQuantizeInfo(info->image_info);
9273           if (attribute_flag[0] != 0)
9274             quantize_info->number_colors=(size_t)
9275               argument_list[0].integer_reference;
9276           if (attribute_flag[1] != 0)
9277             quantize_info->tree_depth=(size_t)
9278               argument_list[1].integer_reference;
9279           if (attribute_flag[2] != 0)
9280             quantize_info->colorspace=(ColorspaceType)
9281               argument_list[2].integer_reference;
9282           if (attribute_flag[3] != 0)
9283             quantize_info->dither_method=(DitherMethod)
9284               argument_list[3].integer_reference;
9285           if (attribute_flag[4] != 0)
9286             quantize_info->measure_error=
9287               argument_list[4].integer_reference != 0 ? MagickTrue : MagickFalse;
9288           if (attribute_flag[6] != 0)
9289             (void) QueryColorCompliance(argument_list[6].string_reference,
9290               AllCompliance,&image->transparent_color,exception);
9291           if (attribute_flag[7] != 0)
9292             quantize_info->dither_method=(DitherMethod)
9293               argument_list[7].integer_reference;
9294           if (attribute_flag[5] && argument_list[5].integer_reference)
9295             (void) QuantizeImages(quantize_info,image,exception);
9296           else
9297             if ((image->storage_class == DirectClass) ||
9298                (image->colors > quantize_info->number_colors) ||
9299                (quantize_info->colorspace == GRAYColorspace))
9300              (void) QuantizeImage(quantize_info,image,exception);
9301            else
9302              CompressImageColormap(image,exception);
9303           quantize_info=DestroyQuantizeInfo(quantize_info);
9304           break;
9305         }
9306         case 49:  /* Raise */
9307         {
9308           if (attribute_flag[0] != 0)
9309             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9310               &geometry,exception);
9311           if (attribute_flag[1] != 0)
9312             geometry.width=argument_list[1].integer_reference;
9313           if (attribute_flag[2] != 0)
9314             geometry.height=argument_list[2].integer_reference;
9315           if (attribute_flag[3] == 0)
9316             argument_list[3].integer_reference=1;
9317           (void) RaiseImage(image,&geometry,
9318             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
9319             exception);
9320           break;
9321         }
9322         case 50:  /* Segment */
9323         {
9324           ColorspaceType
9325             colorspace;
9326
9327           double
9328             cluster_threshold,
9329             smoothing_threshold;
9330
9331           MagickBooleanType
9332             verbose;
9333
9334           cluster_threshold=1.0;
9335           smoothing_threshold=1.5;
9336           colorspace=sRGBColorspace;
9337           verbose=MagickFalse;
9338           if (attribute_flag[0] != 0)
9339             {
9340               flags=ParseGeometry(argument_list[0].string_reference,
9341                 &geometry_info);
9342               cluster_threshold=geometry_info.rho;
9343               if (flags & SigmaValue)
9344                 smoothing_threshold=geometry_info.sigma;
9345             }
9346           if (attribute_flag[1] != 0)
9347             cluster_threshold=argument_list[1].real_reference;
9348           if (attribute_flag[2] != 0)
9349             smoothing_threshold=argument_list[2].real_reference;
9350           if (attribute_flag[3] != 0)
9351             colorspace=(ColorspaceType) argument_list[3].integer_reference;
9352           if (attribute_flag[4] != 0)
9353             verbose=argument_list[4].integer_reference != 0 ?
9354               MagickTrue : MagickFalse;
9355           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
9356             smoothing_threshold,exception);
9357           break;
9358         }
9359         case 51:  /* Signature */
9360         {
9361           (void) SignatureImage(image,exception);
9362           break;
9363         }
9364         case 52:  /* Solarize */
9365         {
9366           geometry_info.rho=QuantumRange/2.0;
9367           if (attribute_flag[0] != 0)
9368             flags=ParseGeometry(argument_list[0].string_reference,
9369               &geometry_info);
9370           if (attribute_flag[1] != 0)
9371             geometry_info.rho=StringToDoubleInterval(
9372               argument_list[1].string_reference,(double) QuantumRange+1.0);
9373           (void) SolarizeImage(image,geometry_info.rho,exception);
9374           break;
9375         }
9376         case 53:  /* Sync */
9377         {
9378           (void) SyncImage(image,exception);
9379           break;
9380         }
9381         case 54:  /* Texture */
9382         {
9383           if (attribute_flag[0] == 0)
9384             break;
9385           TextureImage(image,argument_list[0].image_reference,exception);
9386           break;
9387         }
9388         case 55:  /* Evalute */
9389         {
9390           MagickEvaluateOperator
9391             op;
9392
9393           op=SetEvaluateOperator;
9394           if (attribute_flag[0] == MagickFalse)
9395             argument_list[0].real_reference=0.0;
9396           if (attribute_flag[1] != MagickFalse)
9397             op=(MagickEvaluateOperator) argument_list[1].integer_reference;
9398           if (attribute_flag[2] != MagickFalse)
9399             channel=(ChannelType) argument_list[2].integer_reference;
9400           channel_mask=SetImageChannelMask(image,channel);
9401           (void) EvaluateImage(image,op,argument_list[0].real_reference,
9402             exception);
9403           (void) SetImageChannelMask(image,channel_mask);
9404           break;
9405         }
9406         case 56:  /* Transparent */
9407         {
9408           double
9409             opacity;
9410
9411           MagickBooleanType
9412             invert;
9413
9414           PixelInfo
9415             target;
9416
9417           (void) QueryColorCompliance("none",AllCompliance,&target,
9418             exception);
9419           if (attribute_flag[0] != 0)
9420             (void) QueryColorCompliance(argument_list[0].string_reference,
9421               AllCompliance,&target,exception);
9422           opacity=TransparentAlpha;
9423           if (attribute_flag[1] != 0)
9424             opacity=StringToDoubleInterval(argument_list[1].string_reference,
9425               (double) QuantumRange+1.0);
9426           if (attribute_flag[2] != 0)
9427             image->fuzz=StringToDoubleInterval(
9428               argument_list[2].string_reference,(double) QuantumRange+1.0);
9429           if (attribute_flag[3] == 0)
9430             argument_list[3].integer_reference=0;
9431           invert=MagickFalse;
9432           if (attribute_flag[3] != 0)
9433             invert=(MagickBooleanType) argument_list[3].integer_reference;
9434           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9435             invert,exception);
9436           break;
9437         }
9438         case 57:  /* Threshold */
9439         {
9440           double
9441             threshold;
9442
9443           if (attribute_flag[0] == 0)
9444             argument_list[0].string_reference="50%";
9445           if (attribute_flag[1] != 0)
9446             channel=(ChannelType) argument_list[1].integer_reference;
9447           threshold=StringToDoubleInterval(argument_list[0].string_reference,
9448             (double) QuantumRange+1.0);
9449           channel_mask=SetImageChannelMask(image,channel);
9450           (void) BilevelImage(image,threshold,exception);
9451           (void) SetImageChannelMask(image,channel_mask);
9452           break;
9453         }
9454         case 58:  /* Charcoal */
9455         {
9456           if (attribute_flag[0] != 0)
9457             {
9458               flags=ParseGeometry(argument_list[0].string_reference,
9459                 &geometry_info);
9460               if ((flags & SigmaValue) == 0)
9461                 geometry_info.sigma=1.0;
9462             }
9463           if (attribute_flag[1] != 0)
9464             geometry_info.rho=argument_list[1].real_reference;
9465           if (attribute_flag[2] != 0)
9466             geometry_info.sigma=argument_list[2].real_reference;
9467           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9468             exception);
9469           break;
9470         }
9471         case 59:  /* Trim */
9472         {
9473           if (attribute_flag[0] != 0)
9474             image->fuzz=StringToDoubleInterval(
9475               argument_list[0].string_reference,(double) QuantumRange+1.0);
9476           image=TrimImage(image,exception);
9477           break;
9478         }
9479         case 60:  /* Wave */
9480         {
9481           PixelInterpolateMethod
9482             method;
9483
9484           if (attribute_flag[0] != 0)
9485             {
9486               flags=ParseGeometry(argument_list[0].string_reference,
9487                 &geometry_info);
9488               if ((flags & SigmaValue) == 0)
9489                 geometry_info.sigma=1.0;
9490             }
9491           if (attribute_flag[1] != 0)
9492             geometry_info.rho=argument_list[1].real_reference;
9493           if (attribute_flag[2] != 0)
9494             geometry_info.sigma=argument_list[2].real_reference;
9495           method=UndefinedInterpolatePixel;
9496           if (attribute_flag[3] != 0)
9497             method=(PixelInterpolateMethod) argument_list[3].integer_reference;
9498           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9499             method,exception);
9500           break;
9501         }
9502         case 61:  /* Separate */
9503         {
9504           if (attribute_flag[0] != 0)
9505             channel=(ChannelType) argument_list[0].integer_reference;
9506           image=SeparateImage(image,channel,exception);
9507           break;
9508         }
9509         case 63:  /* Stereo */
9510         {
9511           if (attribute_flag[0] == 0)
9512             {
9513               ThrowPerlException(exception,OptionError,"StereoImageRequired",
9514                 PackageName);
9515               goto PerlException;
9516             }
9517           if (attribute_flag[1] != 0)
9518             geometry.x=argument_list[1].integer_reference;
9519           if (attribute_flag[2] != 0)
9520             geometry.y=argument_list[2].integer_reference;
9521           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9522             geometry.x,geometry.y,exception);
9523           break;
9524         }
9525         case 64:  /* Stegano */
9526         {
9527           if (attribute_flag[0] == 0)
9528             {
9529               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9530                 PackageName);
9531               goto PerlException;
9532             }
9533           if (attribute_flag[1] == 0)
9534             argument_list[1].integer_reference=0;
9535           image->offset=argument_list[1].integer_reference;
9536           image=SteganoImage(image,argument_list[0].image_reference,exception);
9537           break;
9538         }
9539         case 65:  /* Deconstruct */
9540         {
9541           image=CompareImagesLayers(image,CompareAnyLayer,exception);
9542           break;
9543         }
9544         case 66:  /* GaussianBlur */
9545         {
9546           if (attribute_flag[0] != 0)
9547             {
9548               flags=ParseGeometry(argument_list[0].string_reference,
9549                 &geometry_info);
9550               if ((flags & SigmaValue) == 0)
9551                 geometry_info.sigma=1.0;
9552             }
9553           if (attribute_flag[1] != 0)
9554             geometry_info.rho=argument_list[1].real_reference;
9555           if (attribute_flag[2] != 0)
9556             geometry_info.sigma=argument_list[2].real_reference;
9557           if (attribute_flag[3] != 0)
9558             channel=(ChannelType) argument_list[3].integer_reference;
9559           channel_mask=SetImageChannelMask(image,channel);
9560           image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9561             exception);
9562           if (image != (Image *) NULL)
9563             (void) SetImageChannelMask(image,channel_mask);
9564           break;
9565         }
9566         case 67:  /* Convolve */
9567         {
9568           KernelInfo
9569             *kernel;
9570
9571           kernel=(KernelInfo *) NULL;
9572           if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9573             break;
9574           if (attribute_flag[0] != 0)
9575             {
9576               AV
9577                 *av;
9578
9579               size_t
9580                 order;
9581
9582               kernel=AcquireKernelInfo((const char *) NULL,exception);
9583               if (kernel == (KernelInfo *) NULL)
9584                 break;
9585               av=(AV *) argument_list[0].array_reference;
9586               order=(size_t) sqrt(av_len(av)+1);
9587               kernel->width=order;
9588               kernel->height=order;
9589               kernel->values=(MagickRealType *) AcquireAlignedMemory(order,
9590                 order*sizeof(*kernel->values));
9591               if (kernel->values == (MagickRealType *) NULL)
9592                 {
9593                   kernel=DestroyKernelInfo(kernel);
9594                   ThrowPerlException(exception,ResourceLimitFatalError,
9595                     "MemoryAllocationFailed",PackageName);
9596                   goto PerlException;
9597                 }
9598               for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9599                 kernel->values[j]=(MagickRealType) SvNV(*(av_fetch(av,j,0)));
9600               for ( ; j < (ssize_t) (order*order); j++)
9601                 kernel->values[j]=0.0;
9602             }
9603           if (attribute_flag[1] != 0)
9604             channel=(ChannelType) argument_list[1].integer_reference;
9605           if (attribute_flag[2] != 0)
9606             SetImageArtifact(image,"filter:blur",
9607               argument_list[2].string_reference);
9608           if (attribute_flag[3] != 0)
9609             {
9610               kernel=AcquireKernelInfo(argument_list[3].string_reference,
9611                 exception);
9612               if (kernel == (KernelInfo *) NULL)
9613                 break;
9614             }
9615           channel_mask=SetImageChannelMask(image,channel);
9616           image=ConvolveImage(image,kernel,exception);
9617           if (image != (Image *) NULL)
9618             (void) SetImageChannelMask(image,channel_mask);
9619           kernel=DestroyKernelInfo(kernel);
9620           break;
9621         }
9622         case 68:  /* Profile */
9623         {
9624           const char
9625             *name;
9626
9627           Image
9628             *profile_image;
9629
9630           ImageInfo
9631             *profile_info;
9632
9633           StringInfo
9634             *profile;
9635
9636           name="*";
9637           if (attribute_flag[0] != 0)
9638             name=argument_list[0].string_reference;
9639           if (attribute_flag[2] != 0)
9640             image->rendering_intent=(RenderingIntent)
9641               argument_list[2].integer_reference;
9642           if (attribute_flag[3] != 0)
9643             image->black_point_compensation=
9644               argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9645           if (attribute_flag[1] != 0)
9646             {
9647               if (argument_list[1].length == 0)
9648                 {
9649                   /*
9650                     Remove a profile from the image.
9651                   */
9652                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9653                     exception);
9654                   break;
9655                 }
9656               /*
9657                 Associate user supplied profile with the image.
9658               */
9659               profile=AcquireStringInfo(argument_list[1].length);
9660               SetStringInfoDatum(profile,(const unsigned char *)
9661                 argument_list[1].string_reference);
9662               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9663                 (size_t) GetStringInfoLength(profile),exception);
9664               profile=DestroyStringInfo(profile);
9665               break;
9666             }
9667           /*
9668             Associate a profile with the image.
9669           */
9670           profile_info=CloneImageInfo(info ? info->image_info :
9671             (ImageInfo *) NULL);
9672           profile_image=ReadImages(profile_info,name,exception);
9673           if (profile_image == (Image *) NULL)
9674             break;
9675           ResetImageProfileIterator(profile_image);
9676           name=GetNextImageProfile(profile_image);
9677           while (name != (const char *) NULL)
9678           {
9679             const StringInfo
9680               *profile;
9681
9682             profile=GetImageProfile(profile_image,name);
9683             if (profile != (const StringInfo *) NULL)
9684               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9685                 (size_t) GetStringInfoLength(profile),exception);
9686             name=GetNextImageProfile(profile_image);
9687           }
9688           profile_image=DestroyImage(profile_image);
9689           profile_info=DestroyImageInfo(profile_info);
9690           break;
9691         }
9692         case 69:  /* UnsharpMask */
9693         {
9694           if (attribute_flag[0] != 0)
9695             {
9696               flags=ParseGeometry(argument_list[0].string_reference,
9697                 &geometry_info);
9698               if ((flags & SigmaValue) == 0)
9699                 geometry_info.sigma=1.0;
9700               if ((flags & XiValue) == 0)
9701                 geometry_info.xi=1.0;
9702               if ((flags & PsiValue) == 0)
9703                 geometry_info.psi=0.5;
9704             }
9705           if (attribute_flag[1] != 0)
9706             geometry_info.rho=argument_list[1].real_reference;
9707           if (attribute_flag[2] != 0)
9708             geometry_info.sigma=argument_list[2].real_reference;
9709           if (attribute_flag[3] != 0)
9710             geometry_info.xi=argument_list[3].real_reference;
9711           if (attribute_flag[4] != 0)
9712             geometry_info.psi=argument_list[4].real_reference;
9713           if (attribute_flag[5] != 0)
9714             channel=(ChannelType) argument_list[5].integer_reference;
9715           channel_mask=SetImageChannelMask(image,channel);
9716           image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9717             geometry_info.xi,geometry_info.psi,exception);
9718           if (image != (Image *) NULL)
9719             (void) SetImageChannelMask(image,channel_mask);
9720           break;
9721         }
9722         case 70:  /* MotionBlur */
9723         {
9724           if (attribute_flag[0] != 0)
9725             {
9726               flags=ParseGeometry(argument_list[0].string_reference,
9727                 &geometry_info);
9728               if ((flags & SigmaValue) == 0)
9729                 geometry_info.sigma=1.0;
9730               if ((flags & XiValue) == 0)
9731                 geometry_info.xi=1.0;
9732             }
9733           if (attribute_flag[1] != 0)
9734             geometry_info.rho=argument_list[1].real_reference;
9735           if (attribute_flag[2] != 0)
9736             geometry_info.sigma=argument_list[2].real_reference;
9737           if (attribute_flag[3] != 0)
9738             geometry_info.xi=argument_list[3].real_reference;
9739           if (attribute_flag[4] != 0)
9740             channel=(ChannelType) argument_list[4].integer_reference;
9741           channel_mask=SetImageChannelMask(image,channel);
9742           image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9743             geometry_info.xi,exception);
9744           if (image != (Image *) NULL)
9745             (void) SetImageChannelMask(image,channel_mask);
9746           break;
9747         }
9748         case 71:  /* OrderedDither */
9749         {
9750           if (attribute_flag[0] == 0)
9751             argument_list[0].string_reference="o8x8";
9752           if (attribute_flag[1] != 0)
9753             channel=(ChannelType) argument_list[1].integer_reference;
9754           channel_mask=SetImageChannelMask(image,channel);
9755           (void) OrderedDitherImage(image,argument_list[0].string_reference,
9756             exception);
9757           (void) SetImageChannelMask(image,channel_mask);
9758           break;
9759         }
9760         case 72:  /* Shave */
9761         {
9762           if (attribute_flag[0] != 0)
9763             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9764               &geometry,exception);
9765           if (attribute_flag[1] != 0)
9766             geometry.width=argument_list[1].integer_reference;
9767           if (attribute_flag[2] != 0)
9768             geometry.height=argument_list[2].integer_reference;
9769           image=ShaveImage(image,&geometry,exception);
9770           break;
9771         }
9772         case 73:  /* Level */
9773         {
9774           double
9775             black_point,
9776             gamma,
9777             white_point;
9778
9779           black_point=0.0;
9780           white_point=(double) image->columns*image->rows;
9781           gamma=1.0;
9782           if (attribute_flag[0] != 0)
9783             {
9784               flags=ParseGeometry(argument_list[0].string_reference,
9785                 &geometry_info);
9786               black_point=geometry_info.rho;
9787               if ((flags & SigmaValue) != 0)
9788                 white_point=geometry_info.sigma;
9789               if ((flags & XiValue) != 0)
9790                 gamma=geometry_info.xi;
9791               if ((flags & PercentValue) != 0)
9792                 {
9793                   black_point*=(double) (QuantumRange/100.0);
9794                   white_point*=(double) (QuantumRange/100.0);
9795                 }
9796               if ((flags & SigmaValue) == 0)
9797                 white_point=(double) QuantumRange-black_point;
9798             }
9799           if (attribute_flag[1] != 0)
9800             black_point=argument_list[1].real_reference;
9801           if (attribute_flag[2] != 0)
9802             white_point=argument_list[2].real_reference;
9803           if (attribute_flag[3] != 0)
9804             gamma=argument_list[3].real_reference;
9805           if (attribute_flag[4] != 0)
9806             channel=(ChannelType) argument_list[4].integer_reference;
9807           if (attribute_flag[5] != 0)
9808             {
9809               argument_list[0].real_reference=argument_list[5].real_reference;
9810               attribute_flag[0]=attribute_flag[5];
9811             }
9812           channel_mask=SetImageChannelMask(image,channel);
9813           (void) LevelImage(image,black_point,white_point,gamma,exception);
9814           (void) SetImageChannelMask(image,channel_mask);
9815           break;
9816         }
9817         case 74:  /* Clip */
9818         {
9819           if (attribute_flag[0] == 0)
9820             argument_list[0].string_reference="#1";
9821           if (attribute_flag[1] == 0)
9822             argument_list[1].integer_reference=MagickTrue;
9823           (void) ClipImagePath(image,argument_list[0].string_reference,
9824             argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse,
9825             exception);
9826           break;
9827         }
9828         case 75:  /* AffineTransform */
9829         {
9830           DrawInfo
9831             *draw_info;
9832
9833           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9834             (DrawInfo *) NULL);
9835           if (attribute_flag[0] != 0)
9836             {
9837               AV
9838                 *av;
9839
9840               av=(AV *) argument_list[0].array_reference;
9841               if ((av_len(av) != 3) && (av_len(av) != 5))
9842                 {
9843                   ThrowPerlException(exception,OptionError,
9844                     "affine matrix must have 4 or 6 elements",PackageName);
9845                   goto PerlException;
9846                 }
9847               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9848               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9849               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9850               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9851               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9852                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9853                 {
9854                   ThrowPerlException(exception,OptionError,
9855                     "affine matrix is singular",PackageName);
9856                    goto PerlException;
9857                 }
9858               if (av_len(av) == 5)
9859                 {
9860                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9861                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9862                 }
9863             }
9864           for (j=1; j < 6; j++)
9865           {
9866             if (attribute_flag[j] == 0)
9867               continue;
9868             value=argument_list[j].string_reference;
9869             angle=argument_list[j].real_reference;
9870             current=draw_info->affine;
9871             GetAffineMatrix(&affine);
9872             switch (j)
9873             {
9874               case 1:
9875               {
9876                 /*
9877                   Translate.
9878                 */
9879                 flags=ParseGeometry(value,&geometry_info);
9880                 affine.tx=geometry_info.xi;
9881                 affine.ty=geometry_info.psi;
9882                 if ((flags & PsiValue) == 0)
9883                   affine.ty=affine.tx;
9884                 break;
9885               }
9886               case 2:
9887               {
9888                 /*
9889                   Scale.
9890                 */
9891                 flags=ParseGeometry(value,&geometry_info);
9892                 affine.sx=geometry_info.rho;
9893                 affine.sy=geometry_info.sigma;
9894                 if ((flags & SigmaValue) == 0)
9895                   affine.sy=affine.sx;
9896                 break;
9897               }
9898               case 3:
9899               {
9900                 /*
9901                   Rotate.
9902                 */
9903                 if (angle == 0.0)
9904                   break;
9905                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9906                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9907                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9908                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9909                 break;
9910               }
9911               case 4:
9912               {
9913                 /*
9914                   SkewX.
9915                 */
9916                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9917                 break;
9918               }
9919               case 5:
9920               {
9921                 /*
9922                   SkewY.
9923                 */
9924                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9925                 break;
9926               }
9927             }
9928             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9929             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9930             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9931             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9932             draw_info->affine.tx=
9933               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9934             draw_info->affine.ty=
9935               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9936           }
9937           if (attribute_flag[6] != 0)
9938             image->interpolate=(PixelInterpolateMethod)
9939               argument_list[6].integer_reference;
9940           if (attribute_flag[7] != 0)
9941             QueryColorCompliance(argument_list[7].string_reference,
9942               AllCompliance,&image->background_color,exception);
9943           image=AffineTransformImage(image,&draw_info->affine,exception);
9944           draw_info=DestroyDrawInfo(draw_info);
9945           break;
9946         }
9947         case 76:  /* Difference */
9948         {
9949           if (attribute_flag[0] == 0)
9950             {
9951               ThrowPerlException(exception,OptionError,
9952                 "ReferenceImageRequired",PackageName);
9953               goto PerlException;
9954             }
9955           if (attribute_flag[1] != 0)
9956             image->fuzz=StringToDoubleInterval(
9957               argument_list[1].string_reference,(double) QuantumRange+1.0);
9958           (void) SetImageColorMetric(image,argument_list[0].image_reference,
9959             exception);
9960           break;
9961         }
9962         case 77:  /* AdaptiveThreshold */
9963         {
9964           if (attribute_flag[0] != 0)
9965             {
9966               flags=ParseGeometry(argument_list[0].string_reference,
9967                 &geometry_info);
9968               if ((flags & PercentValue) != 0)
9969                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9970             }
9971           if (attribute_flag[1] != 0)
9972             geometry_info.rho=argument_list[1].integer_reference;
9973           if (attribute_flag[2] != 0)
9974             geometry_info.sigma=argument_list[2].integer_reference;
9975           if (attribute_flag[3] != 0)
9976             geometry_info.xi=argument_list[3].integer_reference;;
9977           image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
9978             (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
9979           break;
9980         }
9981         case 78:  /* Resample */
9982         {
9983           size_t
9984             height,
9985             width;
9986
9987           if (attribute_flag[0] != 0)
9988             {
9989               flags=ParseGeometry(argument_list[0].string_reference,
9990                 &geometry_info);
9991               if ((flags & SigmaValue) == 0)
9992                 geometry_info.sigma=geometry_info.rho;
9993             }
9994           if (attribute_flag[1] != 0)
9995             geometry_info.rho=argument_list[1].real_reference;
9996           if (attribute_flag[2] != 0)
9997             geometry_info.sigma=argument_list[2].real_reference;
9998           if (attribute_flag[3] == 0)
9999             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
10000           if (attribute_flag[4] == 0)
10001             SetImageArtifact(image,"filter:support",
10002               argument_list[4].string_reference);
10003           width=(size_t) (geometry_info.rho*image->columns/
10004             (image->resolution.x == 0.0 ? 72.0 : image->resolution.x)+0.5);
10005           height=(size_t) (geometry_info.sigma*image->rows/
10006             (image->resolution.y == 0.0 ? 72.0 : image->resolution.y)+0.5);
10007           image=ResizeImage(image,width,height,(FilterType)
10008             argument_list[3].integer_reference,exception);
10009           if (image != (Image *) NULL)
10010             {
10011               image->resolution.x=geometry_info.rho;
10012               image->resolution.y=geometry_info.sigma;
10013             }
10014           break;
10015         }
10016         case 79:  /* Describe */
10017         {
10018           if (attribute_flag[0] == 0)
10019             argument_list[0].file_reference=(FILE *) NULL;
10020           if (attribute_flag[1] != 0)
10021             (void) SetImageArtifact(image,"identify:features",
10022               argument_list[1].string_reference);
10023           (void) IdentifyImage(image,argument_list[0].file_reference,
10024             MagickTrue,exception);
10025           break;
10026         }
10027         case 80:  /* BlackThreshold */
10028         {
10029           if (attribute_flag[0] == 0)
10030             argument_list[0].string_reference="50%";
10031           if (attribute_flag[2] != 0)
10032             channel=(ChannelType) argument_list[2].integer_reference;
10033           channel_mask=SetImageChannelMask(image,channel);
10034           BlackThresholdImage(image,argument_list[0].string_reference,
10035             exception);
10036           (void) SetImageChannelMask(image,channel_mask);
10037           break;
10038         }
10039         case 81:  /* WhiteThreshold */
10040         {
10041           if (attribute_flag[0] == 0)
10042             argument_list[0].string_reference="50%";
10043           if (attribute_flag[2] != 0)
10044             channel=(ChannelType) argument_list[2].integer_reference;
10045           channel_mask=SetImageChannelMask(image,channel);
10046           WhiteThresholdImage(image,argument_list[0].string_reference,
10047             exception);
10048           (void) SetImageChannelMask(image,channel_mask);
10049           break;
10050         }
10051         case 82:  /* RotationalBlur */
10052         {
10053           if (attribute_flag[0] != 0)
10054             {
10055               flags=ParseGeometry(argument_list[0].string_reference,
10056                 &geometry_info);
10057             }
10058           if (attribute_flag[1] != 0)
10059             geometry_info.rho=argument_list[1].real_reference;
10060           if (attribute_flag[2] != 0)
10061             channel=(ChannelType) argument_list[2].integer_reference;
10062           channel_mask=SetImageChannelMask(image,channel);
10063           image=RotationalBlurImage(image,geometry_info.rho,exception);
10064           if (image != (Image *) NULL)
10065             (void) SetImageChannelMask(image,channel_mask);
10066           break;
10067         }
10068         case 83:  /* Thumbnail */
10069         {
10070           if (attribute_flag[0] != 0)
10071             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10072               &geometry,exception);
10073           if (attribute_flag[1] != 0)
10074             geometry.width=argument_list[1].integer_reference;
10075           if (attribute_flag[2] != 0)
10076             geometry.height=argument_list[2].integer_reference;
10077           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
10078           break;
10079         }
10080         case 84:  /* Strip */
10081         {
10082           (void) StripImage(image,exception);
10083           break;
10084         }
10085         case 85:  /* Tint */
10086         {
10087           PixelInfo
10088             tint;
10089
10090           GetPixelInfo(image,&tint);
10091           if (attribute_flag[0] != 0)
10092             (void) QueryColorCompliance(argument_list[0].string_reference,
10093               AllCompliance,&tint,exception);
10094           if (attribute_flag[1] == 0)
10095             argument_list[1].string_reference="100";
10096           image=TintImage(image,argument_list[1].string_reference,&tint,
10097             exception);
10098           break;
10099         }
10100         case 86:  /* Channel */
10101         {
10102           if (attribute_flag[0] != 0)
10103             channel=(ChannelType) argument_list[0].integer_reference;
10104           image=SeparateImage(image,channel,exception);
10105           break;
10106         }
10107         case 87:  /* Splice */
10108         {
10109           if (attribute_flag[7] != 0)
10110             image->gravity=(GravityType) argument_list[7].integer_reference;
10111           if (attribute_flag[0] != 0)
10112             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
10113               &geometry,exception);
10114           if (attribute_flag[1] != 0)
10115             geometry.width=argument_list[1].integer_reference;
10116           if (attribute_flag[2] != 0)
10117             geometry.height=argument_list[2].integer_reference;
10118           if (attribute_flag[3] != 0)
10119             geometry.x=argument_list[3].integer_reference;
10120           if (attribute_flag[4] != 0)
10121             geometry.y=argument_list[4].integer_reference;
10122           if (attribute_flag[5] != 0)
10123             image->fuzz=StringToDoubleInterval(
10124               argument_list[5].string_reference,(double) QuantumRange+1.0);
10125           if (attribute_flag[6] != 0)
10126             (void) QueryColorCompliance(argument_list[6].string_reference,
10127               AllCompliance,&image->background_color,exception);
10128           image=SpliceImage(image,&geometry,exception);
10129           break;
10130         }
10131         case 88:  /* Posterize */
10132         {
10133           if (attribute_flag[0] == 0)
10134             argument_list[0].integer_reference=3;
10135           if (attribute_flag[1] == 0)
10136             argument_list[1].integer_reference=0;
10137           (void) PosterizeImage(image,argument_list[0].integer_reference,
10138             argument_list[1].integer_reference ? RiemersmaDitherMethod :
10139             NoDitherMethod,exception);
10140           break;
10141         }
10142         case 89:  /* Shadow */
10143         {
10144           if (attribute_flag[0] != 0)
10145             {
10146               flags=ParseGeometry(argument_list[0].string_reference,
10147                 &geometry_info);
10148               if ((flags & SigmaValue) == 0)
10149                 geometry_info.sigma=1.0;
10150               if ((flags & XiValue) == 0)
10151                 geometry_info.xi=4.0;
10152               if ((flags & PsiValue) == 0)
10153                 geometry_info.psi=4.0;
10154             }
10155           if (attribute_flag[1] != 0)
10156             geometry_info.rho=argument_list[1].real_reference;
10157           if (attribute_flag[2] != 0)
10158             geometry_info.sigma=argument_list[2].real_reference;
10159           if (attribute_flag[3] != 0)
10160             geometry_info.xi=argument_list[3].integer_reference;
10161           if (attribute_flag[4] != 0)
10162             geometry_info.psi=argument_list[4].integer_reference;
10163           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
10164             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10165             ceil(geometry_info.psi-0.5),exception);
10166           break;
10167         }
10168         case 90:  /* Identify */
10169         {
10170           if (attribute_flag[0] == 0)
10171             argument_list[0].file_reference=(FILE *) NULL;
10172           if (attribute_flag[1] != 0)
10173             (void) SetImageArtifact(image,"identify:features",
10174               argument_list[1].string_reference);
10175           if ((attribute_flag[2] != 0) &&
10176               (argument_list[2].integer_reference != 0))
10177             (void) SetImageArtifact(image,"identify:unique","true");
10178           (void) IdentifyImage(image,argument_list[0].file_reference,
10179             MagickTrue,exception);
10180           break;
10181         }
10182         case 91:  /* SepiaTone */
10183         {
10184           if (attribute_flag[0] == 0)
10185             argument_list[0].real_reference=80.0*QuantumRange/100.0;
10186           image=SepiaToneImage(image,argument_list[0].real_reference,
10187             exception);
10188           break;
10189         }
10190         case 92:  /* SigmoidalContrast */
10191         {
10192           MagickBooleanType
10193             sharpen;
10194
10195           if (attribute_flag[0] != 0)
10196             {
10197               flags=ParseGeometry(argument_list[0].string_reference,
10198                 &geometry_info);
10199               if ((flags & SigmaValue) == 0)
10200                 geometry_info.sigma=QuantumRange/2.0;
10201               if ((flags & PercentValue) != 0)
10202                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
10203             }
10204           if (attribute_flag[1] != 0)
10205             geometry_info.rho=argument_list[1].real_reference;
10206           if (attribute_flag[2] != 0)
10207             geometry_info.sigma=argument_list[2].real_reference;
10208           if (attribute_flag[3] != 0)
10209             channel=(ChannelType) argument_list[3].integer_reference;
10210           sharpen=MagickTrue;
10211           if (attribute_flag[4] != 0)
10212             sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
10213               MagickFalse;
10214           channel_mask=SetImageChannelMask(image,channel);
10215           (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
10216             geometry_info.sigma,exception);
10217           (void) SetImageChannelMask(image,channel_mask);
10218           break;
10219         }
10220         case 93:  /* Extent */
10221         {
10222           if (attribute_flag[7] != 0)
10223             image->gravity=(GravityType) argument_list[7].integer_reference;
10224           if (attribute_flag[0] != 0)
10225             {
10226               int
10227                 flags;
10228
10229               flags=ParseGravityGeometry(image,
10230                 argument_list[0].string_reference,&geometry,exception);
10231               (void) flags;
10232               if (geometry.width == 0)
10233                 geometry.width=image->columns;
10234               if (geometry.height == 0)
10235                 geometry.height=image->rows;
10236             }
10237           if (attribute_flag[1] != 0)
10238             geometry.width=argument_list[1].integer_reference;
10239           if (attribute_flag[2] != 0)
10240             geometry.height=argument_list[2].integer_reference;
10241           if (attribute_flag[3] != 0)
10242             geometry.x=argument_list[3].integer_reference;
10243           if (attribute_flag[4] != 0)
10244             geometry.y=argument_list[4].integer_reference;
10245           if (attribute_flag[5] != 0)
10246             image->fuzz=StringToDoubleInterval(
10247               argument_list[5].string_reference,(double) QuantumRange+1.0);
10248           if (attribute_flag[6] != 0)
10249             (void) QueryColorCompliance(argument_list[6].string_reference,
10250               AllCompliance,&image->background_color,exception);
10251           image=ExtentImage(image,&geometry,exception);
10252           break;
10253         }
10254         case 94:  /* Vignette */
10255         {
10256           if (attribute_flag[0] != 0)
10257             {
10258               flags=ParseGeometry(argument_list[0].string_reference,
10259                 &geometry_info);
10260               if ((flags & SigmaValue) == 0)
10261                 geometry_info.sigma=1.0;
10262               if ((flags & XiValue) == 0)
10263                 geometry_info.xi=0.1*image->columns;
10264               if ((flags & PsiValue) == 0)
10265                 geometry_info.psi=0.1*image->rows;
10266             }
10267           if (attribute_flag[1] != 0)
10268             geometry_info.rho=argument_list[1].real_reference;
10269           if (attribute_flag[2] != 0)
10270             geometry_info.sigma=argument_list[2].real_reference;
10271           if (attribute_flag[3] != 0)
10272             geometry_info.xi=argument_list[3].integer_reference;
10273           if (attribute_flag[4] != 0)
10274             geometry_info.psi=argument_list[4].integer_reference;
10275           if (attribute_flag[5] != 0)
10276             (void) QueryColorCompliance(argument_list[5].string_reference,
10277               AllCompliance,&image->background_color,exception);
10278           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
10279             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10280             ceil(geometry_info.psi-0.5),exception);
10281           break;
10282         }
10283         case 95:  /* ContrastStretch */
10284         {
10285           double
10286             black_point,
10287             white_point;
10288
10289           black_point=0.0;
10290           white_point=(double) image->columns*image->rows;
10291           if (attribute_flag[0] != 0)
10292             {
10293               flags=ParseGeometry(argument_list[0].string_reference,
10294                 &geometry_info);
10295               black_point=geometry_info.rho;
10296               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
10297                 black_point;
10298               if ((flags & PercentValue) != 0)
10299                 {
10300                   black_point*=(double) image->columns*image->rows/100.0;
10301                   white_point*=(double) image->columns*image->rows/100.0;
10302                 }
10303               white_point=(double) image->columns*image->rows-
10304                 white_point;
10305             }
10306           if (attribute_flag[1] != 0)
10307             black_point=argument_list[1].real_reference;
10308           if (attribute_flag[2] != 0)
10309             white_point=argument_list[2].real_reference;
10310           if (attribute_flag[4] != 0)
10311             channel=(ChannelType) argument_list[4].integer_reference;
10312           channel_mask=SetImageChannelMask(image,channel);
10313           (void) ContrastStretchImage(image,black_point,white_point,exception);
10314           (void) SetImageChannelMask(image,channel_mask);
10315           break;
10316         }
10317         case 96:  /* Sans0 */
10318         {
10319           break;
10320         }
10321         case 97:  /* Sans1 */
10322         {
10323           break;
10324         }
10325         case 98:  /* AdaptiveSharpen */
10326         {
10327           if (attribute_flag[0] != 0)
10328             {
10329               flags=ParseGeometry(argument_list[0].string_reference,
10330                 &geometry_info);
10331               if ((flags & SigmaValue) == 0)
10332                 geometry_info.sigma=1.0;
10333               if ((flags & XiValue) == 0)
10334                 geometry_info.xi=0.0;
10335             }
10336           if (attribute_flag[1] != 0)
10337             geometry_info.rho=argument_list[1].real_reference;
10338           if (attribute_flag[2] != 0)
10339             geometry_info.sigma=argument_list[2].real_reference;
10340           if (attribute_flag[3] != 0)
10341             geometry_info.xi=argument_list[3].real_reference;
10342           if (attribute_flag[4] != 0)
10343             channel=(ChannelType) argument_list[4].integer_reference;
10344           channel_mask=SetImageChannelMask(image,channel);
10345           image=AdaptiveSharpenImage(image,geometry_info.rho,
10346             geometry_info.sigma,exception);
10347           if (image != (Image *) NULL)
10348             (void) SetImageChannelMask(image,channel_mask);
10349           break;
10350         }
10351         case 99:  /* Transpose */
10352         {
10353           image=TransposeImage(image,exception);
10354           break;
10355         }
10356         case 100:  /* Tranverse */
10357         {
10358           image=TransverseImage(image,exception);
10359           break;
10360         }
10361         case 101:  /* AutoOrient */
10362         {
10363           image=AutoOrientImage(image,image->orientation,exception);
10364           break;
10365         }
10366         case 102:  /* AdaptiveBlur */
10367         {
10368           if (attribute_flag[0] != 0)
10369             {
10370               flags=ParseGeometry(argument_list[0].string_reference,
10371                 &geometry_info);
10372               if ((flags & SigmaValue) == 0)
10373                 geometry_info.sigma=1.0;
10374               if ((flags & XiValue) == 0)
10375                 geometry_info.xi=0.0;
10376             }
10377           if (attribute_flag[1] != 0)
10378             geometry_info.rho=argument_list[1].real_reference;
10379           if (attribute_flag[2] != 0)
10380             geometry_info.sigma=argument_list[2].real_reference;
10381           if (attribute_flag[3] != 0)
10382             channel=(ChannelType) argument_list[3].integer_reference;
10383           channel_mask=SetImageChannelMask(image,channel);
10384           image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10385             exception);
10386           if (image != (Image *) NULL)
10387             (void) SetImageChannelMask(image,channel_mask);
10388           break;
10389         }
10390         case 103:  /* Sketch */
10391         {
10392           if (attribute_flag[0] != 0)
10393             {
10394               flags=ParseGeometry(argument_list[0].string_reference,
10395                 &geometry_info);
10396               if ((flags & SigmaValue) == 0)
10397                 geometry_info.sigma=1.0;
10398               if ((flags & XiValue) == 0)
10399                 geometry_info.xi=1.0;
10400             }
10401           if (attribute_flag[1] != 0)
10402             geometry_info.rho=argument_list[1].real_reference;
10403           if (attribute_flag[2] != 0)
10404             geometry_info.sigma=argument_list[2].real_reference;
10405           if (attribute_flag[3] != 0)
10406             geometry_info.xi=argument_list[3].real_reference;
10407           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10408             geometry_info.xi,exception);
10409           break;
10410         }
10411         case 104:  /* UniqueColors */
10412         {
10413           image=UniqueImageColors(image,exception);
10414           break;
10415         }
10416         case 105:  /* AdaptiveResize */
10417         {
10418           if (attribute_flag[0] != 0)
10419             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10420               &geometry,exception);
10421           if (attribute_flag[1] != 0)
10422             geometry.width=argument_list[1].integer_reference;
10423           if (attribute_flag[2] != 0)
10424             geometry.height=argument_list[2].integer_reference;
10425           if (attribute_flag[3] != 0)
10426             image->filter=(FilterType) argument_list[4].integer_reference;
10427           if (attribute_flag[4] != 0)
10428             SetImageArtifact(image,"filter:support",
10429               argument_list[4].string_reference);
10430           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10431             exception);
10432           break;
10433         }
10434         case 106:  /* ClipMask */
10435         {
10436           Image
10437             *mask_image;
10438
10439           if (attribute_flag[0] == 0)
10440             {
10441               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10442                 PackageName);
10443               goto PerlException;
10444             }
10445           mask_image=CloneImage(argument_list[0].image_reference,0,0,MagickTrue,
10446             exception);
10447           (void) SetImageMask(image,ReadPixelMask,mask_image,exception);
10448           mask_image=DestroyImage(mask_image);
10449           break;
10450         }
10451         case 107:  /* LinearStretch */
10452         {
10453            double
10454              black_point,
10455              white_point;
10456
10457            black_point=0.0;
10458            white_point=(double) image->columns*image->rows;
10459            if (attribute_flag[0] != 0)
10460              {
10461                flags=ParseGeometry(argument_list[0].string_reference,
10462                  &geometry_info);
10463                if ((flags & SigmaValue) != 0)
10464                   white_point=geometry_info.sigma;
10465                if ((flags & PercentValue) != 0)
10466                  {
10467                    black_point*=(double) image->columns*image->rows/100.0;
10468                    white_point*=(double) image->columns*image->rows/100.0;
10469                  }
10470                if ((flags & SigmaValue) == 0)
10471                  white_point=(double) image->columns*image->rows-black_point;
10472              }
10473           if (attribute_flag[1] != 0)
10474             black_point=argument_list[1].real_reference;
10475           if (attribute_flag[2] != 0)
10476             white_point=argument_list[2].real_reference;
10477           (void) LinearStretchImage(image,black_point,white_point,exception);
10478           break;
10479         }
10480         case 108:  /* ColorMatrix */
10481         {
10482           AV
10483             *av;
10484
10485           double
10486             *color_matrix;
10487
10488           KernelInfo
10489             *kernel_info;
10490
10491           size_t
10492             order;
10493
10494           if (attribute_flag[0] == 0)
10495             break;
10496           av=(AV *) argument_list[0].array_reference;
10497           order=(size_t) sqrt(av_len(av)+1);
10498           color_matrix=(double *) AcquireQuantumMemory(order,order*
10499             sizeof(*color_matrix));
10500           if (color_matrix == (double *) NULL)
10501             {
10502               ThrowPerlException(exception,ResourceLimitFatalError,
10503                 "MemoryAllocationFailed",PackageName);
10504               goto PerlException;
10505            }
10506           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10507             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10508           for ( ; j < (ssize_t) (order*order); j++)
10509             color_matrix[j]=0.0;
10510           kernel_info=AcquireKernelInfo((const char *) NULL,exception);
10511           if (kernel_info == (KernelInfo *) NULL)
10512             break;
10513           kernel_info->width=order;
10514           kernel_info->height=order;
10515           kernel_info->values=(MagickRealType *) AcquireAlignedMemory(order,
10516             order*sizeof(*kernel_info->values));
10517           if (kernel_info->values != (MagickRealType *) NULL)
10518             {
10519               for (i=0; i < (ssize_t) (order*order); i++)
10520                 kernel_info->values[i]=(MagickRealType) color_matrix[i];
10521               image=ColorMatrixImage(image,kernel_info,exception);
10522             }
10523           kernel_info=DestroyKernelInfo(kernel_info);
10524           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10525           break;
10526         }
10527         case 109:  /* Mask */
10528         {
10529           Image
10530             *mask_image;
10531
10532           if (attribute_flag[0] == 0)
10533             {
10534               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10535                 PackageName);
10536               goto PerlException;
10537             }
10538           mask_image=CloneImage(argument_list[0].image_reference,0,0,
10539             MagickTrue,exception);
10540           (void) SetImageMask(image,ReadPixelMask,mask_image,exception);
10541           mask_image=DestroyImage(mask_image);
10542           break;
10543         }
10544         case 110:  /* Polaroid */
10545         {
10546           char
10547             *caption;
10548
10549           DrawInfo
10550             *draw_info;
10551
10552           double
10553             angle;
10554
10555           PixelInterpolateMethod
10556             method;
10557
10558           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10559             (DrawInfo *) NULL);
10560           caption=(char *) NULL;
10561           if (attribute_flag[0] != 0)
10562             caption=InterpretImageProperties(info ? info->image_info :
10563               (ImageInfo *) NULL,image,argument_list[0].string_reference,
10564               exception);
10565           angle=0.0;
10566           if (attribute_flag[1] != 0)
10567             angle=argument_list[1].real_reference;
10568           if (attribute_flag[2] != 0)
10569             (void) CloneString(&draw_info->font,
10570               argument_list[2].string_reference);
10571           if (attribute_flag[3] != 0)
10572             (void) QueryColorCompliance(argument_list[3].string_reference,
10573               AllCompliance,&draw_info->stroke,exception);
10574           if (attribute_flag[4] != 0)
10575             (void) QueryColorCompliance(argument_list[4].string_reference,
10576               AllCompliance,&draw_info->fill,exception);
10577           if (attribute_flag[5] != 0)
10578             draw_info->stroke_width=argument_list[5].real_reference;
10579           if (attribute_flag[6] != 0)
10580             draw_info->pointsize=argument_list[6].real_reference;
10581           if (attribute_flag[7] != 0)
10582             draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10583           if (attribute_flag[8] != 0)
10584             (void) QueryColorCompliance(argument_list[8].string_reference,
10585               AllCompliance,&image->background_color,exception);
10586           method=UndefinedInterpolatePixel;
10587           if (attribute_flag[9] != 0)
10588             method=(PixelInterpolateMethod) argument_list[9].integer_reference;
10589           image=PolaroidImage(image,draw_info,caption,angle,method,exception);
10590           draw_info=DestroyDrawInfo(draw_info);
10591           if (caption != (char *) NULL)
10592             caption=DestroyString(caption);
10593           break;
10594         }
10595         case 111:  /* FloodfillPaint */
10596         {
10597           DrawInfo
10598             *draw_info;
10599
10600           MagickBooleanType
10601             invert;
10602
10603           PixelInfo
10604             target;
10605
10606           draw_info=CloneDrawInfo(info ? info->image_info :
10607             (ImageInfo *) NULL,(DrawInfo *) NULL);
10608           if (attribute_flag[0] != 0)
10609             flags=ParsePageGeometry(image,argument_list[0].string_reference,
10610               &geometry,exception);
10611           if (attribute_flag[1] != 0)
10612             geometry.x=argument_list[1].integer_reference;
10613           if (attribute_flag[2] != 0)
10614             geometry.y=argument_list[2].integer_reference;
10615           if (attribute_flag[3] != 0)
10616             (void) QueryColorCompliance(argument_list[3].string_reference,
10617               AllCompliance,&draw_info->fill,exception);
10618           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
10619             geometry.x,geometry.y,&target,exception);
10620           if (attribute_flag[4] != 0)
10621             QueryColorCompliance(argument_list[4].string_reference,
10622               AllCompliance,&target,exception);
10623           if (attribute_flag[5] != 0)
10624             image->fuzz=StringToDoubleInterval(
10625               argument_list[5].string_reference,(double) QuantumRange+1.0);
10626           if (attribute_flag[6] != 0)
10627             channel=(ChannelType) argument_list[6].integer_reference;
10628           invert=MagickFalse;
10629           if (attribute_flag[7] != 0)
10630             invert=(MagickBooleanType) argument_list[7].integer_reference;
10631           channel_mask=SetImageChannelMask(image,channel);
10632           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10633             geometry.y,invert,exception);
10634           (void) SetImageChannelMask(image,channel_mask);
10635           draw_info=DestroyDrawInfo(draw_info);
10636           break;
10637         }
10638         case 112:  /* Distort */
10639         {
10640           AV
10641             *av;
10642
10643           double
10644             *coordinates;
10645
10646           DistortMethod
10647             method;
10648
10649           size_t
10650             number_coordinates;
10651
10652           VirtualPixelMethod
10653             virtual_pixel;
10654
10655           if (attribute_flag[0] == 0)
10656             break;
10657           method=UndefinedDistortion;
10658           if (attribute_flag[1] != 0)
10659             method=(DistortMethod) argument_list[1].integer_reference;
10660           av=(AV *) argument_list[0].array_reference;
10661           number_coordinates=(size_t) av_len(av)+1;
10662           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10663             sizeof(*coordinates));
10664           if (coordinates == (double *) NULL)
10665             {
10666               ThrowPerlException(exception,ResourceLimitFatalError,
10667                 "MemoryAllocationFailed",PackageName);
10668               goto PerlException;
10669             }
10670           for (j=0; j < (ssize_t) number_coordinates; j++)
10671             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10672           virtual_pixel=UndefinedVirtualPixelMethod;
10673           if (attribute_flag[2] != 0)
10674             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10675               argument_list[2].integer_reference,exception);
10676           image=DistortImage(image,method,number_coordinates,coordinates,
10677             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10678             exception);
10679           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10680             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10681               exception);
10682           coordinates=(double *) RelinquishMagickMemory(coordinates);
10683           break;
10684         }
10685         case 113:  /* Clut */
10686         {
10687           PixelInterpolateMethod
10688             method;
10689
10690           if (attribute_flag[0] == 0)
10691             {
10692               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10693                 PackageName);
10694               goto PerlException;
10695             }
10696           method=UndefinedInterpolatePixel;
10697           if (attribute_flag[1] != 0)
10698             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
10699           if (attribute_flag[2] != 0)
10700             channel=(ChannelType) argument_list[2].integer_reference;
10701           channel_mask=SetImageChannelMask(image,channel);
10702           (void) ClutImage(image,argument_list[0].image_reference,method,
10703             exception);
10704           (void) SetImageChannelMask(image,channel_mask);
10705           break;
10706         }
10707         case 114:  /* LiquidRescale */
10708         {
10709           if (attribute_flag[0] != 0)
10710             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10711               &geometry,exception);
10712           if (attribute_flag[1] != 0)
10713             geometry.width=argument_list[1].integer_reference;
10714           if (attribute_flag[2] != 0)
10715             geometry.height=argument_list[2].integer_reference;
10716           if (attribute_flag[3] == 0)
10717             argument_list[3].real_reference=1.0;
10718           if (attribute_flag[4] == 0)
10719             argument_list[4].real_reference=0.0;
10720           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10721             argument_list[3].real_reference,argument_list[4].real_reference,
10722             exception);
10723           break;
10724         }
10725         case 115:  /* EncipherImage */
10726         {
10727           (void) EncipherImage(image,argument_list[0].string_reference,
10728             exception);
10729           break;
10730         }
10731         case 116:  /* DecipherImage */
10732         {
10733           (void) DecipherImage(image,argument_list[0].string_reference,
10734             exception);
10735           break;
10736         }
10737         case 117:  /* Deskew */
10738         {
10739           geometry_info.rho=QuantumRange/2.0;
10740           if (attribute_flag[0] != 0)
10741             flags=ParseGeometry(argument_list[0].string_reference,
10742               &geometry_info);
10743           if (attribute_flag[1] != 0)
10744             geometry_info.rho=StringToDoubleInterval(
10745               argument_list[1].string_reference,(double) QuantumRange+1.0);
10746           image=DeskewImage(image,geometry_info.rho,exception);
10747           break;
10748         }
10749         case 118:  /* Remap */
10750         {
10751           QuantizeInfo
10752             *quantize_info;
10753
10754           if (attribute_flag[0] == 0)
10755             {
10756               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10757                 PackageName);
10758               goto PerlException;
10759             }
10760           quantize_info=AcquireQuantizeInfo(info->image_info);
10761           if (attribute_flag[1] != 0)
10762             quantize_info->dither_method=(DitherMethod)
10763               argument_list[1].integer_reference;
10764           (void) RemapImages(quantize_info,image,
10765             argument_list[0].image_reference,exception);
10766           quantize_info=DestroyQuantizeInfo(quantize_info);
10767           break;
10768         }
10769         case 119:  /* SparseColor */
10770         {
10771           AV
10772             *av;
10773
10774           double
10775             *coordinates;
10776
10777           SparseColorMethod
10778             method;
10779
10780           size_t
10781             number_coordinates;
10782
10783           VirtualPixelMethod
10784             virtual_pixel;
10785
10786           if (attribute_flag[0] == 0)
10787             break;
10788           method=UndefinedColorInterpolate;
10789           if (attribute_flag[1] != 0)
10790             method=(SparseColorMethod) argument_list[1].integer_reference;
10791           av=(AV *) argument_list[0].array_reference;
10792           number_coordinates=(size_t) av_len(av)+1;
10793           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10794             sizeof(*coordinates));
10795           if (coordinates == (double *) NULL)
10796             {
10797               ThrowPerlException(exception,ResourceLimitFatalError,
10798                 "MemoryAllocationFailed",PackageName);
10799               goto PerlException;
10800             }
10801           for (j=0; j < (ssize_t) number_coordinates; j++)
10802             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10803           virtual_pixel=UndefinedVirtualPixelMethod;
10804           if (attribute_flag[2] != 0)
10805             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10806               argument_list[2].integer_reference,exception);
10807           if (attribute_flag[3] != 0)
10808             channel=(ChannelType) argument_list[3].integer_reference;
10809           channel_mask=SetImageChannelMask(image,channel);
10810           image=SparseColorImage(image,method,number_coordinates,coordinates,
10811             exception);
10812           if (image != (Image *) NULL)
10813             (void) SetImageChannelMask(image,channel_mask);
10814           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10815             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10816               exception);
10817           coordinates=(double *) RelinquishMagickMemory(coordinates);
10818           break;
10819         }
10820         case 120:  /* Function */
10821         {
10822           AV
10823             *av;
10824
10825           double
10826             *parameters;
10827
10828           MagickFunction
10829             function;
10830
10831           size_t
10832             number_parameters;
10833
10834           VirtualPixelMethod
10835             virtual_pixel;
10836
10837           if (attribute_flag[0] == 0)
10838             break;
10839           function=UndefinedFunction;
10840           if (attribute_flag[1] != 0)
10841             function=(MagickFunction) argument_list[1].integer_reference;
10842           av=(AV *) argument_list[0].array_reference;
10843           number_parameters=(size_t) av_len(av)+1;
10844           parameters=(double *) AcquireQuantumMemory(number_parameters,
10845             sizeof(*parameters));
10846           if (parameters == (double *) NULL)
10847             {
10848               ThrowPerlException(exception,ResourceLimitFatalError,
10849                 "MemoryAllocationFailed",PackageName);
10850               goto PerlException;
10851             }
10852           for (j=0; j < (ssize_t) number_parameters; j++)
10853             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10854           virtual_pixel=UndefinedVirtualPixelMethod;
10855           if (attribute_flag[2] != 0)
10856             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10857               argument_list[2].integer_reference,exception);
10858           (void) FunctionImage(image,function,number_parameters,parameters,
10859             exception);
10860           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10861             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10862               exception);
10863           parameters=(double *) RelinquishMagickMemory(parameters);
10864           break;
10865         }
10866         case 121:  /* SelectiveBlur */
10867         {
10868           if (attribute_flag[0] != 0)
10869             {
10870               flags=ParseGeometry(argument_list[0].string_reference,
10871                 &geometry_info);
10872               if ((flags & SigmaValue) == 0)
10873                 geometry_info.sigma=1.0;
10874               if ((flags & PercentValue) != 0)
10875                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10876             }
10877           if (attribute_flag[1] != 0)
10878             geometry_info.rho=argument_list[1].real_reference;
10879           if (attribute_flag[2] != 0)
10880             geometry_info.sigma=argument_list[2].real_reference;
10881           if (attribute_flag[3] != 0)
10882             geometry_info.xi=argument_list[3].integer_reference;;
10883           if (attribute_flag[5] != 0)
10884             channel=(ChannelType) argument_list[5].integer_reference;
10885           channel_mask=SetImageChannelMask(image,channel);
10886           image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10887             geometry_info.xi,exception);
10888           if (image != (Image *) NULL)
10889             (void) SetImageChannelMask(image,channel_mask);
10890           break;
10891         }
10892         case 122:  /* HaldClut */
10893         {
10894           if (attribute_flag[0] == 0)
10895             {
10896               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10897                 PackageName);
10898               goto PerlException;
10899             }
10900           if (attribute_flag[1] != 0)
10901             channel=(ChannelType) argument_list[1].integer_reference;
10902           channel_mask=SetImageChannelMask(image,channel);
10903           (void) HaldClutImage(image,argument_list[0].image_reference,
10904             exception);
10905           (void) SetImageChannelMask(image,channel_mask);
10906           break;
10907         }
10908         case 123:  /* BlueShift */
10909         {
10910           if (attribute_flag[0] != 0)
10911             (void) ParseGeometry(argument_list[0].string_reference,
10912               &geometry_info);
10913           image=BlueShiftImage(image,geometry_info.rho,exception);
10914           break;
10915         }
10916         case 124:  /* ForwardFourierTransformImage */
10917         {
10918           image=ForwardFourierTransformImage(image,
10919             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10920             exception);
10921           break;
10922         }
10923         case 125:  /* InverseFourierTransformImage */
10924         {
10925           image=InverseFourierTransformImage(image,image->next,
10926             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10927             exception);
10928           break;
10929         }
10930         case 126:  /* ColorDecisionList */
10931         {
10932           if (attribute_flag[0] == 0)
10933             argument_list[0].string_reference=(char *) NULL;
10934           (void) ColorDecisionListImage(image,
10935             argument_list[0].string_reference,exception);
10936           break;
10937         }
10938         case 127:  /* AutoGamma */
10939         {
10940           if (attribute_flag[0] != 0)
10941             channel=(ChannelType) argument_list[0].integer_reference;
10942           channel_mask=SetImageChannelMask(image,channel);
10943           (void) AutoGammaImage(image,exception);
10944           (void) SetImageChannelMask(image,channel_mask);
10945           break;
10946         }
10947         case 128:  /* AutoLevel */
10948         {
10949           if (attribute_flag[0] != 0)
10950             channel=(ChannelType) argument_list[0].integer_reference;
10951           channel_mask=SetImageChannelMask(image,channel);
10952           (void) AutoLevelImage(image,exception);
10953           (void) SetImageChannelMask(image,channel_mask);
10954           break;
10955         }
10956         case 129:  /* LevelColors */
10957         {
10958           PixelInfo
10959             black_point,
10960             white_point;
10961
10962           (void) QueryColorCompliance("#000000",AllCompliance,&black_point,
10963             exception);
10964           (void) QueryColorCompliance("#ffffff",AllCompliance,&white_point,
10965             exception);
10966           if (attribute_flag[1] != 0)
10967              (void) QueryColorCompliance(
10968                argument_list[1].string_reference,AllCompliance,&black_point,
10969                exception);
10970           if (attribute_flag[2] != 0)
10971              (void) QueryColorCompliance(
10972                argument_list[2].string_reference,AllCompliance,&white_point,
10973                exception);
10974           if (attribute_flag[3] != 0)
10975             channel=(ChannelType) argument_list[3].integer_reference;
10976           channel_mask=SetImageChannelMask(image,channel);
10977           (void) LevelImageColors(image,&black_point,&white_point,
10978             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10979             exception);
10980           (void) SetImageChannelMask(image,channel_mask);
10981           break;
10982         }
10983         case 130:  /* Clamp */
10984         {
10985           if (attribute_flag[0] != 0)
10986             channel=(ChannelType) argument_list[0].integer_reference;
10987           channel_mask=SetImageChannelMask(image,channel);
10988           (void) ClampImage(image,exception);
10989           (void) SetImageChannelMask(image,channel_mask);
10990           break;
10991         }
10992         case 131:  /* BrightnessContrast */
10993         {
10994           double
10995             brightness,
10996             contrast;
10997
10998           brightness=0.0;
10999           contrast=0.0;
11000           if (attribute_flag[0] != 0)
11001             {
11002               flags=ParseGeometry(argument_list[0].string_reference,
11003                 &geometry_info);
11004               brightness=geometry_info.rho;
11005               if ((flags & SigmaValue) == 0)
11006                 contrast=geometry_info.sigma;
11007             }
11008           if (attribute_flag[1] != 0)
11009             brightness=argument_list[1].real_reference;
11010           if (attribute_flag[2] != 0)
11011             contrast=argument_list[2].real_reference;
11012           if (attribute_flag[4] != 0)
11013             channel=(ChannelType) argument_list[4].integer_reference;
11014           channel_mask=SetImageChannelMask(image,channel);
11015           (void) BrightnessContrastImage(image,brightness,contrast,exception);
11016           (void) SetImageChannelMask(image,channel_mask);
11017           break;
11018         }
11019         case 132:  /* Morphology */
11020         {
11021           KernelInfo
11022             *kernel;
11023
11024           MorphologyMethod
11025             method;
11026
11027           ssize_t
11028             iterations;
11029
11030           if (attribute_flag[0] == 0)
11031             break;
11032           kernel=AcquireKernelInfo(argument_list[0].string_reference,exception);
11033           if (kernel == (KernelInfo *) NULL)
11034             break;
11035           if (attribute_flag[1] != 0)
11036             channel=(ChannelType) argument_list[1].integer_reference;
11037           method=UndefinedMorphology;
11038           if (attribute_flag[2] != 0)
11039             method=argument_list[2].integer_reference;
11040           iterations=1;
11041           if (attribute_flag[3] != 0)
11042             iterations=argument_list[3].integer_reference;
11043           channel_mask=SetImageChannelMask(image,channel);
11044           image=MorphologyImage(image,method,iterations,kernel,exception);
11045           if (image != (Image *) NULL)
11046             (void) SetImageChannelMask(image,channel_mask);
11047           kernel=DestroyKernelInfo(kernel);
11048           break;
11049         }
11050         case 133:  /* Mode */
11051         {
11052           if (attribute_flag[0] != 0)
11053             {
11054               flags=ParseGeometry(argument_list[0].string_reference,
11055                 &geometry_info);
11056               if ((flags & SigmaValue) == 0)
11057                 geometry_info.sigma=1.0;
11058             }
11059           if (attribute_flag[1] != 0)
11060             geometry_info.rho=argument_list[1].real_reference;
11061           if (attribute_flag[2] != 0)
11062             geometry_info.sigma=argument_list[2].real_reference;
11063           if (attribute_flag[3] != 0)
11064             channel=(ChannelType) argument_list[3].integer_reference;
11065           channel_mask=SetImageChannelMask(image,channel);
11066           image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
11067             (size_t) geometry_info.sigma,exception);
11068           if (image != (Image *) NULL)
11069             (void) SetImageChannelMask(image,channel_mask);
11070           break;
11071         }
11072         case 134:  /* Statistic */
11073         {
11074           StatisticType
11075             statistic;
11076
11077           statistic=UndefinedStatistic;
11078           if (attribute_flag[0] != 0)
11079             {
11080               flags=ParseGeometry(argument_list[0].string_reference,
11081                 &geometry_info);
11082               if ((flags & SigmaValue) == 0)
11083                 geometry_info.sigma=1.0;
11084             }
11085           if (attribute_flag[1] != 0)
11086             geometry_info.rho=argument_list[1].real_reference;
11087           if (attribute_flag[2] != 0)
11088             geometry_info.sigma=argument_list[2].real_reference;
11089           if (attribute_flag[3] != 0)
11090             channel=(ChannelType) argument_list[3].integer_reference;
11091           if (attribute_flag[4] != 0)
11092             statistic=(StatisticType) argument_list[4].integer_reference;
11093           channel_mask=SetImageChannelMask(image,channel);
11094           image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
11095             (size_t) geometry_info.sigma,exception);
11096           if (image != (Image *) NULL)
11097             (void) SetImageChannelMask(image,channel_mask);
11098           break;
11099         }
11100         case 135:  /* Perceptible */
11101         {
11102           double
11103             epsilon;
11104
11105           epsilon=MagickEpsilon;
11106           if (attribute_flag[0] != 0)
11107             epsilon=argument_list[0].real_reference;
11108           if (attribute_flag[1] != 0)
11109             channel=(ChannelType) argument_list[1].integer_reference;
11110           channel_mask=SetImageChannelMask(image,channel);
11111           (void) PerceptibleImage(image,epsilon,exception);
11112           (void) SetImageChannelMask(image,channel_mask);
11113           break;
11114         }
11115         case 136:  /* Poly */
11116         {
11117           AV
11118             *av;
11119
11120           double
11121             *terms;
11122
11123           size_t
11124             number_terms;
11125
11126           if (attribute_flag[0] == 0)
11127             break;
11128           if (attribute_flag[1] != 0)
11129             channel=(ChannelType) argument_list[1].integer_reference;
11130           av=(AV *) argument_list[0].array_reference;
11131           number_terms=(size_t) av_len(av);
11132           terms=(double *) AcquireQuantumMemory(number_terms,sizeof(*terms));
11133           if (terms == (double *) NULL)
11134             {
11135               ThrowPerlException(exception,ResourceLimitFatalError,
11136                 "MemoryAllocationFailed",PackageName);
11137               goto PerlException;
11138             }
11139           for (j=0; j < av_len(av); j++)
11140             terms[j]=(double) SvNV(*(av_fetch(av,j,0)));
11141           image=PolynomialImage(image,number_terms >> 1,terms,exception);
11142           terms=(double *) RelinquishMagickMemory(terms);
11143           break;
11144         }
11145         case 137:  /* Grayscale */
11146         {
11147           PixelIntensityMethod
11148             method;
11149
11150           method=UndefinedPixelIntensityMethod;
11151           if (attribute_flag[0] != 0)
11152             method=(PixelIntensityMethod) argument_list[0].integer_reference;
11153           (void) GrayscaleImage(image,method,exception);
11154           break;
11155         }
11156         case 138:  /* Canny */
11157         {
11158           if (attribute_flag[0] != 0)
11159             {
11160               flags=ParseGeometry(argument_list[0].string_reference,
11161                 &geometry_info);
11162               if ((flags & SigmaValue) == 0)
11163                 geometry_info.sigma=1.0;
11164               if ((flags & XiValue) == 0)
11165                 geometry_info.xi=0.10;
11166               if ((flags & PsiValue) == 0)
11167                 geometry_info.psi=0.30;
11168               if ((flags & PercentValue) != 0)
11169                 {
11170                   geometry_info.xi/=100.0;
11171                   geometry_info.psi/=100.0;
11172                 }
11173             }
11174           if (attribute_flag[1] != 0)
11175             geometry_info.rho=argument_list[1].real_reference;
11176           if (attribute_flag[2] != 0)
11177             geometry_info.sigma=argument_list[2].real_reference;
11178           if (attribute_flag[3] != 0)
11179             geometry_info.xi=argument_list[3].real_reference;
11180           if (attribute_flag[4] != 0)
11181             geometry_info.psi=argument_list[4].real_reference;
11182           if (attribute_flag[5] != 0)
11183             channel=(ChannelType) argument_list[5].integer_reference;
11184           channel_mask=SetImageChannelMask(image,channel);
11185           image=CannyEdgeImage(image,geometry_info.rho,geometry_info.sigma,
11186             geometry_info.xi,geometry_info.psi,exception);
11187           if (image != (Image *) NULL)
11188             (void) SetImageChannelMask(image,channel_mask);
11189           break;
11190         }
11191         case 139:  /* HoughLine */
11192         {
11193           if (attribute_flag[0] != 0)
11194             {
11195               flags=ParseGeometry(argument_list[0].string_reference,
11196                 &geometry_info);
11197               if ((flags & SigmaValue) == 0)
11198                 geometry_info.sigma=geometry_info.rho;
11199               if ((flags & XiValue) == 0)
11200                 geometry_info.xi=40;
11201             }
11202           if (attribute_flag[1] != 0)
11203             geometry_info.rho=(double) argument_list[1].integer_reference;
11204           if (attribute_flag[2] != 0)
11205             geometry_info.sigma=(double) argument_list[2].integer_reference;
11206           if (attribute_flag[3] != 0)
11207             geometry_info.xi=(double) argument_list[3].integer_reference;
11208           image=HoughLineImage(image,(size_t) geometry_info.rho,(size_t)
11209             geometry_info.sigma,(size_t) geometry_info.xi,exception);
11210           break;
11211         }
11212         case 140:  /* MeanShift */
11213         {
11214           if (attribute_flag[0] != 0)
11215             {
11216               flags=ParseGeometry(argument_list[0].string_reference,
11217                 &geometry_info);
11218               if ((flags & SigmaValue) == 0)
11219                 geometry_info.sigma=geometry_info.rho;
11220               if ((flags & XiValue) == 0)
11221                 geometry_info.xi=0.10*QuantumRange;
11222               if ((flags & PercentValue) != 0)
11223                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
11224             }
11225           if (attribute_flag[1] != 0)
11226             geometry_info.rho=(double) argument_list[1].integer_reference;
11227           if (attribute_flag[2] != 0)
11228             geometry_info.sigma=(double) argument_list[2].integer_reference;
11229           if (attribute_flag[3] != 0)
11230             geometry_info.xi=(double) argument_list[3].integer_reference;
11231           image=MeanShiftImage(image,(size_t) geometry_info.rho,(size_t)
11232             geometry_info.sigma,geometry_info.xi,exception);
11233           break;
11234         }
11235         case 141:  /* Kuwahara */
11236         {
11237           if (attribute_flag[0] != 0)
11238             {
11239               flags=ParseGeometry(argument_list[0].string_reference,
11240                 &geometry_info);
11241               if ((flags & SigmaValue) == 0)
11242                 geometry_info.sigma=geometry_info.rho-0.5;
11243             }
11244           if (attribute_flag[1] != 0)
11245             geometry_info.rho=argument_list[1].real_reference;
11246           if (attribute_flag[2] != 0)
11247             geometry_info.sigma=argument_list[2].real_reference;
11248           if (attribute_flag[3] != 0)
11249             channel=(ChannelType) argument_list[3].integer_reference;
11250           channel_mask=SetImageChannelMask(image,channel);
11251           image=KuwaharaImage(image,geometry_info.rho,geometry_info.sigma,
11252             exception);
11253           if (image != (Image *) NULL)
11254             (void) SetImageChannelMask(image,channel_mask);
11255           break;
11256         }
11257         case 142:  /* ConnectedComponent */
11258         {
11259           size_t
11260             connectivity;
11261
11262           connectivity=4;
11263           if (attribute_flag[0] != 0)
11264             connectivity=argument_list[0].integer_reference;
11265           image=ConnectedComponentsImage(image,connectivity,
11266             (CCObjectInfo **) NULL,exception);
11267           break;
11268         }
11269         case 143:  /* Copy */
11270         {
11271           Image
11272             *source_image;
11273
11274           OffsetInfo
11275             offset;
11276
11277           RectangleInfo
11278             offset_geometry;
11279
11280           source_image=image;
11281           if (attribute_flag[0] != 0)
11282             source_image=argument_list[0].image_reference;
11283           SetGeometry(source_image,&geometry);
11284           if (attribute_flag[1] != 0)
11285             flags=ParseGravityGeometry(source_image,
11286               argument_list[1].string_reference,&geometry,exception);
11287           if (attribute_flag[2] != 0)
11288             geometry.width=argument_list[2].integer_reference;
11289           if (attribute_flag[3] != 0)
11290             geometry.height=argument_list[3].integer_reference;
11291           if (attribute_flag[4] != 0)
11292             geometry.x=argument_list[4].integer_reference;
11293           if (attribute_flag[5] != 0)
11294             geometry.y=argument_list[5].integer_reference;
11295           if (attribute_flag[6] != 0)
11296             image->gravity=(GravityType) argument_list[6].integer_reference;
11297           SetGeometry(image,&offset_geometry);
11298           if (attribute_flag[7] != 0)
11299             flags=ParseGravityGeometry(image,argument_list[7].string_reference,
11300               &offset_geometry,exception);
11301           offset.x=offset_geometry.x;
11302           offset.y=offset_geometry.y;
11303           if (attribute_flag[8] != 0)
11304             offset.x=argument_list[8].integer_reference;
11305           if (attribute_flag[9] != 0)
11306             offset.y=argument_list[9].integer_reference;
11307           (void) CopyImagePixels(image,source_image,&geometry,&offset,
11308             exception);
11309           break;
11310         }
11311       }
11312       if (next != (Image *) NULL)
11313         (void) CatchImageException(next);
11314       if (region_image != (Image *) NULL)
11315         {
11316           /*
11317             Composite region.
11318           */
11319           status=CompositeImage(region_image,image,CopyCompositeOp,MagickTrue,
11320             region_info.x,region_info.y,exception);
11321           (void) status;
11322           (void) CatchImageException(region_image);
11323           image=DestroyImage(image);
11324           image=region_image;
11325         }
11326       if (image != (Image *) NULL)
11327         {
11328           number_images++;
11329           if (next && (next != image))
11330             {
11331               image->next=next->next;
11332               if (image->next != (Image *) NULL)
11333                 image->next->previous=image;
11334               DeleteImageFromRegistry(*pv,next);
11335             }
11336           sv_setiv(*pv,PTR2IV(image));
11337           next=image;
11338         }
11339       if (*pv)
11340         pv++;
11341     }
11342
11343   PerlException:
11344     if (reference_vector)
11345       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
11346     InheritPerlException(exception,perl_exception);
11347     exception=DestroyExceptionInfo(exception);
11348     sv_setiv(perl_exception,(IV) number_images);
11349     SvPOK_on(perl_exception);
11350     ST(0)=sv_2mortal(perl_exception);
11351     XSRETURN(1);
11352   }
11353 \f
11354 #
11355 ###############################################################################
11356 #                                                                             #
11357 #                                                                             #
11358 #                                                                             #
11359 #   M o n t a g e                                                             #
11360 #                                                                             #
11361 #                                                                             #
11362 #                                                                             #
11363 ###############################################################################
11364 #
11365 #
11366 void
11367 Montage(ref,...)
11368   Image::Magick ref=NO_INIT
11369   ALIAS:
11370     MontageImage  = 1
11371     montage       = 2
11372     montageimage  = 3
11373   PPCODE:
11374   {
11375     AV
11376       *av;
11377
11378     char
11379       *attribute;
11380
11381     ExceptionInfo
11382       *exception;
11383
11384     HV
11385       *hv;
11386
11387     Image
11388       *image,
11389       *next;
11390
11391     PixelInfo
11392       transparent_color;
11393
11394     MontageInfo
11395       *montage_info;
11396
11397     register ssize_t
11398       i;
11399
11400     ssize_t
11401       sp;
11402
11403     struct PackageInfo
11404       *info;
11405
11406     SV
11407       *av_reference,
11408       *perl_exception,
11409       *reference,
11410       *rv,
11411       *sv;
11412
11413     PERL_UNUSED_VAR(ref);
11414     PERL_UNUSED_VAR(ix);
11415     exception=AcquireExceptionInfo();
11416     perl_exception=newSVpv("",0);
11417     sv=NULL;
11418     attribute=NULL;
11419     if (sv_isobject(ST(0)) == 0)
11420       {
11421         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11422           PackageName);
11423         goto PerlException;
11424       }
11425     reference=SvRV(ST(0));
11426     hv=SvSTASH(reference);
11427     av=newAV();
11428     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11429     SvREFCNT_dec(av);
11430     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11431     if (image == (Image *) NULL)
11432       {
11433         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11434           PackageName);
11435         goto PerlException;
11436       }
11437     /*
11438       Get options.
11439     */
11440     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11441     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
11442     (void) QueryColorCompliance("none",AllCompliance,&transparent_color,
11443       exception);
11444     for (i=2; i < items; i+=2)
11445     {
11446       attribute=(char *) SvPV(ST(i-1),na);
11447       switch (*attribute)
11448       {
11449         case 'B':
11450         case 'b':
11451         {
11452           if (LocaleCompare(attribute,"background") == 0)
11453             {
11454               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11455                 &montage_info->background_color,exception);
11456               for (next=image; next; next=next->next)
11457                 next->background_color=montage_info->background_color;
11458               break;
11459             }
11460           if (LocaleCompare(attribute,"border") == 0)
11461             {
11462               montage_info->border_width=SvIV(ST(i));
11463               break;
11464             }
11465           if (LocaleCompare(attribute,"bordercolor") == 0)
11466             {
11467               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11468                 &montage_info->border_color,exception);
11469               for (next=image; next; next=next->next)
11470                 next->border_color=montage_info->border_color;
11471               break;
11472             }
11473           if (LocaleCompare(attribute,"borderwidth") == 0)
11474             {
11475               montage_info->border_width=SvIV(ST(i));
11476               break;
11477             }
11478           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11479             attribute);
11480           break;
11481         }
11482         case 'C':
11483         case 'c':
11484         {
11485           if (LocaleCompare(attribute,"compose") == 0)
11486             {
11487               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11488                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
11489               if (sp < 0)
11490                 {
11491                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11492                     SvPV(ST(i),na));
11493                   break;
11494                 }
11495               for (next=image; next; next=next->next)
11496                 next->compose=(CompositeOperator) sp;
11497               break;
11498             }
11499           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11500             attribute);
11501           break;
11502         }
11503         case 'F':
11504         case 'f':
11505         {
11506           if (LocaleCompare(attribute,"fill") == 0)
11507             {
11508               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11509                 &montage_info->fill,exception);
11510               break;
11511             }
11512           if (LocaleCompare(attribute,"font") == 0)
11513             {
11514               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
11515               break;
11516             }
11517           if (LocaleCompare(attribute,"frame") == 0)
11518             {
11519               char
11520                 *p;
11521
11522               p=SvPV(ST(i),na);
11523               if (IsGeometry(p) == MagickFalse)
11524                 {
11525                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11526                     p);
11527                   break;
11528                 }
11529               (void) CloneString(&montage_info->frame,p);
11530               if (*p == '\0')
11531                 montage_info->frame=(char *) NULL;
11532               break;
11533             }
11534           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11535             attribute);
11536           break;
11537         }
11538         case 'G':
11539         case 'g':
11540         {
11541           if (LocaleCompare(attribute,"geometry") == 0)
11542             {
11543               char
11544                 *p;
11545
11546               p=SvPV(ST(i),na);
11547               if (IsGeometry(p) == MagickFalse)
11548                 {
11549                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11550                     p);
11551                   break;
11552                 }
11553              (void) CloneString(&montage_info->geometry,p);
11554              if (*p == '\0')
11555                montage_info->geometry=(char *) NULL;
11556              break;
11557            }
11558          if (LocaleCompare(attribute,"gravity") == 0)
11559            {
11560              ssize_t
11561                in;
11562
11563              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11564                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11565              if (in < 0)
11566                {
11567                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
11568                    SvPV(ST(i),na));
11569                  return;
11570                }
11571              montage_info->gravity=(GravityType) in;
11572              for (next=image; next; next=next->next)
11573                next->gravity=(GravityType) in;
11574              break;
11575            }
11576           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11577             attribute);
11578           break;
11579         }
11580         case 'L':
11581         case 'l':
11582         {
11583           if (LocaleCompare(attribute,"label") == 0)
11584             {
11585               for (next=image; next; next=next->next)
11586                 (void) SetImageProperty(next,"label",InterpretImageProperties(
11587                   info ? info->image_info : (ImageInfo *) NULL,next,
11588                   SvPV(ST(i),na),exception),exception);
11589               break;
11590             }
11591           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11592             attribute);
11593           break;
11594         }
11595         case 'M':
11596         case 'm':
11597         {
11598           if (LocaleCompare(attribute,"mattecolor") == 0)
11599             {
11600               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11601                 &montage_info->alpha_color,exception);
11602               for (next=image; next; next=next->next)
11603                 next->alpha_color=montage_info->alpha_color;
11604               break;
11605             }
11606           if (LocaleCompare(attribute,"mode") == 0)
11607             {
11608               ssize_t
11609                 in;
11610
11611               in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11612                 MagickModeOptions,MagickFalse,SvPV(ST(i),na));
11613               switch (in)
11614               {
11615                 default:
11616                 {
11617                   ThrowPerlException(exception,OptionError,
11618                     "UnrecognizedModeType",SvPV(ST(i),na));
11619                   break;
11620                 }
11621                 case FrameMode:
11622                 {
11623                   (void) CloneString(&montage_info->frame,"15x15+3+3");
11624                   montage_info->shadow=MagickTrue;
11625                   break;
11626                 }
11627                 case UnframeMode:
11628                 {
11629                   montage_info->frame=(char *) NULL;
11630                   montage_info->shadow=MagickFalse;
11631                   montage_info->border_width=0;
11632                   break;
11633                 }
11634                 case ConcatenateMode:
11635                 {
11636                   montage_info->frame=(char *) NULL;
11637                   montage_info->shadow=MagickFalse;
11638                   (void) CloneString(&montage_info->geometry,"+0+0");
11639                   montage_info->border_width=0;
11640                 }
11641               }
11642               break;
11643             }
11644           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11645             attribute);
11646           break;
11647         }
11648         case 'P':
11649         case 'p':
11650         {
11651           if (LocaleCompare(attribute,"pointsize") == 0)
11652             {
11653               montage_info->pointsize=SvIV(ST(i));
11654               break;
11655             }
11656           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11657             attribute);
11658           break;
11659         }
11660         case 'S':
11661         case 's':
11662         {
11663           if (LocaleCompare(attribute,"shadow") == 0)
11664             {
11665               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11666                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11667               if (sp < 0)
11668                 {
11669                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11670                     SvPV(ST(i),na));
11671                   break;
11672                 }
11673              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11674              break;
11675             }
11676           if (LocaleCompare(attribute,"stroke") == 0)
11677             {
11678               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11679                 &montage_info->stroke,exception);
11680               break;
11681             }
11682           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11683             attribute);
11684           break;
11685         }
11686         case 'T':
11687         case 't':
11688         {
11689           if (LocaleCompare(attribute,"texture") == 0)
11690             {
11691               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11692               break;
11693             }
11694           if (LocaleCompare(attribute,"tile") == 0)
11695             {
11696               char *p=SvPV(ST(i),na);
11697               if (IsGeometry(p) == MagickFalse)
11698                 {
11699                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11700                     p);
11701                   break;
11702                 }
11703               (void) CloneString(&montage_info->tile,p);
11704               if (*p == '\0')
11705                 montage_info->tile=(char *) NULL;
11706               break;
11707             }
11708           if (LocaleCompare(attribute,"title") == 0)
11709             {
11710               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11711               break;
11712             }
11713           if (LocaleCompare(attribute,"transparent") == 0)
11714             {
11715               PixelInfo
11716                 transparent_color;
11717
11718               QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11719                 &transparent_color,exception);
11720               for (next=image; next; next=next->next)
11721                 (void) TransparentPaintImage(next,&transparent_color,
11722                   TransparentAlpha,MagickFalse,exception);
11723               break;
11724             }
11725           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11726             attribute);
11727           break;
11728         }
11729         default:
11730         {
11731           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11732             attribute);
11733           break;
11734         }
11735       }
11736     }
11737     image=MontageImageList(info->image_info,montage_info,image,exception);
11738     montage_info=DestroyMontageInfo(montage_info);
11739     if (image == (Image *) NULL)
11740       goto PerlException;
11741     if (transparent_color.alpha != TransparentAlpha)
11742       for (next=image; next; next=next->next)
11743         (void) TransparentPaintImage(next,&transparent_color,
11744           TransparentAlpha,MagickFalse,exception);
11745     for (  ; image; image=image->next)
11746     {
11747       AddImageToRegistry(sv,image);
11748       rv=newRV(sv);
11749       av_push(av,sv_bless(rv,hv));
11750       SvREFCNT_dec(sv);
11751     }
11752     exception=DestroyExceptionInfo(exception);
11753     ST(0)=av_reference;
11754     SvREFCNT_dec(perl_exception);
11755     XSRETURN(1);
11756
11757   PerlException:
11758     InheritPerlException(exception,perl_exception);
11759     exception=DestroyExceptionInfo(exception);
11760     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11761     SvPOK_on(perl_exception);
11762     ST(0)=sv_2mortal(perl_exception);
11763     XSRETURN(1);
11764   }
11765 \f
11766 #
11767 ###############################################################################
11768 #                                                                             #
11769 #                                                                             #
11770 #                                                                             #
11771 #   M o r p h                                                                 #
11772 #                                                                             #
11773 #                                                                             #
11774 #                                                                             #
11775 ###############################################################################
11776 #
11777 #
11778 void
11779 Morph(ref,...)
11780   Image::Magick ref=NO_INIT
11781   ALIAS:
11782     MorphImage  = 1
11783     morph       = 2
11784     morphimage  = 3
11785   PPCODE:
11786   {
11787     AV
11788       *av;
11789
11790     char
11791       *attribute;
11792
11793     ExceptionInfo
11794       *exception;
11795
11796     HV
11797       *hv;
11798
11799     Image
11800       *image;
11801
11802     register ssize_t
11803       i;
11804
11805     ssize_t
11806       number_frames;
11807
11808     struct PackageInfo
11809       *info;
11810
11811     SV
11812       *av_reference,
11813       *perl_exception,
11814       *reference,
11815       *rv,
11816       *sv;
11817
11818     PERL_UNUSED_VAR(ref);
11819     PERL_UNUSED_VAR(ix);
11820     exception=AcquireExceptionInfo();
11821     perl_exception=newSVpv("",0);
11822     sv=NULL;
11823     av=NULL;
11824     attribute=NULL;
11825     if (sv_isobject(ST(0)) == 0)
11826       {
11827         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11828           PackageName);
11829         goto PerlException;
11830       }
11831     reference=SvRV(ST(0));
11832     hv=SvSTASH(reference);
11833     av=newAV();
11834     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11835     SvREFCNT_dec(av);
11836     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11837     if (image == (Image *) NULL)
11838       {
11839         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11840           PackageName);
11841         goto PerlException;
11842       }
11843     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11844     /*
11845       Get attribute.
11846     */
11847     number_frames=30;
11848     for (i=2; i < items; i+=2)
11849     {
11850       attribute=(char *) SvPV(ST(i-1),na);
11851       switch (*attribute)
11852       {
11853         case 'F':
11854         case 'f':
11855         {
11856           if (LocaleCompare(attribute,"frames") == 0)
11857             {
11858               number_frames=SvIV(ST(i));
11859               break;
11860             }
11861           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11862             attribute);
11863           break;
11864         }
11865         default:
11866         {
11867           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11868             attribute);
11869           break;
11870         }
11871       }
11872     }
11873     image=MorphImages(image,number_frames,exception);
11874     if (image == (Image *) NULL)
11875       goto PerlException;
11876     for ( ; image; image=image->next)
11877     {
11878       AddImageToRegistry(sv,image);
11879       rv=newRV(sv);
11880       av_push(av,sv_bless(rv,hv));
11881       SvREFCNT_dec(sv);
11882     }
11883     exception=DestroyExceptionInfo(exception);
11884     ST(0)=av_reference;
11885     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11886     XSRETURN(1);
11887
11888   PerlException:
11889     InheritPerlException(exception,perl_exception);
11890     exception=DestroyExceptionInfo(exception);
11891     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11892     SvPOK_on(perl_exception);
11893     ST(0)=sv_2mortal(perl_exception);
11894     XSRETURN(1);
11895   }
11896 \f
11897 #
11898 ###############################################################################
11899 #                                                                             #
11900 #                                                                             #
11901 #                                                                             #
11902 #   M o s a i c                                                               #
11903 #                                                                             #
11904 #                                                                             #
11905 #                                                                             #
11906 ###############################################################################
11907 #
11908 #
11909 void
11910 Mosaic(ref)
11911   Image::Magick ref=NO_INIT
11912   ALIAS:
11913     MosaicImage   = 1
11914     mosaic        = 2
11915     mosaicimage   = 3
11916   PPCODE:
11917   {
11918     AV
11919       *av;
11920
11921     ExceptionInfo
11922       *exception;
11923
11924     HV
11925       *hv;
11926
11927     Image
11928       *image;
11929
11930     struct PackageInfo
11931       *info;
11932
11933     SV
11934       *perl_exception,
11935       *reference,
11936       *rv,
11937       *sv;
11938
11939     PERL_UNUSED_VAR(ref);
11940     PERL_UNUSED_VAR(ix);
11941     exception=AcquireExceptionInfo();
11942     perl_exception=newSVpv("",0);
11943     sv=NULL;
11944     if (sv_isobject(ST(0)) == 0)
11945       {
11946         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11947           PackageName);
11948         goto PerlException;
11949       }
11950     reference=SvRV(ST(0));
11951     hv=SvSTASH(reference);
11952     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11953     if (image == (Image *) NULL)
11954       {
11955         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11956           PackageName);
11957         goto PerlException;
11958       }
11959     image=MergeImageLayers(image,MosaicLayer,exception);
11960     /*
11961       Create blessed Perl array for the returned image.
11962     */
11963     av=newAV();
11964     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11965     SvREFCNT_dec(av);
11966     AddImageToRegistry(sv,image);
11967     rv=newRV(sv);
11968     av_push(av,sv_bless(rv,hv));
11969     SvREFCNT_dec(sv);
11970     (void) CopyMagickString(info->image_info->filename,image->filename,
11971       MagickPathExtent);
11972     SetImageInfo(info->image_info,0,exception);
11973     exception=DestroyExceptionInfo(exception);
11974     SvREFCNT_dec(perl_exception);
11975     XSRETURN(1);
11976
11977   PerlException:
11978     InheritPerlException(exception,perl_exception);
11979     exception=DestroyExceptionInfo(exception);
11980     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11981     SvPOK_on(perl_exception);  /* return messages in string context */
11982     ST(0)=sv_2mortal(perl_exception);
11983     XSRETURN(1);
11984   }
11985 \f
11986 #
11987 ###############################################################################
11988 #                                                                             #
11989 #                                                                             #
11990 #                                                                             #
11991 #   P i n g                                                                   #
11992 #                                                                             #
11993 #                                                                             #
11994 #                                                                             #
11995 ###############################################################################
11996 #
11997 #
11998 void
11999 Ping(ref,...)
12000   Image::Magick ref=NO_INIT
12001   ALIAS:
12002     PingImage  = 1
12003     ping       = 2
12004     pingimage  = 3
12005   PPCODE:
12006   {
12007     AV
12008       *av;
12009
12010     char
12011       **keep,
12012       **list;
12013
12014     ExceptionInfo
12015       *exception;
12016
12017     Image
12018       *image,
12019       *next;
12020
12021     int
12022       n;
12023
12024     MagickBooleanType
12025       status;
12026
12027     register char
12028       **p;
12029
12030     register ssize_t
12031       i;
12032
12033     ssize_t
12034       ac;
12035
12036     STRLEN
12037       *length;
12038
12039     struct PackageInfo
12040       *info,
12041       *package_info;
12042
12043     SV
12044       *perl_exception,
12045       *reference;
12046
12047     size_t
12048       count;
12049
12050     PERL_UNUSED_VAR(ref);
12051     PERL_UNUSED_VAR(ix);
12052     exception=AcquireExceptionInfo();
12053     perl_exception=newSVpv("",0);
12054     package_info=(struct PackageInfo *) NULL;
12055     ac=(items < 2) ? 1 : items-1;
12056     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
12057     keep=list;
12058     length=(STRLEN *) NULL;
12059     if (list == (char **) NULL)
12060       {
12061         ThrowPerlException(exception,ResourceLimitError,
12062           "MemoryAllocationFailed",PackageName);
12063         goto PerlException;
12064       }
12065     keep=list;
12066     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
12067     if (length == (STRLEN *) NULL)
12068       {
12069         ThrowPerlException(exception,ResourceLimitError,
12070           "MemoryAllocationFailed",PackageName);
12071         goto PerlException;
12072       }
12073     if (sv_isobject(ST(0)) == 0)
12074       {
12075         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12076           PackageName);
12077         goto PerlException;
12078       }
12079     reference=SvRV(ST(0));
12080     if (SvTYPE(reference) != SVt_PVAV)
12081       {
12082         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12083           PackageName);
12084         goto PerlException;
12085       }
12086     av=(AV *) reference;
12087     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12088       exception);
12089     package_info=ClonePackageInfo(info,exception);
12090     n=1;
12091     if (items <= 1)
12092       *list=(char *) (*package_info->image_info->filename ?
12093         package_info->image_info->filename : "XC:black");
12094     else
12095       for (n=0, i=0; i < ac; i++)
12096       {
12097         list[n]=(char *) SvPV(ST(i+1),length[n]);
12098         if ((items >= 3) && strEQcase(list[n],"blob"))
12099           {
12100             void
12101               *blob;
12102
12103             i++;
12104             blob=(void *) (SvPV(ST(i+1),length[n]));
12105             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
12106           }
12107         if ((items >= 3) && strEQcase(list[n],"filename"))
12108           continue;
12109         if ((items >= 3) && strEQcase(list[n],"file"))
12110           {
12111             FILE
12112               *file;
12113
12114             PerlIO
12115               *io_info;
12116
12117             i++;
12118             io_info=IoIFP(sv_2io(ST(i+1)));
12119             if (io_info == (PerlIO *) NULL)
12120               {
12121                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12122                   PackageName);
12123                 continue;
12124               }
12125             file=PerlIO_findFILE(io_info);
12126             if (file == (FILE *) NULL)
12127               {
12128                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12129                   PackageName);
12130                 continue;
12131               }
12132             SetImageInfoFile(package_info->image_info,file);
12133           }
12134         if ((items >= 3) && strEQcase(list[n],"magick"))
12135           continue;
12136         n++;
12137       }
12138     list[n]=(char *) NULL;
12139     keep=list;
12140     status=ExpandFilenames(&n,&list);
12141     if (status == MagickFalse)
12142       {
12143         ThrowPerlException(exception,ResourceLimitError,
12144           "MemoryAllocationFailed",PackageName);
12145         goto PerlException;
12146       }
12147     count=0;
12148     for (i=0; i < n; i++)
12149     {
12150       (void) CopyMagickString(package_info->image_info->filename,list[i],
12151         MagickPathExtent);
12152       image=PingImage(package_info->image_info,exception);
12153       if (image == (Image *) NULL)
12154         break;
12155       if ((package_info->image_info->file != (FILE *) NULL) ||
12156           (package_info->image_info->blob != (void *) NULL))
12157         DisassociateImageStream(image);
12158       count+=GetImageListLength(image);
12159       EXTEND(sp,4*count);
12160       for (next=image; next; next=next->next)
12161       {
12162         PUSHs(sv_2mortal(newSViv(next->columns)));
12163         PUSHs(sv_2mortal(newSViv(next->rows)));
12164         PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
12165         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
12166       }
12167       image=DestroyImageList(image);
12168     }
12169     /*
12170       Free resources.
12171     */
12172     for (i=0; i < n; i++)
12173       if (list[i] != (char *) NULL)
12174         for (p=keep; list[i] != *p++; )
12175           if (*p == NULL)
12176             {
12177               list[i]=(char *) RelinquishMagickMemory(list[i]);
12178               break;
12179             }
12180
12181   PerlException:
12182     if (package_info != (struct PackageInfo *) NULL)
12183       DestroyPackageInfo(package_info);
12184     if (list && (list != keep))
12185       list=(char **) RelinquishMagickMemory(list);
12186     if (keep)
12187       keep=(char **) RelinquishMagickMemory(keep);
12188     if (length)
12189       length=(STRLEN *) RelinquishMagickMemory(length);
12190     InheritPerlException(exception,perl_exception);
12191     exception=DestroyExceptionInfo(exception);
12192     SvREFCNT_dec(perl_exception);  /* throw away all errors */
12193   }
12194 \f
12195 #
12196 ###############################################################################
12197 #                                                                             #
12198 #                                                                             #
12199 #                                                                             #
12200 #   P r e v i e w                                                             #
12201 #                                                                             #
12202 #                                                                             #
12203 #                                                                             #
12204 ###############################################################################
12205 #
12206 #
12207 void
12208 Preview(ref,...)
12209   Image::Magick ref=NO_INIT
12210   ALIAS:
12211     PreviewImage = 1
12212     preview      = 2
12213     previewimage = 3
12214   PPCODE:
12215   {
12216     AV
12217       *av;
12218
12219     ExceptionInfo
12220       *exception;
12221
12222     HV
12223       *hv;
12224
12225     Image
12226       *image,
12227       *preview_image;
12228
12229     PreviewType
12230       preview_type;
12231
12232     struct PackageInfo
12233       *info;
12234
12235     SV
12236       *av_reference,
12237       *perl_exception,
12238       *reference,
12239       *rv,
12240       *sv;
12241
12242     PERL_UNUSED_VAR(ref);
12243     PERL_UNUSED_VAR(ix);
12244     exception=AcquireExceptionInfo();
12245     perl_exception=newSVpv("",0);
12246     sv=NULL;
12247     av=NULL;
12248     if (sv_isobject(ST(0)) == 0)
12249       {
12250         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12251           PackageName);
12252         goto PerlException;
12253       }
12254     reference=SvRV(ST(0));
12255     hv=SvSTASH(reference);
12256     av=newAV();
12257     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12258     SvREFCNT_dec(av);
12259     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12260     if (image == (Image *) NULL)
12261       {
12262         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12263           PackageName);
12264         goto PerlException;
12265       }
12266     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
12267     preview_type=GammaPreview;
12268     if (items > 1)
12269       preview_type=(PreviewType)
12270         ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
12271     for ( ; image; image=image->next)
12272     {
12273       preview_image=PreviewImage(image,preview_type,exception);
12274       if (preview_image == (Image *) NULL)
12275         goto PerlException;
12276       AddImageToRegistry(sv,preview_image);
12277       rv=newRV(sv);
12278       av_push(av,sv_bless(rv,hv));
12279       SvREFCNT_dec(sv);
12280     }
12281     exception=DestroyExceptionInfo(exception);
12282     ST(0)=av_reference;
12283     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12284     XSRETURN(1);
12285
12286   PerlException:
12287     InheritPerlException(exception,perl_exception);
12288     exception=DestroyExceptionInfo(exception);
12289     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12290     SvPOK_on(perl_exception);
12291     ST(0)=sv_2mortal(perl_exception);
12292     XSRETURN(1);
12293   }
12294 \f
12295 #
12296 ###############################################################################
12297 #                                                                             #
12298 #                                                                             #
12299 #                                                                             #
12300 #   Q u e r y C o l o r                                                       #
12301 #                                                                             #
12302 #                                                                             #
12303 #                                                                             #
12304 ###############################################################################
12305 #
12306 #
12307 void
12308 QueryColor(ref,...)
12309   Image::Magick ref=NO_INIT
12310   ALIAS:
12311     querycolor = 1
12312   PPCODE:
12313   {
12314     char
12315       *name;
12316
12317     ExceptionInfo
12318       *exception;
12319
12320     PixelInfo
12321       color;
12322
12323     register ssize_t
12324       i;
12325
12326     SV
12327       *perl_exception;
12328
12329     PERL_UNUSED_VAR(ref);
12330     PERL_UNUSED_VAR(ix);
12331     exception=AcquireExceptionInfo();
12332     perl_exception=newSVpv("",0);
12333     if (items == 1)
12334       {
12335         const ColorInfo
12336           **colorlist;
12337
12338         size_t
12339           colors;
12340
12341         colorlist=GetColorInfoList("*",&colors,exception);
12342         EXTEND(sp,colors);
12343         for (i=0; i < (ssize_t) colors; i++)
12344         {
12345           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
12346         }
12347         colorlist=(const ColorInfo **)
12348           RelinquishMagickMemory((ColorInfo **) colorlist);
12349         goto PerlException;
12350       }
12351     EXTEND(sp,5*items);
12352     for (i=1; i < items; i++)
12353     {
12354       name=(char *) SvPV(ST(i),na);
12355       if (QueryColorCompliance(name,AllCompliance,&color,exception) == MagickFalse)
12356         {
12357           PUSHs(&sv_undef);
12358           continue;
12359         }
12360       PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
12361       PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
12362       PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
12363       if (color.colorspace == CMYKColorspace)
12364         PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
12365       if (color.alpha_trait != UndefinedPixelTrait)
12366         PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
12367     }
12368
12369   PerlException:
12370     InheritPerlException(exception,perl_exception);
12371     exception=DestroyExceptionInfo(exception);
12372     SvREFCNT_dec(perl_exception);
12373   }
12374 \f
12375 #
12376 ###############################################################################
12377 #                                                                             #
12378 #                                                                             #
12379 #                                                                             #
12380 #   Q u e r y C o l o r N a m e                                               #
12381 #                                                                             #
12382 #                                                                             #
12383 #                                                                             #
12384 ###############################################################################
12385 #
12386 #
12387 void
12388 QueryColorname(ref,...)
12389   Image::Magick ref=NO_INIT
12390   ALIAS:
12391     querycolorname = 1
12392   PPCODE:
12393   {
12394     AV
12395       *av;
12396
12397     char
12398       message[MagickPathExtent];
12399
12400     ExceptionInfo
12401       *exception;
12402
12403     Image
12404       *image;
12405
12406     PixelInfo
12407       target_color;
12408
12409     register ssize_t
12410       i;
12411
12412     struct PackageInfo
12413       *info;
12414
12415     SV
12416       *perl_exception,
12417       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12418
12419     PERL_UNUSED_VAR(ref);
12420     PERL_UNUSED_VAR(ix);
12421     exception=AcquireExceptionInfo();
12422     perl_exception=newSVpv("",0);
12423     reference=SvRV(ST(0));
12424     av=(AV *) reference;
12425     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12426       exception);
12427     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12428     if (image == (Image *) NULL)
12429       {
12430         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12431           PackageName);
12432         goto PerlException;
12433       }
12434     EXTEND(sp,items);
12435     for (i=1; i < items; i++)
12436     {
12437       (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,&target_color,
12438         exception);
12439       (void) QueryColorname(image,&target_color,SVGCompliance,message,
12440         exception);
12441       PUSHs(sv_2mortal(newSVpv(message,0)));
12442     }
12443
12444   PerlException:
12445     InheritPerlException(exception,perl_exception);
12446     exception=DestroyExceptionInfo(exception);
12447     SvREFCNT_dec(perl_exception);
12448   }
12449 \f
12450 #
12451 ###############################################################################
12452 #                                                                             #
12453 #                                                                             #
12454 #                                                                             #
12455 #   Q u e r y F o n t                                                         #
12456 #                                                                             #
12457 #                                                                             #
12458 #                                                                             #
12459 ###############################################################################
12460 #
12461 #
12462 void
12463 QueryFont(ref,...)
12464   Image::Magick ref=NO_INIT
12465   ALIAS:
12466     queryfont = 1
12467   PPCODE:
12468   {
12469     char
12470       *name,
12471       message[MagickPathExtent];
12472
12473     ExceptionInfo
12474       *exception;
12475
12476     register ssize_t
12477       i;
12478
12479     SV
12480       *perl_exception;
12481
12482     volatile const TypeInfo
12483       *type_info;
12484
12485     PERL_UNUSED_VAR(ref);
12486     PERL_UNUSED_VAR(ix);
12487     exception=AcquireExceptionInfo();
12488     perl_exception=newSVpv("",0);
12489     if (items == 1)
12490       {
12491         const TypeInfo
12492           **typelist;
12493
12494         size_t
12495           types;
12496
12497         typelist=GetTypeInfoList("*",&types,exception);
12498         EXTEND(sp,types);
12499         for (i=0; i < (ssize_t) types; i++)
12500         {
12501           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
12502         }
12503         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
12504           typelist);
12505         goto PerlException;
12506       }
12507     EXTEND(sp,10*items);
12508     for (i=1; i < items; i++)
12509     {
12510       name=(char *) SvPV(ST(i),na);
12511       type_info=GetTypeInfo(name,exception);
12512       if (type_info == (TypeInfo *) NULL)
12513         {
12514           PUSHs(&sv_undef);
12515           continue;
12516         }
12517       if (type_info->name == (char *) NULL)
12518         PUSHs(&sv_undef);
12519       else
12520         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
12521       if (type_info->description == (char *) NULL)
12522         PUSHs(&sv_undef);
12523       else
12524         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
12525       if (type_info->family == (char *) NULL)
12526         PUSHs(&sv_undef);
12527       else
12528         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
12529       if (type_info->style == UndefinedStyle)
12530         PUSHs(&sv_undef);
12531       else
12532         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
12533           type_info->style),0)));
12534       if (type_info->stretch == UndefinedStretch)
12535         PUSHs(&sv_undef);
12536       else
12537         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
12538           type_info->stretch),0)));
12539       (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
12540         type_info->weight);
12541       PUSHs(sv_2mortal(newSVpv(message,0)));
12542       if (type_info->encoding == (char *) NULL)
12543         PUSHs(&sv_undef);
12544       else
12545         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
12546       if (type_info->foundry == (char *) NULL)
12547         PUSHs(&sv_undef);
12548       else
12549         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
12550       if (type_info->format == (char *) NULL)
12551         PUSHs(&sv_undef);
12552       else
12553         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
12554       if (type_info->metrics == (char *) NULL)
12555         PUSHs(&sv_undef);
12556       else
12557         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
12558       if (type_info->glyphs == (char *) NULL)
12559         PUSHs(&sv_undef);
12560       else
12561         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
12562     }
12563
12564   PerlException:
12565     InheritPerlException(exception,perl_exception);
12566     exception=DestroyExceptionInfo(exception);
12567     SvREFCNT_dec(perl_exception);
12568   }
12569 \f
12570 #
12571 ###############################################################################
12572 #                                                                             #
12573 #                                                                             #
12574 #                                                                             #
12575 #   Q u e r y F o n t M e t r i c s                                           #
12576 #                                                                             #
12577 #                                                                             #
12578 #                                                                             #
12579 ###############################################################################
12580 #
12581 #
12582 void
12583 QueryFontMetrics(ref,...)
12584   Image::Magick ref=NO_INIT
12585   ALIAS:
12586     queryfontmetrics = 1
12587   PPCODE:
12588   {
12589     AffineMatrix
12590       affine,
12591       current;
12592
12593     AV
12594       *av;
12595
12596     char
12597       *attribute;
12598
12599     double
12600       x,
12601       y;
12602
12603     DrawInfo
12604       *draw_info;
12605
12606     ExceptionInfo
12607       *exception;
12608
12609     GeometryInfo
12610       geometry_info;
12611
12612     Image
12613       *image;
12614
12615     MagickBooleanType
12616       status;
12617
12618     MagickStatusType
12619       flags;
12620
12621     register ssize_t
12622       i;
12623
12624     ssize_t
12625       type;
12626
12627     struct PackageInfo
12628       *info,
12629       *package_info;
12630
12631     SV
12632       *perl_exception,
12633       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12634
12635     TypeMetric
12636       metrics;
12637
12638     PERL_UNUSED_VAR(ref);
12639     PERL_UNUSED_VAR(ix);
12640     exception=AcquireExceptionInfo();
12641     package_info=(struct PackageInfo *) NULL;
12642     perl_exception=newSVpv("",0);
12643     reference=SvRV(ST(0));
12644     av=(AV *) reference;
12645     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12646       exception);
12647     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12648     if (image == (Image *) NULL)
12649       {
12650         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12651           PackageName);
12652         goto PerlException;
12653       }
12654     package_info=ClonePackageInfo(info,exception);
12655     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12656     CloneString(&draw_info->text,"");
12657     current=draw_info->affine;
12658     GetAffineMatrix(&affine);
12659     x=0.0;
12660     y=0.0;
12661     EXTEND(sp,7*items);
12662     for (i=2; i < items; i+=2)
12663     {
12664       attribute=(char *) SvPV(ST(i-1),na);
12665       switch (*attribute)
12666       {
12667         case 'A':
12668         case 'a':
12669         {
12670           if (LocaleCompare(attribute,"antialias") == 0)
12671             {
12672               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12673                 SvPV(ST(i),na));
12674               if (type < 0)
12675                 {
12676                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12677                     SvPV(ST(i),na));
12678                   break;
12679                 }
12680               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12681               break;
12682             }
12683           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12684             attribute);
12685           break;
12686         }
12687         case 'd':
12688         case 'D':
12689         {
12690           if (LocaleCompare(attribute,"density") == 0)
12691             {
12692               CloneString(&draw_info->density,SvPV(ST(i),na));
12693               break;
12694             }
12695           if (LocaleCompare(attribute,"direction") == 0)
12696             {
12697               draw_info->direction=(DirectionType) ParseCommandOption(
12698                 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12699               break;
12700             }
12701           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12702             attribute);
12703           break;
12704         }
12705         case 'e':
12706         case 'E':
12707         {
12708           if (LocaleCompare(attribute,"encoding") == 0)
12709             {
12710               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12711               break;
12712             }
12713           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12714             attribute);
12715           break;
12716         }
12717         case 'f':
12718         case 'F':
12719         {
12720           if (LocaleCompare(attribute,"family") == 0)
12721             {
12722               CloneString(&draw_info->family,SvPV(ST(i),na));
12723               break;
12724             }
12725           if (LocaleCompare(attribute,"fill") == 0)
12726             {
12727               if (info)
12728                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12729                   &draw_info->fill,exception);
12730               break;
12731             }
12732           if (LocaleCompare(attribute,"font") == 0)
12733             {
12734               CloneString(&draw_info->font,SvPV(ST(i),na));
12735               break;
12736             }
12737           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12738             attribute);
12739           break;
12740         }
12741         case 'g':
12742         case 'G':
12743         {
12744           if (LocaleCompare(attribute,"geometry") == 0)
12745             {
12746               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12747               break;
12748             }
12749           if (LocaleCompare(attribute,"gravity") == 0)
12750             {
12751               draw_info->gravity=(GravityType) ParseCommandOption(
12752                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12753               break;
12754             }
12755           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12756             attribute);
12757           break;
12758         }
12759         case 'i':
12760         case 'I':
12761         {
12762           if (LocaleCompare(attribute,"interline-spacing") == 0)
12763             {
12764               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12765               draw_info->interline_spacing=geometry_info.rho;
12766               break;
12767             }
12768           if (LocaleCompare(attribute,"interword-spacing") == 0)
12769             {
12770               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12771               draw_info->interword_spacing=geometry_info.rho;
12772               break;
12773             }
12774           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12775             attribute);
12776           break;
12777         }
12778         case 'k':
12779         case 'K':
12780         {
12781           if (LocaleCompare(attribute,"kerning") == 0)
12782             {
12783               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12784               draw_info->kerning=geometry_info.rho;
12785               break;
12786             }
12787           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12788             attribute);
12789           break;
12790         }
12791         case 'p':
12792         case 'P':
12793         {
12794           if (LocaleCompare(attribute,"pointsize") == 0)
12795             {
12796               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12797               draw_info->pointsize=geometry_info.rho;
12798               break;
12799             }
12800           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12801             attribute);
12802           break;
12803         }
12804         case 'r':
12805         case 'R':
12806         {
12807           if (LocaleCompare(attribute,"rotate") == 0)
12808             {
12809               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12810               affine.rx=geometry_info.rho;
12811               affine.ry=geometry_info.sigma;
12812               if ((flags & SigmaValue) == 0)
12813                 affine.ry=affine.rx;
12814               break;
12815             }
12816           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12817             attribute);
12818           break;
12819         }
12820         case 's':
12821         case 'S':
12822         {
12823           if (LocaleCompare(attribute,"scale") == 0)
12824             {
12825               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12826               affine.sx=geometry_info.rho;
12827               affine.sy=geometry_info.sigma;
12828               if ((flags & SigmaValue) == 0)
12829                 affine.sy=affine.sx;
12830               break;
12831             }
12832           if (LocaleCompare(attribute,"skew") == 0)
12833             {
12834               double
12835                 x_angle,
12836                 y_angle;
12837
12838               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12839               x_angle=geometry_info.rho;
12840               y_angle=geometry_info.sigma;
12841               if ((flags & SigmaValue) == 0)
12842                 y_angle=x_angle;
12843               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12844               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12845               break;
12846             }
12847           if (LocaleCompare(attribute,"stroke") == 0)
12848             {
12849               if (info)
12850                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12851                   &draw_info->stroke,exception);
12852               break;
12853             }
12854           if (LocaleCompare(attribute,"style") == 0)
12855             {
12856               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12857                 SvPV(ST(i),na));
12858               if (type < 0)
12859                 {
12860                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12861                     SvPV(ST(i),na));
12862                   break;
12863                 }
12864               draw_info->style=(StyleType) type;
12865               break;
12866             }
12867           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12868             attribute);
12869           break;
12870         }
12871         case 't':
12872         case 'T':
12873         {
12874           if (LocaleCompare(attribute,"text") == 0)
12875             {
12876               CloneString(&draw_info->text,SvPV(ST(i),na));
12877               break;
12878             }
12879           if (LocaleCompare(attribute,"translate") == 0)
12880             {
12881               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12882               affine.tx=geometry_info.rho;
12883               affine.ty=geometry_info.sigma;
12884               if ((flags & SigmaValue) == 0)
12885                 affine.ty=affine.tx;
12886               break;
12887             }
12888           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12889             attribute);
12890           break;
12891         }
12892         case 'w':
12893         case 'W':
12894         {
12895           if (LocaleCompare(attribute,"weight") == 0)
12896             {
12897               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12898               draw_info->weight=(size_t) geometry_info.rho;
12899               break;
12900             }
12901           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12902             attribute);
12903           break;
12904         }
12905         case 'x':
12906         case 'X':
12907         {
12908           if (LocaleCompare(attribute,"x") == 0)
12909             {
12910               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12911               x=geometry_info.rho;
12912               break;
12913             }
12914           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12915             attribute);
12916           break;
12917         }
12918         case 'y':
12919         case 'Y':
12920         {
12921           if (LocaleCompare(attribute,"y") == 0)
12922             {
12923               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12924               y=geometry_info.rho;
12925               break;
12926             }
12927           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12928             attribute);
12929           break;
12930         }
12931         default:
12932         {
12933           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12934             attribute);
12935           break;
12936         }
12937       }
12938     }
12939     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12940     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12941     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12942     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12943     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12944     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12945     if (draw_info->geometry == (char *) NULL)
12946       {
12947         draw_info->geometry=AcquireString((char *) NULL);
12948         (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
12949           "%.15g,%.15g",x,y);
12950       }
12951     status=GetTypeMetrics(image,draw_info,&metrics,exception);
12952     (void) CatchImageException(image);
12953     if (status == MagickFalse)
12954       PUSHs(&sv_undef);
12955     else
12956       {
12957         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12958         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12959         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12960         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12961         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12962         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12963         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12964         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12965         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12966         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12967         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12968         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12969         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12970       }
12971     draw_info=DestroyDrawInfo(draw_info);
12972
12973   PerlException:
12974     if (package_info != (struct PackageInfo *) NULL)
12975       DestroyPackageInfo(package_info);
12976     InheritPerlException(exception,perl_exception);
12977     exception=DestroyExceptionInfo(exception);
12978     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12979   }
12980 \f
12981 #
12982 ###############################################################################
12983 #                                                                             #
12984 #                                                                             #
12985 #                                                                             #
12986 #   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                         #
12987 #                                                                             #
12988 #                                                                             #
12989 #                                                                             #
12990 ###############################################################################
12991 #
12992 #
12993 void
12994 QueryMultilineFontMetrics(ref,...)
12995   Image::Magick ref=NO_INIT
12996   ALIAS:
12997     querymultilinefontmetrics = 1
12998   PPCODE:
12999   {
13000     AffineMatrix
13001       affine,
13002       current;
13003
13004     AV
13005       *av;
13006
13007     char
13008       *attribute;
13009
13010     double
13011       x,
13012       y;
13013
13014     DrawInfo
13015       *draw_info;
13016
13017     ExceptionInfo
13018       *exception;
13019
13020     GeometryInfo
13021       geometry_info;
13022
13023     Image
13024       *image;
13025
13026     MagickBooleanType
13027       status;
13028
13029     MagickStatusType
13030       flags;
13031
13032     register ssize_t
13033       i;
13034
13035     ssize_t
13036       type;
13037
13038     struct PackageInfo
13039       *info,
13040       *package_info;
13041
13042     SV
13043       *perl_exception,
13044       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13045
13046     TypeMetric
13047       metrics;
13048
13049     PERL_UNUSED_VAR(ref);
13050     PERL_UNUSED_VAR(ix);
13051     exception=AcquireExceptionInfo();
13052     package_info=(struct PackageInfo *) NULL;
13053     perl_exception=newSVpv("",0);
13054     reference=SvRV(ST(0));
13055     av=(AV *) reference;
13056     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13057       exception);
13058     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13059     if (image == (Image *) NULL)
13060       {
13061         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13062           PackageName);
13063         goto PerlException;
13064       }
13065     package_info=ClonePackageInfo(info,exception);
13066     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
13067     CloneString(&draw_info->text,"");
13068     current=draw_info->affine;
13069     GetAffineMatrix(&affine);
13070     x=0.0;
13071     y=0.0;
13072     EXTEND(sp,7*items);
13073     for (i=2; i < items; i+=2)
13074     {
13075       attribute=(char *) SvPV(ST(i-1),na);
13076       switch (*attribute)
13077       {
13078         case 'A':
13079         case 'a':
13080         {
13081           if (LocaleCompare(attribute,"antialias") == 0)
13082             {
13083               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13084                 SvPV(ST(i),na));
13085               if (type < 0)
13086                 {
13087                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13088                     SvPV(ST(i),na));
13089                   break;
13090                 }
13091               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
13092               break;
13093             }
13094           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13095             attribute);
13096           break;
13097         }
13098         case 'd':
13099         case 'D':
13100         {
13101           if (LocaleCompare(attribute,"density") == 0)
13102             {
13103               CloneString(&draw_info->density,SvPV(ST(i),na));
13104               break;
13105             }
13106           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13107             attribute);
13108           break;
13109         }
13110         case 'e':
13111         case 'E':
13112         {
13113           if (LocaleCompare(attribute,"encoding") == 0)
13114             {
13115               CloneString(&draw_info->encoding,SvPV(ST(i),na));
13116               break;
13117             }
13118           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13119             attribute);
13120           break;
13121         }
13122         case 'f':
13123         case 'F':
13124         {
13125           if (LocaleCompare(attribute,"family") == 0)
13126             {
13127               CloneString(&draw_info->family,SvPV(ST(i),na));
13128               break;
13129             }
13130           if (LocaleCompare(attribute,"fill") == 0)
13131             {
13132               if (info)
13133                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13134                   &draw_info->fill,exception);
13135               break;
13136             }
13137           if (LocaleCompare(attribute,"font") == 0)
13138             {
13139               CloneString(&draw_info->font,SvPV(ST(i),na));
13140               break;
13141             }
13142           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13143             attribute);
13144           break;
13145         }
13146         case 'g':
13147         case 'G':
13148         {
13149           if (LocaleCompare(attribute,"geometry") == 0)
13150             {
13151               CloneString(&draw_info->geometry,SvPV(ST(i),na));
13152               break;
13153             }
13154           if (LocaleCompare(attribute,"gravity") == 0)
13155             {
13156               draw_info->gravity=(GravityType) ParseCommandOption(
13157                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13158               break;
13159             }
13160           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13161             attribute);
13162           break;
13163         }
13164         case 'p':
13165         case 'P':
13166         {
13167           if (LocaleCompare(attribute,"pointsize") == 0)
13168             {
13169               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13170               draw_info->pointsize=geometry_info.rho;
13171               break;
13172             }
13173           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13174             attribute);
13175           break;
13176         }
13177         case 'r':
13178         case 'R':
13179         {
13180           if (LocaleCompare(attribute,"rotate") == 0)
13181             {
13182               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13183               affine.rx=geometry_info.rho;
13184               affine.ry=geometry_info.sigma;
13185               if ((flags & SigmaValue) == 0)
13186                 affine.ry=affine.rx;
13187               break;
13188             }
13189           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13190             attribute);
13191           break;
13192         }
13193         case 's':
13194         case 'S':
13195         {
13196           if (LocaleCompare(attribute,"scale") == 0)
13197             {
13198               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13199               affine.sx=geometry_info.rho;
13200               affine.sy=geometry_info.sigma;
13201               if ((flags & SigmaValue) == 0)
13202                 affine.sy=affine.sx;
13203               break;
13204             }
13205           if (LocaleCompare(attribute,"skew") == 0)
13206             {
13207               double
13208                 x_angle,
13209                 y_angle;
13210
13211               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13212               x_angle=geometry_info.rho;
13213               y_angle=geometry_info.sigma;
13214               if ((flags & SigmaValue) == 0)
13215                 y_angle=x_angle;
13216               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
13217               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
13218               break;
13219             }
13220           if (LocaleCompare(attribute,"stroke") == 0)
13221             {
13222               if (info)
13223                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13224                   &draw_info->stroke,exception);
13225               break;
13226             }
13227           if (LocaleCompare(attribute,"style") == 0)
13228             {
13229               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
13230                 SvPV(ST(i),na));
13231               if (type < 0)
13232                 {
13233                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13234                     SvPV(ST(i),na));
13235                   break;
13236                 }
13237               draw_info->style=(StyleType) type;
13238               break;
13239             }
13240           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13241             attribute);
13242           break;
13243         }
13244         case 't':
13245         case 'T':
13246         {
13247           if (LocaleCompare(attribute,"text") == 0)
13248             {
13249               CloneString(&draw_info->text,SvPV(ST(i),na));
13250               break;
13251             }
13252           if (LocaleCompare(attribute,"translate") == 0)
13253             {
13254               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13255               affine.tx=geometry_info.rho;
13256               affine.ty=geometry_info.sigma;
13257               if ((flags & SigmaValue) == 0)
13258                 affine.ty=affine.tx;
13259               break;
13260             }
13261           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13262             attribute);
13263           break;
13264         }
13265         case 'w':
13266         case 'W':
13267         {
13268           if (LocaleCompare(attribute,"weight") == 0)
13269             {
13270               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13271               draw_info->weight=(size_t) geometry_info.rho;
13272               break;
13273             }
13274           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13275             attribute);
13276           break;
13277         }
13278         case 'x':
13279         case 'X':
13280         {
13281           if (LocaleCompare(attribute,"x") == 0)
13282             {
13283               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13284               x=geometry_info.rho;
13285               break;
13286             }
13287           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13288             attribute);
13289           break;
13290         }
13291         case 'y':
13292         case 'Y':
13293         {
13294           if (LocaleCompare(attribute,"y") == 0)
13295             {
13296               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13297               y=geometry_info.rho;
13298               break;
13299             }
13300           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13301             attribute);
13302           break;
13303         }
13304         default:
13305         {
13306           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13307             attribute);
13308           break;
13309         }
13310       }
13311     }
13312     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
13313     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
13314     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
13315     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
13316     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
13317     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
13318     if (draw_info->geometry == (char *) NULL)
13319       {
13320         draw_info->geometry=AcquireString((char *) NULL);
13321         (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
13322           "%.15g,%.15g",x,y);
13323       }
13324     status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
13325     (void) CatchException(exception);
13326     if (status == MagickFalse)
13327       PUSHs(&sv_undef);
13328     else
13329       {
13330         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
13331         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
13332         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
13333         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13334         PUSHs(sv_2mortal(newSVnv(metrics.width)));
13335         PUSHs(sv_2mortal(newSVnv(metrics.height)));
13336         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13337         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13338         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13339         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13340         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13341         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13342         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13343       }
13344     draw_info=DestroyDrawInfo(draw_info);
13345
13346   PerlException:
13347     if (package_info != (struct PackageInfo *) NULL)
13348       DestroyPackageInfo(package_info);
13349     InheritPerlException(exception,perl_exception);
13350     exception=DestroyExceptionInfo(exception);
13351     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13352   }
13353 \f
13354 #
13355 ###############################################################################
13356 #                                                                             #
13357 #                                                                             #
13358 #                                                                             #
13359 #   Q u e r y F o r m a t                                                     #
13360 #                                                                             #
13361 #                                                                             #
13362 #                                                                             #
13363 ###############################################################################
13364 #
13365 #
13366 void
13367 QueryFormat(ref,...)
13368   Image::Magick ref=NO_INIT
13369   ALIAS:
13370     queryformat = 1
13371   PPCODE:
13372   {
13373     char
13374       *name;
13375
13376     ExceptionInfo
13377       *exception;
13378
13379     register ssize_t
13380       i;
13381
13382     SV
13383       *perl_exception;
13384
13385     volatile const MagickInfo
13386       *magick_info;
13387
13388     PERL_UNUSED_VAR(ref);
13389     PERL_UNUSED_VAR(ix);
13390     exception=AcquireExceptionInfo();
13391     perl_exception=newSVpv("",0);
13392     if (items == 1)
13393       {
13394         char
13395           format[MagickPathExtent];
13396
13397         const MagickInfo
13398           **format_list;
13399
13400         size_t
13401           types;
13402
13403         format_list=GetMagickInfoList("*",&types,exception);
13404         EXTEND(sp,types);
13405         for (i=0; i < (ssize_t) types; i++)
13406         {
13407           (void) CopyMagickString(format,format_list[i]->name,MagickPathExtent);
13408           LocaleLower(format);
13409           PUSHs(sv_2mortal(newSVpv(format,0)));
13410         }
13411         format_list=(const MagickInfo **)
13412           RelinquishMagickMemory((MagickInfo *) format_list);
13413         goto PerlException;
13414       }
13415     EXTEND(sp,8*items);
13416     for (i=1; i < items; i++)
13417     {
13418       name=(char *) SvPV(ST(i),na);
13419       magick_info=GetMagickInfo(name,exception);
13420       if (magick_info == (const MagickInfo *) NULL)
13421         {
13422           PUSHs(&sv_undef);
13423           continue;
13424         }
13425       if (magick_info->description == (char *) NULL)
13426         PUSHs(&sv_undef);
13427       else
13428         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
13429       if (magick_info->module == (char *) NULL)
13430         PUSHs(&sv_undef);
13431       else
13432         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
13433     }
13434
13435   PerlException:
13436     InheritPerlException(exception,perl_exception);
13437     exception=DestroyExceptionInfo(exception);
13438     SvREFCNT_dec(perl_exception);
13439   }
13440 \f
13441 #
13442 ###############################################################################
13443 #                                                                             #
13444 #                                                                             #
13445 #                                                                             #
13446 #   Q u e r y O p t i o n                                                     #
13447 #                                                                             #
13448 #                                                                             #
13449 #                                                                             #
13450 ###############################################################################
13451 #
13452 #
13453 void
13454 QueryOption(ref,...)
13455   Image::Magick ref=NO_INIT
13456   ALIAS:
13457     queryoption = 1
13458   PPCODE:
13459   {
13460     char
13461       **options;
13462
13463     ExceptionInfo
13464       *exception;
13465
13466     register ssize_t
13467       i;
13468
13469     ssize_t
13470       j,
13471       option;
13472
13473     SV
13474       *perl_exception;
13475
13476     PERL_UNUSED_VAR(ref);
13477     PERL_UNUSED_VAR(ix);
13478     exception=AcquireExceptionInfo();
13479     perl_exception=newSVpv("",0);
13480     EXTEND(sp,8*items);
13481     for (i=1; i < items; i++)
13482     {
13483       option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
13484         SvPV(ST(i),na));
13485       options=GetCommandOptions((CommandOption) option);
13486       if (options == (char **) NULL)
13487         PUSHs(&sv_undef);
13488       else
13489         {
13490           for (j=0; options[j] != (char *) NULL; j++)
13491             PUSHs(sv_2mortal(newSVpv(options[j],0)));
13492           options=DestroyStringList(options);
13493         }
13494     }
13495
13496     InheritPerlException(exception,perl_exception);
13497     exception=DestroyExceptionInfo(exception);
13498     SvREFCNT_dec(perl_exception);
13499   }
13500 \f
13501 #
13502 ###############################################################################
13503 #                                                                             #
13504 #                                                                             #
13505 #                                                                             #
13506 #   R e a d                                                                   #
13507 #                                                                             #
13508 #                                                                             #
13509 #                                                                             #
13510 ###############################################################################
13511 #
13512 #
13513 void
13514 Read(ref,...)
13515   Image::Magick ref=NO_INIT
13516   ALIAS:
13517     ReadImage  = 1
13518     read       = 2
13519     readimage  = 3
13520   PPCODE:
13521   {
13522     AV
13523       *av;
13524
13525     char
13526       **keep,
13527       **list;
13528
13529     ExceptionInfo
13530       *exception;
13531
13532     HV
13533       *hv;
13534
13535     Image
13536       *image;
13537
13538     int
13539       n;
13540
13541     MagickBooleanType
13542       status;
13543
13544     register char
13545       **p;
13546
13547     register ssize_t
13548       i;
13549
13550     ssize_t
13551       ac,
13552       number_images;
13553
13554     STRLEN
13555       *length;
13556
13557     struct PackageInfo
13558       *info,
13559       *package_info;
13560
13561     SV
13562       *perl_exception,  /* Perl variable for storing messages */
13563       *reference,
13564       *rv,
13565       *sv;
13566
13567     PERL_UNUSED_VAR(ref);
13568     PERL_UNUSED_VAR(ix);
13569     exception=AcquireExceptionInfo();
13570     perl_exception=newSVpv("",0);
13571     sv=NULL;
13572     package_info=(struct PackageInfo *) NULL;
13573     number_images=0;
13574     ac=(items < 2) ? 1 : items-1;
13575     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
13576     keep=list;
13577     length=(STRLEN *) NULL;
13578     if (list == (char **) NULL)
13579       {
13580         ThrowPerlException(exception,ResourceLimitError,
13581           "MemoryAllocationFailed",PackageName);
13582         goto PerlException;
13583       }
13584     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
13585     if (length == (STRLEN *) NULL)
13586       {
13587         ThrowPerlException(exception,ResourceLimitError,
13588           "MemoryAllocationFailed",PackageName);
13589         goto PerlException;
13590       }
13591     if (sv_isobject(ST(0)) == 0)
13592       {
13593         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13594           PackageName);
13595         goto PerlException;
13596       }
13597     reference=SvRV(ST(0));
13598     hv=SvSTASH(reference);
13599     if (SvTYPE(reference) != SVt_PVAV)
13600       {
13601         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13602           PackageName);
13603         goto PerlException;
13604       }
13605     av=(AV *) reference;
13606     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13607       exception);
13608     package_info=ClonePackageInfo(info,exception);
13609     n=1;
13610     if (items <= 1)
13611       *list=(char *) (*package_info->image_info->filename ?
13612         package_info->image_info->filename : "XC:black");
13613     else
13614       for (n=0, i=0; i < ac; i++)
13615       {
13616         list[n]=(char *) SvPV(ST(i+1),length[n]);
13617         if ((items >= 3) && strEQcase(list[n],"blob"))
13618           {
13619             void
13620               *blob;
13621
13622             i++;
13623             blob=(void *) (SvPV(ST(i+1),length[n]));
13624             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13625           }
13626         if ((items >= 3) && strEQcase(list[n],"filename"))
13627           continue;
13628         if ((items >= 3) && strEQcase(list[n],"file"))
13629           {
13630             FILE
13631               *file;
13632
13633             PerlIO
13634               *io_info;
13635
13636             i++;
13637             io_info=IoIFP(sv_2io(ST(i+1)));
13638             if (io_info == (PerlIO *) NULL)
13639               {
13640                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13641                   PackageName);
13642                 continue;
13643               }
13644             file=PerlIO_findFILE(io_info);
13645             if (file == (FILE *) NULL)
13646               {
13647                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13648                   PackageName);
13649                 continue;
13650               }
13651             SetImageInfoFile(package_info->image_info,file);
13652           }
13653         if ((items >= 3) && strEQcase(list[n],"magick"))
13654           continue;
13655         n++;
13656       }
13657     list[n]=(char *) NULL;
13658     keep=list;
13659     status=ExpandFilenames(&n,&list);
13660     if (status == MagickFalse)
13661       {
13662         ThrowPerlException(exception,ResourceLimitError,
13663           "MemoryAllocationFailed",PackageName);
13664         goto PerlException;
13665       }
13666     number_images=0;
13667     for (i=0; i < n; i++)
13668     {
13669       if ((package_info->image_info->file == (FILE *) NULL) &&
13670           (package_info->image_info->blob == (void *) NULL))
13671         image=ReadImages(package_info->image_info,list[i],exception);
13672       else
13673         {
13674           image=ReadImages(package_info->image_info,
13675             package_info->image_info->filename,exception);
13676           if (image != (Image *) NULL)
13677             DisassociateImageStream(image);
13678         }
13679       if (image == (Image *) NULL)
13680         break;
13681       for ( ; image; image=image->next)
13682       {
13683         AddImageToRegistry(sv,image);
13684         rv=newRV(sv);
13685         av_push(av,sv_bless(rv,hv));
13686         SvREFCNT_dec(sv);
13687         number_images++;
13688       }
13689     }
13690     /*
13691       Free resources.
13692     */
13693     for (i=0; i < n; i++)
13694       if (list[i] != (char *) NULL)
13695         for (p=keep; list[i] != *p++; )
13696           if (*p == (char *) NULL)
13697             {
13698               list[i]=(char *) RelinquishMagickMemory(list[i]);
13699               break;
13700             }
13701
13702   PerlException:
13703     if (package_info != (struct PackageInfo *) NULL)
13704       DestroyPackageInfo(package_info);
13705     if (list && (list != keep))
13706       list=(char **) RelinquishMagickMemory(list);
13707     if (keep)
13708       keep=(char **) RelinquishMagickMemory(keep);
13709     if (length)
13710       length=(STRLEN *) RelinquishMagickMemory(length);
13711     InheritPerlException(exception,perl_exception);
13712     exception=DestroyExceptionInfo(exception);
13713     sv_setiv(perl_exception,(IV) number_images);
13714     SvPOK_on(perl_exception);
13715     ST(0)=sv_2mortal(perl_exception);
13716     XSRETURN(1);
13717   }
13718 \f
13719 #
13720 ###############################################################################
13721 #                                                                             #
13722 #                                                                             #
13723 #                                                                             #
13724 #   R e m o t e                                                               #
13725 #                                                                             #
13726 #                                                                             #
13727 #                                                                             #
13728 ###############################################################################
13729 #
13730 #
13731 void
13732 Remote(ref,...)
13733   Image::Magick ref=NO_INIT
13734   ALIAS:
13735     RemoteCommand  = 1
13736     remote         = 2
13737     remoteCommand  = 3
13738   PPCODE:
13739   {
13740     AV
13741       *av;
13742
13743     ExceptionInfo
13744       *exception;
13745
13746     register ssize_t
13747       i;
13748
13749     SV
13750       *perl_exception,
13751       *reference;
13752
13753     struct PackageInfo
13754       *info;
13755
13756     PERL_UNUSED_VAR(ref);
13757     PERL_UNUSED_VAR(ix);
13758     exception=AcquireExceptionInfo();
13759     perl_exception=newSVpv("",0);
13760     reference=SvRV(ST(0));
13761     av=(AV *) reference;
13762     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13763       exception);
13764     for (i=1; i < items; i++)
13765       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13766         SvPV(ST(i),na),exception);
13767     InheritPerlException(exception,perl_exception);
13768     exception=DestroyExceptionInfo(exception);
13769     SvREFCNT_dec(perl_exception);    /* throw away all errors */
13770   }
13771 \f
13772 #
13773 ###############################################################################
13774 #                                                                             #
13775 #                                                                             #
13776 #                                                                             #
13777 #   S e t                                                                     #
13778 #                                                                             #
13779 #                                                                             #
13780 #                                                                             #
13781 ###############################################################################
13782 #
13783 #
13784 void
13785 Set(ref,...)
13786   Image::Magick ref=NO_INIT
13787   ALIAS:
13788     SetAttributes  = 1
13789     SetAttribute   = 2
13790     set            = 3
13791     setattributes  = 4
13792     setattribute   = 5
13793   PPCODE:
13794   {
13795     ExceptionInfo
13796       *exception;
13797
13798     Image
13799       *image;
13800
13801     register ssize_t
13802       i;
13803
13804     struct PackageInfo
13805       *info;
13806
13807     SV
13808       *perl_exception,
13809       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13810
13811     PERL_UNUSED_VAR(ref);
13812     PERL_UNUSED_VAR(ix);
13813     exception=AcquireExceptionInfo();
13814     perl_exception=newSVpv("",0);
13815     if (sv_isobject(ST(0)) == 0)
13816       {
13817         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13818           PackageName);
13819         goto PerlException;
13820       }
13821     reference=SvRV(ST(0));
13822     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13823     if (items == 2)
13824       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13825     else
13826       for (i=2; i < items; i+=2)
13827         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13828
13829   PerlException:
13830     InheritPerlException(exception,perl_exception);
13831     exception=DestroyExceptionInfo(exception);
13832     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13833     SvPOK_on(perl_exception);
13834     ST(0)=sv_2mortal(perl_exception);
13835     XSRETURN(1);
13836   }
13837 \f
13838 #
13839 ###############################################################################
13840 #                                                                             #
13841 #                                                                             #
13842 #                                                                             #
13843 #   S e t P i x e l                                                           #
13844 #                                                                             #
13845 #                                                                             #
13846 #                                                                             #
13847 ###############################################################################
13848 #
13849 #
13850 void
13851 SetPixel(ref,...)
13852   Image::Magick ref=NO_INIT
13853   ALIAS:
13854     setpixel = 1
13855     setPixel = 2
13856   PPCODE:
13857   {
13858     AV
13859       *av;
13860
13861     char
13862       *attribute;
13863
13864     ChannelType
13865       channel,
13866       channel_mask;
13867
13868     ExceptionInfo
13869       *exception;
13870
13871     Image
13872       *image;
13873
13874     MagickBooleanType
13875       normalize;
13876
13877     RectangleInfo
13878       region;
13879
13880     register ssize_t
13881       i;
13882
13883     register Quantum
13884       *q;
13885
13886     ssize_t
13887       option;
13888
13889     struct PackageInfo
13890       *info;
13891
13892     SV
13893       *perl_exception,
13894       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13895
13896     PERL_UNUSED_VAR(ref);
13897     PERL_UNUSED_VAR(ix);
13898     exception=AcquireExceptionInfo();
13899     perl_exception=newSVpv("",0);
13900     reference=SvRV(ST(0));
13901     av=(AV *) reference;
13902     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13903       exception);
13904     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13905     if (image == (Image *) NULL)
13906       {
13907         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13908           PackageName);
13909         goto PerlException;
13910       }
13911     av=(AV *) NULL;
13912     normalize=MagickTrue;
13913     region.x=0;
13914     region.y=0;
13915     region.width=image->columns;
13916     region.height=1;
13917     if (items == 1)
13918       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13919     channel=DefaultChannels;
13920     for (i=2; i < items; i+=2)
13921     {
13922       attribute=(char *) SvPV(ST(i-1),na);
13923       switch (*attribute)
13924       {
13925         case 'C':
13926         case 'c':
13927         {
13928           if (LocaleCompare(attribute,"channel") == 0)
13929             {
13930               ssize_t
13931                 option;
13932
13933               option=ParseChannelOption(SvPV(ST(i),na));
13934               if (option < 0)
13935                 {
13936                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13937                     SvPV(ST(i),na));
13938                   return;
13939                 }
13940               channel=(ChannelType) option;
13941               break;
13942             }
13943           if (LocaleCompare(attribute,"color") == 0)
13944             {
13945               if (SvTYPE(ST(i)) != SVt_RV)
13946                 {
13947                   char
13948                     message[MagickPathExtent];
13949
13950                   (void) FormatLocaleString(message,MagickPathExtent,
13951                     "invalid %.60s value",attribute);
13952                   ThrowPerlException(exception,OptionError,message,
13953                     SvPV(ST(i),na));
13954                 }
13955               av=(AV *) SvRV(ST(i));
13956               break;
13957             }
13958           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13959             attribute);
13960           break;
13961         }
13962         case 'g':
13963         case 'G':
13964         {
13965           if (LocaleCompare(attribute,"geometry") == 0)
13966             {
13967               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
13968               break;
13969             }
13970           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13971             attribute);
13972           break;
13973         }
13974         case 'N':
13975         case 'n':
13976         {
13977           if (LocaleCompare(attribute,"normalize") == 0)
13978             {
13979               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13980                 SvPV(ST(i),na));
13981               if (option < 0)
13982                 {
13983                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13984                     SvPV(ST(i),na));
13985                   break;
13986                 }
13987              normalize=option != 0 ? MagickTrue : MagickFalse;
13988              break;
13989             }
13990           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13991             attribute);
13992           break;
13993         }
13994         case 'x':
13995         case 'X':
13996         {
13997           if (LocaleCompare(attribute,"x") == 0)
13998             {
13999               region.x=SvIV(ST(i));
14000               break;
14001             }
14002           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14003             attribute);
14004           break;
14005         }
14006         case 'y':
14007         case 'Y':
14008         {
14009           if (LocaleCompare(attribute,"y") == 0)
14010             {
14011               region.y=SvIV(ST(i));
14012               break;
14013             }
14014           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14015             attribute);
14016           break;
14017         }
14018         default:
14019         {
14020           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14021             attribute);
14022           break;
14023         }
14024       }
14025     }
14026     (void) SetImageStorageClass(image,DirectClass,exception);
14027     channel_mask=SetImageChannelMask(image,channel);
14028     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
14029     if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
14030         (SvTYPE(av) != SVt_PVAV))
14031       PUSHs(&sv_undef);
14032     else
14033       {
14034         double
14035           scale;
14036
14037         register ssize_t
14038           i;
14039
14040         i=0;
14041         scale=1.0;
14042         if (normalize != MagickFalse)
14043           scale=QuantumRange;
14044         if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
14045             (i <= av_len(av)))
14046           {
14047             SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
14048               av_fetch(av,i,0)))),q);
14049             i++;
14050           }
14051         if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
14052             (i <= av_len(av)))
14053           {
14054             SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
14055               av_fetch(av,i,0)))),q);
14056             i++;
14057           }
14058         if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
14059             (i <= av_len(av)))
14060           {
14061             SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
14062               av_fetch(av,i,0)))),q);
14063             i++;
14064           }
14065         if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
14066             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
14067           {
14068             SetPixelBlack(image,ClampToQuantum(scale*
14069               SvNV(*(av_fetch(av,i,0)))),q);
14070             i++;
14071           }
14072         if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
14073             (i <= av_len(av)))
14074           {
14075             SetPixelAlpha(image,ClampToQuantum(scale*
14076               SvNV(*(av_fetch(av,i,0)))),q);
14077             i++;
14078           }
14079         (void) SyncAuthenticPixels(image,exception);
14080       }
14081     (void) SetImageChannelMask(image,channel_mask);
14082
14083   PerlException:
14084     InheritPerlException(exception,perl_exception);
14085     exception=DestroyExceptionInfo(exception);
14086     SvREFCNT_dec(perl_exception);
14087   }
14088 \f
14089 #
14090 ###############################################################################
14091 #                                                                             #
14092 #                                                                             #
14093 #                                                                             #
14094 #   S m u s h                                                                 #
14095 #                                                                             #
14096 #                                                                             #
14097 #                                                                             #
14098 ###############################################################################
14099 #
14100 #
14101 void
14102 Smush(ref,...)
14103   Image::Magick ref=NO_INIT
14104   ALIAS:
14105     SmushImage  = 1
14106     smush       = 2
14107     smushimage  = 3
14108   PPCODE:
14109   {
14110     AV
14111       *av;
14112
14113     char
14114       *attribute;
14115
14116     ExceptionInfo
14117       *exception;
14118
14119     HV
14120       *hv;
14121
14122     Image
14123       *image;
14124
14125     register ssize_t
14126       i;
14127
14128     ssize_t
14129       offset,
14130       stack;
14131
14132     struct PackageInfo
14133       *info;
14134
14135     SV
14136       *av_reference,
14137       *perl_exception,
14138       *reference,
14139       *rv,
14140       *sv;
14141
14142     PERL_UNUSED_VAR(ref);
14143     PERL_UNUSED_VAR(ix);
14144     exception=AcquireExceptionInfo();
14145     perl_exception=newSVpv("",0);
14146     sv=NULL;
14147     attribute=NULL;
14148     av=NULL;
14149     if (sv_isobject(ST(0)) == 0)
14150       {
14151         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14152           PackageName);
14153         goto PerlException;
14154       }
14155     reference=SvRV(ST(0));
14156     hv=SvSTASH(reference);
14157     av=newAV();
14158     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14159     SvREFCNT_dec(av);
14160     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14161     if (image == (Image *) NULL)
14162       {
14163         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14164           PackageName);
14165         goto PerlException;
14166       }
14167     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14168     /*
14169       Get options.
14170     */
14171     offset=0;
14172     stack=MagickTrue;
14173     for (i=2; i < items; i+=2)
14174     {
14175       attribute=(char *) SvPV(ST(i-1),na);
14176       switch (*attribute)
14177       {
14178         case 'O':
14179         case 'o':
14180         {
14181           if (LocaleCompare(attribute,"offset") == 0)
14182             {
14183               offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
14184               break;
14185             }
14186           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14187             attribute);
14188           break;
14189         }
14190         case 'S':
14191         case 's':
14192         {
14193           if (LocaleCompare(attribute,"stack") == 0)
14194             {
14195               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14196                 SvPV(ST(i),na));
14197               if (stack < 0)
14198                 {
14199                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
14200                     SvPV(ST(i),na));
14201                   return;
14202                 }
14203               break;
14204             }
14205           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14206             attribute);
14207           break;
14208         }
14209         default:
14210         {
14211           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14212             attribute);
14213           break;
14214         }
14215       }
14216     }
14217     image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
14218       exception);
14219     if (image == (Image *) NULL)
14220       goto PerlException;
14221     for ( ; image; image=image->next)
14222     {
14223       AddImageToRegistry(sv,image);
14224       rv=newRV(sv);
14225       av_push(av,sv_bless(rv,hv));
14226       SvREFCNT_dec(sv);
14227     }
14228     exception=DestroyExceptionInfo(exception);
14229     ST(0)=av_reference;
14230     SvREFCNT_dec(perl_exception);
14231     XSRETURN(1);
14232
14233   PerlException:
14234     InheritPerlException(exception,perl_exception);
14235     exception=DestroyExceptionInfo(exception);
14236     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14237     SvPOK_on(perl_exception);
14238     ST(0)=sv_2mortal(perl_exception);
14239     XSRETURN(1);
14240   }
14241 \f
14242 #
14243 ###############################################################################
14244 #                                                                             #
14245 #                                                                             #
14246 #                                                                             #
14247 #   S t a t i s t i c s                                                       #
14248 #                                                                             #
14249 #                                                                             #
14250 #                                                                             #
14251 ###############################################################################
14252 #
14253 #
14254 void
14255 Statistics(ref,...)
14256   Image::Magick ref=NO_INIT
14257   ALIAS:
14258     StatisticsImage = 1
14259     statistics      = 2
14260     statisticsimage = 3
14261   PPCODE:
14262   {
14263 #define ChannelStatistics(channel) \
14264 { \
14265   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14266     (double) channel_statistics[channel].depth); \
14267   PUSHs(sv_2mortal(newSVpv(message,0))); \
14268   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14269     channel_statistics[channel].minima/scale); \
14270   PUSHs(sv_2mortal(newSVpv(message,0))); \
14271   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14272     channel_statistics[channel].maxima/scale); \
14273   PUSHs(sv_2mortal(newSVpv(message,0))); \
14274   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14275     channel_statistics[channel].mean/scale); \
14276   PUSHs(sv_2mortal(newSVpv(message,0))); \
14277   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14278     channel_statistics[channel].standard_deviation/scale); \
14279   PUSHs(sv_2mortal(newSVpv(message,0))); \
14280   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14281     channel_statistics[channel].kurtosis); \
14282   PUSHs(sv_2mortal(newSVpv(message,0))); \
14283   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14284     channel_statistics[channel].skewness); \
14285   PUSHs(sv_2mortal(newSVpv(message,0))); \
14286   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14287     channel_statistics[channel].entropy); \
14288   PUSHs(sv_2mortal(newSVpv(message,0))); \
14289 }
14290
14291     AV
14292       *av;
14293
14294     char
14295       message[MagickPathExtent];
14296
14297     ChannelStatistics
14298       *channel_statistics;
14299
14300     double
14301       scale;
14302
14303     ExceptionInfo
14304       *exception;
14305
14306     Image
14307       *image;
14308
14309     ssize_t
14310       count;
14311
14312     struct PackageInfo
14313       *info;
14314
14315     SV
14316       *perl_exception,
14317       *reference;
14318
14319     PERL_UNUSED_VAR(ref);
14320     PERL_UNUSED_VAR(ix);
14321     exception=AcquireExceptionInfo();
14322     perl_exception=newSVpv("",0);
14323     av=NULL;
14324     if (sv_isobject(ST(0)) == 0)
14325       {
14326         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14327           PackageName);
14328         goto PerlException;
14329       }
14330     reference=SvRV(ST(0));
14331     av=newAV();
14332     SvREFCNT_dec(av);
14333     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14334     if (image == (Image *) NULL)
14335       {
14336         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14337           PackageName);
14338         goto PerlException;
14339       }
14340     count=0;
14341     for ( ; image; image=image->next)
14342     {
14343       channel_statistics=GetImageStatistics(image,exception);
14344       if (channel_statistics == (ChannelStatistics *) NULL)
14345         continue;
14346       count++;
14347       EXTEND(sp,35*count);
14348       scale=(double) QuantumRange;
14349       ChannelStatistics(RedChannel);
14350       ChannelStatistics(GreenChannel);
14351       ChannelStatistics(BlueChannel);
14352       if (image->colorspace == CMYKColorspace)
14353         ChannelStatistics(BlackChannel);
14354       if (image->alpha_trait != UndefinedPixelTrait)
14355         ChannelStatistics(AlphaChannel);
14356       channel_statistics=(ChannelStatistics *)
14357         RelinquishMagickMemory(channel_statistics);
14358     }
14359
14360   PerlException:
14361     InheritPerlException(exception,perl_exception);
14362     exception=DestroyExceptionInfo(exception);
14363     SvREFCNT_dec(perl_exception);
14364   }
14365 \f
14366 #
14367 ###############################################################################
14368 #                                                                             #
14369 #                                                                             #
14370 #                                                                             #
14371 #   S y n c A u t h e n t i c P i x e l s                                     #
14372 #                                                                             #
14373 #                                                                             #
14374 #                                                                             #
14375 ###############################################################################
14376 #
14377 #
14378 void
14379 SyncAuthenticPixels(ref,...)
14380   Image::Magick ref = NO_INIT
14381   ALIAS:
14382     Syncauthenticpixels = 1
14383     SyncImagePixels = 2
14384     syncimagepixels = 3
14385   CODE:
14386   {
14387     ExceptionInfo
14388       *exception;
14389
14390     Image
14391       *image;
14392
14393     MagickBooleanType
14394       status;
14395
14396     struct PackageInfo
14397       *info;
14398
14399     SV
14400       *perl_exception,
14401       *reference;
14402
14403     PERL_UNUSED_VAR(ref);
14404     PERL_UNUSED_VAR(ix);
14405     exception=AcquireExceptionInfo();
14406     perl_exception=newSVpv("",0);
14407     if (sv_isobject(ST(0)) == 0)
14408       {
14409         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14410           PackageName);
14411         goto PerlException;
14412       }
14413
14414     reference=SvRV(ST(0));
14415     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14416     if (image == (Image *) NULL)
14417       {
14418         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14419           PackageName);
14420         goto PerlException;
14421       }
14422
14423     status=SyncAuthenticPixels(image,exception);
14424     if (status != MagickFalse)
14425       return;
14426
14427   PerlException:
14428     InheritPerlException(exception,perl_exception);
14429     exception=DestroyExceptionInfo(exception);
14430     SvREFCNT_dec(perl_exception);  /* throw away all errors */
14431   }
14432 \f
14433 #
14434 ###############################################################################
14435 #                                                                             #
14436 #                                                                             #
14437 #                                                                             #
14438 #   T r a n s f o r m                                                         #
14439 #                                                                             #
14440 #                                                                             #
14441 #                                                                             #
14442 ###############################################################################
14443 #
14444 #
14445 void
14446 Transform(ref,...)
14447   Image::Magick ref=NO_INIT
14448   ALIAS:
14449     TransformImage = 1
14450     transform      = 2
14451     transformimage = 3
14452   PPCODE:
14453   {
14454     AV
14455       *av;
14456
14457     char
14458       *attribute,
14459       *crop_geometry,
14460       *geometry;
14461
14462     ExceptionInfo
14463       *exception;
14464
14465     HV
14466       *hv;
14467
14468     Image
14469       *clone,
14470       *image;
14471
14472     register ssize_t
14473       i;
14474
14475     struct PackageInfo
14476       *info;
14477
14478     SV
14479       *av_reference,
14480       *perl_exception,
14481       *reference,
14482       *rv,
14483       *sv;
14484
14485     PERL_UNUSED_VAR(ref);
14486     PERL_UNUSED_VAR(ix);
14487     exception=AcquireExceptionInfo();
14488     perl_exception=newSVpv("",0);
14489     sv=NULL;
14490     av=NULL;
14491     attribute=NULL;
14492     if (sv_isobject(ST(0)) == 0)
14493       {
14494         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14495           PackageName);
14496         goto PerlException;
14497       }
14498     reference=SvRV(ST(0));
14499     hv=SvSTASH(reference);
14500     av=newAV();
14501     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14502     SvREFCNT_dec(av);
14503     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14504     if (image == (Image *) NULL)
14505       {
14506         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14507           PackageName);
14508         goto PerlException;
14509       }
14510     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14511     /*
14512       Get attribute.
14513     */
14514     crop_geometry=(char *) NULL;
14515     geometry=(char *) NULL;
14516     for (i=2; i < items; i+=2)
14517     {
14518       attribute=(char *) SvPV(ST(i-1),na);
14519       switch (*attribute)
14520       {
14521         case 'c':
14522         case 'C':
14523         {
14524           if (LocaleCompare(attribute,"crop") == 0)
14525             {
14526               crop_geometry=SvPV(ST(i),na);
14527               break;
14528             }
14529           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14530             attribute);
14531           break;
14532         }
14533         case 'g':
14534         case 'G':
14535         {
14536           if (LocaleCompare(attribute,"geometry") == 0)
14537             {
14538               geometry=SvPV(ST(i),na);
14539               break;
14540             }
14541           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14542             attribute);
14543           break;
14544         }
14545         default:
14546         {
14547           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14548             attribute);
14549           break;
14550         }
14551       }
14552     }
14553     for ( ; image; image=image->next)
14554     {
14555       clone=CloneImage(image,0,0,MagickTrue,exception);
14556       if (clone == (Image *) NULL)
14557         goto PerlException;
14558       TransformImage(&clone,crop_geometry,geometry,exception);
14559       for ( ; clone; clone=clone->next)
14560       {
14561         AddImageToRegistry(sv,clone);
14562         rv=newRV(sv);
14563         av_push(av,sv_bless(rv,hv));
14564         SvREFCNT_dec(sv);
14565       }
14566     }
14567     exception=DestroyExceptionInfo(exception);
14568     ST(0)=av_reference;
14569     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
14570     XSRETURN(1);
14571
14572   PerlException:
14573     InheritPerlException(exception,perl_exception);
14574     exception=DestroyExceptionInfo(exception);
14575     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14576     SvPOK_on(perl_exception);
14577     ST(0)=sv_2mortal(perl_exception);
14578     XSRETURN(1);
14579   }
14580 \f
14581 #
14582 ###############################################################################
14583 #                                                                             #
14584 #                                                                             #
14585 #                                                                             #
14586 #   W r i t e                                                                 #
14587 #                                                                             #
14588 #                                                                             #
14589 #                                                                             #
14590 ###############################################################################
14591 #
14592 #
14593 void
14594 Write(ref,...)
14595   Image::Magick ref=NO_INIT
14596   ALIAS:
14597     WriteImage    = 1
14598     write         = 2
14599     writeimage    = 3
14600   PPCODE:
14601   {
14602     char
14603       filename[MagickPathExtent];
14604
14605     ExceptionInfo
14606       *exception;
14607
14608     Image
14609       *image,
14610       *next;
14611
14612     register ssize_t
14613       i;
14614
14615     ssize_t
14616       number_images,
14617       scene;
14618
14619     struct PackageInfo
14620       *info,
14621       *package_info;
14622
14623     SV
14624       *perl_exception,
14625       *reference;
14626
14627     PERL_UNUSED_VAR(ref);
14628     PERL_UNUSED_VAR(ix);
14629     exception=AcquireExceptionInfo();
14630     perl_exception=newSVpv("",0);
14631     number_images=0;
14632     package_info=(struct PackageInfo *) NULL;
14633     if (sv_isobject(ST(0)) == 0)
14634       {
14635         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14636           PackageName);
14637         goto PerlException;
14638       }
14639     reference=SvRV(ST(0));
14640     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14641     if (image == (Image *) NULL)
14642       {
14643         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14644           PackageName);
14645         goto PerlException;
14646       }
14647     package_info=ClonePackageInfo(info,exception);
14648     if (items == 2)
14649       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14650     else
14651       if (items > 2)
14652         for (i=2; i < items; i+=2)
14653           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14654             exception);
14655     (void) CopyMagickString(filename,package_info->image_info->filename,
14656       MagickPathExtent);
14657     scene=0;
14658     for (next=image; next; next=next->next)
14659     {
14660       (void) CopyMagickString(next->filename,filename,MagickPathExtent);
14661       next->scene=scene++;
14662     }
14663     *package_info->image_info->magick='\0';
14664     SetImageInfo(package_info->image_info,(unsigned int)
14665       GetImageListLength(image),exception);
14666     for (next=image; next; next=next->next)
14667     {
14668       (void) WriteImage(package_info->image_info,next,exception);
14669       number_images++;
14670       if (package_info->image_info->adjoin)
14671         break;
14672     }
14673
14674   PerlException:
14675     if (package_info != (struct PackageInfo *) NULL)
14676       DestroyPackageInfo(package_info);
14677     InheritPerlException(exception,perl_exception);
14678     exception=DestroyExceptionInfo(exception);
14679     sv_setiv(perl_exception,(IV) number_images);
14680     SvPOK_on(perl_exception);
14681     ST(0)=sv_2mortal(perl_exception);
14682     XSRETURN(1);
14683   }