]> granicus.if.org Git - imagemagick/blob - PerlMagick/Magick.xs
9d6ebcc3db4539b67a101900cc440f55c513842d
[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->matte_color=target_color;
1712           for ( ; image; image=image->next)
1713             image->matte_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,"view") == 0)
2202         {
2203           if (info)
2204             (void) CloneString(&info->image_info->view,SvPV(sval,na));
2205           break;
2206         }
2207       if (LocaleCompare(attribute,"virtual-pixel") == 0)
2208         {
2209           sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2210             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2211           if (sp < 0)
2212             {
2213               ThrowPerlException(exception,OptionError,
2214                 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2215               break;
2216             }
2217           for ( ; image; image=image->next)
2218             SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp,exception);
2219           break;
2220         }
2221       if (info)
2222         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2223       for ( ; image; image=image->next)
2224         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2225       break;
2226     }
2227     case 'W':
2228     case 'w':
2229     {
2230       if (LocaleCompare(attribute,"white-point") == 0)
2231         {
2232           for ( ; image; image=image->next)
2233           {
2234             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2235             image->chromaticity.white_point.x=geometry_info.rho;
2236             image->chromaticity.white_point.y=geometry_info.sigma;
2237             if ((flags & SigmaValue) == 0)
2238               image->chromaticity.white_point.y=
2239                 image->chromaticity.white_point.x;
2240           }
2241           break;
2242         }
2243       if (LocaleCompare(attribute,"write-mask") == 0)
2244         {
2245           Image
2246             *mask;
2247
2248           mask=(Image *) NULL;
2249           if (SvPOK(sval))
2250             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
2251           for ( ; image; image=image->next)
2252             SetImageMask(image,WritePixelMask,mask,exception);
2253           break;
2254         }
2255       if (info)
2256         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2257       for ( ; image; image=image->next)
2258         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2259       break;
2260     }
2261     default:
2262     {
2263       if (info)
2264         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2265       for ( ; image; image=image->next)
2266         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2267       break;
2268     }
2269   }
2270 }
2271 \f
2272 /*
2273 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2274 %                                                                             %
2275 %                                                                             %
2276 %                                                                             %
2277 %   S e t u p L i s t                                                         %
2278 %                                                                             %
2279 %                                                                             %
2280 %                                                                             %
2281 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2282 %
2283 %  Method SetupList returns the list of all the images linked by their
2284 %  image->next and image->previous link lists for use with ImageMagick.  If
2285 %  info is non-NULL, an info structure is returned in *info.  If
2286 %  reference_vector is non-NULL,an array of SV* are returned in
2287 %  *reference_vector.  Reference_vector is used when the images are going to be
2288 %  replaced with new Image*'s.
2289 %
2290 %  The format of the SetupList routine is:
2291 %
2292 %      Image *SetupList(SV *reference,struct PackageInfo **info,
2293 %        SV ***reference_vector,ExceptionInfo *exception)
2294 %
2295 %  A description of each parameter follows:
2296 %
2297 %    o list: a list of strings.
2298 %
2299 %    o string: a character string.
2300 %
2301 %    o exception: Return any errors or warnings in this structure.
2302 %
2303 */
2304 static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2305   SV ***reference_vector,ExceptionInfo *exception)
2306 {
2307   Image
2308     *image;
2309
2310   ssize_t
2311     current,
2312     last;
2313
2314   if (reference_vector)
2315     *reference_vector=NULL;
2316   if (info)
2317     *info=NULL;
2318   current=0;
2319   last=0;
2320   image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2321   if (info && (SvTYPE(reference) == SVt_PVAV))
2322     *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2323       exception);
2324   return(image);
2325 }
2326 \f
2327 /*
2328 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2329 %                                                                             %
2330 %                                                                             %
2331 %                                                                             %
2332 %   s t r E Q c a s e                                                         %
2333 %                                                                             %
2334 %                                                                             %
2335 %                                                                             %
2336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2337 %
2338 %  strEQcase() compares two strings and returns 0 if they are the
2339 %  same or if the second string runs out first.  The comparison is case
2340 %  insensitive.
2341 %
2342 %  The format of the strEQcase routine is:
2343 %
2344 %      ssize_t strEQcase(const char *p,const char *q)
2345 %
2346 %  A description of each parameter follows:
2347 %
2348 %    o p: a character string.
2349 %
2350 %    o q: a character string.
2351 %
2352 %
2353 */
2354 static ssize_t strEQcase(const char *p,const char *q)
2355 {
2356   char
2357     c;
2358
2359   register ssize_t
2360     i;
2361
2362   for (i=0 ; (c=(*q)) != 0; i++)
2363   {
2364     if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2365         (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2366       return(0);
2367     p++;
2368     q++;
2369   }
2370   return(((*q == 0) && (*p == 0)) ? i : 0);
2371 }
2372 \f
2373 /*
2374 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2375 %                                                                             %
2376 %                                                                             %
2377 %                                                                             %
2378 %   I m a g e : : M a g i c k                                                 %
2379 %                                                                             %
2380 %                                                                             %
2381 %                                                                             %
2382 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2383 %
2384 %
2385 */
2386 MODULE = Image::Magick PACKAGE = Image::Magick
2387
2388 PROTOTYPES: ENABLE
2389
2390 BOOT:
2391   MagickCoreGenesis("PerlMagick",MagickFalse);
2392   SetWarningHandler(NULL);
2393   SetErrorHandler(NULL);
2394   magick_registry=NewSplayTree((int (*)(const void *,const void *))
2395     NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2396
2397 void
2398 UNLOAD()
2399   PPCODE:
2400   {
2401     if (magick_registry != (SplayTreeInfo *) NULL)
2402       magick_registry=DestroySplayTree(magick_registry);
2403     MagickCoreTerminus();
2404   }
2405
2406 double
2407 constant(name,argument)
2408   char *name
2409   ssize_t argument
2410 \f
2411 #
2412 ###############################################################################
2413 #                                                                             #
2414 #                                                                             #
2415 #                                                                             #
2416 #   A n i m a t e                                                             #
2417 #                                                                             #
2418 #                                                                             #
2419 #                                                                             #
2420 ###############################################################################
2421 #
2422 #
2423 void
2424 Animate(ref,...)
2425   Image::Magick ref=NO_INIT
2426   ALIAS:
2427     AnimateImage  = 1
2428     animate       = 2
2429     animateimage  = 3
2430   PPCODE:
2431   {
2432     ExceptionInfo
2433       *exception;
2434
2435     Image
2436       *image;
2437
2438     register ssize_t
2439       i;
2440
2441     struct PackageInfo
2442       *info,
2443       *package_info;
2444
2445     SV
2446       *perl_exception,
2447       *reference;
2448
2449     PERL_UNUSED_VAR(ref);
2450     PERL_UNUSED_VAR(ix);
2451     exception=AcquireExceptionInfo();
2452     perl_exception=newSVpv("",0);
2453     package_info=(struct PackageInfo *) NULL;
2454     if (sv_isobject(ST(0)) == 0)
2455       {
2456         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2457           PackageName);
2458         goto PerlException;
2459       }
2460     reference=SvRV(ST(0));
2461     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2462     if (image == (Image *) NULL)
2463       {
2464         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2465           PackageName);
2466         goto PerlException;
2467       }
2468     package_info=ClonePackageInfo(info,exception);
2469     if (items == 2)
2470       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2471     else
2472       if (items > 2)
2473         for (i=2; i < items; i+=2)
2474           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2475             exception);
2476     (void) AnimateImages(package_info->image_info,image,exception);
2477     (void) CatchImageException(image);
2478
2479   PerlException:
2480     if (package_info != (struct PackageInfo *) NULL)
2481       DestroyPackageInfo(package_info);
2482     InheritPerlException(exception,perl_exception);
2483     exception=DestroyExceptionInfo(exception);
2484     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2485     SvPOK_on(perl_exception);
2486     ST(0)=sv_2mortal(perl_exception);
2487     XSRETURN(1);
2488   }
2489 \f
2490 #
2491 ###############################################################################
2492 #                                                                             #
2493 #                                                                             #
2494 #                                                                             #
2495 #   A p p e n d                                                               #
2496 #                                                                             #
2497 #                                                                             #
2498 #                                                                             #
2499 ###############################################################################
2500 #
2501 #
2502 void
2503 Append(ref,...)
2504   Image::Magick ref=NO_INIT
2505   ALIAS:
2506     AppendImage  = 1
2507     append       = 2
2508     appendimage  = 3
2509   PPCODE:
2510   {
2511     AV
2512       *av;
2513
2514     char
2515       *attribute;
2516
2517     ExceptionInfo
2518       *exception;
2519
2520     HV
2521       *hv;
2522
2523     Image
2524       *image;
2525
2526     register ssize_t
2527       i;
2528
2529     ssize_t
2530       stack;
2531
2532     struct PackageInfo
2533       *info;
2534
2535     SV
2536       *av_reference,
2537       *perl_exception,
2538       *reference,
2539       *rv,
2540       *sv;
2541
2542     PERL_UNUSED_VAR(ref);
2543     PERL_UNUSED_VAR(ix);
2544     exception=AcquireExceptionInfo();
2545     perl_exception=newSVpv("",0);
2546     sv=NULL;
2547     attribute=NULL;
2548     av=NULL;
2549     if (sv_isobject(ST(0)) == 0)
2550       {
2551         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2552           PackageName);
2553         goto PerlException;
2554       }
2555     reference=SvRV(ST(0));
2556     hv=SvSTASH(reference);
2557     av=newAV();
2558     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2559     SvREFCNT_dec(av);
2560     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2561     if (image == (Image *) NULL)
2562       {
2563         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2564           PackageName);
2565         goto PerlException;
2566       }
2567     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2568     /*
2569       Get options.
2570     */
2571     stack=MagickTrue;
2572     for (i=2; i < items; i+=2)
2573     {
2574       attribute=(char *) SvPV(ST(i-1),na);
2575       switch (*attribute)
2576       {
2577         case 'S':
2578         case 's':
2579         {
2580           if (LocaleCompare(attribute,"stack") == 0)
2581             {
2582               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2583                 SvPV(ST(i),na));
2584               if (stack < 0)
2585                 {
2586                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
2587                     SvPV(ST(i),na));
2588                   return;
2589                 }
2590               break;
2591             }
2592           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2593             attribute);
2594           break;
2595         }
2596         default:
2597         {
2598           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2599             attribute);
2600           break;
2601         }
2602       }
2603     }
2604     image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2605     if (image == (Image *) NULL)
2606       goto PerlException;
2607     for ( ; image; image=image->next)
2608     {
2609       AddImageToRegistry(sv,image);
2610       rv=newRV(sv);
2611       av_push(av,sv_bless(rv,hv));
2612       SvREFCNT_dec(sv);
2613     }
2614     exception=DestroyExceptionInfo(exception);
2615     ST(0)=av_reference;
2616     SvREFCNT_dec(perl_exception);
2617     XSRETURN(1);
2618
2619   PerlException:
2620     InheritPerlException(exception,perl_exception);
2621     exception=DestroyExceptionInfo(exception);
2622     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2623     SvPOK_on(perl_exception);
2624     ST(0)=sv_2mortal(perl_exception);
2625     XSRETURN(1);
2626   }
2627 \f
2628 #
2629 ###############################################################################
2630 #                                                                             #
2631 #                                                                             #
2632 #                                                                             #
2633 #   A v e r a g e                                                             #
2634 #                                                                             #
2635 #                                                                             #
2636 #                                                                             #
2637 ###############################################################################
2638 #
2639 #
2640 void
2641 Average(ref)
2642   Image::Magick ref=NO_INIT
2643   ALIAS:
2644     AverageImage   = 1
2645     average        = 2
2646     averageimage   = 3
2647   PPCODE:
2648   {
2649     AV
2650       *av;
2651
2652     char
2653       *p;
2654
2655     ExceptionInfo
2656       *exception;
2657
2658     HV
2659       *hv;
2660
2661     Image
2662       *image;
2663
2664     struct PackageInfo
2665       *info;
2666
2667     SV
2668       *perl_exception,
2669       *reference,
2670       *rv,
2671       *sv;
2672
2673     PERL_UNUSED_VAR(ref);
2674     PERL_UNUSED_VAR(ix);
2675     exception=AcquireExceptionInfo();
2676     perl_exception=newSVpv("",0);
2677     sv=NULL;
2678     if (sv_isobject(ST(0)) == 0)
2679       {
2680         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2681           PackageName);
2682         goto PerlException;
2683       }
2684     reference=SvRV(ST(0));
2685     hv=SvSTASH(reference);
2686     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2687     if (image == (Image *) NULL)
2688       {
2689         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2690           PackageName);
2691         goto PerlException;
2692       }
2693     image=EvaluateImages(image,MeanEvaluateOperator,exception);
2694     if (image == (Image *) NULL)
2695       goto PerlException;
2696     /*
2697       Create blessed Perl array for the returned image.
2698     */
2699     av=newAV();
2700     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2701     SvREFCNT_dec(av);
2702     AddImageToRegistry(sv,image);
2703     rv=newRV(sv);
2704     av_push(av,sv_bless(rv,hv));
2705     SvREFCNT_dec(sv);
2706     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2707     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
2708       "average-%.*s",(int) (MagickPathExtent-9),
2709       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2710     (void) CopyMagickString(image->filename,info->image_info->filename,
2711       MagickPathExtent);
2712     SetImageInfo(info->image_info,0,exception);
2713     exception=DestroyExceptionInfo(exception);
2714     SvREFCNT_dec(perl_exception);
2715     XSRETURN(1);
2716
2717   PerlException:
2718     InheritPerlException(exception,perl_exception);
2719     exception=DestroyExceptionInfo(exception);
2720     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2721     SvPOK_on(perl_exception);
2722     ST(0)=sv_2mortal(perl_exception);
2723     XSRETURN(1);
2724   }
2725 \f
2726 #
2727 ###############################################################################
2728 #                                                                             #
2729 #                                                                             #
2730 #                                                                             #
2731 #   B l o b T o I m a g e                                                     #
2732 #                                                                             #
2733 #                                                                             #
2734 #                                                                             #
2735 ###############################################################################
2736 #
2737 #
2738 void
2739 BlobToImage(ref,...)
2740   Image::Magick ref=NO_INIT
2741   ALIAS:
2742     BlobToImage  = 1
2743     blobtoimage  = 2
2744     blobto       = 3
2745   PPCODE:
2746   {
2747     AV
2748       *av;
2749
2750     char
2751       **keep,
2752       **list;
2753
2754     ExceptionInfo
2755       *exception;
2756
2757     HV
2758       *hv;
2759
2760     Image
2761       *image;
2762
2763     register char
2764       **p;
2765
2766     register ssize_t
2767       i;
2768
2769     ssize_t
2770       ac,
2771       n,
2772       number_images;
2773
2774     STRLEN
2775       *length;
2776
2777     struct PackageInfo
2778       *info;
2779
2780     SV
2781       *perl_exception,
2782       *reference,
2783       *rv,
2784       *sv;
2785
2786     PERL_UNUSED_VAR(ref);
2787     PERL_UNUSED_VAR(ix);
2788     exception=AcquireExceptionInfo();
2789     perl_exception=newSVpv("",0);
2790     sv=NULL;
2791     number_images=0;
2792     ac=(items < 2) ? 1 : items-1;
2793     length=(STRLEN *) NULL;
2794     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2795     if (list == (char **) NULL)
2796       {
2797         ThrowPerlException(exception,ResourceLimitError,
2798           "MemoryAllocationFailed",PackageName);
2799         goto PerlException;
2800       }
2801     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2802     if (length == (STRLEN *) NULL)
2803       {
2804         ThrowPerlException(exception,ResourceLimitError,
2805           "MemoryAllocationFailed",PackageName);
2806         goto PerlException;
2807       }
2808     if (sv_isobject(ST(0)) == 0)
2809       {
2810         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2811           PackageName);
2812         goto PerlException;
2813       }
2814     reference=SvRV(ST(0));
2815     hv=SvSTASH(reference);
2816     if (SvTYPE(reference) != SVt_PVAV)
2817       {
2818         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2819           PackageName);
2820         goto PerlException;
2821       }
2822     av=(AV *) reference;
2823     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2824       exception);
2825     n=1;
2826     if (items <= 1)
2827       {
2828         ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2829         goto PerlException;
2830       }
2831     for (n=0, i=0; i < ac; i++)
2832     {
2833       list[n]=(char *) (SvPV(ST(i+1),length[n]));
2834       if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2835         {
2836           list[n]=(char *) (SvPV(ST(i+2),length[n]));
2837           continue;
2838         }
2839       n++;
2840     }
2841     list[n]=(char *) NULL;
2842     keep=list;
2843     for (i=number_images=0; i < n; i++)
2844     {
2845       image=BlobToImage(info->image_info,list[i],length[i],exception);
2846       if (image == (Image *) NULL)
2847         break;
2848       for ( ; image; image=image->next)
2849       {
2850         AddImageToRegistry(sv,image);
2851         rv=newRV(sv);
2852         av_push(av,sv_bless(rv,hv));
2853         SvREFCNT_dec(sv);
2854         number_images++;
2855       }
2856     }
2857     /*
2858       Free resources.
2859     */
2860     for (i=0; i < n; i++)
2861       if (list[i] != (char *) NULL)
2862         for (p=keep; list[i] != *p++; )
2863           if (*p == (char *) NULL)
2864             {
2865               list[i]=(char *) RelinquishMagickMemory(list[i]);
2866               break;
2867             }
2868
2869   PerlException:
2870     if (list)
2871       list=(char **) RelinquishMagickMemory(list);
2872     if (length)
2873       length=(STRLEN *) RelinquishMagickMemory(length);
2874     InheritPerlException(exception,perl_exception);
2875     exception=DestroyExceptionInfo(exception);
2876     sv_setiv(perl_exception,(IV) number_images);
2877     SvPOK_on(perl_exception);
2878     ST(0)=sv_2mortal(perl_exception);
2879     XSRETURN(1);
2880   }
2881 \f
2882 #
2883 ###############################################################################
2884 #                                                                             #
2885 #                                                                             #
2886 #                                                                             #
2887 #   C h a n n e l F x                                                         #
2888 #                                                                             #
2889 #                                                                             #
2890 #                                                                             #
2891 ###############################################################################
2892 #
2893 #
2894 void
2895 ChannelFx(ref,...)
2896   Image::Magick ref=NO_INIT
2897   ALIAS:
2898     ChannelFxImage  = 1
2899     channelfx       = 2
2900     channelfximage  = 3
2901   PPCODE:
2902   {
2903     AV
2904       *av;
2905
2906     char
2907       *attribute,
2908       expression[MagickPathExtent];
2909
2910     ChannelType
2911       channel,
2912       channel_mask;
2913
2914     ExceptionInfo
2915       *exception;
2916
2917     HV
2918       *hv;
2919
2920     Image
2921       *image;
2922
2923     register ssize_t
2924       i;
2925
2926     struct PackageInfo
2927       *info;
2928
2929     SV
2930       *av_reference,
2931       *perl_exception,
2932       *reference,
2933       *rv,
2934       *sv;
2935
2936     PERL_UNUSED_VAR(ref);
2937     PERL_UNUSED_VAR(ix);
2938     exception=AcquireExceptionInfo();
2939     perl_exception=newSVpv("",0);
2940     sv=NULL;
2941     attribute=NULL;
2942     av=NULL;
2943     if (sv_isobject(ST(0)) == 0)
2944       {
2945         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2946           PackageName);
2947         goto PerlException;
2948       }
2949     reference=SvRV(ST(0));
2950     hv=SvSTASH(reference);
2951     av=newAV();
2952     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2953     SvREFCNT_dec(av);
2954     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2955     if (image == (Image *) NULL)
2956       {
2957         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2958           PackageName);
2959         goto PerlException;
2960       }
2961     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2962     /*
2963       Get options.
2964     */
2965     channel=DefaultChannels;
2966     (void) CopyMagickString(expression,"u",MagickPathExtent);
2967     if (items == 2)
2968       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
2969     else
2970       for (i=2; i < items; i+=2)
2971       {
2972         attribute=(char *) SvPV(ST(i-1),na);
2973         switch (*attribute)
2974         {
2975           case 'C':
2976           case 'c':
2977           {
2978             if (LocaleCompare(attribute,"channel") == 0)
2979               {
2980                 ssize_t
2981                   option;
2982
2983                 option=ParseChannelOption(SvPV(ST(i),na));
2984                 if (option < 0)
2985                   {
2986                     ThrowPerlException(exception,OptionError,
2987                       "UnrecognizedType",SvPV(ST(i),na));
2988                     return;
2989                   }
2990                 channel=(ChannelType) option;
2991                 break;
2992               }
2993             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2994               attribute);
2995             break;
2996           }
2997           case 'E':
2998           case 'e':
2999           {
3000             if (LocaleCompare(attribute,"expression") == 0)
3001               {
3002                 (void) CopyMagickString(expression,SvPV(ST(i),na),
3003                   MagickPathExtent);
3004                 break;
3005               }
3006             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3007               attribute);
3008             break;
3009           }
3010           default:
3011           {
3012             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3013               attribute);
3014             break;
3015           }
3016         }
3017       }
3018     channel_mask=SetImageChannelMask(image,channel);
3019     image=ChannelFxImage(image,expression,exception);
3020     if (image != (Image *) NULL)
3021       (void) SetImageChannelMask(image,channel_mask);
3022     if (image == (Image *) NULL)
3023       goto PerlException;
3024     for ( ; image; image=image->next)
3025     {
3026       AddImageToRegistry(sv,image);
3027       rv=newRV(sv);
3028       av_push(av,sv_bless(rv,hv));
3029       SvREFCNT_dec(sv);
3030     }
3031     exception=DestroyExceptionInfo(exception);
3032     ST(0)=av_reference;
3033     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3034     XSRETURN(1);
3035
3036   PerlException:
3037     InheritPerlException(exception,perl_exception);
3038     exception=DestroyExceptionInfo(exception);
3039     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3040     SvPOK_on(perl_exception);
3041     ST(0)=sv_2mortal(perl_exception);
3042     XSRETURN(1);
3043   }
3044 \f
3045 #
3046 ###############################################################################
3047 #                                                                             #
3048 #                                                                             #
3049 #                                                                             #
3050 #   C l o n e                                                                 #
3051 #                                                                             #
3052 #                                                                             #
3053 #                                                                             #
3054 ###############################################################################
3055 #
3056 #
3057 void
3058 Clone(ref)
3059   Image::Magick ref=NO_INIT
3060   ALIAS:
3061     CopyImage   = 1
3062     copy        = 2
3063     copyimage   = 3
3064     CloneImage  = 4
3065     clone       = 5
3066     cloneimage  = 6
3067     Clone       = 7
3068   PPCODE:
3069   {
3070     AV
3071       *av;
3072
3073     ExceptionInfo
3074       *exception;
3075
3076     HV
3077       *hv;
3078
3079     Image
3080       *clone,
3081       *image;
3082
3083     struct PackageInfo
3084       *info;
3085
3086     SV
3087       *perl_exception,
3088       *reference,
3089       *rv,
3090       *sv;
3091
3092     PERL_UNUSED_VAR(ref);
3093     PERL_UNUSED_VAR(ix);
3094     exception=AcquireExceptionInfo();
3095     perl_exception=newSVpv("",0);
3096     sv=NULL;
3097     if (sv_isobject(ST(0)) == 0)
3098       {
3099         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3100           PackageName);
3101         goto PerlException;
3102       }
3103     reference=SvRV(ST(0));
3104     hv=SvSTASH(reference);
3105     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3106     if (image == (Image *) NULL)
3107       {
3108         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3109           PackageName);
3110         goto PerlException;
3111       }
3112     /*
3113       Create blessed Perl array for the returned image.
3114     */
3115     av=newAV();
3116     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3117     SvREFCNT_dec(av);
3118     for ( ; image; image=image->next)
3119     {
3120       clone=CloneImage(image,0,0,MagickTrue,exception);
3121       if (clone == (Image *) NULL)
3122         break;
3123       AddImageToRegistry(sv,clone);
3124       rv=newRV(sv);
3125       av_push(av,sv_bless(rv,hv));
3126       SvREFCNT_dec(sv);
3127     }
3128     exception=DestroyExceptionInfo(exception);
3129     SvREFCNT_dec(perl_exception);
3130     XSRETURN(1);
3131
3132   PerlException:
3133     InheritPerlException(exception,perl_exception);
3134     exception=DestroyExceptionInfo(exception);
3135     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3136     SvPOK_on(perl_exception);
3137     ST(0)=sv_2mortal(perl_exception);
3138     XSRETURN(1);
3139   }
3140 \f
3141 #
3142 ###############################################################################
3143 #                                                                             #
3144 #                                                                             #
3145 #                                                                             #
3146 #   C L O N E                                                                 #
3147 #                                                                             #
3148 #                                                                             #
3149 #                                                                             #
3150 ###############################################################################
3151 #
3152 #
3153 void
3154 CLONE(ref,...)
3155   SV *ref;
3156   CODE:
3157   {
3158     PERL_UNUSED_VAR(ref);
3159     if (magick_registry != (SplayTreeInfo *) NULL)
3160       {
3161         register Image
3162           *p;
3163
3164         ResetSplayTreeIterator(magick_registry);
3165         p=(Image *) GetNextKeyInSplayTree(magick_registry);
3166         while (p != (Image *) NULL)
3167         {
3168           ReferenceImage(p);
3169           p=(Image *) GetNextKeyInSplayTree(magick_registry);
3170         }
3171       }
3172   }
3173 \f
3174 #
3175 ###############################################################################
3176 #                                                                             #
3177 #                                                                             #
3178 #                                                                             #
3179 #   C o a l e s c e                                                           #
3180 #                                                                             #
3181 #                                                                             #
3182 #                                                                             #
3183 ###############################################################################
3184 #
3185 #
3186 void
3187 Coalesce(ref)
3188   Image::Magick ref=NO_INIT
3189   ALIAS:
3190     CoalesceImage   = 1
3191     coalesce        = 2
3192     coalesceimage   = 3
3193   PPCODE:
3194   {
3195     AV
3196       *av;
3197
3198     ExceptionInfo
3199       *exception;
3200
3201     HV
3202       *hv;
3203
3204     Image
3205       *image;
3206
3207     struct PackageInfo
3208       *info;
3209
3210     SV
3211       *av_reference,
3212       *perl_exception,
3213       *reference,
3214       *rv,
3215       *sv;
3216
3217     PERL_UNUSED_VAR(ref);
3218     PERL_UNUSED_VAR(ix);
3219     exception=AcquireExceptionInfo();
3220     perl_exception=newSVpv("",0);
3221     sv=NULL;
3222     if (sv_isobject(ST(0)) == 0)
3223       {
3224         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3225           PackageName);
3226         goto PerlException;
3227       }
3228     reference=SvRV(ST(0));
3229     hv=SvSTASH(reference);
3230     av=newAV();
3231     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3232     SvREFCNT_dec(av);
3233     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3234     if (image == (Image *) NULL)
3235       {
3236         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3237           PackageName);
3238         goto PerlException;
3239       }
3240     image=CoalesceImages(image,exception);
3241     if (image == (Image *) NULL)
3242       goto PerlException;
3243     for ( ; image; image=image->next)
3244     {
3245       AddImageToRegistry(sv,image);
3246       rv=newRV(sv);
3247       av_push(av,sv_bless(rv,hv));
3248       SvREFCNT_dec(sv);
3249     }
3250     exception=DestroyExceptionInfo(exception);
3251     ST(0)=av_reference;
3252     SvREFCNT_dec(perl_exception);
3253     XSRETURN(1);
3254
3255   PerlException:
3256     InheritPerlException(exception,perl_exception);
3257     exception=DestroyExceptionInfo(exception);
3258     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3259     SvPOK_on(perl_exception);
3260     ST(0)=sv_2mortal(perl_exception);
3261     XSRETURN(1);
3262   }
3263 \f
3264 #
3265 ###############################################################################
3266 #                                                                             #
3267 #                                                                             #
3268 #                                                                             #
3269 #   C o m p a r e                                                             #
3270 #                                                                             #
3271 #                                                                             #
3272 #                                                                             #
3273 ###############################################################################
3274 #
3275 #
3276 void
3277 Compare(ref,...)
3278   Image::Magick ref=NO_INIT
3279   ALIAS:
3280     CompareImages = 1
3281     compare      = 2
3282     compareimage = 3
3283   PPCODE:
3284   {
3285     AV
3286       *av;
3287
3288     char
3289       *attribute;
3290
3291     double
3292       distortion;
3293
3294     ExceptionInfo
3295       *exception;
3296
3297     HV
3298       *hv;
3299
3300     Image
3301       *difference_image,
3302       *image,
3303       *reconstruct_image;
3304
3305     MetricType
3306       metric;
3307
3308     register ssize_t
3309       i;
3310
3311     ssize_t
3312       option;
3313
3314     struct PackageInfo
3315       *info;
3316
3317     SV
3318       *av_reference,
3319       *perl_exception,
3320       *reference,
3321       *rv,
3322       *sv;
3323
3324     PERL_UNUSED_VAR(ref);
3325     PERL_UNUSED_VAR(ix);
3326     exception=AcquireExceptionInfo();
3327     perl_exception=newSVpv("",0);
3328     sv=NULL;
3329     av=NULL;
3330     attribute=NULL;
3331     if (sv_isobject(ST(0)) == 0)
3332       {
3333         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3334           PackageName);
3335         goto PerlException;
3336       }
3337     reference=SvRV(ST(0));
3338     hv=SvSTASH(reference);
3339     av=newAV();
3340     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3341     SvREFCNT_dec(av);
3342     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3343     if (image == (Image *) NULL)
3344       {
3345         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3346           PackageName);
3347         goto PerlException;
3348       }
3349     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3350     /*
3351       Get attribute.
3352     */
3353     reconstruct_image=image;
3354     metric=RootMeanSquaredErrorMetric;
3355     for (i=2; i < items; i+=2)
3356     {
3357       attribute=(char *) SvPV(ST(i-1),na);
3358       switch (*attribute)
3359       {
3360         case 'C':
3361         case 'c':
3362         {
3363           if (LocaleCompare(attribute,"channel") == 0)
3364             {
3365               ssize_t
3366                 option;
3367
3368               option=ParseChannelOption(SvPV(ST(i),na));
3369               if (option < 0)
3370                 {
3371                   ThrowPerlException(exception,OptionError,
3372                     "UnrecognizedType",SvPV(ST(i),na));
3373                   return;
3374                 }
3375               (void) SetPixelChannelMask(image,(ChannelType) option);
3376               break;
3377             }
3378           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3379             attribute);
3380           break;
3381         }
3382         case 'F':
3383         case 'f':
3384         {
3385           if (LocaleCompare(attribute,"fuzz") == 0)
3386             {
3387               image->fuzz=StringToDoubleInterval(SvPV(ST(i),na),100.0);
3388               break;
3389             }
3390           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3391             attribute);
3392           break;
3393         }
3394         case 'I':
3395         case 'i':
3396         {
3397           if (LocaleCompare(attribute,"image") == 0)
3398             {
3399               reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3400                 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3401               break;
3402             }
3403           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3404             attribute);
3405           break;
3406         }
3407         case 'M':
3408         case 'm':
3409         {
3410           if (LocaleCompare(attribute,"metric") == 0)
3411             {
3412               option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3413                 SvPV(ST(i),na));
3414               if (option < 0)
3415                 {
3416                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3417                     SvPV(ST(i),na));
3418                   break;
3419                 }
3420               metric=(MetricType) option;
3421               break;
3422             }
3423           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3424             attribute);
3425           break;
3426         }
3427         default:
3428         {
3429           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3430             attribute);
3431           break;
3432         }
3433       }
3434     }
3435     difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3436       exception);
3437     if (difference_image != (Image *) NULL)
3438       {
3439         difference_image->error.mean_error_per_pixel=distortion;
3440         AddImageToRegistry(sv,difference_image);
3441         rv=newRV(sv);
3442         av_push(av,sv_bless(rv,hv));
3443         SvREFCNT_dec(sv);
3444       }
3445     exception=DestroyExceptionInfo(exception);
3446     ST(0)=av_reference;
3447     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3448     XSRETURN(1);
3449
3450   PerlException:
3451     InheritPerlException(exception,perl_exception);
3452     exception=DestroyExceptionInfo(exception);
3453     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3454     SvPOK_on(perl_exception);
3455     ST(0)=sv_2mortal(perl_exception);
3456     XSRETURN(1);
3457   }
3458 \f
3459 #
3460 ###############################################################################
3461 #                                                                             #
3462 #                                                                             #
3463 #                                                                             #
3464 #   C o m p l e x I m a g e s                                                 #
3465 #                                                                             #
3466 #                                                                             #
3467 #                                                                             #
3468 ###############################################################################
3469 #
3470 #
3471 void
3472 ComplexImages(ref)
3473   Image::Magick ref=NO_INIT
3474   ALIAS:
3475     ComplexImages   = 1
3476     compleximages   = 2
3477   PPCODE:
3478   {
3479     AV
3480       *av;
3481
3482     char
3483       *attribute,
3484       *p;
3485
3486     ComplexOperator
3487       op;
3488
3489     ExceptionInfo
3490       *exception;
3491
3492     HV
3493       *hv;
3494
3495     Image
3496       *image;
3497
3498     register ssize_t
3499       i;
3500
3501     struct PackageInfo
3502       *info;
3503
3504     SV
3505       *perl_exception,
3506       *reference,
3507       *rv,
3508       *sv;
3509
3510     PERL_UNUSED_VAR(ref);
3511     PERL_UNUSED_VAR(ix);
3512     exception=AcquireExceptionInfo();
3513     perl_exception=newSVpv("",0);
3514     sv=NULL;
3515     if (sv_isobject(ST(0)) == 0)
3516       {
3517         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3518           PackageName);
3519         goto PerlException;
3520       }
3521     reference=SvRV(ST(0));
3522     hv=SvSTASH(reference);
3523     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3524     if (image == (Image *) NULL)
3525       {
3526         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3527           PackageName);
3528         goto PerlException;
3529       }
3530     op=UndefinedComplexOperator;
3531     if (items == 2)
3532       {
3533         ssize_t
3534           in;
3535
3536         in=ParseCommandOption(MagickComplexOptions,MagickFalse,(char *)
3537           SvPV(ST(1),na));
3538         if (in < 0)
3539           {
3540             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3541               SvPV(ST(1),na));
3542             return;
3543           }
3544         op=(ComplexOperator) in;
3545       }
3546     else
3547       for (i=2; i < items; i+=2)
3548       {
3549         attribute=(char *) SvPV(ST(i-1),na);
3550         switch (*attribute)
3551         {
3552           case 'O':
3553           case 'o':
3554           {
3555             if (LocaleCompare(attribute,"operator") == 0)
3556               {
3557                 ssize_t
3558                   in;
3559
3560                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3561                   MagickComplexOptions,MagickFalse,SvPV(ST(i),na));
3562                 if (in < 0)
3563                   {
3564                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3565                       SvPV(ST(i),na));
3566                     return;
3567                   }
3568                 op=(ComplexOperator) in;
3569                 break;
3570               }
3571             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3572               attribute);
3573             break;
3574           }
3575           default:
3576           {
3577             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3578               attribute);
3579             break;
3580           }
3581         }
3582       }
3583     image=ComplexImages(image,op,exception);
3584     if (image == (Image *) NULL)
3585       goto PerlException;
3586     /*
3587       Create blessed Perl array for the returned image.
3588     */
3589     av=newAV();
3590     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3591     SvREFCNT_dec(av);
3592     AddImageToRegistry(sv,image);
3593     rv=newRV(sv);
3594     av_push(av,sv_bless(rv,hv));
3595     SvREFCNT_dec(sv);
3596     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3597     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
3598       "complex-%.*s",(int) (MagickPathExtent-9),
3599       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3600     (void) CopyMagickString(image->filename,info->image_info->filename,
3601       MagickPathExtent);
3602     SetImageInfo(info->image_info,0,exception);
3603     exception=DestroyExceptionInfo(exception);
3604     SvREFCNT_dec(perl_exception);
3605     XSRETURN(1);
3606
3607   PerlException:
3608     InheritPerlException(exception,perl_exception);
3609     exception=DestroyExceptionInfo(exception);
3610     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3611     SvPOK_on(perl_exception);
3612     ST(0)=sv_2mortal(perl_exception);
3613     XSRETURN(1);
3614   }
3615 \f
3616 #
3617 ###############################################################################
3618 #                                                                             #
3619 #                                                                             #
3620 #                                                                             #
3621 #   C o m p a r e L a y e r s                                                 #
3622 #                                                                             #
3623 #                                                                             #
3624 #                                                                             #
3625 ###############################################################################
3626 #
3627 #
3628 void
3629 CompareLayers(ref)
3630   Image::Magick ref=NO_INIT
3631   ALIAS:
3632     CompareImagesLayers   = 1
3633     comparelayers        = 2
3634     compareimagelayers   = 3
3635   PPCODE:
3636   {
3637     AV
3638       *av;
3639
3640     char
3641       *attribute;
3642
3643     ExceptionInfo
3644       *exception;
3645
3646     HV
3647       *hv;
3648
3649     Image
3650       *image;
3651
3652     LayerMethod
3653       method;
3654
3655     register ssize_t
3656       i;
3657
3658     ssize_t
3659       option;
3660
3661     struct PackageInfo
3662       *info;
3663
3664     SV
3665       *av_reference,
3666       *perl_exception,
3667       *reference,
3668       *rv,
3669       *sv;
3670
3671     PERL_UNUSED_VAR(ref);
3672     PERL_UNUSED_VAR(ix);
3673     exception=AcquireExceptionInfo();
3674     perl_exception=newSVpv("",0);
3675     sv=NULL;
3676     if (sv_isobject(ST(0)) == 0)
3677       {
3678         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3679           PackageName);
3680         goto PerlException;
3681       }
3682     reference=SvRV(ST(0));
3683     hv=SvSTASH(reference);
3684     av=newAV();
3685     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3686     SvREFCNT_dec(av);
3687     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3688     if (image == (Image *) NULL)
3689       {
3690         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3691           PackageName);
3692         goto PerlException;
3693       }
3694     method=CompareAnyLayer;
3695     for (i=2; i < items; i+=2)
3696     {
3697       attribute=(char *) SvPV(ST(i-1),na);
3698       switch (*attribute)
3699       {
3700         case 'M':
3701         case 'm':
3702         {
3703           if (LocaleCompare(attribute,"method") == 0)
3704             {
3705               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3706                 SvPV(ST(i),na));
3707               if (option < 0)
3708                 {
3709                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3710                     SvPV(ST(i),na));
3711                   break;
3712                 }
3713                method=(LayerMethod) option;
3714               break;
3715             }
3716           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3717             attribute);
3718           break;
3719         }
3720         default:
3721         {
3722           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3723             attribute);
3724           break;
3725         }
3726       }
3727     }
3728     image=CompareImagesLayers(image,method,exception);
3729     if (image == (Image *) NULL)
3730       goto PerlException;
3731     for ( ; image; image=image->next)
3732     {
3733       AddImageToRegistry(sv,image);
3734       rv=newRV(sv);
3735       av_push(av,sv_bless(rv,hv));
3736       SvREFCNT_dec(sv);
3737     }
3738     exception=DestroyExceptionInfo(exception);
3739     ST(0)=av_reference;
3740     SvREFCNT_dec(perl_exception);
3741     XSRETURN(1);
3742
3743   PerlException:
3744     InheritPerlException(exception,perl_exception);
3745     exception=DestroyExceptionInfo(exception);
3746     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3747     SvPOK_on(perl_exception);
3748     ST(0)=sv_2mortal(perl_exception);
3749     XSRETURN(1);
3750   }
3751 \f
3752 #
3753 ###############################################################################
3754 #                                                                             #
3755 #                                                                             #
3756 #                                                                             #
3757 #   D e s t r o y                                                             #
3758 #                                                                             #
3759 #                                                                             #
3760 #                                                                             #
3761 ###############################################################################
3762 #
3763 #
3764 void
3765 DESTROY(ref)
3766   Image::Magick ref=NO_INIT
3767   PPCODE:
3768   {
3769     SV
3770       *reference;
3771
3772     PERL_UNUSED_VAR(ref);
3773     if (sv_isobject(ST(0)) == 0)
3774       croak("ReferenceIsNotMyType");
3775     reference=SvRV(ST(0));
3776     switch (SvTYPE(reference))
3777     {
3778       case SVt_PVAV:
3779       {
3780         char
3781           message[MagickPathExtent];
3782
3783         const SV
3784           *key;
3785
3786         HV
3787           *hv;
3788
3789         GV
3790           **gvp;
3791
3792         struct PackageInfo
3793           *info;
3794
3795         SV
3796           *sv;
3797
3798         /*
3799           Array (AV *) reference
3800         */
3801         (void) FormatLocaleString(message,MagickPathExtent,"package%s%p",
3802           XS_VERSION,reference);
3803         hv=gv_stashpv(PackageName, FALSE);
3804         if (!hv)
3805           break;
3806         gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3807         if (!gvp)
3808           break;
3809         sv=GvSV(*gvp);
3810         if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3811           {
3812             info=INT2PTR(struct PackageInfo *,SvIV(sv));
3813             DestroyPackageInfo(info);
3814           }
3815         key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3816         (void) key;
3817         break;
3818       }
3819       case SVt_PVMG:
3820       {
3821         Image
3822           *image;
3823
3824         /*
3825           Blessed scalar = (Image *) SvIV(reference)
3826         */
3827         image=INT2PTR(Image *,SvIV(reference));
3828         if (image != (Image *) NULL)
3829           DeleteImageFromRegistry(reference,image);
3830         break;
3831       }
3832       default:
3833         break;
3834     }
3835   }
3836 \f
3837 #
3838 ###############################################################################
3839 #                                                                             #
3840 #                                                                             #
3841 #                                                                             #
3842 #   D i s p l a y                                                             #
3843 #                                                                             #
3844 #                                                                             #
3845 #                                                                             #
3846 ###############################################################################
3847 #
3848 #
3849 void
3850 Display(ref,...)
3851   Image::Magick ref=NO_INIT
3852   ALIAS:
3853     DisplayImage  = 1
3854     display       = 2
3855     displayimage  = 3
3856   PPCODE:
3857   {
3858     ExceptionInfo
3859       *exception;
3860
3861     Image
3862       *image;
3863
3864     register ssize_t
3865       i;
3866
3867     struct PackageInfo
3868       *info,
3869       *package_info;
3870
3871     SV
3872       *perl_exception,
3873       *reference;
3874
3875     PERL_UNUSED_VAR(ref);
3876     PERL_UNUSED_VAR(ix);
3877     exception=AcquireExceptionInfo();
3878     perl_exception=newSVpv("",0);
3879     package_info=(struct PackageInfo *) NULL;
3880     if (sv_isobject(ST(0)) == 0)
3881       {
3882         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3883           PackageName);
3884         goto PerlException;
3885       }
3886     reference=SvRV(ST(0));
3887     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3888     if (image == (Image *) NULL)
3889       {
3890         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3891           PackageName);
3892         goto PerlException;
3893       }
3894     package_info=ClonePackageInfo(info,exception);
3895     if (items == 2)
3896       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3897     else
3898       if (items > 2)
3899         for (i=2; i < items; i+=2)
3900           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3901             exception);
3902     (void) DisplayImages(package_info->image_info,image,exception);
3903     (void) CatchImageException(image);
3904
3905   PerlException:
3906     if (package_info != (struct PackageInfo *) NULL)
3907       DestroyPackageInfo(package_info);
3908     InheritPerlException(exception,perl_exception);
3909     exception=DestroyExceptionInfo(exception);
3910     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3911     SvPOK_on(perl_exception);
3912     ST(0)=sv_2mortal(perl_exception);
3913     XSRETURN(1);
3914   }
3915 \f
3916 #
3917 ###############################################################################
3918 #                                                                             #
3919 #                                                                             #
3920 #                                                                             #
3921 #   E v a l u a t e I m a g e s                                               #
3922 #                                                                             #
3923 #                                                                             #
3924 #                                                                             #
3925 ###############################################################################
3926 #
3927 #
3928 void
3929 EvaluateImages(ref)
3930   Image::Magick ref=NO_INIT
3931   ALIAS:
3932     EvaluateImages   = 1
3933     evaluateimages   = 2
3934   PPCODE:
3935   {
3936     AV
3937       *av;
3938
3939     char
3940       *attribute,
3941       *p;
3942
3943     ExceptionInfo
3944       *exception;
3945
3946     HV
3947       *hv;
3948
3949     Image
3950       *image;
3951
3952     MagickEvaluateOperator
3953       op;
3954
3955     register ssize_t
3956       i;
3957
3958     struct PackageInfo
3959       *info;
3960
3961     SV
3962       *perl_exception,
3963       *reference,
3964       *rv,
3965       *sv;
3966
3967     PERL_UNUSED_VAR(ref);
3968     PERL_UNUSED_VAR(ix);
3969     exception=AcquireExceptionInfo();
3970     perl_exception=newSVpv("",0);
3971     sv=NULL;
3972     if (sv_isobject(ST(0)) == 0)
3973       {
3974         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3975           PackageName);
3976         goto PerlException;
3977       }
3978     reference=SvRV(ST(0));
3979     hv=SvSTASH(reference);
3980     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3981     if (image == (Image *) NULL)
3982       {
3983         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3984           PackageName);
3985         goto PerlException;
3986       }
3987     op=MeanEvaluateOperator;
3988     if (items == 2)
3989       {
3990         ssize_t
3991           in;
3992
3993         in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
3994           SvPV(ST(1),na));
3995         if (in < 0)
3996           {
3997             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3998               SvPV(ST(1),na));
3999             return;
4000           }
4001         op=(MagickEvaluateOperator) in;
4002       }
4003     else
4004       for (i=2; i < items; i+=2)
4005       {
4006         attribute=(char *) SvPV(ST(i-1),na);
4007         switch (*attribute)
4008         {
4009           case 'O':
4010           case 'o':
4011           {
4012             if (LocaleCompare(attribute,"operator") == 0)
4013               {
4014                 ssize_t
4015                   in;
4016
4017                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
4018                   MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
4019                 if (in < 0)
4020                   {
4021                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
4022                       SvPV(ST(i),na));
4023                     return;
4024                   }
4025                 op=(MagickEvaluateOperator) in;
4026                 break;
4027               }
4028             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4029               attribute);
4030             break;
4031           }
4032           default:
4033           {
4034             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4035               attribute);
4036             break;
4037           }
4038         }
4039       }
4040     image=EvaluateImages(image,op,exception);
4041     if (image == (Image *) NULL)
4042       goto PerlException;
4043     /*
4044       Create blessed Perl array for the returned image.
4045     */
4046     av=newAV();
4047     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4048     SvREFCNT_dec(av);
4049     AddImageToRegistry(sv,image);
4050     rv=newRV(sv);
4051     av_push(av,sv_bless(rv,hv));
4052     SvREFCNT_dec(sv);
4053     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4054     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4055       "evaluate-%.*s",(int) (MagickPathExtent-9),
4056       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4057     (void) CopyMagickString(image->filename,info->image_info->filename,
4058       MagickPathExtent);
4059     SetImageInfo(info->image_info,0,exception);
4060     exception=DestroyExceptionInfo(exception);
4061     SvREFCNT_dec(perl_exception);
4062     XSRETURN(1);
4063
4064   PerlException:
4065     InheritPerlException(exception,perl_exception);
4066     exception=DestroyExceptionInfo(exception);
4067     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4068     SvPOK_on(perl_exception);
4069     ST(0)=sv_2mortal(perl_exception);
4070     XSRETURN(1);
4071   }
4072 \f
4073 #
4074 ###############################################################################
4075 #                                                                             #
4076 #                                                                             #
4077 #                                                                             #
4078 #   F e a t u r e s                                                           #
4079 #                                                                             #
4080 #                                                                             #
4081 #                                                                             #
4082 ###############################################################################
4083 #
4084 #
4085 void
4086 Features(ref,...)
4087   Image::Magick ref=NO_INIT
4088   ALIAS:
4089     FeaturesImage = 1
4090     features      = 2
4091     featuresimage = 3
4092   PPCODE:
4093   {
4094 #define ChannelFeatures(channel,direction) \
4095 { \
4096   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4097     channel_features[channel].angular_second_moment[direction]); \
4098   PUSHs(sv_2mortal(newSVpv(message,0))); \
4099   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4100     channel_features[channel].contrast[direction]); \
4101   PUSHs(sv_2mortal(newSVpv(message,0))); \
4102   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4103     channel_features[channel].contrast[direction]); \
4104   PUSHs(sv_2mortal(newSVpv(message,0))); \
4105   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4106     channel_features[channel].variance_sum_of_squares[direction]); \
4107   PUSHs(sv_2mortal(newSVpv(message,0))); \
4108   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4109     channel_features[channel].inverse_difference_moment[direction]); \
4110   PUSHs(sv_2mortal(newSVpv(message,0))); \
4111   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4112     channel_features[channel].sum_average[direction]); \
4113   PUSHs(sv_2mortal(newSVpv(message,0))); \
4114   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4115     channel_features[channel].sum_variance[direction]); \
4116   PUSHs(sv_2mortal(newSVpv(message,0))); \
4117   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4118     channel_features[channel].sum_entropy[direction]); \
4119   PUSHs(sv_2mortal(newSVpv(message,0))); \
4120   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4121     channel_features[channel].entropy[direction]); \
4122   PUSHs(sv_2mortal(newSVpv(message,0))); \
4123   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4124     channel_features[channel].difference_variance[direction]); \
4125   PUSHs(sv_2mortal(newSVpv(message,0))); \
4126   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4127     channel_features[channel].difference_entropy[direction]); \
4128   PUSHs(sv_2mortal(newSVpv(message,0))); \
4129   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4130     channel_features[channel].measure_of_correlation_1[direction]); \
4131   PUSHs(sv_2mortal(newSVpv(message,0))); \
4132   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4133     channel_features[channel].measure_of_correlation_2[direction]); \
4134   PUSHs(sv_2mortal(newSVpv(message,0))); \
4135   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4136     channel_features[channel].maximum_correlation_coefficient[direction]); \
4137   PUSHs(sv_2mortal(newSVpv(message,0))); \
4138 }
4139
4140     AV
4141       *av;
4142
4143     char
4144       *attribute,
4145       message[MagickPathExtent];
4146
4147     ChannelFeatures
4148       *channel_features;
4149
4150     double
4151       distance;
4152
4153     ExceptionInfo
4154       *exception;
4155
4156     Image
4157       *image;
4158
4159     register ssize_t
4160       i;
4161
4162     ssize_t
4163       count;
4164
4165     struct PackageInfo
4166       *info;
4167
4168     SV
4169       *perl_exception,
4170       *reference;
4171
4172     PERL_UNUSED_VAR(ref);
4173     PERL_UNUSED_VAR(ix);
4174     exception=AcquireExceptionInfo();
4175     perl_exception=newSVpv("",0);
4176     av=NULL;
4177     if (sv_isobject(ST(0)) == 0)
4178       {
4179         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4180           PackageName);
4181         goto PerlException;
4182       }
4183     reference=SvRV(ST(0));
4184     av=newAV();
4185     SvREFCNT_dec(av);
4186     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4187     if (image == (Image *) NULL)
4188       {
4189         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4190           PackageName);
4191         goto PerlException;
4192       }
4193     distance=1.0;
4194     for (i=2; i < items; i+=2)
4195     {
4196       attribute=(char *) SvPV(ST(i-1),na);
4197       switch (*attribute)
4198       {
4199         case 'D':
4200         case 'd':
4201         {
4202           if (LocaleCompare(attribute,"distance") == 0)
4203             {
4204               distance=StringToLong((char *) SvPV(ST(1),na));
4205               break;
4206             }
4207           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4208             attribute);
4209           break;
4210         }
4211         default:
4212         {
4213           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4214             attribute);
4215           break;
4216         }
4217       }
4218     }
4219     count=0;
4220     for ( ; image; image=image->next)
4221     {
4222       channel_features=GetImageFeatures(image,distance,exception);
4223       if (channel_features == (ChannelFeatures *) NULL)
4224         continue;
4225       count++;
4226       EXTEND(sp,280*count);
4227       for (i=0; i < 4; i++)
4228       {
4229         ChannelFeatures(RedChannel,i);
4230         ChannelFeatures(GreenChannel,i);
4231         ChannelFeatures(BlueChannel,i);
4232         if (image->colorspace == CMYKColorspace)
4233           ChannelFeatures(BlackChannel,i);
4234         if (image->alpha_trait != UndefinedPixelTrait)
4235           ChannelFeatures(AlphaChannel,i);
4236       }
4237       channel_features=(ChannelFeatures *)
4238         RelinquishMagickMemory(channel_features);
4239     }
4240
4241   PerlException:
4242     InheritPerlException(exception,perl_exception);
4243     exception=DestroyExceptionInfo(exception);
4244     SvREFCNT_dec(perl_exception);
4245   }
4246 \f
4247 #
4248 ###############################################################################
4249 #                                                                             #
4250 #                                                                             #
4251 #                                                                             #
4252 #   F l a t t e n                                                             #
4253 #                                                                             #
4254 #                                                                             #
4255 #                                                                             #
4256 ###############################################################################
4257 #
4258 #
4259 void
4260 Flatten(ref)
4261   Image::Magick ref=NO_INIT
4262   ALIAS:
4263     FlattenImage   = 1
4264     flatten        = 2
4265     flattenimage   = 3
4266   PPCODE:
4267   {
4268     AV
4269       *av;
4270
4271     char
4272       *attribute,
4273       *p;
4274
4275     ExceptionInfo
4276       *exception;
4277
4278     HV
4279       *hv;
4280
4281     Image
4282       *image;
4283
4284     PixelInfo
4285       background_color;
4286
4287     register ssize_t
4288       i;
4289
4290     struct PackageInfo
4291       *info;
4292
4293     SV
4294       *perl_exception,
4295       *reference,
4296       *rv,
4297       *sv;
4298
4299     PERL_UNUSED_VAR(ref);
4300     PERL_UNUSED_VAR(ix);
4301     exception=AcquireExceptionInfo();
4302     perl_exception=newSVpv("",0);
4303     sv=NULL;
4304     if (sv_isobject(ST(0)) == 0)
4305       {
4306         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4307           PackageName);
4308         goto PerlException;
4309       }
4310     reference=SvRV(ST(0));
4311     hv=SvSTASH(reference);
4312     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4313     if (image == (Image *) NULL)
4314       {
4315         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4316           PackageName);
4317         goto PerlException;
4318       }
4319     background_color=image->background_color;
4320     if (items == 2)
4321       (void) QueryColorCompliance((char *) SvPV(ST(1),na),AllCompliance,
4322         &background_color,exception);
4323     else
4324       for (i=2; i < items; i+=2)
4325       {
4326         attribute=(char *) SvPV(ST(i-1),na);
4327         switch (*attribute)
4328         {
4329           case 'B':
4330           case 'b':
4331           {
4332             if (LocaleCompare(attribute,"background") == 0)
4333               {
4334                 (void) QueryColorCompliance((char *) SvPV(ST(1),na),
4335                   AllCompliance,&background_color,exception);
4336                 break;
4337               }
4338             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4339               attribute);
4340             break;
4341           }
4342           default:
4343           {
4344             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4345               attribute);
4346             break;
4347           }
4348         }
4349       }
4350     image->background_color=background_color;
4351     image=MergeImageLayers(image,FlattenLayer,exception);
4352     if (image == (Image *) NULL)
4353       goto PerlException;
4354     /*
4355       Create blessed Perl array for the returned image.
4356     */
4357     av=newAV();
4358     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4359     SvREFCNT_dec(av);
4360     AddImageToRegistry(sv,image);
4361     rv=newRV(sv);
4362     av_push(av,sv_bless(rv,hv));
4363     SvREFCNT_dec(sv);
4364     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4365     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4366       "flatten-%.*s",(int) (MagickPathExtent-9),
4367       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4368     (void) CopyMagickString(image->filename,info->image_info->filename,
4369       MagickPathExtent);
4370     SetImageInfo(info->image_info,0,exception);
4371     exception=DestroyExceptionInfo(exception);
4372     SvREFCNT_dec(perl_exception);
4373     XSRETURN(1);
4374
4375   PerlException:
4376     InheritPerlException(exception,perl_exception);
4377     exception=DestroyExceptionInfo(exception);
4378     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4379     SvPOK_on(perl_exception);  /* return messages in string context */
4380     ST(0)=sv_2mortal(perl_exception);
4381     XSRETURN(1);
4382   }
4383 \f
4384 #
4385 ###############################################################################
4386 #                                                                             #
4387 #                                                                             #
4388 #                                                                             #
4389 #   F x                                                                       #
4390 #                                                                             #
4391 #                                                                             #
4392 #                                                                             #
4393 ###############################################################################
4394 #
4395 #
4396 void
4397 Fx(ref,...)
4398   Image::Magick ref=NO_INIT
4399   ALIAS:
4400     FxImage  = 1
4401     fx       = 2
4402     fximage  = 3
4403   PPCODE:
4404   {
4405     AV
4406       *av;
4407
4408     char
4409       *attribute,
4410       expression[MagickPathExtent];
4411
4412     ChannelType
4413       channel,
4414       channel_mask;
4415
4416     ExceptionInfo
4417       *exception;
4418
4419     HV
4420       *hv;
4421
4422     Image
4423       *image;
4424
4425     register ssize_t
4426       i;
4427
4428     struct PackageInfo
4429       *info;
4430
4431     SV
4432       *av_reference,
4433       *perl_exception,
4434       *reference,
4435       *rv,
4436       *sv;
4437
4438     PERL_UNUSED_VAR(ref);
4439     PERL_UNUSED_VAR(ix);
4440     exception=AcquireExceptionInfo();
4441     perl_exception=newSVpv("",0);
4442     sv=NULL;
4443     attribute=NULL;
4444     av=NULL;
4445     if (sv_isobject(ST(0)) == 0)
4446       {
4447         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4448           PackageName);
4449         goto PerlException;
4450       }
4451     reference=SvRV(ST(0));
4452     hv=SvSTASH(reference);
4453     av=newAV();
4454     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4455     SvREFCNT_dec(av);
4456     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4457     if (image == (Image *) NULL)
4458       {
4459         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4460           PackageName);
4461         goto PerlException;
4462       }
4463     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4464     /*
4465       Get options.
4466     */
4467     channel=DefaultChannels;
4468     (void) CopyMagickString(expression,"u",MagickPathExtent);
4469     if (items == 2)
4470       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
4471     else
4472       for (i=2; i < items; i+=2)
4473       {
4474         attribute=(char *) SvPV(ST(i-1),na);
4475         switch (*attribute)
4476         {
4477           case 'C':
4478           case 'c':
4479           {
4480             if (LocaleCompare(attribute,"channel") == 0)
4481               {
4482                 ssize_t
4483                   option;
4484
4485                 option=ParseChannelOption(SvPV(ST(i),na));
4486                 if (option < 0)
4487                   {
4488                     ThrowPerlException(exception,OptionError,
4489                       "UnrecognizedType",SvPV(ST(i),na));
4490                     return;
4491                   }
4492                 channel=(ChannelType) option;
4493                 break;
4494               }
4495             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4496               attribute);
4497             break;
4498           }
4499           case 'E':
4500           case 'e':
4501           {
4502             if (LocaleCompare(attribute,"expression") == 0)
4503               {
4504                 (void) CopyMagickString(expression,SvPV(ST(i),na),
4505                   MagickPathExtent);
4506                 break;
4507               }
4508             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4509               attribute);
4510             break;
4511           }
4512           default:
4513           {
4514             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4515               attribute);
4516             break;
4517           }
4518         }
4519       }
4520     channel_mask=SetImageChannelMask(image,channel);
4521     image=FxImage(image,expression,exception);
4522     if (image != (Image *) NULL)
4523       (void) SetImageChannelMask(image,channel_mask);
4524     if (image == (Image *) NULL)
4525       goto PerlException;
4526     for ( ; image; image=image->next)
4527     {
4528       AddImageToRegistry(sv,image);
4529       rv=newRV(sv);
4530       av_push(av,sv_bless(rv,hv));
4531       SvREFCNT_dec(sv);
4532     }
4533     exception=DestroyExceptionInfo(exception);
4534     ST(0)=av_reference;
4535     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4536     XSRETURN(1);
4537
4538   PerlException:
4539     InheritPerlException(exception,perl_exception);
4540     exception=DestroyExceptionInfo(exception);
4541     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4542     SvPOK_on(perl_exception);
4543     ST(0)=sv_2mortal(perl_exception);
4544     XSRETURN(1);
4545   }
4546 \f
4547 #
4548 ###############################################################################
4549 #                                                                             #
4550 #                                                                             #
4551 #                                                                             #
4552 #   G e t                                                                     #
4553 #                                                                             #
4554 #                                                                             #
4555 #                                                                             #
4556 ###############################################################################
4557 #
4558 #
4559 void
4560 Get(ref,...)
4561   Image::Magick ref=NO_INIT
4562   ALIAS:
4563     GetAttributes = 1
4564     GetAttribute  = 2
4565     get           = 3
4566     getattributes = 4
4567     getattribute  = 5
4568   PPCODE:
4569   {
4570     char
4571       *attribute,
4572       color[MagickPathExtent];
4573
4574     const char
4575       *value;
4576
4577     ExceptionInfo
4578       *exception;
4579
4580     Image
4581       *image;
4582
4583     long
4584       j;
4585
4586     register ssize_t
4587       i;
4588
4589     struct PackageInfo
4590       *info;
4591
4592     SV
4593       *perl_exception,
4594       *reference,
4595       *s;
4596
4597     PERL_UNUSED_VAR(ref);
4598     PERL_UNUSED_VAR(ix);
4599     exception=AcquireExceptionInfo();
4600     perl_exception=newSVpv("",0);
4601     if (sv_isobject(ST(0)) == 0)
4602       {
4603         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4604           PackageName);
4605         XSRETURN_EMPTY;
4606       }
4607     reference=SvRV(ST(0));
4608     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4609     if (image == (Image *) NULL && !info)
4610       XSRETURN_EMPTY;
4611     EXTEND(sp,items);
4612     for (i=1; i < items; i++)
4613     {
4614       attribute=(char *) SvPV(ST(i),na);
4615       s=NULL;
4616       switch (*attribute)
4617       {
4618         case 'A':
4619         case 'a':
4620         {
4621           if (LocaleCompare(attribute,"adjoin") == 0)
4622             {
4623               if (info)
4624                 s=newSViv((ssize_t) info->image_info->adjoin);
4625               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4626               continue;
4627             }
4628           if (LocaleCompare(attribute,"antialias") == 0)
4629             {
4630               if (info)
4631                 s=newSViv((ssize_t) info->image_info->antialias);
4632               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4633               continue;
4634             }
4635           if (LocaleCompare(attribute,"area") == 0)
4636             {
4637               s=newSViv(GetMagickResource(AreaResource));
4638               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4639               continue;
4640             }
4641           if (LocaleCompare(attribute,"attenuate") == 0)
4642             {
4643               const char
4644                 *value;
4645
4646               value=GetImageProperty(image,attribute,exception);
4647               if (value != (const char *) NULL)
4648                 s=newSVpv(value,0);
4649               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4650               continue;
4651             }
4652           if (LocaleCompare(attribute,"authenticate") == 0)
4653             {
4654               if (info)
4655                 {
4656                   const char
4657                     *option;
4658
4659                   option=GetImageOption(info->image_info,attribute);
4660                   if (option != (const char *) NULL)
4661                     s=newSVpv(option,0);
4662                 }
4663               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4664               continue;
4665             }
4666           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4667             attribute);
4668           break;
4669         }
4670         case 'B':
4671         case 'b':
4672         {
4673           if (LocaleCompare(attribute,"background") == 0)
4674             {
4675               if (image == (Image *) NULL)
4676                 break;
4677               (void) FormatLocaleString(color,MagickPathExtent,
4678                 "%.20g,%.20g,%.20g,%.20g",(double) image->background_color.red,
4679                 (double) image->background_color.green,
4680                 (double) image->background_color.blue,
4681                 (double) image->background_color.alpha);
4682               s=newSVpv(color,0);
4683               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4684               continue;
4685             }
4686           if (LocaleCompare(attribute,"base-columns") == 0)
4687             {
4688               if (image != (Image *) NULL)
4689                 s=newSViv((ssize_t) image->magick_columns);
4690               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4691               continue;
4692             }
4693           if (LocaleCompare(attribute,"base-filename") == 0)
4694             {
4695               if (image != (Image *) NULL)
4696                 s=newSVpv(image->magick_filename,0);
4697               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4698               continue;
4699             }
4700           if (LocaleCompare(attribute,"base-height") == 0)
4701             {
4702               if (image != (Image *) NULL)
4703                 s=newSViv((ssize_t) image->magick_rows);
4704               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4705               continue;
4706             }
4707           if (LocaleCompare(attribute,"base-rows") == 0)
4708             {
4709               if (image != (Image *) NULL)
4710                 s=newSViv((ssize_t) image->magick_rows);
4711               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4712               continue;
4713             }
4714           if (LocaleCompare(attribute,"base-width") == 0)
4715             {
4716               if (image != (Image *) NULL)
4717                 s=newSViv((ssize_t) image->magick_columns);
4718               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4719               continue;
4720             }
4721           if (LocaleCompare(attribute,"blue-primary") == 0)
4722             {
4723               if (image == (Image *) NULL)
4724                 break;
4725               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
4726                 image->chromaticity.blue_primary.x,
4727                 image->chromaticity.blue_primary.y);
4728               s=newSVpv(color,0);
4729               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4730               continue;
4731             }
4732           if (LocaleCompare(attribute,"bordercolor") == 0)
4733             {
4734               if (image == (Image *) NULL)
4735                 break;
4736               (void) FormatLocaleString(color,MagickPathExtent,
4737                 "%.20g,%.20g,%.20g,%.20g",(double) image->border_color.red,
4738                 (double) image->border_color.green,
4739                 (double) image->border_color.blue,
4740                 (double) image->border_color.alpha);
4741               s=newSVpv(color,0);
4742               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4743               continue;
4744             }
4745           if (LocaleCompare(attribute,"bounding-box") == 0)
4746             {
4747               char
4748                 geometry[MagickPathExtent];
4749
4750               RectangleInfo
4751                 page;
4752
4753               if (image == (Image *) NULL)
4754                 break;
4755               page=GetImageBoundingBox(image,exception);
4756               (void) FormatLocaleString(geometry,MagickPathExtent,
4757                 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4758                 page.height,(double) page.x,(double) page.y);
4759               s=newSVpv(geometry,0);
4760               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4761               continue;
4762             }
4763           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4764             attribute);
4765           break;
4766         }
4767         case 'C':
4768         case 'c':
4769         {
4770           if (LocaleCompare(attribute,"class") == 0)
4771             {
4772               if (image == (Image *) NULL)
4773                 break;
4774               s=newSViv(image->storage_class);
4775               (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4776                 image->storage_class));
4777               SvIOK_on(s);
4778               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4779               continue;
4780             }
4781           if (LocaleCompare(attribute,"clip-mask") == 0)
4782             {
4783               if (image != (Image *) NULL)
4784                 {
4785                   Image
4786                     *mask_image;
4787
4788                   SV
4789                     *sv;
4790
4791                   sv=NULL;
4792                   if (image->read_mask == MagickFalse)
4793                     ClipImage(image,exception);
4794                   mask_image=GetImageMask(image,exception);
4795                   if (mask_image != (Image *) NULL)
4796                     {
4797                       AddImageToRegistry(sv,mask_image);
4798                       s=sv_bless(newRV(sv),SvSTASH(reference));
4799                     }
4800                 }
4801               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4802               continue;
4803             }
4804           if (LocaleCompare(attribute,"clip-path") == 0)
4805             {
4806               if (image != (Image *) NULL)
4807                 {
4808                   Image
4809                     *mask_image;
4810
4811                   SV
4812                     *sv;
4813
4814                   sv=NULL;
4815                   if (image->read_mask != MagickFalse)
4816                     ClipImage(image,exception);
4817                   mask_image=GetImageMask(image,exception);
4818                   if (mask_image != (Image *) NULL)
4819                     {
4820                       AddImageToRegistry(sv,mask_image);
4821                       s=sv_bless(newRV(sv),SvSTASH(reference));
4822                     }
4823                 }
4824               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4825               continue;
4826             }
4827           if (LocaleCompare(attribute,"compression") == 0)
4828             {
4829               j=info ? info->image_info->compression : image ?
4830                 image->compression : UndefinedCompression;
4831               if (info)
4832                 if (info->image_info->compression == UndefinedCompression)
4833                   j=image->compression;
4834               s=newSViv(j);
4835               (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4836                 j));
4837               SvIOK_on(s);
4838               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4839               continue;
4840             }
4841           if (LocaleCompare(attribute,"colorspace") == 0)
4842             {
4843               j=image ? image->colorspace : RGBColorspace;
4844               s=newSViv(j);
4845               (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4846                 j));
4847               SvIOK_on(s);
4848               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4849               continue;
4850             }
4851           if (LocaleCompare(attribute,"colors") == 0)
4852             {
4853               if (image != (Image *) NULL)
4854                 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4855                   exception));
4856               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4857               continue;
4858             }
4859           if (LocaleNCompare(attribute,"colormap",8) == 0)
4860             {
4861               int
4862                 items;
4863
4864               if (image == (Image *) NULL || !image->colormap)
4865                 break;
4866               j=0;
4867               items=sscanf(attribute,"%*[^[][%ld",&j);
4868               (void) items;
4869               if (j > (ssize_t) image->colors)
4870                 j%=image->colors;
4871               (void) FormatLocaleString(color,MagickPathExtent,
4872                 "%.20g,%.20g,%.20g,%.20g",(double) image->colormap[j].red,
4873                 (double) image->colormap[j].green,
4874                 (double) image->colormap[j].blue,
4875                 (double) image->colormap[j].alpha);
4876               s=newSVpv(color,0);
4877               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4878               continue;
4879             }
4880           if (LocaleCompare(attribute,"columns") == 0)
4881             {
4882               if (image != (Image *) NULL)
4883                 s=newSViv((ssize_t) image->columns);
4884               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4885               continue;
4886             }
4887           if (LocaleCompare(attribute,"comment") == 0)
4888             {
4889               const char
4890                 *value;
4891
4892               value=GetImageProperty(image,attribute,exception);
4893               if (value != (const char *) NULL)
4894                 s=newSVpv(value,0);
4895               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4896               continue;
4897             }
4898           if (LocaleCompare(attribute,"copyright") == 0)
4899             {
4900               s=newSVpv(GetMagickCopyright(),0);
4901               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4902               continue;
4903             }
4904           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4905             attribute);
4906           break;
4907         }
4908         case 'D':
4909         case 'd':
4910         {
4911           if (LocaleCompare(attribute,"density") == 0)
4912             {
4913               char
4914                 geometry[MagickPathExtent];
4915
4916               if (image == (Image *) NULL)
4917                 break;
4918               (void) FormatLocaleString(geometry,MagickPathExtent,"%.15gx%.15g",
4919                 image->resolution.x,image->resolution.y);
4920               s=newSVpv(geometry,0);
4921               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4922               continue;
4923             }
4924           if (LocaleCompare(attribute,"delay") == 0)
4925             {
4926               if (image != (Image *) NULL)
4927                 s=newSViv((ssize_t) image->delay);
4928               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4929               continue;
4930             }
4931           if (LocaleCompare(attribute,"depth") == 0)
4932             {
4933               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4934               if (image != (Image *) NULL)
4935                 s=newSViv((ssize_t) GetImageDepth(image,exception));
4936               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4937               continue;
4938             }
4939           if (LocaleCompare(attribute,"directory") == 0)
4940             {
4941               if (image && image->directory)
4942                 s=newSVpv(image->directory,0);
4943               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4944               continue;
4945             }
4946           if (LocaleCompare(attribute,"dispose") == 0)
4947             {
4948               if (image == (Image *) NULL)
4949                 break;
4950
4951               s=newSViv(image->dispose);
4952               (void) sv_setpv(s,
4953                 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
4954               SvIOK_on(s);
4955               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4956               continue;
4957             }
4958           if (LocaleCompare(attribute,"disk") == 0)
4959             {
4960               s=newSViv(GetMagickResource(DiskResource));
4961               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4962               continue;
4963             }
4964           if (LocaleCompare(attribute,"dither") == 0)
4965             {
4966               if (info)
4967                 s=newSViv((ssize_t) info->image_info->dither);
4968               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4969               continue;
4970             }
4971           if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4972             {
4973               if (info && info->image_info->server_name)
4974                 s=newSVpv(info->image_info->server_name,0);
4975               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4976               continue;
4977             }
4978           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4979             attribute);
4980           break;
4981         }
4982         case 'E':
4983         case 'e':
4984         {
4985           if (LocaleCompare(attribute,"elapsed-time") == 0)
4986             {
4987               if (image != (Image *) NULL)
4988                 s=newSVnv(GetElapsedTime(&image->timer));
4989               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4990               continue;
4991             }
4992           if (LocaleCompare(attribute,"endian") == 0)
4993             {
4994               j=info ? info->image_info->endian : image ? image->endian :
4995                 UndefinedEndian;
4996               s=newSViv(j);
4997               (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
4998               SvIOK_on(s);
4999               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5000               continue;
5001             }
5002           if (LocaleCompare(attribute,"error") == 0)
5003             {
5004               if (image != (Image *) NULL)
5005                 s=newSVnv(image->error.mean_error_per_pixel);
5006               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5007               continue;
5008             }
5009           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5010             attribute);
5011           break;
5012         }
5013         case 'F':
5014         case 'f':
5015         {
5016           if (LocaleCompare(attribute,"filesize") == 0)
5017             {
5018               if (image != (Image *) NULL)
5019                 s=newSViv((ssize_t) GetBlobSize(image));
5020               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5021               continue;
5022             }
5023           if (LocaleCompare(attribute,"filename") == 0)
5024             {
5025               if (info && info->image_info->filename &&
5026                   *info->image_info->filename)
5027                 s=newSVpv(info->image_info->filename,0);
5028               if (image != (Image *) NULL)
5029                 s=newSVpv(image->filename,0);
5030               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5031               continue;
5032             }
5033           if (LocaleCompare(attribute,"filter") == 0)
5034             {
5035               s=image ? newSViv(image->filter) : newSViv(0);
5036               (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
5037                 image->filter));
5038               SvIOK_on(s);
5039               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5040               continue;
5041             }
5042           if (LocaleCompare(attribute,"font") == 0)
5043             {
5044               if (info && info->image_info->font)
5045                 s=newSVpv(info->image_info->font,0);
5046               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5047               continue;
5048             }
5049           if (LocaleCompare(attribute,"foreground") == 0)
5050             continue;
5051           if (LocaleCompare(attribute,"format") == 0)
5052             {
5053               const MagickInfo
5054                 *magick_info;
5055
5056               magick_info=(const MagickInfo *) NULL;
5057               if (info && (*info->image_info->magick != '\0'))
5058                 magick_info=GetMagickInfo(info->image_info->magick,exception);
5059               if (image != (Image *) NULL)
5060                 magick_info=GetMagickInfo(image->magick,exception);
5061               if ((magick_info != (const MagickInfo *) NULL) &&
5062                   (*magick_info->description != '\0'))
5063                 s=newSVpv((char *) magick_info->description,0);
5064               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5065               continue;
5066             }
5067           if (LocaleCompare(attribute,"fuzz") == 0)
5068             {
5069               if (info)
5070                 s=newSVnv(info->image_info->fuzz);
5071               if (image != (Image *) NULL)
5072                 s=newSVnv(image->fuzz);
5073               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5074               continue;
5075             }
5076           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5077             attribute);
5078           break;
5079         }
5080         case 'G':
5081         case 'g':
5082         {
5083           if (LocaleCompare(attribute,"gamma") == 0)
5084             {
5085               if (image != (Image *) NULL)
5086                 s=newSVnv(image->gamma);
5087               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5088               continue;
5089             }
5090           if (LocaleCompare(attribute,"geometry") == 0)
5091             {
5092               if (image && image->geometry)
5093                 s=newSVpv(image->geometry,0);
5094               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5095               continue;
5096             }
5097           if (LocaleCompare(attribute,"gravity") == 0)
5098             {
5099               s=image ? newSViv(image->gravity) : newSViv(0);
5100               (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
5101                 image->gravity));
5102               SvIOK_on(s);
5103               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5104               continue;
5105             }
5106           if (LocaleCompare(attribute,"green-primary") == 0)
5107             {
5108               if (image == (Image *) NULL)
5109                 break;
5110               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
5111                 image->chromaticity.green_primary.x,
5112                 image->chromaticity.green_primary.y);
5113               s=newSVpv(color,0);
5114               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5115               continue;
5116             }
5117           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5118             attribute);
5119           break;
5120         }
5121         case 'H':
5122         case 'h':
5123         {
5124           if (LocaleCompare(attribute,"height") == 0)
5125             {
5126               if (image != (Image *) NULL)
5127                 s=newSViv((ssize_t) image->rows);
5128               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5129               continue;
5130             }
5131           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5132             attribute);
5133           break;
5134         }
5135         case 'I':
5136         case 'i':
5137         {
5138           if (LocaleCompare(attribute,"icc") == 0)
5139             {
5140               if (image != (Image *) NULL)
5141                 {
5142                   const StringInfo
5143                     *profile;
5144
5145                   profile=GetImageProfile(image,"icc");
5146                   if (profile != (StringInfo *) NULL)
5147                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5148                       GetStringInfoLength(profile));
5149                 }
5150               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5151               continue;
5152             }
5153           if (LocaleCompare(attribute,"icm") == 0)
5154             {
5155               if (image != (Image *) NULL)
5156                 {
5157                   const StringInfo
5158                     *profile;
5159
5160                   profile=GetImageProfile(image,"icm");
5161                   if (profile != (const StringInfo *) NULL)
5162                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5163                       GetStringInfoLength(profile));
5164                 }
5165               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5166               continue;
5167             }
5168           if (LocaleCompare(attribute,"id") == 0)
5169             {
5170               if (image != (Image *) NULL)
5171                 {
5172                   char
5173                     key[MagickPathExtent];
5174
5175                   MagickBooleanType
5176                     status;
5177
5178                   static ssize_t
5179                     id = 0;
5180
5181                   (void) FormatLocaleString(key,MagickPathExtent,"%.20g\n",(double)
5182                     id);
5183                   status=SetImageRegistry(ImageRegistryType,key,image,
5184                     exception);
5185                   (void) status;
5186                   s=newSViv(id++);
5187                 }
5188               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5189               continue;
5190             }
5191           if (LocaleNCompare(attribute,"index",5) == 0)
5192             {
5193               char
5194                 name[MagickPathExtent];
5195
5196               int
5197                 items;
5198
5199               long
5200                 x,
5201                 y;
5202
5203               register const Quantum
5204                 *p;
5205
5206               CacheView
5207                 *image_view;
5208
5209               if (image == (Image *) NULL)
5210                 break;
5211               if (image->storage_class != PseudoClass)
5212                 break;
5213               x=0;
5214               y=0;
5215               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5216               (void) items;
5217               image_view=AcquireVirtualCacheView(image,exception);
5218               p=GetCacheViewVirtualPixels(image_view,x,y,1,1,exception);
5219               if (p != (const Quantum *) NULL)
5220                 {
5221                   (void) FormatLocaleString(name,MagickPathExtent,QuantumFormat,
5222                     GetPixelIndex(image,p));
5223                   s=newSVpv(name,0);
5224                   PUSHs(s ? sv_2mortal(s) : &sv_undef);
5225                 }
5226               image_view=DestroyCacheView(image_view);
5227               continue;
5228             }
5229           if (LocaleCompare(attribute,"iptc") == 0)
5230             {
5231               if (image != (Image *) NULL)
5232                 {
5233                   const StringInfo
5234                     *profile;
5235
5236                   profile=GetImageProfile(image,"iptc");
5237                   if (profile != (const StringInfo *) NULL)
5238                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5239                       GetStringInfoLength(profile));
5240                 }
5241               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5242               continue;
5243             }
5244           if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
5245             {
5246               if (image != (Image *) NULL)
5247                 s=newSViv((ssize_t) image->iterations);
5248               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5249               continue;
5250             }
5251           if (LocaleCompare(attribute,"interlace") == 0)
5252             {
5253               j=info ? info->image_info->interlace : image ? image->interlace :
5254                 UndefinedInterlace;
5255               s=newSViv(j);
5256               (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
5257                 j));
5258               SvIOK_on(s);
5259               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5260               continue;
5261             }
5262           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5263             attribute);
5264           break;
5265         }
5266         case 'L':
5267         case 'l':
5268         {
5269           if (LocaleCompare(attribute,"label") == 0)
5270             {
5271               const char
5272                 *value;
5273
5274               if (image == (Image *) NULL)
5275                 break;
5276               value=GetImageProperty(image,"Label",exception);
5277               if (value != (const char *) NULL)
5278                 s=newSVpv(value,0);
5279               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5280               continue;
5281             }
5282           if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
5283             {
5284               if (image != (Image *) NULL)
5285                 s=newSViv((ssize_t) image->iterations);
5286               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5287               continue;
5288             }
5289           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5290             attribute);
5291           break;
5292         }
5293         case 'M':
5294         case 'm':
5295         {
5296           if (LocaleCompare(attribute,"magick") == 0)
5297             {
5298               if (info && *info->image_info->magick)
5299                 s=newSVpv(info->image_info->magick,0);
5300               if (image != (Image *) NULL)
5301                 s=newSVpv(image->magick,0);
5302               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5303               continue;
5304             }
5305           if (LocaleCompare(attribute,"map") == 0)
5306             {
5307               s=newSViv(GetMagickResource(MapResource));
5308               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5309               continue;
5310             }
5311           if (LocaleCompare(attribute,"maximum-error") == 0)
5312             {
5313               if (image != (Image *) NULL)
5314                 s=newSVnv(image->error.normalized_maximum_error);
5315               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5316               continue;
5317             }
5318           if (LocaleCompare(attribute,"memory") == 0)
5319             {
5320               s=newSViv(GetMagickResource(MemoryResource));
5321               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5322               continue;
5323             }
5324           if (LocaleCompare(attribute,"mean-error") == 0)
5325             {
5326               if (image != (Image *) NULL)
5327                 s=newSVnv(image->error.normalized_mean_error);
5328               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5329               continue;
5330             }
5331           if (LocaleCompare(attribute,"mime") == 0)
5332             {
5333               if (info && *info->image_info->magick)
5334                 s=newSVpv(MagickToMime(info->image_info->magick),0);
5335               if (image != (Image *) NULL)
5336                 s=newSVpv(MagickToMime(image->magick),0);
5337               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5338               continue;
5339             }
5340           if (LocaleCompare(attribute,"mattecolor") == 0)
5341             {
5342               if (image == (Image *) NULL)
5343                 break;
5344               (void) FormatLocaleString(color,MagickPathExtent,
5345                 "%.20g,%.20g,%.20g,%.20g",(double) image->matte_color.red,
5346                 (double) image->matte_color.green,
5347                 (double) image->matte_color.blue,
5348                 (double) image->matte_color.alpha);
5349               s=newSVpv(color,0);
5350               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5351               continue;
5352             }
5353           if (LocaleCompare(attribute,"matte") == 0)
5354             {
5355               if (image != (Image *) NULL)
5356                 s=newSViv((ssize_t) image->alpha_trait != UndefinedPixelTrait ?
5357                   1 : 0);
5358               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5359               continue;
5360             }
5361           if (LocaleCompare(attribute,"mime") == 0)
5362             {
5363               const char
5364                 *magick;
5365
5366               magick=NULL;
5367               if (info && *info->image_info->magick)
5368                 magick=info->image_info->magick;
5369               if (image != (Image *) NULL)
5370                 magick=image->magick;
5371               if (magick)
5372                 {
5373                   char
5374                     *mime;
5375
5376                   mime=MagickToMime(magick);
5377                   s=newSVpv(mime,0);
5378                   mime=(char *) RelinquishMagickMemory(mime);
5379                 }
5380               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5381               continue;
5382             }
5383           if (LocaleCompare(attribute,"monochrome") == 0)
5384             {
5385               if (image == (Image *) NULL)
5386                 continue;
5387               j=info ? info->image_info->monochrome :
5388                 SetImageMonochrome(image,exception);
5389               s=newSViv(j);
5390               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5391               continue;
5392             }
5393           if (LocaleCompare(attribute,"montage") == 0)
5394             {
5395               if (image && image->montage)
5396                 s=newSVpv(image->montage,0);
5397               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5398               continue;
5399             }
5400           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5401             attribute);
5402           break;
5403         }
5404         case 'O':
5405         case 'o':
5406         {
5407           if (LocaleCompare(attribute,"orientation") == 0)
5408             {
5409               j=info ? info->image_info->orientation : image ?
5410                 image->orientation : UndefinedOrientation;
5411               s=newSViv(j);
5412               (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5413                 j));
5414               SvIOK_on(s);
5415               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5416               continue;
5417             }
5418           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5419             attribute);
5420           break;
5421         }
5422         case 'P':
5423         case 'p':
5424         {
5425           if (LocaleCompare(attribute,"page") == 0)
5426             {
5427               if (info && info->image_info->page)
5428                 s=newSVpv(info->image_info->page,0);
5429               if (image != (Image *) NULL)
5430                 {
5431                   char
5432                     geometry[MagickPathExtent];
5433
5434                   (void) FormatLocaleString(geometry,MagickPathExtent,
5435                     "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5436                     (double) image->page.height,(double) image->page.x,(double)
5437                     image->page.y);
5438                   s=newSVpv(geometry,0);
5439                 }
5440               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5441               continue;
5442             }
5443           if (LocaleCompare(attribute,"page.x") == 0)
5444             {
5445               if (image != (Image *) NULL)
5446                 s=newSViv((ssize_t) image->page.x);
5447               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5448               continue;
5449             }
5450           if (LocaleCompare(attribute,"page.y") == 0)
5451             {
5452               if (image != (Image *) NULL)
5453                 s=newSViv((ssize_t) image->page.y);
5454               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5455               continue;
5456             }
5457           if (LocaleNCompare(attribute,"pixel",5) == 0)
5458             {
5459               char
5460                 tuple[MagickPathExtent];
5461
5462               int
5463                 items;
5464
5465               long
5466                 x,
5467                 y;
5468
5469               register const Quantum
5470                 *p;
5471
5472               if (image == (Image *) NULL)
5473                 break;
5474               x=0;
5475               y=0;
5476               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5477               (void) items;
5478               p=GetVirtualPixels(image,x,y,1,1,exception);
5479               if (image->colorspace != CMYKColorspace)
5480                 (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
5481                   QuantumFormat "," QuantumFormat "," QuantumFormat,
5482                   GetPixelRed(image,p),GetPixelGreen(image,p),
5483                   GetPixelBlue(image,p),GetPixelAlpha(image,p));
5484               else
5485                 (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
5486                   QuantumFormat "," QuantumFormat "," QuantumFormat ","
5487                   QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5488                   GetPixelBlue(image,p),GetPixelBlack(image,p),
5489                   GetPixelAlpha(image,p));
5490               s=newSVpv(tuple,0);
5491               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5492               continue;
5493             }
5494           if (LocaleCompare(attribute,"pointsize") == 0)
5495             {
5496               if (info)
5497                 s=newSViv((ssize_t) info->image_info->pointsize);
5498               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5499               continue;
5500             }
5501           if (LocaleCompare(attribute,"preview") == 0)
5502             {
5503               s=newSViv(info->image_info->preview_type);
5504               (void) sv_setpv(s,CommandOptionToMnemonic(MagickPreviewOptions,
5505                 info->image_info->preview_type));
5506               SvIOK_on(s);
5507               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5508               continue;
5509             }
5510           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5511             attribute);
5512           break;
5513         }
5514         case 'Q':
5515         case 'q':
5516         {
5517           if (LocaleCompare(attribute,"quality") == 0)
5518             {
5519               if (info)
5520                 s=newSViv((ssize_t) info->image_info->quality);
5521               if (image != (Image *) NULL)
5522                 s=newSViv((ssize_t) image->quality);
5523               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5524               continue;
5525             }
5526           if (LocaleCompare(attribute,"quantum") == 0)
5527             {
5528               if (info)
5529                 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5530               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5531               continue;
5532             }
5533           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5534             attribute);
5535           break;
5536         }
5537         case 'R':
5538         case 'r':
5539         {
5540           if (LocaleCompare(attribute,"rendering-intent") == 0)
5541             {
5542               s=newSViv(image->rendering_intent);
5543               (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5544                 image->rendering_intent));
5545               SvIOK_on(s);
5546               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5547               continue;
5548             }
5549           if (LocaleCompare(attribute,"red-primary") == 0)
5550             {
5551               if (image == (Image *) NULL)
5552                 break;
5553               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
5554                 image->chromaticity.red_primary.x,
5555                 image->chromaticity.red_primary.y);
5556               s=newSVpv(color,0);
5557               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5558               continue;
5559             }
5560           if (LocaleCompare(attribute,"rows") == 0)
5561             {
5562               if (image != (Image *) NULL)
5563                 s=newSViv((ssize_t) image->rows);
5564               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5565               continue;
5566             }
5567           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5568             attribute);
5569           break;
5570         }
5571         case 'S':
5572         case 's':
5573         {
5574           if (LocaleCompare(attribute,"sampling-factor") == 0)
5575             {
5576               if (info && info->image_info->sampling_factor)
5577                 s=newSVpv(info->image_info->sampling_factor,0);
5578               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5579               continue;
5580             }
5581           if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5582             {
5583               if (info && info->image_info->server_name)
5584                 s=newSVpv(info->image_info->server_name,0);
5585               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5586               continue;
5587             }
5588           if (LocaleCompare(attribute,"size") == 0)
5589             {
5590               if (info && info->image_info->size)
5591                 s=newSVpv(info->image_info->size,0);
5592               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5593               continue;
5594             }
5595           if (LocaleCompare(attribute,"scene") == 0)
5596             {
5597               if (image != (Image *) NULL)
5598                 s=newSViv((ssize_t) image->scene);
5599               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5600               continue;
5601             }
5602           if (LocaleCompare(attribute,"scenes") == 0)
5603             {
5604               if (image != (Image *) NULL)
5605                 s=newSViv((ssize_t) info->image_info->number_scenes);
5606               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5607               continue;
5608             }
5609           if (LocaleCompare(attribute,"signature") == 0)
5610             {
5611               const char
5612                 *value;
5613
5614               if (image == (Image *) NULL)
5615                 break;
5616               (void) SignatureImage(image,exception);
5617               value=GetImageProperty(image,"Signature",exception);
5618               if (value != (const char *) NULL)
5619                 s=newSVpv(value,0);
5620               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5621               continue;
5622             }
5623           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5624             attribute);
5625           break;
5626         }
5627         case 'T':
5628         case 't':
5629         {
5630           if (LocaleCompare(attribute,"taint") == 0)
5631             {
5632               if (image != (Image *) NULL)
5633                 s=newSViv((ssize_t) IsTaintImage(image));
5634               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5635               continue;
5636             }
5637           if (LocaleCompare(attribute,"texture") == 0)
5638             {
5639               if (info && info->image_info->texture)
5640                 s=newSVpv(info->image_info->texture,0);
5641               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5642               continue;
5643             }
5644           if (LocaleCompare(attribute,"total-ink-density") == 0)
5645             {
5646               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5647               if (image != (Image *) NULL)
5648                 s=newSVnv(GetImageTotalInkDensity(image,exception));
5649               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5650               continue;
5651             }
5652           if (LocaleCompare(attribute,"transparent-color") == 0)
5653             {
5654               if (image == (Image *) NULL)
5655                 break;
5656               (void) FormatLocaleString(color,MagickPathExtent,
5657                 "%.20g,%.20g,%.20g,%.20g",(double) image->transparent_color.red,
5658                 (double) image->transparent_color.green,
5659                 (double) image->transparent_color.blue,
5660                 (double) image->transparent_color.alpha);
5661               s=newSVpv(color,0);
5662               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5663               continue;
5664             }
5665           if (LocaleCompare(attribute,"type") == 0)
5666             {
5667               if (image == (Image *) NULL)
5668                 break;
5669               j=(ssize_t) GetImageType(image);
5670               s=newSViv(j);
5671               (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5672               SvIOK_on(s);
5673               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5674               continue;
5675             }
5676           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5677             attribute);
5678           break;
5679         }
5680         case 'U':
5681         case 'u':
5682         {
5683           if (LocaleCompare(attribute,"units") == 0)
5684             {
5685               j=info ? info->image_info->units : image ? image->units :
5686                 UndefinedResolution;
5687               if (info && (info->image_info->units == UndefinedResolution))
5688                 if (image)
5689                   j=image->units;
5690               if (j == UndefinedResolution)
5691                 s=newSVpv("undefined units",0);
5692               else
5693                 if (j == PixelsPerInchResolution)
5694                   s=newSVpv("pixels / inch",0);
5695                 else
5696                   s=newSVpv("pixels / centimeter",0);
5697               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5698               continue;
5699             }
5700           if (LocaleCompare(attribute,"user-time") == 0)
5701             {
5702               if (image != (Image *) NULL)
5703                 s=newSVnv(GetUserTime(&image->timer));
5704               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5705               continue;
5706             }
5707           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5708             attribute);
5709           break;
5710         }
5711         case 'V':
5712         case 'v':
5713         {
5714           if (LocaleCompare(attribute,"verbose") == 0)
5715             {
5716               if (info)
5717                 s=newSViv((ssize_t) info->image_info->verbose);
5718               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5719               continue;
5720             }
5721           if (LocaleCompare(attribute,"version") == 0)
5722             {
5723               s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5724               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5725               continue;
5726             }
5727           if (LocaleCompare(attribute,"view") == 0)
5728             {
5729               if (info && info->image_info->view)
5730                 s=newSVpv(info->image_info->view,0);
5731               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5732               continue;
5733             }
5734           if (LocaleCompare(attribute,"virtual-pixel") == 0)
5735             {
5736               if (image == (Image *) NULL)
5737                 break;
5738               j=(ssize_t) GetImageVirtualPixelMethod(image);
5739               s=newSViv(j);
5740               (void) sv_setpv(s,CommandOptionToMnemonic(
5741                 MagickVirtualPixelOptions,j));
5742               SvIOK_on(s);
5743               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5744               continue;
5745             }
5746           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5747             attribute);
5748           break;
5749         }
5750         case 'W':
5751         case 'w':
5752         {
5753           if (LocaleCompare(attribute,"white-point") == 0)
5754             {
5755               if (image == (Image *) NULL)
5756                 break;
5757               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
5758                 image->chromaticity.white_point.x,
5759                 image->chromaticity.white_point.y);
5760               s=newSVpv(color,0);
5761               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5762               continue;
5763             }
5764           if (LocaleCompare(attribute,"width") == 0)
5765             {
5766               if (image != (Image *) NULL)
5767                 s=newSViv((ssize_t) image->columns);
5768               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5769               continue;
5770             }
5771           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5772              attribute);
5773           break;
5774         }
5775         case 'X':
5776         case 'x':
5777         {
5778           if (LocaleCompare(attribute,"xmp") == 0)
5779             {
5780               if (image != (Image *) NULL)
5781                 {
5782                   const StringInfo
5783                     *profile;
5784
5785                   profile=GetImageProfile(image,"xmp");
5786                   if (profile != (StringInfo *) NULL)
5787                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5788                       GetStringInfoLength(profile));
5789                 }
5790               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5791               continue;
5792             }
5793           if (LocaleCompare(attribute,"x-resolution") == 0)
5794             {
5795               if (image != (Image *) NULL)
5796                 s=newSVnv(image->resolution.x);
5797               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5798               continue;
5799             }
5800           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5801             attribute);
5802           break;
5803         }
5804         case 'Y':
5805         case 'y':
5806         {
5807           if (LocaleCompare(attribute,"y-resolution") == 0)
5808             {
5809               if (image != (Image *) NULL)
5810                 s=newSVnv(image->resolution.y);
5811               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5812               continue;
5813             }
5814           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5815             attribute);
5816           break;
5817         }
5818         default:
5819           break;
5820       }
5821       if (image == (Image *) NULL)
5822         ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5823           attribute)
5824       else
5825         {
5826           value=GetImageProperty(image,attribute,exception);
5827           if (value != (const char *) NULL)
5828             {
5829               s=newSVpv(value,0);
5830               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5831             }
5832           else
5833             if (*attribute != '%')
5834               ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5835                 attribute)
5836             else
5837               {
5838                  char
5839                    *meta;
5840
5841                  meta=InterpretImageProperties(info ? info->image_info :
5842                    (ImageInfo *) NULL,image,attribute,exception);
5843                  s=newSVpv(meta,0);
5844                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5845                  meta=(char *) RelinquishMagickMemory(meta);
5846               }
5847         }
5848     }
5849     exception=DestroyExceptionInfo(exception);
5850     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5851   }
5852 \f
5853 #
5854 ###############################################################################
5855 #                                                                             #
5856 #                                                                             #
5857 #                                                                             #
5858 #   G e t A u t h e n t i c P i x e l s                                       #
5859 #                                                                             #
5860 #                                                                             #
5861 #                                                                             #
5862 ###############################################################################
5863 #
5864 #
5865 void *
5866 GetAuthenticPixels(ref,...)
5867   Image::Magick ref = NO_INIT
5868   ALIAS:
5869     getauthenticpixels = 1
5870     GetImagePixels = 2
5871     getimagepixels = 3
5872   CODE:
5873   {
5874     char
5875       *attribute;
5876
5877     ExceptionInfo
5878       *exception;
5879
5880     Image
5881       *image;
5882
5883     RectangleInfo
5884       region;
5885
5886     ssize_t
5887       i;
5888
5889     struct PackageInfo
5890       *info;
5891
5892     SV
5893       *perl_exception,
5894       *reference;
5895
5896     void
5897       *blob = NULL;
5898
5899     PERL_UNUSED_VAR(ref);
5900     PERL_UNUSED_VAR(ix);
5901     exception=AcquireExceptionInfo();
5902     perl_exception=newSVpv("",0);
5903     if (sv_isobject(ST(0)) == 0)
5904       {
5905         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5906           PackageName);
5907         goto PerlException;
5908       }
5909     reference=SvRV(ST(0));
5910
5911     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5912     if (image == (Image *) NULL)
5913       {
5914         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5915           PackageName);
5916         goto PerlException;
5917       }
5918
5919     region.x=0;
5920     region.y=0;
5921     region.width=image->columns;
5922     region.height=1;
5923     if (items == 1)
5924       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5925     for (i=2; i < items; i+=2)
5926     {
5927       attribute=(char *) SvPV(ST(i-1),na);
5928       switch (*attribute)
5929       {
5930         case 'g':
5931         case 'G':
5932         {
5933           if (LocaleCompare(attribute,"geometry") == 0)
5934             {
5935               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5936               break;
5937             }
5938           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5939             attribute);
5940           break;
5941         }
5942         case 'H':
5943         case 'h':
5944         {
5945           if (LocaleCompare(attribute,"height") == 0)
5946             {
5947               region.height=SvIV(ST(i));
5948               continue;
5949             }
5950           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5951             attribute);
5952           break;
5953         }
5954         case 'X':
5955         case 'x':
5956         {
5957           if (LocaleCompare(attribute,"x") == 0)
5958             {
5959               region.x=SvIV(ST(i));
5960               continue;
5961             }
5962           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5963             attribute);
5964           break;
5965         }
5966         case 'Y':
5967         case 'y':
5968         {
5969           if (LocaleCompare(attribute,"y") == 0)
5970             {
5971               region.y=SvIV(ST(i));
5972               continue;
5973             }
5974           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5975             attribute);
5976           break;
5977         }
5978         case 'W':
5979         case 'w':
5980         {
5981           if (LocaleCompare(attribute,"width") == 0)
5982             {
5983               region.width=SvIV(ST(i));
5984               continue;
5985             }
5986           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5987             attribute);
5988           break;
5989         }
5990       }
5991     }
5992     blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5993       region.height,exception);
5994     if (blob != (void *) NULL)
5995       goto PerlEnd;
5996
5997   PerlException:
5998     InheritPerlException(exception,perl_exception);
5999     exception=DestroyExceptionInfo(exception);
6000     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6001
6002   PerlEnd:
6003     RETVAL = blob;
6004   }
6005   OUTPUT:
6006     RETVAL
6007 \f
6008 #
6009 ###############################################################################
6010 #                                                                             #
6011 #                                                                             #
6012 #                                                                             #
6013 #   G e t V i r t u a l P i x e l s                                           #
6014 #                                                                             #
6015 #                                                                             #
6016 #                                                                             #
6017 ###############################################################################
6018 #
6019 #
6020 void *
6021 GetVirtualPixels(ref,...)
6022   Image::Magick ref = NO_INIT
6023   ALIAS:
6024     getvirtualpixels = 1
6025     AcquireImagePixels = 2
6026     acquireimagepixels = 3
6027   CODE:
6028   {
6029     char
6030       *attribute;
6031
6032     const void
6033       *blob = NULL;
6034
6035     ExceptionInfo
6036       *exception;
6037
6038     Image
6039       *image;
6040
6041     RectangleInfo
6042       region;
6043
6044     ssize_t
6045       i;
6046
6047     struct PackageInfo
6048       *info;
6049
6050     SV
6051       *perl_exception,
6052       *reference;
6053
6054     PERL_UNUSED_VAR(ref);
6055     PERL_UNUSED_VAR(ix);
6056     exception=AcquireExceptionInfo();
6057     perl_exception=newSVpv("",0);
6058     if (sv_isobject(ST(0)) == 0)
6059       {
6060         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6061           PackageName);
6062         goto PerlException;
6063       }
6064     reference=SvRV(ST(0));
6065
6066     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6067     if (image == (Image *) NULL)
6068       {
6069         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6070           PackageName);
6071         goto PerlException;
6072       }
6073
6074     region.x=0;
6075     region.y=0;
6076     region.width=image->columns;
6077     region.height=1;
6078     if (items == 1)
6079       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6080     for (i=2; i < items; i+=2)
6081     {
6082       attribute=(char *) SvPV(ST(i-1),na);
6083       switch (*attribute)
6084       {
6085         case 'g':
6086         case 'G':
6087         {
6088           if (LocaleCompare(attribute,"geometry") == 0)
6089             {
6090               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6091               break;
6092             }
6093           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6094             attribute);
6095           break;
6096         }
6097         case 'H':
6098         case 'h':
6099         {
6100           if (LocaleCompare(attribute,"height") == 0)
6101             {
6102               region.height=SvIV(ST(i));
6103               continue;
6104             }
6105           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6106             attribute);
6107           break;
6108         }
6109         case 'X':
6110         case 'x':
6111         {
6112           if (LocaleCompare(attribute,"x") == 0)
6113             {
6114               region.x=SvIV(ST(i));
6115               continue;
6116             }
6117           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6118             attribute);
6119           break;
6120         }
6121         case 'Y':
6122         case 'y':
6123         {
6124           if (LocaleCompare(attribute,"y") == 0)
6125             {
6126               region.y=SvIV(ST(i));
6127               continue;
6128             }
6129           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6130             attribute);
6131           break;
6132         }
6133         case 'W':
6134         case 'w':
6135         {
6136           if (LocaleCompare(attribute,"width") == 0)
6137             {
6138               region.width=SvIV(ST(i));
6139               continue;
6140             }
6141           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6142             attribute);
6143           break;
6144         }
6145       }
6146     }
6147     blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
6148       region.height,exception);
6149     if (blob != (void *) NULL)
6150       goto PerlEnd;
6151
6152   PerlException:
6153     InheritPerlException(exception,perl_exception);
6154     exception=DestroyExceptionInfo(exception);
6155     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6156
6157   PerlEnd:
6158     RETVAL = (void *) blob;
6159   }
6160   OUTPUT:
6161     RETVAL
6162 \f
6163 #
6164 ###############################################################################
6165 #                                                                             #
6166 #                                                                             #
6167 #                                                                             #
6168 #   G e t A u t h e n t i c M e t a c o n t e n t                             #
6169 #                                                                             #
6170 #                                                                             #
6171 #                                                                             #
6172 ###############################################################################
6173 #
6174 #
6175 void *
6176 GetAuthenticMetacontent(ref,...)
6177   Image::Magick ref = NO_INIT
6178   ALIAS:
6179     getauthenticmetacontent = 1
6180     GetMetacontent = 2
6181     getmetacontent = 3
6182   CODE:
6183   {
6184     ExceptionInfo
6185       *exception;
6186
6187     Image
6188       *image;
6189
6190     struct PackageInfo
6191       *info;
6192
6193     SV
6194       *perl_exception,
6195       *reference;
6196
6197     void
6198       *blob = NULL;
6199
6200     PERL_UNUSED_VAR(ref);
6201     PERL_UNUSED_VAR(ix);
6202     exception=AcquireExceptionInfo();
6203     perl_exception=newSVpv("",0);
6204     if (sv_isobject(ST(0)) == 0)
6205       {
6206         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6207           PackageName);
6208         goto PerlException;
6209       }
6210     reference=SvRV(ST(0));
6211
6212     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6213     if (image == (Image *) NULL)
6214       {
6215         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6216           PackageName);
6217         goto PerlException;
6218       }
6219
6220     blob=(void *) GetAuthenticMetacontent(image);
6221     if (blob != (void *) NULL)
6222       goto PerlEnd;
6223
6224   PerlException:
6225     InheritPerlException(exception,perl_exception);
6226     exception=DestroyExceptionInfo(exception);
6227     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6228
6229   PerlEnd:
6230     RETVAL = blob;
6231   }
6232   OUTPUT:
6233     RETVAL
6234 \f
6235 #
6236 ###############################################################################
6237 #                                                                             #
6238 #                                                                             #
6239 #                                                                             #
6240 #   G e t V i r t u a l M e t a c o n t e n t                                 #
6241 #                                                                             #
6242 #                                                                             #
6243 #                                                                             #
6244 ###############################################################################
6245 #
6246 #
6247 void *
6248 GetVirtualMetacontent(ref,...)
6249   Image::Magick ref = NO_INIT
6250   ALIAS:
6251     getvirtualmetacontent = 1
6252   CODE:
6253   {
6254     ExceptionInfo
6255       *exception;
6256
6257     Image
6258       *image;
6259
6260     struct PackageInfo
6261       *info;
6262
6263     SV
6264       *perl_exception,
6265       *reference;
6266
6267     void
6268       *blob = NULL;
6269
6270     PERL_UNUSED_VAR(ref);
6271     PERL_UNUSED_VAR(ix);
6272     exception=AcquireExceptionInfo();
6273     perl_exception=newSVpv("",0);
6274     if (sv_isobject(ST(0)) == 0)
6275       {
6276         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6277           PackageName);
6278         goto PerlException;
6279       }
6280     reference=SvRV(ST(0));
6281
6282     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6283     if (image == (Image *) NULL)
6284       {
6285         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6286           PackageName);
6287         goto PerlException;
6288       }
6289
6290     blob=(void *) GetVirtualMetacontent(image);
6291     if (blob != (void *) NULL)
6292       goto PerlEnd;
6293
6294   PerlException:
6295     InheritPerlException(exception,perl_exception);
6296     exception=DestroyExceptionInfo(exception);
6297     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6298
6299   PerlEnd:
6300     RETVAL = blob;
6301   }
6302   OUTPUT:
6303     RETVAL
6304 \f
6305 #
6306 ###############################################################################
6307 #                                                                             #
6308 #                                                                             #
6309 #                                                                             #
6310 #   H i s t o g r a m                                                         #
6311 #                                                                             #
6312 #                                                                             #
6313 #                                                                             #
6314 ###############################################################################
6315 #
6316 #
6317 void
6318 Histogram(ref,...)
6319   Image::Magick ref=NO_INIT
6320   ALIAS:
6321     HistogramImage = 1
6322     histogram      = 2
6323     histogramimage = 3
6324   PPCODE:
6325   {
6326     AV
6327       *av;
6328
6329     char
6330       message[MagickPathExtent];
6331
6332     PixelInfo
6333       *histogram;
6334
6335     ExceptionInfo
6336       *exception;
6337
6338     Image
6339       *image;
6340
6341     register ssize_t
6342       i;
6343
6344     ssize_t
6345       count;
6346
6347     struct PackageInfo
6348       *info;
6349
6350     SV
6351       *perl_exception,
6352       *reference;
6353
6354     size_t
6355       number_colors;
6356
6357     PERL_UNUSED_VAR(ref);
6358     PERL_UNUSED_VAR(ix);
6359     exception=AcquireExceptionInfo();
6360     perl_exception=newSVpv("",0);
6361     av=NULL;
6362     if (sv_isobject(ST(0)) == 0)
6363       {
6364         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6365           PackageName);
6366         goto PerlException;
6367       }
6368     reference=SvRV(ST(0));
6369     av=newAV();
6370     SvREFCNT_dec(av);
6371     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6372     if (image == (Image *) NULL)
6373       {
6374         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6375           PackageName);
6376         goto PerlException;
6377       }
6378     count=0;
6379     for ( ; image; image=image->next)
6380     {
6381       histogram=GetImageHistogram(image,&number_colors,exception);
6382       if (histogram == (PixelInfo *) NULL)
6383         continue;
6384       count+=(ssize_t) number_colors;
6385       EXTEND(sp,6*count);
6386       for (i=0; i < (ssize_t) number_colors; i++)
6387       {
6388         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6389           histogram[i].red);
6390         PUSHs(sv_2mortal(newSVpv(message,0)));
6391         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6392           histogram[i].green);
6393         PUSHs(sv_2mortal(newSVpv(message,0)));
6394         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6395           histogram[i].blue);
6396         PUSHs(sv_2mortal(newSVpv(message,0)));
6397         if (image->colorspace == CMYKColorspace)
6398           {
6399             (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6400               histogram[i].black);
6401             PUSHs(sv_2mortal(newSVpv(message,0)));
6402           }
6403         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6404           histogram[i].alpha);
6405         PUSHs(sv_2mortal(newSVpv(message,0)));
6406         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
6407           histogram[i].count);
6408         PUSHs(sv_2mortal(newSVpv(message,0)));
6409       }
6410       histogram=(PixelInfo *) RelinquishMagickMemory(histogram);
6411     }
6412
6413   PerlException:
6414     InheritPerlException(exception,perl_exception);
6415     exception=DestroyExceptionInfo(exception);
6416     SvREFCNT_dec(perl_exception);
6417   }
6418 \f
6419 #
6420 ###############################################################################
6421 #                                                                             #
6422 #                                                                             #
6423 #                                                                             #
6424 #   G e t P i x e l                                                           #
6425 #                                                                             #
6426 #                                                                             #
6427 #                                                                             #
6428 ###############################################################################
6429 #
6430 #
6431 void
6432 GetPixel(ref,...)
6433   Image::Magick ref=NO_INIT
6434   ALIAS:
6435     getpixel = 1
6436     getPixel = 2
6437   PPCODE:
6438   {
6439     AV
6440       *av;
6441
6442     char
6443       *attribute;
6444
6445     ExceptionInfo
6446       *exception;
6447
6448     Image
6449       *image;
6450
6451     MagickBooleanType
6452       normalize;
6453
6454     RectangleInfo
6455       region;
6456
6457     register const Quantum
6458       *p;
6459
6460     register ssize_t
6461       i;
6462
6463     ssize_t
6464       option;
6465
6466     struct PackageInfo
6467       *info;
6468
6469     SV
6470       *perl_exception,
6471       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6472
6473     PERL_UNUSED_VAR(ref);
6474     PERL_UNUSED_VAR(ix);
6475     exception=AcquireExceptionInfo();
6476     perl_exception=newSVpv("",0);
6477     reference=SvRV(ST(0));
6478     av=(AV *) reference;
6479     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6480       exception);
6481     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6482     if (image == (Image *) NULL)
6483       {
6484         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6485           PackageName);
6486         goto PerlException;
6487       }
6488     normalize=MagickTrue;
6489     region.x=0;
6490     region.y=0;
6491     region.width=image->columns;
6492     region.height=1;
6493     if (items == 1)
6494       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6495     for (i=2; i < items; i+=2)
6496     {
6497       attribute=(char *) SvPV(ST(i-1),na);
6498       switch (*attribute)
6499       {
6500         case 'C':
6501         case 'c':
6502         {
6503           if (LocaleCompare(attribute,"channel") == 0)
6504             {
6505               ssize_t
6506                 option;
6507
6508               option=ParseChannelOption(SvPV(ST(i),na));
6509               if (option < 0)
6510                 {
6511                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6512                     SvPV(ST(i),na));
6513                   return;
6514                 }
6515               (void) SetPixelChannelMask(image,(ChannelType) option);
6516               break;
6517             }
6518           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6519             attribute);
6520           break;
6521         }
6522         case 'g':
6523         case 'G':
6524         {
6525           if (LocaleCompare(attribute,"geometry") == 0)
6526             {
6527               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6528               break;
6529             }
6530           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6531             attribute);
6532           break;
6533         }
6534         case 'N':
6535         case 'n':
6536         {
6537           if (LocaleCompare(attribute,"normalize") == 0)
6538             {
6539               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6540                 SvPV(ST(i),na));
6541               if (option < 0)
6542                 {
6543                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6544                     SvPV(ST(i),na));
6545                   break;
6546                 }
6547              normalize=option != 0 ? MagickTrue : MagickFalse;
6548              break;
6549             }
6550           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6551             attribute);
6552           break;
6553         }
6554         case 'x':
6555         case 'X':
6556         {
6557           if (LocaleCompare(attribute,"x") == 0)
6558             {
6559               region.x=SvIV(ST(i));
6560               break;
6561             }
6562           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6563             attribute);
6564           break;
6565         }
6566         case 'y':
6567         case 'Y':
6568         {
6569           if (LocaleCompare(attribute,"y") == 0)
6570             {
6571               region.y=SvIV(ST(i));
6572               break;
6573             }
6574           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6575             attribute);
6576           break;
6577         }
6578         default:
6579         {
6580           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6581             attribute);
6582           break;
6583         }
6584       }
6585     }
6586     p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6587     if (p == (const Quantum *) NULL)
6588       PUSHs(&sv_undef);
6589     else
6590       {
6591         double
6592           scale;
6593
6594         scale=1.0;
6595         if (normalize != MagickFalse)
6596           scale=1.0/QuantumRange;
6597         if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
6598           PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6599         if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6600           PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6601         if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6602           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6603         if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6604             (image->colorspace == CMYKColorspace))
6605           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6606         if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
6607           PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6608       }
6609
6610   PerlException:
6611     InheritPerlException(exception,perl_exception);
6612     exception=DestroyExceptionInfo(exception);
6613     SvREFCNT_dec(perl_exception);
6614   }
6615 \f
6616 #
6617 ###############################################################################
6618 #                                                                             #
6619 #                                                                             #
6620 #                                                                             #
6621 #   G e t P i x e l s                                                         #
6622 #                                                                             #
6623 #                                                                             #
6624 #                                                                             #
6625 ###############################################################################
6626 #
6627 #
6628 void
6629 GetPixels(ref,...)
6630   Image::Magick ref=NO_INIT
6631   ALIAS:
6632     getpixels = 1
6633     getPixels = 2
6634   PPCODE:
6635   {
6636     AV
6637       *av;
6638
6639     char
6640       *attribute;
6641
6642     const char
6643       *map;
6644
6645     ExceptionInfo
6646       *exception;
6647
6648     Image
6649       *image;
6650
6651     MagickBooleanType
6652       normalize,
6653       status;
6654
6655     RectangleInfo
6656       region;
6657
6658     register ssize_t
6659       i;
6660
6661     ssize_t
6662       option;
6663
6664     struct PackageInfo
6665       *info;
6666
6667     SV
6668       *perl_exception,
6669       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6670
6671     PERL_UNUSED_VAR(ref);
6672     PERL_UNUSED_VAR(ix);
6673     exception=AcquireExceptionInfo();
6674     perl_exception=newSVpv("",0);
6675     reference=SvRV(ST(0));
6676     av=(AV *) reference;
6677     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6678       exception);
6679     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6680     if (image == (Image *) NULL)
6681       {
6682         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6683           PackageName);
6684         goto PerlException;
6685       }
6686     map="RGB";
6687     if (image->alpha_trait != UndefinedPixelTrait)
6688       map="RGBA";
6689     if (image->colorspace == CMYKColorspace)
6690       {
6691         map="CMYK";
6692         if (image->alpha_trait != UndefinedPixelTrait)
6693           map="CMYKA";
6694       }
6695     normalize=MagickFalse;
6696     region.x=0;
6697     region.y=0;
6698     region.width=image->columns;
6699     region.height=1;
6700     if (items == 1)
6701       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6702     for (i=2; i < items; i+=2)
6703     {
6704       attribute=(char *) SvPV(ST(i-1),na);
6705       switch (*attribute)
6706       {
6707         case 'g':
6708         case 'G':
6709         {
6710           if (LocaleCompare(attribute,"geometry") == 0)
6711             {
6712               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6713               break;
6714             }
6715           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6716             attribute);
6717           break;
6718         }
6719         case 'H':
6720         case 'h':
6721         {
6722           if (LocaleCompare(attribute,"height") == 0)
6723             {
6724               region.height=SvIV(ST(i));
6725               break;
6726             }
6727           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6728             attribute);
6729           break;
6730         }
6731         case 'M':
6732         case 'm':
6733         {
6734           if (LocaleCompare(attribute,"map") == 0)
6735             {
6736               map=SvPV(ST(i),na);
6737               break;
6738             }
6739           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6740             attribute);
6741           break;
6742         }
6743         case 'N':
6744         case 'n':
6745         {
6746           if (LocaleCompare(attribute,"normalize") == 0)
6747             {
6748               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6749                 SvPV(ST(i),na));
6750               if (option < 0)
6751                 {
6752                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6753                     SvPV(ST(i),na));
6754                   break;
6755                 }
6756              normalize=option != 0 ? MagickTrue : MagickFalse;
6757              break;
6758             }
6759           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6760             attribute);
6761           break;
6762         }
6763         case 'W':
6764         case 'w':
6765         {
6766           if (LocaleCompare(attribute,"width") == 0)
6767             {
6768               region.width=SvIV(ST(i));
6769               break;
6770             }
6771           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6772             attribute);
6773           break;
6774         }
6775         case 'x':
6776         case 'X':
6777         {
6778           if (LocaleCompare(attribute,"x") == 0)
6779             {
6780               region.x=SvIV(ST(i));
6781               break;
6782             }
6783           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6784             attribute);
6785           break;
6786         }
6787         case 'y':
6788         case 'Y':
6789         {
6790           if (LocaleCompare(attribute,"y") == 0)
6791             {
6792               region.y=SvIV(ST(i));
6793               break;
6794             }
6795           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6796             attribute);
6797           break;
6798         }
6799         default:
6800         {
6801           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6802             attribute);
6803           break;
6804         }
6805       }
6806     }
6807     if (normalize != MagickFalse)
6808       {
6809         float
6810           *pixels;
6811
6812         pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6813           region.height*sizeof(*pixels));
6814         if (pixels == (float *) NULL)
6815           {
6816             ThrowPerlException(exception,ResourceLimitError,
6817               "MemoryAllocationFailed",PackageName);
6818             goto PerlException;
6819           }
6820         status=ExportImagePixels(image,region.x,region.y,region.width,
6821           region.height,map,FloatPixel,pixels,exception);
6822         if (status == MagickFalse)
6823           PUSHs(&sv_undef);
6824         else
6825           {
6826             EXTEND(sp,strlen(map)*region.width*region.height);
6827             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6828               PUSHs(sv_2mortal(newSVnv(pixels[i])));
6829           }
6830         pixels=(float *) RelinquishMagickMemory(pixels);
6831       }
6832     else
6833       {
6834         Quantum
6835           *pixels;
6836
6837         pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6838           region.height*sizeof(*pixels));
6839         if (pixels == (Quantum *) NULL)
6840           {
6841             ThrowPerlException(exception,ResourceLimitError,
6842               "MemoryAllocationFailed",PackageName);
6843             goto PerlException;
6844           }
6845         status=ExportImagePixels(image,region.x,region.y,region.width,
6846           region.height,map,QuantumPixel,pixels,exception);
6847         if (status == MagickFalse)
6848           PUSHs(&sv_undef);
6849         else
6850           {
6851             EXTEND(sp,strlen(map)*region.width*region.height);
6852             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6853               PUSHs(sv_2mortal(newSViv(pixels[i])));
6854           }
6855         pixels=(Quantum *) RelinquishMagickMemory(pixels);
6856       }
6857
6858   PerlException:
6859     InheritPerlException(exception,perl_exception);
6860     exception=DestroyExceptionInfo(exception);
6861     SvREFCNT_dec(perl_exception);
6862   }
6863 \f
6864 #
6865 ###############################################################################
6866 #                                                                             #
6867 #                                                                             #
6868 #                                                                             #
6869 #   I m a g e T o B l o b                                                     #
6870 #                                                                             #
6871 #                                                                             #
6872 #                                                                             #
6873 ###############################################################################
6874 #
6875 #
6876 void
6877 ImageToBlob(ref,...)
6878   Image::Magick ref=NO_INIT
6879   ALIAS:
6880     ImageToBlob  = 1
6881     imagetoblob  = 2
6882     toblob       = 3
6883     blob         = 4
6884   PPCODE:
6885   {
6886     char
6887       filename[MagickPathExtent];
6888
6889     ExceptionInfo
6890       *exception;
6891
6892     Image
6893       *image,
6894       *next;
6895
6896     register ssize_t
6897       i;
6898
6899     struct PackageInfo
6900       *info,
6901       *package_info;
6902
6903     size_t
6904       length;
6905
6906     ssize_t
6907       scene;
6908
6909     SV
6910       *perl_exception,
6911       *reference;
6912
6913     void
6914       *blob;
6915
6916     PERL_UNUSED_VAR(ref);
6917     PERL_UNUSED_VAR(ix);
6918     exception=AcquireExceptionInfo();
6919     perl_exception=newSVpv("",0);
6920     package_info=(struct PackageInfo *) NULL;
6921     if (sv_isobject(ST(0)) == 0)
6922       {
6923         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6924           PackageName);
6925         goto PerlException;
6926       }
6927     reference=SvRV(ST(0));
6928     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6929     if (image == (Image *) NULL)
6930       {
6931         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6932           PackageName);
6933         goto PerlException;
6934       }
6935     package_info=ClonePackageInfo(info,exception);
6936     for (i=2; i < items; i+=2)
6937       SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6938     (void) CopyMagickString(filename,package_info->image_info->filename,
6939       MagickPathExtent);
6940     scene=0;
6941     for (next=image; next; next=next->next)
6942     {
6943       (void) CopyMagickString(next->filename,filename,MagickPathExtent);
6944       next->scene=scene++;
6945     }
6946     SetImageInfo(package_info->image_info,(unsigned int)
6947       GetImageListLength(image),exception);
6948     EXTEND(sp,(ssize_t) GetImageListLength(image));
6949     for ( ; image; image=image->next)
6950     {
6951       length=0;
6952       blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6953       if (blob != (char *) NULL)
6954         {
6955           PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6956           blob=(unsigned char *) RelinquishMagickMemory(blob);
6957         }
6958       if (package_info->image_info->adjoin)
6959         break;
6960     }
6961
6962   PerlException:
6963     if (package_info != (struct PackageInfo *) NULL)
6964       DestroyPackageInfo(package_info);
6965     InheritPerlException(exception,perl_exception);
6966     exception=DestroyExceptionInfo(exception);
6967     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6968   }
6969 \f
6970 #
6971 ###############################################################################
6972 #                                                                             #
6973 #                                                                             #
6974 #                                                                             #
6975 #   L a y e r s                                                               #
6976 #                                                                             #
6977 #                                                                             #
6978 #                                                                             #
6979 ###############################################################################
6980 #
6981 #
6982 void
6983 Layers(ref,...)
6984   Image::Magick ref=NO_INIT
6985   ALIAS:
6986     Layers                = 1
6987     layers           = 2
6988     OptimizeImageLayers   = 3
6989     optimizelayers        = 4
6990     optimizeimagelayers   = 5
6991   PPCODE:
6992   {
6993     AV
6994       *av;
6995
6996     char
6997       *attribute;
6998
6999     CompositeOperator
7000       compose;
7001
7002     ExceptionInfo
7003       *exception;
7004
7005     HV
7006       *hv;
7007
7008     Image
7009       *image,
7010       *layers;
7011
7012     LayerMethod
7013       method;
7014
7015     register ssize_t
7016       i;
7017
7018     ssize_t
7019       option,
7020       sp;
7021
7022     struct PackageInfo
7023       *info;
7024
7025     SV
7026       *av_reference,
7027       *perl_exception,
7028       *reference,
7029       *rv,
7030       *sv;
7031
7032     PERL_UNUSED_VAR(ref);
7033     PERL_UNUSED_VAR(ix);
7034     exception=AcquireExceptionInfo();
7035     perl_exception=newSVpv("",0);
7036     sv=NULL;
7037     if (sv_isobject(ST(0)) == 0)
7038       {
7039         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7040           PackageName);
7041         goto PerlException;
7042       }
7043     reference=SvRV(ST(0));
7044     hv=SvSTASH(reference);
7045     av=newAV();
7046     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
7047     SvREFCNT_dec(av);
7048     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
7049     if (image == (Image *) NULL)
7050       {
7051         ThrowPerlException(exception,OptionError,"NoImagesDefined",
7052           PackageName);
7053         goto PerlException;
7054       }
7055     compose=image->compose;
7056     method=OptimizeLayer;
7057     for (i=2; i < items; i+=2)
7058     {
7059       attribute=(char *) SvPV(ST(i-1),na);
7060       switch (*attribute)
7061       {
7062         case 'C':
7063         case 'c':
7064         {
7065           if (LocaleCompare(attribute,"compose") == 0)
7066             {
7067               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
7068                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
7069               if (sp < 0)
7070                 {
7071                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
7072                     SvPV(ST(i),na));
7073                   break;
7074                 }
7075               compose=(CompositeOperator) sp;
7076               break;
7077             }
7078           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7079             attribute);
7080           break;
7081         }
7082         case 'M':
7083         case 'm':
7084         {
7085           if (LocaleCompare(attribute,"method") == 0)
7086             {
7087               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
7088                 SvPV(ST(i),na));
7089               if (option < 0)
7090                 {
7091                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
7092                     SvPV(ST(i),na));
7093                   break;
7094                 }
7095               method=(LayerMethod) option;
7096               break;
7097             }
7098           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7099             attribute);
7100           break;
7101         }
7102         default:
7103         {
7104           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7105             attribute);
7106           break;
7107         }
7108       }
7109     }
7110     layers=(Image *) NULL;
7111     switch (method)
7112     {
7113       case CompareAnyLayer:
7114       case CompareClearLayer:
7115       case CompareOverlayLayer:
7116       default:
7117       {
7118         layers=CompareImagesLayers(image,method,exception);
7119         break;
7120       }
7121       case MergeLayer:
7122       case FlattenLayer:
7123       case MosaicLayer:
7124       {
7125         layers=MergeImageLayers(image,method,exception);
7126         break;
7127       }
7128       case DisposeLayer:
7129       {
7130         layers=DisposeImages(image,exception);
7131         break;
7132       }
7133       case OptimizeImageLayer:
7134       {
7135         layers=OptimizeImageLayers(image,exception);
7136         break;
7137       }
7138       case OptimizePlusLayer:
7139       {
7140         layers=OptimizePlusImageLayers(image,exception);
7141         break;
7142       }
7143       case OptimizeTransLayer:
7144       {
7145         OptimizeImageTransparency(image,exception);
7146         break;
7147       }
7148       case RemoveDupsLayer:
7149       {
7150         RemoveDuplicateLayers(&image,exception);
7151         break;
7152       }
7153       case RemoveZeroLayer:
7154       {
7155         RemoveZeroDelayLayers(&image,exception);
7156         break;
7157       }
7158       case OptimizeLayer:
7159       {
7160         QuantizeInfo
7161           *quantize_info;
7162
7163         /*
7164           General Purpose, GIF Animation Optimizer.
7165         */
7166         layers=CoalesceImages(image,exception);
7167         if (layers == (Image *) NULL)
7168           break;
7169         image=layers;
7170         layers=OptimizeImageLayers(image,exception);
7171         if (layers == (Image *) NULL)
7172           break;
7173         image=DestroyImageList(image);
7174         image=layers;
7175         layers=(Image *) NULL;
7176         OptimizeImageTransparency(image,exception);
7177         quantize_info=AcquireQuantizeInfo(info->image_info);
7178         (void) RemapImages(quantize_info,image,(Image *) NULL,exception);
7179         quantize_info=DestroyQuantizeInfo(quantize_info);
7180         break;
7181       }
7182       case CompositeLayer:
7183       {
7184         Image
7185           *source;
7186
7187         RectangleInfo
7188           geometry;
7189
7190         /*
7191           Split image sequence at the first 'NULL:' image.
7192         */
7193         source=image;
7194         while (source != (Image *) NULL)
7195         {
7196           source=GetNextImageInList(source);
7197           if ((source != (Image *) NULL) &&
7198               (LocaleCompare(source->magick,"NULL") == 0))
7199             break;
7200         }
7201         if (source != (Image *) NULL)
7202           {
7203             if ((GetPreviousImageInList(source) == (Image *) NULL) ||
7204                 (GetNextImageInList(source) == (Image *) NULL))
7205               source=(Image *) NULL;
7206             else
7207               {
7208                 /*
7209                   Separate the two lists, junk the null: image.
7210                 */
7211                 source=SplitImageList(source->previous);
7212                 DeleteImageFromList(&source);
7213               }
7214           }
7215         if (source == (Image *) NULL)
7216           {
7217             (void) ThrowMagickException(exception,GetMagickModule(),
7218               OptionError,"MissingNullSeparator","layers Composite");
7219             break;
7220           }
7221         /*
7222           Adjust offset with gravity and virtual canvas.
7223         */
7224         SetGeometry(image,&geometry);
7225         (void) ParseAbsoluteGeometry(image->geometry,&geometry);
7226         geometry.width=source->page.width != 0 ? source->page.width :
7227           source->columns;
7228         geometry.height=source->page.height != 0 ? source->page.height :
7229           source->rows;
7230         GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
7231           image->columns,image->page.height != 0 ? image->page.height :
7232           image->rows,image->gravity,&geometry);
7233         CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
7234         source=DestroyImageList(source);
7235         break;
7236       }
7237     }
7238     if (layers != (Image *) NULL)
7239       image=layers;
7240     else
7241       image=CloneImage(image,0,0,MagickTrue,exception);
7242     if (image == (Image *) NULL)
7243       goto PerlException;
7244     for ( ; image; image=image->next)
7245     {
7246       AddImageToRegistry(sv,image);
7247       rv=newRV(sv);
7248       av_push(av,sv_bless(rv,hv));
7249       SvREFCNT_dec(sv);
7250     }
7251     exception=DestroyExceptionInfo(exception);
7252     ST(0)=av_reference;
7253     SvREFCNT_dec(perl_exception);
7254     XSRETURN(1);
7255
7256   PerlException:
7257     InheritPerlException(exception,perl_exception);
7258     exception=DestroyExceptionInfo(exception);
7259     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
7260     SvPOK_on(perl_exception);
7261     ST(0)=sv_2mortal(perl_exception);
7262     XSRETURN(1);
7263   }
7264 \f
7265 #
7266 ###############################################################################
7267 #                                                                             #
7268 #                                                                             #
7269 #                                                                             #
7270 #   M a g i c k T o M i m e                                                   #
7271 #                                                                             #
7272 #                                                                             #
7273 #                                                                             #
7274 ###############################################################################
7275 #
7276 #
7277 SV *
7278 MagickToMime(ref,name)
7279   Image::Magick ref=NO_INIT
7280   char *name
7281   ALIAS:
7282     magicktomime = 1
7283   CODE:
7284   {
7285     char
7286       *mime;
7287
7288     PERL_UNUSED_VAR(ref);
7289     PERL_UNUSED_VAR(ix);
7290     mime=MagickToMime(name);
7291     RETVAL=newSVpv(mime,0);
7292     mime=(char *) RelinquishMagickMemory(mime);
7293   }
7294   OUTPUT:
7295     RETVAL
7296 \f
7297 #
7298 ###############################################################################
7299 #                                                                             #
7300 #                                                                             #
7301 #                                                                             #
7302 #   M o g r i f y                                                             #
7303 #                                                                             #
7304 #                                                                             #
7305 #                                                                             #
7306 ###############################################################################
7307 #
7308 #
7309 void
7310 Mogrify(ref,...)
7311   Image::Magick ref=NO_INIT
7312   ALIAS:
7313     Comment            =   1
7314     CommentImage       =   2
7315     Label              =   3
7316     LabelImage         =   4
7317     AddNoise           =   5
7318     AddNoiseImage      =   6
7319     Colorize           =   7
7320     ColorizeImage      =   8
7321     Border             =   9
7322     BorderImage        =  10
7323     Blur               =  11
7324     BlurImage          =  12
7325     Chop               =  13
7326     ChopImage          =  14
7327     Crop               =  15
7328     CropImage          =  16
7329     Despeckle          =  17
7330     DespeckleImage     =  18
7331     Edge               =  19
7332     EdgeImage          =  20
7333     Emboss             =  21
7334     EmbossImage        =  22
7335     Enhance            =  23
7336     EnhanceImage       =  24
7337     Flip               =  25
7338     FlipImage          =  26
7339     Flop               =  27
7340     FlopImage          =  28
7341     Frame              =  29
7342     FrameImage         =  30
7343     Implode            =  31
7344     ImplodeImage       =  32
7345     Magnify            =  33
7346     MagnifyImage       =  34
7347     MedianFilter       =  35
7348     MedianConvolveImage  =  36
7349     Minify             =  37
7350     MinifyImage        =  38
7351     OilPaint           =  39
7352     OilPaintImage      =  40
7353     ReduceNoise        =  41
7354     ReduceNoiseImage   =  42
7355     Roll               =  43
7356     RollImage          =  44
7357     Rotate             =  45
7358     RotateImage        =  46
7359     Sample             =  47
7360     SampleImage        =  48
7361     Scale              =  49
7362     ScaleImage         =  50
7363     Shade              =  51
7364     ShadeImage         =  52
7365     Sharpen            =  53
7366     SharpenImage       =  54
7367     Shear              =  55
7368     ShearImage         =  56
7369     Spread             =  57
7370     SpreadImage        =  58
7371     Swirl              =  59
7372     SwirlImage         =  60
7373     Resize             =  61
7374     ResizeImage        =  62
7375     Zoom               =  63
7376     ZoomImage          =  64
7377     Annotate           =  65
7378     AnnotateImage      =  66
7379     ColorFloodfill     =  67
7380     ColorFloodfillImage=  68
7381     Composite          =  69
7382     CompositeImage     =  70
7383     Contrast           =  71
7384     ContrastImage      =  72
7385     CycleColormap      =  73
7386     CycleColormapImage =  74
7387     Draw               =  75
7388     DrawImage          =  76
7389     Equalize           =  77
7390     EqualizeImage      =  78
7391     Gamma              =  79
7392     GammaImage         =  80
7393     Map                =  81
7394     MapImage           =  82
7395     MatteFloodfill     =  83
7396     MatteFloodfillImage=  84
7397     Modulate           =  85
7398     ModulateImage      =  86
7399     Negate             =  87
7400     NegateImage        =  88
7401     Normalize          =  89
7402     NormalizeImage     =  90
7403     NumberColors       =  91
7404     NumberColorsImage  =  92
7405     Opaque             =  93
7406     OpaqueImage        =  94
7407     Quantize           =  95
7408     QuantizeImage      =  96
7409     Raise              =  97
7410     RaiseImage         =  98
7411     Segment            =  99
7412     SegmentImage       = 100
7413     Signature          = 101
7414     SignatureImage     = 102
7415     Solarize           = 103
7416     SolarizeImage      = 104
7417     Sync               = 105
7418     SyncImage          = 106
7419     Texture            = 107
7420     TextureImage       = 108
7421     Evaluate           = 109
7422     EvaluateImage      = 110
7423     Transparent        = 111
7424     TransparentImage   = 112
7425     Threshold          = 113
7426     ThresholdImage     = 114
7427     Charcoal           = 115
7428     CharcoalImage      = 116
7429     Trim               = 117
7430     TrimImage          = 118
7431     Wave               = 119
7432     WaveImage          = 120
7433     Separate           = 121
7434     SeparateImage      = 122
7435     Stereo             = 125
7436     StereoImage        = 126
7437     Stegano            = 127
7438     SteganoImage       = 128
7439     Deconstruct        = 129
7440     DeconstructImage   = 130
7441     GaussianBlur       = 131
7442     GaussianBlurImage  = 132
7443     Convolve           = 133
7444     ConvolveImage      = 134
7445     Profile            = 135
7446     ProfileImage       = 136
7447     UnsharpMask        = 137
7448     UnsharpMaskImage   = 138
7449     MotionBlur         = 139
7450     MotionBlurImage    = 140
7451     OrderedDither      = 141
7452     OrderedDitherImage = 142
7453     Shave              = 143
7454     ShaveImage         = 144
7455     Level              = 145
7456     LevelImage         = 146
7457     Clip               = 147
7458     ClipImage          = 148
7459     AffineTransform    = 149
7460     AffineTransformImage = 150
7461     Difference         = 151
7462     DifferenceImage    = 152
7463     AdaptiveThreshold  = 153
7464     AdaptiveThresholdImage = 154
7465     Resample           = 155
7466     ResampleImage      = 156
7467     Describe           = 157
7468     DescribeImage      = 158
7469     BlackThreshold     = 159
7470     BlackThresholdImage= 160
7471     WhiteThreshold     = 161
7472     WhiteThresholdImage= 162
7473     RotationalBlur     = 163
7474     RotationalBlurImage= 164
7475     Thumbnail          = 165
7476     ThumbnailImage     = 166
7477     Strip              = 167
7478     StripImage         = 168
7479     Tint               = 169
7480     TintImage          = 170
7481     Channel            = 171
7482     ChannelImage       = 172
7483     Splice             = 173
7484     SpliceImage        = 174
7485     Posterize          = 175
7486     PosterizeImage     = 176
7487     Shadow             = 177
7488     ShadowImage        = 178
7489     Identify           = 179
7490     IdentifyImage      = 180
7491     SepiaTone          = 181
7492     SepiaToneImage     = 182
7493     SigmoidalContrast  = 183
7494     SigmoidalContrastImage = 184
7495     Extent             = 185
7496     ExtentImage        = 186
7497     Vignette           = 187
7498     VignetteImage      = 188
7499     ContrastStretch    = 189
7500     ContrastStretchImage = 190
7501     Sans0              = 191
7502     Sans0Image         = 192
7503     Sans1              = 193
7504     Sans1Image         = 194
7505     AdaptiveSharpen    = 195
7506     AdaptiveSharpenImage = 196
7507     Transpose          = 197
7508     TransposeImage     = 198
7509     Transverse         = 199
7510     TransverseImage    = 200
7511     AutoOrient         = 201
7512     AutoOrientImage    = 202
7513     AdaptiveBlur       = 203
7514     AdaptiveBlurImage  = 204
7515     Sketch             = 205
7516     SketchImage        = 206
7517     UniqueColors       = 207
7518     UniqueColorsImage  = 208
7519     AdaptiveResize     = 209
7520     AdaptiveResizeImage= 210
7521     ClipMask           = 211
7522     ClipMaskImage      = 212
7523     LinearStretch      = 213
7524     LinearStretchImage = 214
7525     ColorMatrix        = 215
7526     ColorMatrixImage   = 216
7527     Mask               = 217
7528     MaskImage          = 218
7529     Polaroid           = 219
7530     PolaroidImage      = 220
7531     FloodfillPaint     = 221
7532     FloodfillPaintImage= 222
7533     Distort            = 223
7534     DistortImage       = 224
7535     Clut               = 225
7536     ClutImage          = 226
7537     LiquidRescale      = 227
7538     LiquidRescaleImage = 228
7539     Encipher           = 229
7540     EncipherImage      = 230
7541     Decipher           = 231
7542     DecipherImage      = 232
7543     Deskew             = 233
7544     DeskewImage        = 234
7545     Remap              = 235
7546     RemapImage         = 236
7547     SparseColor        = 237
7548     SparseColorImage   = 238
7549     Function           = 239
7550     FunctionImage      = 240
7551     SelectiveBlur      = 241
7552     SelectiveBlurImage = 242
7553     HaldClut           = 243
7554     HaldClutImage      = 244
7555     BlueShift          = 245
7556     BlueShiftImage     = 246
7557     ForwardFourierTransform  = 247
7558     ForwardFourierTransformImage = 248
7559     InverseFourierTransform = 249
7560     InverseFourierTransformImage = 250
7561     ColorDecisionList  = 251
7562     ColorDecisionListImage = 252
7563     AutoGamma          = 253
7564     AutoGammaImage     = 254
7565     AutoLevel          = 255
7566     AutoLevelImage     = 256
7567     LevelColors        = 257
7568     LevelImageColors   = 258
7569     Clamp              = 259
7570     ClampImage         = 260
7571     BrightnessContrast = 261
7572     BrightnessContrastImage = 262
7573     Morphology         = 263
7574     MorphologyImage    = 264
7575     Color              = 265
7576     ColorImage         = 266
7577     Mode               = 267
7578     ModeImage          = 268
7579     Statistic          = 269
7580     StatisticImage     = 270
7581     Perceptible        = 271
7582     PerceptibleImage   = 272
7583     Poly               = 273
7584     PolyImage          = 274
7585     Grayscale          = 275
7586     GrayscaleImage     = 276
7587     CannyEdge          = 278
7588     CannyEdgeImage     = 279
7589     HoughLine          = 280
7590     HoughLineImage     = 281
7591     MeanShift          = 282
7592     MeanShiftImage     = 283
7593     Kuwahara           = 284
7594     KuwaharaImage      = 285
7595     ConnectedComponent = 286
7596     ConnectedComponentImage = 287
7597     CopyPixels         = 288
7598     CopyImagePixels    = 289
7599     MogrifyRegion      = 666
7600   PPCODE:
7601   {
7602     AffineMatrix
7603       affine,
7604       current;
7605
7606     char
7607       attribute_flag[MaxArguments],
7608       message[MagickPathExtent];
7609
7610     ChannelType
7611       channel,
7612       channel_mask;
7613
7614     CompositeOperator
7615       compose;
7616
7617     const char
7618       *attribute,
7619       *value;
7620
7621     double
7622       angle;
7623
7624     ExceptionInfo
7625       *exception;
7626
7627     GeometryInfo
7628       geometry_info;
7629
7630     Image
7631       *image,
7632       *next,
7633       *region_image;
7634
7635     MagickBooleanType
7636       status;
7637
7638     MagickStatusType
7639       flags;
7640
7641     PixelInfo
7642       fill_color;
7643
7644     RectangleInfo
7645       geometry,
7646       region_info;
7647
7648     register ssize_t
7649       i;
7650
7651     ssize_t
7652       base,
7653       j,
7654       number_images;
7655
7656     struct Methods
7657       *rp;
7658
7659     struct PackageInfo
7660       *info;
7661
7662     SV
7663       *perl_exception,
7664       **pv,
7665       *reference,
7666       **reference_vector;
7667
7668     struct ArgumentList
7669       argument_list[MaxArguments];
7670
7671     PERL_UNUSED_VAR(ref);
7672     PERL_UNUSED_VAR(ix);
7673     exception=AcquireExceptionInfo();
7674     perl_exception=newSVpv("",0);
7675     reference_vector=NULL;
7676     region_image=NULL;
7677     number_images=0;
7678     base=2;
7679     if (sv_isobject(ST(0)) == 0)
7680       {
7681         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7682           PackageName);
7683         goto PerlException;
7684       }
7685     reference=SvRV(ST(0));
7686     region_info.width=0;
7687     region_info.height=0;
7688     region_info.x=0;
7689     region_info.y=0;
7690     region_image=(Image *) NULL;
7691     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7692     if (ix && (ix != 666))
7693       {
7694         /*
7695           Called as Method(...)
7696         */
7697         ix=(ix+1)/2;
7698         rp=(&Methods[ix-1]);
7699         attribute=rp->name;
7700       }
7701     else
7702       {
7703         /*
7704           Called as Mogrify("Method",...)
7705         */
7706         attribute=(char *) SvPV(ST(1),na);
7707         if (ix)
7708           {
7709             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7710             attribute=(char *) SvPV(ST(2),na);
7711             base++;
7712           }
7713         for (rp=Methods; ; rp++)
7714         {
7715           if (rp >= EndOf(Methods))
7716             {
7717               ThrowPerlException(exception,OptionError,
7718                 "UnrecognizedPerlMagickMethod",attribute);
7719               goto PerlException;
7720             }
7721           if (strEQcase(attribute,rp->name))
7722             break;
7723         }
7724         ix=rp-Methods+1;
7725         base++;
7726       }
7727     if (image == (Image *) NULL)
7728       {
7729         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7730         goto PerlException;
7731       }
7732     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7733     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7734     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7735     {
7736       Arguments
7737         *pp,
7738         *qq;
7739
7740       ssize_t
7741         ssize_test;
7742
7743       struct ArgumentList
7744         *al;
7745
7746       SV
7747         *sv;
7748
7749       sv=NULL;
7750       ssize_test=0;
7751       pp=(Arguments *) NULL;
7752       qq=rp->arguments;
7753       if (i == items)
7754         {
7755           pp=rp->arguments,
7756           sv=ST(i-1);
7757         }
7758       else
7759         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7760         {
7761           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7762             break;
7763           if (strEQcase(attribute,qq->method) > ssize_test)
7764             {
7765               pp=qq;
7766               ssize_test=strEQcase(attribute,qq->method);
7767             }
7768         }
7769       if (pp == (Arguments *) NULL)
7770         {
7771           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7772             attribute);
7773           goto continue_outer_loop;
7774         }
7775       al=(&argument_list[pp-rp->arguments]);
7776       switch (pp->type)
7777       {
7778         case ArrayReference:
7779         {
7780           if (SvTYPE(sv) != SVt_RV)
7781             {
7782               (void) FormatLocaleString(message,MagickPathExtent,
7783                 "invalid %.60s value",pp->method);
7784               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7785               goto continue_outer_loop;
7786             }
7787           al->array_reference=SvRV(sv);
7788           break;
7789         }
7790         case RealReference:
7791         {
7792           al->real_reference=SvNV(sv);
7793           break;
7794         }
7795         case FileReference:
7796         {
7797           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7798           break;
7799         }
7800         case ImageReference:
7801         {
7802           if (!sv_isobject(sv) ||
7803               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7804                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7805             {
7806               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7807                 PackageName);
7808               goto PerlException;
7809             }
7810           break;
7811         }
7812         case IntegerReference:
7813         {
7814           al->integer_reference=SvIV(sv);
7815           break;
7816         }
7817         case StringReference:
7818         {
7819           al->string_reference=(char *) SvPV(sv,al->length);
7820           if (sv_isobject(sv))
7821             al->image_reference=SetupList(aTHX_ SvRV(sv),
7822               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7823           break;
7824         }
7825         default:
7826         {
7827           /*
7828             Is a string; look up name.
7829           */
7830           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7831             {
7832               al->string_reference=(char *) SvPV(sv,al->length);
7833               al->integer_reference=(-1);
7834               break;
7835             }
7836           al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7837             MagickFalse,SvPV(sv,na));
7838           if (pp->type == MagickChannelOptions)
7839             al->integer_reference=ParseChannelOption(SvPV(sv,na));
7840           if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7841             {
7842               (void) FormatLocaleString(message,MagickPathExtent,
7843                 "invalid %.60s value",pp->method);
7844               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7845               goto continue_outer_loop;
7846             }
7847           break;
7848         }
7849       }
7850       attribute_flag[pp-rp->arguments]++;
7851       continue_outer_loop: ;
7852     }
7853     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7854     pv=reference_vector;
7855     SetGeometryInfo(&geometry_info);
7856     channel=DefaultChannels;
7857     for (next=image; next; next=next->next)
7858     {
7859       image=next;
7860       SetGeometry(image,&geometry);
7861       if ((region_info.width*region_info.height) != 0)
7862         {
7863           region_image=image;
7864           image=CropImage(image,&region_info,exception);
7865         }
7866       switch (ix)
7867       {
7868         default:
7869         {
7870           (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double) ix);
7871           ThrowPerlException(exception,OptionError,
7872             "UnrecognizedPerlMagickMethod",message);
7873           goto PerlException;
7874         }
7875         case 1:  /* Comment */
7876         {
7877           if (attribute_flag[0] == 0)
7878             argument_list[0].string_reference=(char *) NULL;
7879           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7880             info ? info->image_info : (ImageInfo *) NULL,image,
7881             argument_list[0].string_reference,exception),exception);
7882           break;
7883         }
7884         case 2:  /* Label */
7885         {
7886           if (attribute_flag[0] == 0)
7887             argument_list[0].string_reference=(char *) NULL;
7888           (void) SetImageProperty(image,"label",InterpretImageProperties(
7889             info ? info->image_info : (ImageInfo *) NULL,image,
7890             argument_list[0].string_reference,exception),exception);
7891           break;
7892         }
7893         case 3:  /* AddNoise */
7894         {
7895           double
7896             attenuate;
7897
7898           if (attribute_flag[0] == 0)
7899             argument_list[0].integer_reference=UniformNoise;
7900           attenuate=1.0;
7901           if (attribute_flag[1] != 0)
7902             attenuate=argument_list[1].real_reference;
7903           if (attribute_flag[2] != 0)
7904             channel=(ChannelType) argument_list[2].integer_reference;
7905           channel_mask=SetImageChannelMask(image,channel);
7906           image=AddNoiseImage(image,(NoiseType)
7907             argument_list[0].integer_reference,attenuate,exception);
7908           if (image != (Image *) NULL)
7909             (void) SetImageChannelMask(image,channel_mask);
7910           break;
7911         }
7912         case 4:  /* Colorize */
7913         {
7914           PixelInfo
7915             target;
7916
7917           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
7918             0,0,&target,exception);
7919           if (attribute_flag[0] != 0)
7920             (void) QueryColorCompliance(argument_list[0].string_reference,
7921               AllCompliance,&target,exception);
7922           if (attribute_flag[1] == 0)
7923             argument_list[1].string_reference="100%";
7924           image=ColorizeImage(image,argument_list[1].string_reference,&target,
7925             exception);
7926           break;
7927         }
7928         case 5:  /* Border */
7929         {
7930           CompositeOperator
7931             compose;
7932
7933           geometry.width=0;
7934           geometry.height=0;
7935           if (attribute_flag[0] != 0)
7936             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7937               &geometry,exception);
7938           if (attribute_flag[1] != 0)
7939             geometry.width=argument_list[1].integer_reference;
7940           if (attribute_flag[2] != 0)
7941             geometry.height=argument_list[2].integer_reference;
7942           if (attribute_flag[3] != 0)
7943             QueryColorCompliance(argument_list[3].string_reference,
7944               AllCompliance,&image->border_color,exception);
7945           if (attribute_flag[4] != 0)
7946             QueryColorCompliance(argument_list[4].string_reference,
7947               AllCompliance,&image->border_color,exception);
7948           if (attribute_flag[5] != 0)
7949             QueryColorCompliance(argument_list[5].string_reference,
7950               AllCompliance,&image->border_color,exception);
7951           compose=image->compose;
7952           if (attribute_flag[6] != 0)
7953             compose=(CompositeOperator) argument_list[6].integer_reference;
7954           image=BorderImage(image,&geometry,compose,exception);
7955           break;
7956         }
7957         case 6:  /* Blur */
7958         {
7959           if (attribute_flag[0] != 0)
7960             {
7961               flags=ParseGeometry(argument_list[0].string_reference,
7962                 &geometry_info);
7963               if ((flags & SigmaValue) == 0)
7964                 geometry_info.sigma=1.0;
7965             }
7966           if (attribute_flag[1] != 0)
7967             geometry_info.rho=argument_list[1].real_reference;
7968           if (attribute_flag[2] != 0)
7969             geometry_info.sigma=argument_list[2].real_reference;
7970           if (attribute_flag[3] != 0)
7971             channel=(ChannelType) argument_list[3].integer_reference;
7972           channel_mask=SetImageChannelMask(image,channel);
7973           image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
7974             exception);
7975           if (image != (Image *) NULL)
7976             (void) SetImageChannelMask(image,channel_mask);
7977           break;
7978         }
7979         case 7:  /* Chop */
7980         {
7981           if (attribute_flag[5] != 0)
7982             image->gravity=(GravityType) argument_list[5].integer_reference;
7983           if (attribute_flag[0] != 0)
7984             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7985               &geometry,exception);
7986           if (attribute_flag[1] != 0)
7987             geometry.width=argument_list[1].integer_reference;
7988           if (attribute_flag[2] != 0)
7989             geometry.height=argument_list[2].integer_reference;
7990           if (attribute_flag[3] != 0)
7991             geometry.x=argument_list[3].integer_reference;
7992           if (attribute_flag[4] != 0)
7993             geometry.y=argument_list[4].integer_reference;
7994           image=ChopImage(image,&geometry,exception);
7995           break;
7996         }
7997         case 8:  /* Crop */
7998         {
7999           if (attribute_flag[6] != 0)
8000             image->gravity=(GravityType) argument_list[6].integer_reference;
8001           if (attribute_flag[0] != 0)
8002             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
8003               &geometry,exception);
8004           if (attribute_flag[1] != 0)
8005             geometry.width=argument_list[1].integer_reference;
8006           if (attribute_flag[2] != 0)
8007             geometry.height=argument_list[2].integer_reference;
8008           if (attribute_flag[3] != 0)
8009             geometry.x=argument_list[3].integer_reference;
8010           if (attribute_flag[4] != 0)
8011             geometry.y=argument_list[4].integer_reference;
8012           if (attribute_flag[5] != 0)
8013             image->fuzz=StringToDoubleInterval(
8014               argument_list[5].string_reference,(double) QuantumRange+1.0);
8015           image=CropImage(image,&geometry,exception);
8016           break;
8017         }
8018         case 9:  /* Despeckle */
8019         {
8020           image=DespeckleImage(image,exception);
8021           break;
8022         }
8023         case 10:  /* Edge */
8024         {
8025           if (attribute_flag[0] != 0)
8026             geometry_info.rho=argument_list[0].real_reference;
8027           image=EdgeImage(image,geometry_info.rho,exception);
8028           break;
8029         }
8030         case 11:  /* Emboss */
8031         {
8032           if (attribute_flag[0] != 0)
8033             {
8034               flags=ParseGeometry(argument_list[0].string_reference,
8035                 &geometry_info);
8036               if ((flags & SigmaValue) == 0)
8037                 geometry_info.sigma=1.0;
8038             }
8039           if (attribute_flag[1] != 0)
8040             geometry_info.rho=argument_list[1].real_reference;
8041           if (attribute_flag[2] != 0)
8042             geometry_info.sigma=argument_list[2].real_reference;
8043           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
8044             exception);
8045           break;
8046         }
8047         case 12:  /* Enhance */
8048         {
8049           image=EnhanceImage(image,exception);
8050           break;
8051         }
8052         case 13:  /* Flip */
8053         {
8054           image=FlipImage(image,exception);
8055           break;
8056         }
8057         case 14:  /* Flop */
8058         {
8059           image=FlopImage(image,exception);
8060           break;
8061         }
8062         case 15:  /* Frame */
8063         {
8064           CompositeOperator
8065             compose;
8066
8067           FrameInfo
8068             frame_info;
8069
8070           if (attribute_flag[0] != 0)
8071             {
8072               flags=ParsePageGeometry(image,argument_list[0].string_reference,
8073                 &geometry,exception);
8074               frame_info.width=geometry.width;
8075               frame_info.height=geometry.height;
8076               frame_info.outer_bevel=geometry.x;
8077               frame_info.inner_bevel=geometry.y;
8078             }
8079           if (attribute_flag[1] != 0)
8080             frame_info.width=argument_list[1].integer_reference;
8081           if (attribute_flag[2] != 0)
8082             frame_info.height=argument_list[2].integer_reference;
8083           if (attribute_flag[3] != 0)
8084             frame_info.inner_bevel=argument_list[3].integer_reference;
8085           if (attribute_flag[4] != 0)
8086             frame_info.outer_bevel=argument_list[4].integer_reference;
8087           if (attribute_flag[5] != 0)
8088             QueryColorCompliance(argument_list[5].string_reference,
8089               AllCompliance,&fill_color,exception);
8090           if (attribute_flag[6] != 0)
8091             QueryColorCompliance(argument_list[6].string_reference,
8092               AllCompliance,&fill_color,exception);
8093           frame_info.x=(ssize_t) frame_info.width;
8094           frame_info.y=(ssize_t) frame_info.height;
8095           frame_info.width=image->columns+2*frame_info.x;
8096           frame_info.height=image->rows+2*frame_info.y;
8097           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
8098             image->matte_color=fill_color;
8099           compose=image->compose;
8100           if (attribute_flag[7] != 0)
8101             compose=(CompositeOperator) argument_list[7].integer_reference;
8102           image=FrameImage(image,&frame_info,compose,exception);
8103           break;
8104         }
8105         case 16:  /* Implode */
8106         {
8107           PixelInterpolateMethod
8108             method;
8109
8110           if (attribute_flag[0] == 0)
8111             argument_list[0].real_reference=0.5;
8112           method=UndefinedInterpolatePixel;
8113           if (attribute_flag[1] != 0)
8114             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8115           image=ImplodeImage(image,argument_list[0].real_reference,
8116             method,exception);
8117           break;
8118         }
8119         case 17:  /* Magnify */
8120         {
8121           image=MagnifyImage(image,exception);
8122           break;
8123         }
8124         case 18:  /* MedianFilter */
8125         {
8126           if (attribute_flag[0] != 0)
8127             {
8128               flags=ParseGeometry(argument_list[0].string_reference,
8129                 &geometry_info);
8130               if ((flags & SigmaValue) == 0)
8131                 geometry_info.sigma=geometry_info.rho;
8132             }
8133           if (attribute_flag[1] != 0)
8134             geometry_info.rho=argument_list[1].real_reference;
8135           if (attribute_flag[2] != 0)
8136             geometry_info.sigma=argument_list[2].real_reference;
8137           if (attribute_flag[3] != 0)
8138             channel=(ChannelType) argument_list[3].integer_reference;
8139           channel_mask=SetImageChannelMask(image,channel);
8140           image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
8141             (size_t) geometry_info.sigma,exception);
8142           if (image != (Image *) NULL)
8143             (void) SetImageChannelMask(image,channel_mask);
8144           break;
8145         }
8146         case 19:  /* Minify */
8147         {
8148           image=MinifyImage(image,exception);
8149           break;
8150         }
8151         case 20:  /* OilPaint */
8152         {
8153           if (attribute_flag[0] == 0)
8154             argument_list[0].real_reference=0.0;
8155           if (attribute_flag[1] == 0)
8156             argument_list[1].real_reference=1.0;
8157           image=OilPaintImage(image,argument_list[0].real_reference,
8158             argument_list[1].real_reference,exception);
8159           break;
8160         }
8161         case 21:  /* ReduceNoise */
8162         {
8163           if (attribute_flag[0] != 0)
8164             {
8165               flags=ParseGeometry(argument_list[0].string_reference,
8166                 &geometry_info);
8167               if ((flags & SigmaValue) == 0)
8168                 geometry_info.sigma=1.0;
8169             }
8170           if (attribute_flag[1] != 0)
8171             geometry_info.rho=argument_list[1].real_reference;
8172           if (attribute_flag[2] != 0)
8173             geometry_info.sigma=argument_list[2].real_reference;
8174           if (attribute_flag[3] != 0)
8175             channel=(ChannelType) argument_list[3].integer_reference;
8176           channel_mask=SetImageChannelMask(image,channel);
8177           image=StatisticImage(image,NonpeakStatistic,(size_t)
8178             geometry_info.rho,(size_t) geometry_info.sigma,exception);
8179           if (image != (Image *) NULL)
8180             (void) SetImageChannelMask(image,channel_mask);
8181           break;
8182         }
8183         case 22:  /* Roll */
8184         {
8185           if (attribute_flag[0] != 0)
8186             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8187               &geometry,exception);
8188           if (attribute_flag[1] != 0)
8189             geometry.x=argument_list[1].integer_reference;
8190           if (attribute_flag[2] != 0)
8191             geometry.y=argument_list[2].integer_reference;
8192           image=RollImage(image,geometry.x,geometry.y,exception);
8193           break;
8194         }
8195         case 23:  /* Rotate */
8196         {
8197           if (attribute_flag[0] == 0)
8198             argument_list[0].real_reference=90.0;
8199           if (attribute_flag[1] != 0)
8200             {
8201               QueryColorCompliance(argument_list[1].string_reference,
8202                 AllCompliance,&image->background_color,exception);
8203               if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
8204                   (image->alpha_trait == UndefinedPixelTrait))
8205                 (void) SetImageAlpha(image,OpaqueAlpha,exception);
8206             }
8207           image=RotateImage(image,argument_list[0].real_reference,exception);
8208           break;
8209         }
8210         case 24:  /* Sample */
8211         {
8212           if (attribute_flag[0] != 0)
8213             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8214               &geometry,exception);
8215           if (attribute_flag[1] != 0)
8216             geometry.width=argument_list[1].integer_reference;
8217           if (attribute_flag[2] != 0)
8218             geometry.height=argument_list[2].integer_reference;
8219           image=SampleImage(image,geometry.width,geometry.height,exception);
8220           break;
8221         }
8222         case 25:  /* Scale */
8223         {
8224           if (attribute_flag[0] != 0)
8225             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8226               &geometry,exception);
8227           if (attribute_flag[1] != 0)
8228             geometry.width=argument_list[1].integer_reference;
8229           if (attribute_flag[2] != 0)
8230             geometry.height=argument_list[2].integer_reference;
8231           image=ScaleImage(image,geometry.width,geometry.height,exception);
8232           break;
8233         }
8234         case 26:  /* Shade */
8235         {
8236           if (attribute_flag[0] != 0)
8237             {
8238               flags=ParseGeometry(argument_list[0].string_reference,
8239                 &geometry_info);
8240               if ((flags & SigmaValue) == 0)
8241                 geometry_info.sigma=0.0;
8242             }
8243           if (attribute_flag[1] != 0)
8244             geometry_info.rho=argument_list[1].real_reference;
8245           if (attribute_flag[2] != 0)
8246             geometry_info.sigma=argument_list[2].real_reference;
8247           image=ShadeImage(image,
8248             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8249             geometry_info.rho,geometry_info.sigma,exception);
8250           break;
8251         }
8252         case 27:  /* Sharpen */
8253         {
8254           if (attribute_flag[0] != 0)
8255             {
8256               flags=ParseGeometry(argument_list[0].string_reference,
8257                 &geometry_info);
8258               if ((flags & SigmaValue) == 0)
8259                 geometry_info.sigma=1.0;
8260             }
8261           if (attribute_flag[1] != 0)
8262             geometry_info.rho=argument_list[1].real_reference;
8263           if (attribute_flag[2] != 0)
8264             geometry_info.sigma=argument_list[2].real_reference;
8265           if (attribute_flag[3] != 0)
8266             channel=(ChannelType) argument_list[3].integer_reference;
8267           channel_mask=SetImageChannelMask(image,channel);
8268           image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
8269             exception);
8270           if (image != (Image *) NULL)
8271             (void) SetImageChannelMask(image,channel_mask);
8272           break;
8273         }
8274         case 28:  /* Shear */
8275         {
8276           if (attribute_flag[0] != 0)
8277             {
8278               flags=ParseGeometry(argument_list[0].string_reference,
8279                 &geometry_info);
8280               if ((flags & SigmaValue) == 0)
8281                 geometry_info.sigma=geometry_info.rho;
8282             }
8283           if (attribute_flag[1] != 0)
8284             geometry_info.rho=argument_list[1].real_reference;
8285           if (attribute_flag[2] != 0)
8286             geometry_info.sigma=argument_list[2].real_reference;
8287           if (attribute_flag[3] != 0)
8288             QueryColorCompliance(argument_list[3].string_reference,
8289               AllCompliance,&image->background_color,exception);
8290           if (attribute_flag[4] != 0)
8291             QueryColorCompliance(argument_list[4].string_reference,
8292               AllCompliance,&image->background_color,exception);
8293           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
8294             exception);
8295           break;
8296         }
8297         case 29:  /* Spread */
8298         {
8299           PixelInterpolateMethod
8300             method;
8301
8302           if (attribute_flag[0] == 0)
8303             argument_list[0].real_reference=1.0;
8304           method=UndefinedInterpolatePixel;
8305           if (attribute_flag[1] != 0)
8306             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8307           image=SpreadImage(image,method,argument_list[0].real_reference,
8308             exception);
8309           break;
8310         }
8311         case 30:  /* Swirl */
8312         {
8313           PixelInterpolateMethod
8314             method;
8315
8316           if (attribute_flag[0] == 0)
8317             argument_list[0].real_reference=50.0;
8318           method=UndefinedInterpolatePixel;
8319           if (attribute_flag[1] != 0)
8320             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8321           image=SwirlImage(image,argument_list[0].real_reference,
8322             method,exception);
8323           break;
8324         }
8325         case 31:  /* Resize */
8326         case 32:  /* Zoom */
8327         {
8328           if (attribute_flag[0] != 0)
8329             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8330               &geometry,exception);
8331           if (attribute_flag[1] != 0)
8332             geometry.width=argument_list[1].integer_reference;
8333           if (attribute_flag[2] != 0)
8334             geometry.height=argument_list[2].integer_reference;
8335           if (attribute_flag[3] == 0)
8336             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
8337           if (attribute_flag[4] != 0)
8338             SetImageArtifact(image,"filter:support",
8339               argument_list[4].string_reference);
8340           image=ResizeImage(image,geometry.width,geometry.height,
8341             (FilterTypes) argument_list[3].integer_reference,
8342             exception);
8343           break;
8344         }
8345         case 33:  /* Annotate */
8346         {
8347           DrawInfo
8348             *draw_info;
8349
8350           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8351             (DrawInfo *) NULL);
8352           if (attribute_flag[0] != 0)
8353             {
8354               char
8355                 *text;
8356
8357               text=InterpretImageProperties(info ? info->image_info :
8358                 (ImageInfo *) NULL,image,argument_list[0].string_reference,
8359                 exception);
8360               (void) CloneString(&draw_info->text,text);
8361               text=DestroyString(text);
8362             }
8363           if (attribute_flag[1] != 0)
8364             (void) CloneString(&draw_info->font,
8365               argument_list[1].string_reference);
8366           if (attribute_flag[2] != 0)
8367             draw_info->pointsize=argument_list[2].real_reference;
8368           if (attribute_flag[3] != 0)
8369             (void) CloneString(&draw_info->density,
8370               argument_list[3].string_reference);
8371           if (attribute_flag[4] != 0)
8372             (void) QueryColorCompliance(argument_list[4].string_reference,
8373               AllCompliance,&draw_info->undercolor,exception);
8374           if (attribute_flag[5] != 0)
8375             {
8376               (void) QueryColorCompliance(argument_list[5].string_reference,
8377                 AllCompliance,&draw_info->stroke,exception);
8378               if (argument_list[5].image_reference != (Image *) NULL)
8379                 draw_info->stroke_pattern=CloneImage(
8380                   argument_list[5].image_reference,0,0,MagickTrue,exception);
8381             }
8382           if (attribute_flag[6] != 0)
8383             {
8384               (void) QueryColorCompliance(argument_list[6].string_reference,
8385                 AllCompliance,&draw_info->fill,exception);
8386               if (argument_list[6].image_reference != (Image *) NULL)
8387                 draw_info->fill_pattern=CloneImage(
8388                   argument_list[6].image_reference,0,0,MagickTrue,exception);
8389             }
8390           if (attribute_flag[7] != 0)
8391             {
8392               (void) CloneString(&draw_info->geometry,
8393                 argument_list[7].string_reference);
8394               flags=ParsePageGeometry(image,argument_list[7].string_reference,
8395                 &geometry,exception);
8396               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8397                 geometry_info.sigma=geometry_info.xi;
8398             }
8399           if (attribute_flag[8] != 0)
8400             (void) QueryColorCompliance(argument_list[8].string_reference,
8401               AllCompliance,&draw_info->fill,exception);
8402           if (attribute_flag[11] != 0)
8403             draw_info->gravity=(GravityType)
8404               argument_list[11].integer_reference;
8405           if (attribute_flag[25] != 0)
8406             {
8407               AV
8408                 *av;
8409
8410               av=(AV *) argument_list[25].array_reference;
8411               if ((av_len(av) != 3) && (av_len(av) != 5))
8412                 {
8413                   ThrowPerlException(exception,OptionError,
8414                     "affine matrix must have 4 or 6 elements",PackageName);
8415                   goto PerlException;
8416                 }
8417               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8418               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8419               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8420               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8421               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8422                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8423                 {
8424                   ThrowPerlException(exception,OptionError,
8425                     "affine matrix is singular",PackageName);
8426                    goto PerlException;
8427                 }
8428               if (av_len(av) == 5)
8429                 {
8430                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8431                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8432                 }
8433             }
8434           for (j=12; j < 17; j++)
8435           {
8436             if (attribute_flag[j] == 0)
8437               continue;
8438             value=argument_list[j].string_reference;
8439             angle=argument_list[j].real_reference;
8440             current=draw_info->affine;
8441             GetAffineMatrix(&affine);
8442             switch (j)
8443             {
8444               case 12:
8445               {
8446                 /*
8447                   Translate.
8448                 */
8449                 flags=ParseGeometry(value,&geometry_info);
8450                 affine.tx=geometry_info.xi;
8451                 affine.ty=geometry_info.psi;
8452                 if ((flags & PsiValue) == 0)
8453                   affine.ty=affine.tx;
8454                 break;
8455               }
8456               case 13:
8457               {
8458                 /*
8459                   Scale.
8460                 */
8461                 flags=ParseGeometry(value,&geometry_info);
8462                 affine.sx=geometry_info.rho;
8463                 affine.sy=geometry_info.sigma;
8464                 if ((flags & SigmaValue) == 0)
8465                   affine.sy=affine.sx;
8466                 break;
8467               }
8468               case 14:
8469               {
8470                 /*
8471                   Rotate.
8472                 */
8473                 if (angle == 0.0)
8474                   break;
8475                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8476                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8477                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8478                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8479                 break;
8480               }
8481               case 15:
8482               {
8483                 /*
8484                   SkewX.
8485                 */
8486                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8487                 break;
8488               }
8489               case 16:
8490               {
8491                 /*
8492                   SkewY.
8493                 */
8494                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8495                 break;
8496               }
8497             }
8498             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8499             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8500             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8501             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8502             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8503               current.tx;
8504             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8505               current.ty;
8506           }
8507           if (attribute_flag[9] == 0)
8508             argument_list[9].real_reference=0.0;
8509           if (attribute_flag[10] == 0)
8510             argument_list[10].real_reference=0.0;
8511           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8512             {
8513               char
8514                 geometry[MagickPathExtent];
8515
8516               (void) FormatLocaleString(geometry,MagickPathExtent,"%+f%+f",
8517                 (double) argument_list[9].real_reference+draw_info->affine.tx,
8518                 (double) argument_list[10].real_reference+draw_info->affine.ty);
8519               (void) CloneString(&draw_info->geometry,geometry);
8520             }
8521           if (attribute_flag[17] != 0)
8522             draw_info->stroke_width=argument_list[17].real_reference;
8523           if (attribute_flag[18] != 0)
8524             {
8525               draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8526                 MagickTrue : MagickFalse;
8527               draw_info->stroke_antialias=draw_info->text_antialias;
8528             }
8529           if (attribute_flag[19] != 0)
8530             (void) CloneString(&draw_info->family,
8531               argument_list[19].string_reference);
8532           if (attribute_flag[20] != 0)
8533             draw_info->style=(StyleType) argument_list[20].integer_reference;
8534           if (attribute_flag[21] != 0)
8535             draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8536           if (attribute_flag[22] != 0)
8537             draw_info->weight=argument_list[22].integer_reference;
8538           if (attribute_flag[23] != 0)
8539             draw_info->align=(AlignType) argument_list[23].integer_reference;
8540           if (attribute_flag[24] != 0)
8541             (void) CloneString(&draw_info->encoding,
8542               argument_list[24].string_reference);
8543           if (attribute_flag[25] != 0)
8544             draw_info->fill_pattern=CloneImage(
8545               argument_list[25].image_reference,0,0,MagickTrue,exception);
8546           if (attribute_flag[26] != 0)
8547             draw_info->fill_pattern=CloneImage(
8548               argument_list[26].image_reference,0,0,MagickTrue,exception);
8549           if (attribute_flag[27] != 0)
8550             draw_info->stroke_pattern=CloneImage(
8551               argument_list[27].image_reference,0,0,MagickTrue,exception);
8552           if (attribute_flag[29] != 0)
8553             draw_info->kerning=argument_list[29].real_reference;
8554           if (attribute_flag[30] != 0)
8555             draw_info->interline_spacing=argument_list[30].real_reference;
8556           if (attribute_flag[31] != 0)
8557             draw_info->interword_spacing=argument_list[31].real_reference;
8558           if (attribute_flag[32] != 0)
8559             draw_info->direction=(DirectionType)
8560               argument_list[32].integer_reference;
8561           (void) AnnotateImage(image,draw_info,exception);
8562           draw_info=DestroyDrawInfo(draw_info);
8563           break;
8564         }
8565         case 34:  /* ColorFloodfill */
8566         {
8567           DrawInfo
8568             *draw_info;
8569
8570           MagickBooleanType
8571             invert;
8572
8573           PixelInfo
8574             target;
8575
8576           draw_info=CloneDrawInfo(info ? info->image_info :
8577             (ImageInfo *) NULL,(DrawInfo *) NULL);
8578           if (attribute_flag[0] != 0)
8579             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8580               &geometry,exception);
8581           if (attribute_flag[1] != 0)
8582             geometry.x=argument_list[1].integer_reference;
8583           if (attribute_flag[2] != 0)
8584             geometry.y=argument_list[2].integer_reference;
8585           if (attribute_flag[3] != 0)
8586             (void) QueryColorCompliance(argument_list[3].string_reference,
8587               AllCompliance,&draw_info->fill,exception);
8588           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
8589             geometry.x,geometry.y,&target,exception);
8590           invert=MagickFalse;
8591           if (attribute_flag[4] != 0)
8592             {
8593               QueryColorCompliance(argument_list[4].string_reference,
8594                 AllCompliance,&target,exception);
8595               invert=MagickTrue;
8596             }
8597           if (attribute_flag[5] != 0)
8598             image->fuzz=StringToDoubleInterval(
8599               argument_list[5].string_reference,(double) QuantumRange+1.0);
8600           if (attribute_flag[6] != 0)
8601             invert=(MagickBooleanType) argument_list[6].integer_reference;
8602           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8603             geometry.y,invert,exception);
8604           draw_info=DestroyDrawInfo(draw_info);
8605           break;
8606         }
8607         case 35:  /* Composite */
8608         {
8609           char
8610             composite_geometry[MagickPathExtent];
8611
8612           Image
8613             *composite_image,
8614             *rotate_image;
8615
8616           MagickBooleanType
8617             clip_to_self;
8618
8619           compose=OverCompositeOp;
8620           if (attribute_flag[0] != 0)
8621             composite_image=argument_list[0].image_reference;
8622           else
8623             {
8624               ThrowPerlException(exception,OptionError,
8625                 "CompositeImageRequired",PackageName);
8626               goto PerlException;
8627             }
8628           /*
8629             Parameter Handling used for BOTH normal and tiled composition.
8630           */
8631           if (attribute_flag[1] != 0) /* compose */
8632             compose=(CompositeOperator) argument_list[1].integer_reference;
8633           if (attribute_flag[6] != 0) /* opacity  */
8634             {
8635               if (compose != DissolveCompositeOp)
8636                 (void) SetImageAlpha(composite_image,(Quantum)
8637                   StringToDoubleInterval(argument_list[6].string_reference,
8638                   (double) QuantumRange+1.0),exception);
8639               else
8640                 {
8641                   CacheView
8642                     *composite_view;
8643
8644                   double
8645                     opacity;
8646
8647                   MagickBooleanType
8648                     sync;
8649
8650                   register ssize_t
8651                     x;
8652
8653                   register Quantum
8654                     *q;
8655
8656                   ssize_t
8657                     y;
8658
8659                   /*
8660                     Handle dissolve composite operator (patch by
8661                     Kevin A. McGrail).
8662                   */
8663                   (void) CloneString(&image->geometry,
8664                     argument_list[6].string_reference);
8665                   opacity=(Quantum) StringToDoubleInterval(
8666                     argument_list[6].string_reference,(double) QuantumRange+
8667                     1.0);
8668                   if (composite_image->alpha_trait != UndefinedPixelTrait)
8669                     (void) SetImageAlpha(composite_image,OpaqueAlpha,exception);
8670                   composite_view=AcquireAuthenticCacheView(composite_image,exception);
8671                   for (y=0; y < (ssize_t) composite_image->rows ; y++)
8672                   {
8673                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8674                       composite_image->columns,1,exception);
8675                     for (x=0; x < (ssize_t) composite_image->columns; x++)
8676                     {
8677                       if (GetPixelAlpha(image,q) == OpaqueAlpha)
8678                         SetPixelAlpha(composite_image,ClampToQuantum(opacity),
8679                           q);
8680                       q+=GetPixelChannels(composite_image);
8681                     }
8682                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8683                     if (sync == MagickFalse)
8684                       break;
8685                   }
8686                   composite_view=DestroyCacheView(composite_view);
8687                 }
8688             }
8689           if (attribute_flag[9] != 0)    /* "color=>" */
8690             QueryColorCompliance(argument_list[9].string_reference,
8691               AllCompliance,&composite_image->background_color,exception);
8692           if (attribute_flag[12] != 0) /* "interpolate=>" */
8693             image->interpolate=(PixelInterpolateMethod)
8694               argument_list[12].integer_reference;
8695           if (attribute_flag[13] != 0)   /* "args=>" */
8696             (void) SetImageArtifact(composite_image,"compose:args",
8697               argument_list[13].string_reference);
8698           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8699             (void) SetImageArtifact(composite_image,"compose:args",
8700               argument_list[14].string_reference);
8701           clip_to_self=MagickTrue;
8702           if (attribute_flag[15] != 0)
8703             clip_to_self=(MagickBooleanType)
8704               argument_list[15].integer_reference;
8705           /*
8706             Tiling Composition (with orthogonal rotate).
8707           */
8708           rotate_image=(Image *) NULL;
8709           if (attribute_flag[8] != 0)   /* "rotate=>" */
8710             {
8711                /*
8712                  Rotate image.
8713                */
8714                rotate_image=RotateImage(composite_image,
8715                  argument_list[8].real_reference,exception);
8716                if (rotate_image == (Image *) NULL)
8717                  break;
8718             }
8719           if ((attribute_flag[7] != 0) &&
8720               (argument_list[7].integer_reference != 0)) /* tile */
8721             {
8722               ssize_t
8723                 x,
8724                 y;
8725
8726               /*
8727                 Tile the composite image.
8728               */
8729              if (attribute_flag[8] != 0)   /* "tile=>" */
8730                (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8731                  "false");
8732              else
8733                (void) SetImageArtifact(composite_image,
8734                  "compose:outside-overlay","false");
8735              for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8736                 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8737                 {
8738                   if (attribute_flag[8] != 0) /* rotate */
8739                     (void) CompositeImage(image,rotate_image,compose,
8740                       MagickTrue,x,y,exception);
8741                   else
8742                     (void) CompositeImage(image,composite_image,compose,
8743                       MagickTrue,x,y,exception);
8744                 }
8745               if (attribute_flag[8] != 0) /* rotate */
8746                 rotate_image=DestroyImage(rotate_image);
8747               break;
8748             }
8749           /*
8750             Parameter Handling used used ONLY for normal composition.
8751           */
8752           if (attribute_flag[5] != 0) /* gravity */
8753             image->gravity=(GravityType) argument_list[5].integer_reference;
8754           if (attribute_flag[2] != 0) /* geometry offset */
8755             {
8756               SetGeometry(image,&geometry);
8757               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8758                 &geometry);
8759               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8760                 &geometry);
8761             }
8762           if (attribute_flag[3] != 0) /* x offset */
8763             geometry.x=argument_list[3].integer_reference;
8764           if (attribute_flag[4] != 0) /* y offset */
8765             geometry.y=argument_list[4].integer_reference;
8766           if (attribute_flag[10] != 0) /* mask */
8767             {
8768               if ((image->compose == DisplaceCompositeOp) ||
8769                   (image->compose == DistortCompositeOp))
8770                 {
8771                   /*
8772                     Merge Y displacement into X displacement image.
8773                   */
8774                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8775                     exception);
8776                   (void) CompositeImage(composite_image,
8777                     argument_list[10].image_reference,CopyGreenCompositeOp,
8778                     MagickTrue,0,0,exception);
8779                 }
8780               else
8781                 {
8782                   Image
8783                     *mask_image;
8784
8785                   /*
8786                     Set a blending mask for the composition.
8787                   */
8788                   mask_image=CloneImage(argument_list[10].image_reference,0,0,
8789                     MagickTrue,exception);
8790                   (void) SetImageMask(composite_image,ReadPixelMask,mask_image,
8791                     exception);
8792                   mask_image=DestroyImage(mask_image);
8793                 }
8794             }
8795           if (attribute_flag[11] != 0) /* channel */
8796             channel=(ChannelType) argument_list[11].integer_reference;
8797           /*
8798             Composite two images (normal composition).
8799           */
8800           (void) FormatLocaleString(composite_geometry,MagickPathExtent,
8801             "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8802             (double) composite_image->rows,(double) geometry.x,(double)
8803             geometry.y);
8804           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8805             exception);
8806           channel_mask=SetImageChannelMask(image,channel);
8807           if (attribute_flag[8] == 0) /* no rotate */
8808             CompositeImage(image,composite_image,compose,clip_to_self,
8809               geometry.x,geometry.y,exception);
8810           else
8811             {
8812               /*
8813                 Position adjust rotated image then composite.
8814               */
8815               geometry.x-=(ssize_t) (rotate_image->columns-
8816                 composite_image->columns)/2;
8817               geometry.y-=(ssize_t) (rotate_image->rows-
8818                 composite_image->rows)/2;
8819               CompositeImage(image,rotate_image,compose,clip_to_self,geometry.x,
8820                 geometry.y,exception);
8821               rotate_image=DestroyImage(rotate_image);
8822             }
8823           if (attribute_flag[10] != 0) /* mask */
8824             {
8825               if ((image->compose == DisplaceCompositeOp) ||
8826                   (image->compose == DistortCompositeOp))
8827                 composite_image=DestroyImage(composite_image);
8828               else
8829                 (void) SetImageMask(image,ReadPixelMask,(Image *) NULL,
8830                   exception);
8831             }
8832           (void) SetImageChannelMask(image,channel_mask);
8833           break;
8834         }
8835         case 36:  /* Contrast */
8836         {
8837           if (attribute_flag[0] == 0)
8838             argument_list[0].integer_reference=0;
8839           (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8840             MagickTrue : MagickFalse,exception);
8841           break;
8842         }
8843         case 37:  /* CycleColormap */
8844         {
8845           if (attribute_flag[0] == 0)
8846             argument_list[0].integer_reference=6;
8847           (void) CycleColormapImage(image,argument_list[0].integer_reference,
8848             exception);
8849           break;
8850         }
8851         case 38:  /* Draw */
8852         {
8853           DrawInfo
8854             *draw_info;
8855
8856           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8857             (DrawInfo *) NULL);
8858           (void) CloneString(&draw_info->primitive,"point");
8859           if (attribute_flag[0] != 0)
8860             {
8861               if (argument_list[0].integer_reference < 0)
8862                 (void) CloneString(&draw_info->primitive,
8863                   argument_list[0].string_reference);
8864               else
8865                 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8866                   MagickPrimitiveOptions,argument_list[0].integer_reference));
8867             }
8868           if (attribute_flag[1] != 0)
8869             {
8870               if (LocaleCompare(draw_info->primitive,"path") == 0)
8871                 {
8872                   (void) ConcatenateString(&draw_info->primitive," '");
8873                   ConcatenateString(&draw_info->primitive,
8874                     argument_list[1].string_reference);
8875                   (void) ConcatenateString(&draw_info->primitive,"'");
8876                 }
8877               else
8878                 {
8879                   (void) ConcatenateString(&draw_info->primitive," ");
8880                   ConcatenateString(&draw_info->primitive,
8881                     argument_list[1].string_reference);
8882                 }
8883             }
8884           if (attribute_flag[2] != 0)
8885             {
8886               (void) ConcatenateString(&draw_info->primitive," ");
8887               (void) ConcatenateString(&draw_info->primitive,
8888                 CommandOptionToMnemonic(MagickMethodOptions,
8889                 argument_list[2].integer_reference));
8890             }
8891           if (attribute_flag[3] != 0)
8892             {
8893               (void) QueryColorCompliance(argument_list[3].string_reference,
8894                 AllCompliance,&draw_info->stroke,exception);
8895               if (argument_list[3].image_reference != (Image *) NULL)
8896                 draw_info->stroke_pattern=CloneImage(
8897                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8898             }
8899           if (attribute_flag[4] != 0)
8900             {
8901               (void) QueryColorCompliance(argument_list[4].string_reference,
8902                 AllCompliance,&draw_info->fill,exception);
8903               if (argument_list[4].image_reference != (Image *) NULL)
8904                 draw_info->fill_pattern=CloneImage(
8905                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8906             }
8907           if (attribute_flag[5] != 0)
8908             draw_info->stroke_width=argument_list[5].real_reference;
8909           if (attribute_flag[6] != 0)
8910             (void) CloneString(&draw_info->font,
8911               argument_list[6].string_reference);
8912           if (attribute_flag[7] != 0)
8913             (void) QueryColorCompliance(argument_list[7].string_reference,
8914               AllCompliance,&draw_info->border_color,exception);
8915           if (attribute_flag[8] != 0)
8916             draw_info->affine.tx=argument_list[8].real_reference;
8917           if (attribute_flag[9] != 0)
8918             draw_info->affine.ty=argument_list[9].real_reference;
8919           if (attribute_flag[20] != 0)
8920             {
8921               AV
8922                 *av;
8923
8924               av=(AV *) argument_list[20].array_reference;
8925               if ((av_len(av) != 3) && (av_len(av) != 5))
8926                 {
8927                   ThrowPerlException(exception,OptionError,
8928                     "affine matrix must have 4 or 6 elements",PackageName);
8929                   goto PerlException;
8930                 }
8931               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8932               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8933               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8934               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8935               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8936                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8937                 {
8938                   ThrowPerlException(exception,OptionError,
8939                     "affine matrix is singular",PackageName);
8940                    goto PerlException;
8941                 }
8942               if (av_len(av) == 5)
8943                 {
8944                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8945                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8946                 }
8947             }
8948           for (j=10; j < 15; j++)
8949           {
8950             if (attribute_flag[j] == 0)
8951               continue;
8952             value=argument_list[j].string_reference;
8953             angle=argument_list[j].real_reference;
8954             current=draw_info->affine;
8955             GetAffineMatrix(&affine);
8956             switch (j)
8957             {
8958               case 10:
8959               {
8960                 /*
8961                   Translate.
8962                 */
8963                 flags=ParseGeometry(value,&geometry_info);
8964                 affine.tx=geometry_info.xi;
8965                 affine.ty=geometry_info.psi;
8966                 if ((flags & PsiValue) == 0)
8967                   affine.ty=affine.tx;
8968                 break;
8969               }
8970               case 11:
8971               {
8972                 /*
8973                   Scale.
8974                 */
8975                 flags=ParseGeometry(value,&geometry_info);
8976                 affine.sx=geometry_info.rho;
8977                 affine.sy=geometry_info.sigma;
8978                 if ((flags & SigmaValue) == 0)
8979                   affine.sy=affine.sx;
8980                 break;
8981               }
8982               case 12:
8983               {
8984                 /*
8985                   Rotate.
8986                 */
8987                 if (angle == 0.0)
8988                   break;
8989                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8990                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8991                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8992                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8993                 break;
8994               }
8995               case 13:
8996               {
8997                 /*
8998                   SkewX.
8999                 */
9000                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9001                 break;
9002               }
9003               case 14:
9004               {
9005                 /*
9006                   SkewY.
9007                 */
9008                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9009                 break;
9010               }
9011             }
9012             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9013             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9014             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9015             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9016             draw_info->affine.tx=
9017               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9018             draw_info->affine.ty=
9019               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9020           }
9021           if (attribute_flag[15] != 0)
9022             draw_info->fill_pattern=CloneImage(
9023               argument_list[15].image_reference,0,0,MagickTrue,exception);
9024           if (attribute_flag[16] != 0)
9025             draw_info->pointsize=argument_list[16].real_reference;
9026           if (attribute_flag[17] != 0)
9027             {
9028               draw_info->stroke_antialias=argument_list[17].integer_reference != 0
9029                 ? MagickTrue : MagickFalse;
9030               draw_info->text_antialias=draw_info->stroke_antialias;
9031             }
9032           if (attribute_flag[18] != 0)
9033             (void) CloneString(&draw_info->density,
9034               argument_list[18].string_reference);
9035           if (attribute_flag[19] != 0)
9036             draw_info->stroke_width=argument_list[19].real_reference;
9037           if (attribute_flag[21] != 0)
9038             draw_info->dash_offset=argument_list[21].real_reference;
9039           if (attribute_flag[22] != 0)
9040             {
9041               AV
9042                 *av;
9043
9044               av=(AV *) argument_list[22].array_reference;
9045               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
9046                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
9047               if (draw_info->dash_pattern != (double *) NULL)
9048                 {
9049                   for (i=0; i <= av_len(av); i++)
9050                     draw_info->dash_pattern[i]=(double)
9051                       SvNV(*(av_fetch(av,i,0)));
9052                   draw_info->dash_pattern[i]=0.0;
9053                 }
9054             }
9055           if (attribute_flag[23] != 0)
9056             image->interpolate=(PixelInterpolateMethod)
9057               argument_list[23].integer_reference;
9058           if ((attribute_flag[24] != 0) &&
9059               (draw_info->fill_pattern != (Image *) NULL))
9060             flags=ParsePageGeometry(draw_info->fill_pattern,
9061               argument_list[24].string_reference,
9062               &draw_info->fill_pattern->tile_offset,exception);
9063           if (attribute_flag[25] != 0)
9064             {
9065               (void) ConcatenateString(&draw_info->primitive," '");
9066               (void) ConcatenateString(&draw_info->primitive,
9067                 argument_list[25].string_reference);
9068               (void) ConcatenateString(&draw_info->primitive,"'");
9069             }
9070           if (attribute_flag[26] != 0)
9071             draw_info->fill_pattern=CloneImage(
9072               argument_list[26].image_reference,0,0,MagickTrue,exception);
9073           if (attribute_flag[27] != 0)
9074             draw_info->stroke_pattern=CloneImage(
9075               argument_list[27].image_reference,0,0,MagickTrue,exception);
9076           if (attribute_flag[28] != 0)
9077             (void) CloneString(&draw_info->primitive,
9078               argument_list[28].string_reference);
9079           if (attribute_flag[29] != 0)
9080             draw_info->kerning=argument_list[29].real_reference;
9081           if (attribute_flag[30] != 0)
9082             draw_info->interline_spacing=argument_list[30].real_reference;
9083           if (attribute_flag[31] != 0)
9084             draw_info->interword_spacing=argument_list[31].real_reference;
9085           if (attribute_flag[32] != 0)
9086             draw_info->direction=(DirectionType)
9087               argument_list[32].integer_reference;
9088           DrawImage(image,draw_info,exception);
9089           draw_info=DestroyDrawInfo(draw_info);
9090           break;
9091         }
9092         case 39:  /* Equalize */
9093         {
9094           if (attribute_flag[0] != 0)
9095             channel=(ChannelType) argument_list[0].integer_reference;
9096           channel_mask=SetImageChannelMask(image,channel);
9097           EqualizeImage(image,exception);
9098           (void) SetImageChannelMask(image,channel_mask);
9099           break;
9100         }
9101         case 40:  /* Gamma */
9102         {
9103           if (attribute_flag[1] != 0)
9104             channel=(ChannelType) argument_list[1].integer_reference;
9105           if (attribute_flag[2] == 0)
9106             argument_list[2].real_reference=1.0;
9107           if (attribute_flag[3] == 0)
9108             argument_list[3].real_reference=1.0;
9109           if (attribute_flag[4] == 0)
9110             argument_list[4].real_reference=1.0;
9111           if (attribute_flag[0] == 0)
9112             {
9113               (void) FormatLocaleString(message,MagickPathExtent,
9114                 "%.15g,%.15g,%.15g",(double) argument_list[2].real_reference,
9115                 (double) argument_list[3].real_reference,
9116                 (double) argument_list[4].real_reference);
9117               argument_list[0].string_reference=message;
9118             }
9119           (void) GammaImage(image,StringToDouble(
9120             argument_list[0].string_reference,(char **) NULL),exception);
9121           break;
9122         }
9123         case 41:  /* Map */
9124         {
9125           QuantizeInfo
9126             *quantize_info;
9127
9128           if (attribute_flag[0] == 0)
9129             {
9130               ThrowPerlException(exception,OptionError,"MapImageRequired",
9131                 PackageName);
9132               goto PerlException;
9133             }
9134           quantize_info=AcquireQuantizeInfo(info->image_info);
9135           if (attribute_flag[1] != 0)
9136             quantize_info->dither_method=(DitherMethod)
9137               argument_list[1].integer_reference;
9138           (void) RemapImages(quantize_info,image,
9139             argument_list[0].image_reference,exception);
9140           quantize_info=DestroyQuantizeInfo(quantize_info);
9141           break;
9142         }
9143         case 42:  /* MatteFloodfill */
9144         {
9145           DrawInfo
9146             *draw_info;
9147
9148           MagickBooleanType
9149             invert;
9150
9151           PixelInfo
9152             target;
9153
9154           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9155             (DrawInfo *) NULL);
9156           if (attribute_flag[0] != 0)
9157             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9158               &geometry,exception);
9159           if (attribute_flag[1] != 0)
9160             geometry.x=argument_list[1].integer_reference;
9161           if (attribute_flag[2] != 0)
9162             geometry.y=argument_list[2].integer_reference;
9163           if (image->alpha_trait == UndefinedPixelTrait)
9164             (void) SetImageAlpha(image,OpaqueAlpha,exception);
9165           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
9166             geometry.x,geometry.y,&target,exception);
9167           if (attribute_flag[4] != 0)
9168             QueryColorCompliance(argument_list[4].string_reference,
9169               AllCompliance,&target,exception);
9170           if (attribute_flag[3] != 0)
9171             target.alpha=StringToDoubleInterval(
9172               argument_list[3].string_reference,(double) (double) QuantumRange+
9173               1.0);
9174           if (attribute_flag[5] != 0)
9175             image->fuzz=StringToDoubleInterval(
9176               argument_list[5].string_reference,(double) QuantumRange+1.0);
9177           invert=MagickFalse;
9178           if (attribute_flag[6] != 0)
9179             invert=(MagickBooleanType) argument_list[6].integer_reference;
9180           channel_mask=SetImageChannelMask(image,AlphaChannel);
9181           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
9182             geometry.y,invert,exception);
9183           (void) SetImageChannelMask(image,channel_mask);
9184           draw_info=DestroyDrawInfo(draw_info);
9185           break;
9186         }
9187         case 43:  /* Modulate */
9188         {
9189           char
9190             modulate[MagickPathExtent];
9191
9192           geometry_info.rho=100.0;
9193           geometry_info.sigma=100.0;
9194           geometry_info.xi=100.0;
9195           if (attribute_flag[0] != 0)
9196             (void)ParseGeometry(argument_list[0].string_reference,
9197               &geometry_info);
9198           if (attribute_flag[1] != 0)
9199             geometry_info.xi=argument_list[1].real_reference;
9200           if (attribute_flag[2] != 0)
9201             geometry_info.sigma=argument_list[2].real_reference;
9202           if (attribute_flag[3] != 0)
9203             {
9204               geometry_info.sigma=argument_list[3].real_reference;
9205               SetImageArtifact(image,"modulate:colorspace","HWB");
9206             }
9207           if (attribute_flag[4] != 0)
9208             {
9209               geometry_info.rho=argument_list[4].real_reference;
9210               SetImageArtifact(image,"modulate:colorspace","HSB");
9211             }
9212           if (attribute_flag[5] != 0)
9213             {
9214               geometry_info.sigma=argument_list[5].real_reference;
9215               SetImageArtifact(image,"modulate:colorspace","HSL");
9216             }
9217           if (attribute_flag[6] != 0)
9218             {
9219               geometry_info.rho=argument_list[6].real_reference;
9220               SetImageArtifact(image,"modulate:colorspace","HWB");
9221             }
9222           (void) FormatLocaleString(modulate,MagickPathExtent,"%.15g,%.15g,%.15g",
9223             geometry_info.rho,geometry_info.sigma,geometry_info.xi);
9224           (void) ModulateImage(image,modulate,exception);
9225           break;
9226         }
9227         case 44:  /* Negate */
9228         {
9229           if (attribute_flag[0] == 0)
9230             argument_list[0].integer_reference=0;
9231           if (attribute_flag[1] != 0)
9232             channel=(ChannelType) argument_list[1].integer_reference;
9233           channel_mask=SetImageChannelMask(image,channel);
9234           (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
9235             MagickTrue : MagickFalse,exception);
9236           (void) SetImageChannelMask(image,channel_mask);
9237           break;
9238         }
9239         case 45:  /* Normalize */
9240         {
9241           if (attribute_flag[0] != 0)
9242             channel=(ChannelType) argument_list[0].integer_reference;
9243           channel_mask=SetImageChannelMask(image,channel);
9244           NormalizeImage(image,exception);
9245           (void) SetImageChannelMask(image,channel_mask);
9246           break;
9247         }
9248         case 46:  /* NumberColors */
9249           break;
9250         case 47:  /* Opaque */
9251         {
9252           MagickBooleanType
9253             invert;
9254
9255           PixelInfo
9256             fill_color,
9257             target;
9258
9259           (void) QueryColorCompliance("none",AllCompliance,&target,
9260              exception);
9261           (void) QueryColorCompliance("none",AllCompliance,&fill_color,
9262             exception);
9263           if (attribute_flag[0] != 0)
9264             (void) QueryColorCompliance(argument_list[0].string_reference,
9265               AllCompliance,&target,exception);
9266           if (attribute_flag[1] != 0)
9267             (void) QueryColorCompliance(argument_list[1].string_reference,
9268               AllCompliance,&fill_color,exception);
9269           if (attribute_flag[2] != 0)
9270             image->fuzz=StringToDoubleInterval(
9271               argument_list[2].string_reference,(double) QuantumRange+1.0);
9272           if (attribute_flag[3] != 0)
9273             channel=(ChannelType) argument_list[3].integer_reference;
9274           invert=MagickFalse;
9275           if (attribute_flag[4] != 0)
9276             invert=(MagickBooleanType) argument_list[4].integer_reference;
9277           channel_mask=SetImageChannelMask(image,channel);
9278           (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
9279           (void) SetImageChannelMask(image,channel_mask);
9280           break;
9281         }
9282         case 48:  /* Quantize */
9283         {
9284           QuantizeInfo
9285             *quantize_info;
9286
9287           quantize_info=AcquireQuantizeInfo(info->image_info);
9288           if (attribute_flag[0] != 0)
9289             quantize_info->number_colors=(size_t)
9290               argument_list[0].integer_reference;
9291           if (attribute_flag[1] != 0)
9292             quantize_info->tree_depth=(size_t)
9293               argument_list[1].integer_reference;
9294           if (attribute_flag[2] != 0)
9295             quantize_info->colorspace=(ColorspaceType)
9296               argument_list[2].integer_reference;
9297           if (attribute_flag[3] != 0)
9298             quantize_info->dither_method=(DitherMethod)
9299               argument_list[3].integer_reference;
9300           if (attribute_flag[4] != 0)
9301             quantize_info->measure_error=
9302               argument_list[4].integer_reference != 0 ? MagickTrue : MagickFalse;
9303           if (attribute_flag[6] != 0)
9304             (void) QueryColorCompliance(argument_list[6].string_reference,
9305               AllCompliance,&image->transparent_color,exception);
9306           if (attribute_flag[7] != 0)
9307             quantize_info->dither_method=(DitherMethod)
9308               argument_list[7].integer_reference;
9309           if (attribute_flag[5] && argument_list[5].integer_reference)
9310             (void) QuantizeImages(quantize_info,image,exception);
9311           else
9312             if ((image->storage_class == DirectClass) ||
9313                (image->colors > quantize_info->number_colors) ||
9314                (quantize_info->colorspace == GRAYColorspace))
9315              (void) QuantizeImage(quantize_info,image,exception);
9316            else
9317              CompressImageColormap(image,exception);
9318           quantize_info=DestroyQuantizeInfo(quantize_info);
9319           break;
9320         }
9321         case 49:  /* Raise */
9322         {
9323           if (attribute_flag[0] != 0)
9324             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9325               &geometry,exception);
9326           if (attribute_flag[1] != 0)
9327             geometry.width=argument_list[1].integer_reference;
9328           if (attribute_flag[2] != 0)
9329             geometry.height=argument_list[2].integer_reference;
9330           if (attribute_flag[3] == 0)
9331             argument_list[3].integer_reference=1;
9332           (void) RaiseImage(image,&geometry,
9333             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
9334             exception);
9335           break;
9336         }
9337         case 50:  /* Segment */
9338         {
9339           ColorspaceType
9340             colorspace;
9341
9342           double
9343             cluster_threshold,
9344             smoothing_threshold;
9345
9346           MagickBooleanType
9347             verbose;
9348
9349           cluster_threshold=1.0;
9350           smoothing_threshold=1.5;
9351           colorspace=sRGBColorspace;
9352           verbose=MagickFalse;
9353           if (attribute_flag[0] != 0)
9354             {
9355               flags=ParseGeometry(argument_list[0].string_reference,
9356                 &geometry_info);
9357               cluster_threshold=geometry_info.rho;
9358               if (flags & SigmaValue)
9359                 smoothing_threshold=geometry_info.sigma;
9360             }
9361           if (attribute_flag[1] != 0)
9362             cluster_threshold=argument_list[1].real_reference;
9363           if (attribute_flag[2] != 0)
9364             smoothing_threshold=argument_list[2].real_reference;
9365           if (attribute_flag[3] != 0)
9366             colorspace=(ColorspaceType) argument_list[3].integer_reference;
9367           if (attribute_flag[4] != 0)
9368             verbose=argument_list[4].integer_reference != 0 ?
9369               MagickTrue : MagickFalse;
9370           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
9371             smoothing_threshold,exception);
9372           break;
9373         }
9374         case 51:  /* Signature */
9375         {
9376           (void) SignatureImage(image,exception);
9377           break;
9378         }
9379         case 52:  /* Solarize */
9380         {
9381           geometry_info.rho=QuantumRange/2.0;
9382           if (attribute_flag[0] != 0)
9383             flags=ParseGeometry(argument_list[0].string_reference,
9384               &geometry_info);
9385           if (attribute_flag[1] != 0)
9386             geometry_info.rho=StringToDoubleInterval(
9387               argument_list[1].string_reference,(double) QuantumRange+1.0);
9388           (void) SolarizeImage(image,geometry_info.rho,exception);
9389           break;
9390         }
9391         case 53:  /* Sync */
9392         {
9393           (void) SyncImage(image,exception);
9394           break;
9395         }
9396         case 54:  /* Texture */
9397         {
9398           if (attribute_flag[0] == 0)
9399             break;
9400           TextureImage(image,argument_list[0].image_reference,exception);
9401           break;
9402         }
9403         case 55:  /* Evalute */
9404         {
9405           MagickEvaluateOperator
9406             op;
9407
9408           op=SetEvaluateOperator;
9409           if (attribute_flag[0] == MagickFalse)
9410             argument_list[0].real_reference=0.0;
9411           if (attribute_flag[1] != MagickFalse)
9412             op=(MagickEvaluateOperator) argument_list[1].integer_reference;
9413           if (attribute_flag[2] != MagickFalse)
9414             channel=(ChannelType) argument_list[2].integer_reference;
9415           channel_mask=SetImageChannelMask(image,channel);
9416           (void) EvaluateImage(image,op,argument_list[0].real_reference,
9417             exception);
9418           (void) SetImageChannelMask(image,channel_mask);
9419           break;
9420         }
9421         case 56:  /* Transparent */
9422         {
9423           double
9424             opacity;
9425
9426           MagickBooleanType
9427             invert;
9428
9429           PixelInfo
9430             target;
9431
9432           (void) QueryColorCompliance("none",AllCompliance,&target,
9433             exception);
9434           if (attribute_flag[0] != 0)
9435             (void) QueryColorCompliance(argument_list[0].string_reference,
9436               AllCompliance,&target,exception);
9437           opacity=TransparentAlpha;
9438           if (attribute_flag[1] != 0)
9439             opacity=StringToDoubleInterval(argument_list[1].string_reference,
9440               (double) QuantumRange+1.0);
9441           if (attribute_flag[2] != 0)
9442             image->fuzz=StringToDoubleInterval(
9443               argument_list[2].string_reference,(double) QuantumRange+1.0);
9444           if (attribute_flag[3] == 0)
9445             argument_list[3].integer_reference=0;
9446           invert=MagickFalse;
9447           if (attribute_flag[3] != 0)
9448             invert=(MagickBooleanType) argument_list[3].integer_reference;
9449           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9450             invert,exception);
9451           break;
9452         }
9453         case 57:  /* Threshold */
9454         {
9455           double
9456             threshold;
9457
9458           if (attribute_flag[0] == 0)
9459             argument_list[0].string_reference="50%";
9460           if (attribute_flag[1] != 0)
9461             channel=(ChannelType) argument_list[1].integer_reference;
9462           threshold=StringToDoubleInterval(argument_list[0].string_reference,
9463             (double) QuantumRange+1.0);
9464           channel_mask=SetImageChannelMask(image,channel);
9465           (void) BilevelImage(image,threshold,exception);
9466           (void) SetImageChannelMask(image,channel_mask);
9467           break;
9468         }
9469         case 58:  /* Charcoal */
9470         {
9471           if (attribute_flag[0] != 0)
9472             {
9473               flags=ParseGeometry(argument_list[0].string_reference,
9474                 &geometry_info);
9475               if ((flags & SigmaValue) == 0)
9476                 geometry_info.sigma=1.0;
9477             }
9478           if (attribute_flag[1] != 0)
9479             geometry_info.rho=argument_list[1].real_reference;
9480           if (attribute_flag[2] != 0)
9481             geometry_info.sigma=argument_list[2].real_reference;
9482           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9483             exception);
9484           break;
9485         }
9486         case 59:  /* Trim */
9487         {
9488           if (attribute_flag[0] != 0)
9489             image->fuzz=StringToDoubleInterval(
9490               argument_list[0].string_reference,(double) QuantumRange+1.0);
9491           image=TrimImage(image,exception);
9492           break;
9493         }
9494         case 60:  /* Wave */
9495         {
9496           PixelInterpolateMethod
9497             method;
9498
9499           if (attribute_flag[0] != 0)
9500             {
9501               flags=ParseGeometry(argument_list[0].string_reference,
9502                 &geometry_info);
9503               if ((flags & SigmaValue) == 0)
9504                 geometry_info.sigma=1.0;
9505             }
9506           if (attribute_flag[1] != 0)
9507             geometry_info.rho=argument_list[1].real_reference;
9508           if (attribute_flag[2] != 0)
9509             geometry_info.sigma=argument_list[2].real_reference;
9510           method=UndefinedInterpolatePixel;
9511           if (attribute_flag[3] != 0)
9512             method=(PixelInterpolateMethod) argument_list[3].integer_reference;
9513           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9514             method,exception);
9515           break;
9516         }
9517         case 61:  /* Separate */
9518         {
9519           if (attribute_flag[0] != 0)
9520             channel=(ChannelType) argument_list[0].integer_reference;
9521           image=SeparateImage(image,channel,exception);
9522           break;
9523         }
9524         case 63:  /* Stereo */
9525         {
9526           if (attribute_flag[0] == 0)
9527             {
9528               ThrowPerlException(exception,OptionError,"StereoImageRequired",
9529                 PackageName);
9530               goto PerlException;
9531             }
9532           if (attribute_flag[1] != 0)
9533             geometry.x=argument_list[1].integer_reference;
9534           if (attribute_flag[2] != 0)
9535             geometry.y=argument_list[2].integer_reference;
9536           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9537             geometry.x,geometry.y,exception);
9538           break;
9539         }
9540         case 64:  /* Stegano */
9541         {
9542           if (attribute_flag[0] == 0)
9543             {
9544               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9545                 PackageName);
9546               goto PerlException;
9547             }
9548           if (attribute_flag[1] == 0)
9549             argument_list[1].integer_reference=0;
9550           image->offset=argument_list[1].integer_reference;
9551           image=SteganoImage(image,argument_list[0].image_reference,exception);
9552           break;
9553         }
9554         case 65:  /* Deconstruct */
9555         {
9556           image=CompareImagesLayers(image,CompareAnyLayer,exception);
9557           break;
9558         }
9559         case 66:  /* GaussianBlur */
9560         {
9561           if (attribute_flag[0] != 0)
9562             {
9563               flags=ParseGeometry(argument_list[0].string_reference,
9564                 &geometry_info);
9565               if ((flags & SigmaValue) == 0)
9566                 geometry_info.sigma=1.0;
9567             }
9568           if (attribute_flag[1] != 0)
9569             geometry_info.rho=argument_list[1].real_reference;
9570           if (attribute_flag[2] != 0)
9571             geometry_info.sigma=argument_list[2].real_reference;
9572           if (attribute_flag[3] != 0)
9573             channel=(ChannelType) argument_list[3].integer_reference;
9574           channel_mask=SetImageChannelMask(image,channel);
9575           image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9576             exception);
9577           if (image != (Image *) NULL)
9578             (void) SetImageChannelMask(image,channel_mask);
9579           break;
9580         }
9581         case 67:  /* Convolve */
9582         {
9583           KernelInfo
9584             *kernel;
9585
9586           kernel=(KernelInfo *) NULL;
9587           if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9588             break;
9589           if (attribute_flag[0] != 0)
9590             {
9591               AV
9592                 *av;
9593
9594               size_t
9595                 order;
9596
9597               kernel=AcquireKernelInfo((const char *) NULL,exception);
9598               if (kernel == (KernelInfo *) NULL)
9599                 break;
9600               av=(AV *) argument_list[0].array_reference;
9601               order=(size_t) sqrt(av_len(av)+1);
9602               kernel->width=order;
9603               kernel->height=order;
9604               kernel->values=(MagickRealType *) AcquireAlignedMemory(order,
9605                 order*sizeof(*kernel->values));
9606               if (kernel->values == (MagickRealType *) NULL)
9607                 {
9608                   kernel=DestroyKernelInfo(kernel);
9609                   ThrowPerlException(exception,ResourceLimitFatalError,
9610                     "MemoryAllocationFailed",PackageName);
9611                   goto PerlException;
9612                 }
9613               for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9614                 kernel->values[j]=(MagickRealType) SvNV(*(av_fetch(av,j,0)));
9615               for ( ; j < (ssize_t) (order*order); j++)
9616                 kernel->values[j]=0.0;
9617             }
9618           if (attribute_flag[1] != 0)
9619             channel=(ChannelType) argument_list[1].integer_reference;
9620           if (attribute_flag[2] != 0)
9621             SetImageArtifact(image,"filter:blur",
9622               argument_list[2].string_reference);
9623           if (attribute_flag[3] != 0)
9624             {
9625               kernel=AcquireKernelInfo(argument_list[3].string_reference,
9626                 exception);
9627               if (kernel == (KernelInfo *) NULL)
9628                 break;
9629             }
9630           channel_mask=SetImageChannelMask(image,channel);
9631           image=ConvolveImage(image,kernel,exception);
9632           if (image != (Image *) NULL)
9633             (void) SetImageChannelMask(image,channel_mask);
9634           kernel=DestroyKernelInfo(kernel);
9635           break;
9636         }
9637         case 68:  /* Profile */
9638         {
9639           const char
9640             *name;
9641
9642           Image
9643             *profile_image;
9644
9645           ImageInfo
9646             *profile_info;
9647
9648           StringInfo
9649             *profile;
9650
9651           name="*";
9652           if (attribute_flag[0] != 0)
9653             name=argument_list[0].string_reference;
9654           if (attribute_flag[2] != 0)
9655             image->rendering_intent=(RenderingIntent)
9656               argument_list[2].integer_reference;
9657           if (attribute_flag[3] != 0)
9658             image->black_point_compensation=
9659               argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9660           if (attribute_flag[1] != 0)
9661             {
9662               if (argument_list[1].length == 0)
9663                 {
9664                   /*
9665                     Remove a profile from the image.
9666                   */
9667                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9668                     exception);
9669                   break;
9670                 }
9671               /*
9672                 Associate user supplied profile with the image.
9673               */
9674               profile=AcquireStringInfo(argument_list[1].length);
9675               SetStringInfoDatum(profile,(const unsigned char *)
9676                 argument_list[1].string_reference);
9677               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9678                 (size_t) GetStringInfoLength(profile),exception);
9679               profile=DestroyStringInfo(profile);
9680               break;
9681             }
9682           /*
9683             Associate a profile with the image.
9684           */
9685           profile_info=CloneImageInfo(info ? info->image_info :
9686             (ImageInfo *) NULL);
9687           profile_image=ReadImages(profile_info,name,exception);
9688           if (profile_image == (Image *) NULL)
9689             break;
9690           ResetImageProfileIterator(profile_image);
9691           name=GetNextImageProfile(profile_image);
9692           while (name != (const char *) NULL)
9693           {
9694             const StringInfo
9695               *profile;
9696
9697             profile=GetImageProfile(profile_image,name);
9698             if (profile != (const StringInfo *) NULL)
9699               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9700                 (size_t) GetStringInfoLength(profile),exception);
9701             name=GetNextImageProfile(profile_image);
9702           }
9703           profile_image=DestroyImage(profile_image);
9704           profile_info=DestroyImageInfo(profile_info);
9705           break;
9706         }
9707         case 69:  /* UnsharpMask */
9708         {
9709           if (attribute_flag[0] != 0)
9710             {
9711               flags=ParseGeometry(argument_list[0].string_reference,
9712                 &geometry_info);
9713               if ((flags & SigmaValue) == 0)
9714                 geometry_info.sigma=1.0;
9715               if ((flags & XiValue) == 0)
9716                 geometry_info.xi=1.0;
9717               if ((flags & PsiValue) == 0)
9718                 geometry_info.psi=0.5;
9719             }
9720           if (attribute_flag[1] != 0)
9721             geometry_info.rho=argument_list[1].real_reference;
9722           if (attribute_flag[2] != 0)
9723             geometry_info.sigma=argument_list[2].real_reference;
9724           if (attribute_flag[3] != 0)
9725             geometry_info.xi=argument_list[3].real_reference;
9726           if (attribute_flag[4] != 0)
9727             geometry_info.psi=argument_list[4].real_reference;
9728           if (attribute_flag[5] != 0)
9729             channel=(ChannelType) argument_list[5].integer_reference;
9730           channel_mask=SetImageChannelMask(image,channel);
9731           image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9732             geometry_info.xi,geometry_info.psi,exception);
9733           if (image != (Image *) NULL)
9734             (void) SetImageChannelMask(image,channel_mask);
9735           break;
9736         }
9737         case 70:  /* MotionBlur */
9738         {
9739           if (attribute_flag[0] != 0)
9740             {
9741               flags=ParseGeometry(argument_list[0].string_reference,
9742                 &geometry_info);
9743               if ((flags & SigmaValue) == 0)
9744                 geometry_info.sigma=1.0;
9745               if ((flags & XiValue) == 0)
9746                 geometry_info.xi=1.0;
9747             }
9748           if (attribute_flag[1] != 0)
9749             geometry_info.rho=argument_list[1].real_reference;
9750           if (attribute_flag[2] != 0)
9751             geometry_info.sigma=argument_list[2].real_reference;
9752           if (attribute_flag[3] != 0)
9753             geometry_info.xi=argument_list[3].real_reference;
9754           if (attribute_flag[4] != 0)
9755             channel=(ChannelType) argument_list[4].integer_reference;
9756           channel_mask=SetImageChannelMask(image,channel);
9757           image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9758             geometry_info.xi,exception);
9759           if (image != (Image *) NULL)
9760             (void) SetImageChannelMask(image,channel_mask);
9761           break;
9762         }
9763         case 71:  /* OrderedDither */
9764         {
9765           if (attribute_flag[0] == 0)
9766             argument_list[0].string_reference="o8x8";
9767           if (attribute_flag[1] != 0)
9768             channel=(ChannelType) argument_list[1].integer_reference;
9769           channel_mask=SetImageChannelMask(image,channel);
9770           (void) OrderedPosterizeImage(image,argument_list[0].string_reference,
9771             exception);
9772           (void) SetImageChannelMask(image,channel_mask);
9773           break;
9774         }
9775         case 72:  /* Shave */
9776         {
9777           if (attribute_flag[0] != 0)
9778             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9779               &geometry,exception);
9780           if (attribute_flag[1] != 0)
9781             geometry.width=argument_list[1].integer_reference;
9782           if (attribute_flag[2] != 0)
9783             geometry.height=argument_list[2].integer_reference;
9784           image=ShaveImage(image,&geometry,exception);
9785           break;
9786         }
9787         case 73:  /* Level */
9788         {
9789           double
9790             black_point,
9791             gamma,
9792             white_point;
9793
9794           black_point=0.0;
9795           white_point=(double) image->columns*image->rows;
9796           gamma=1.0;
9797           if (attribute_flag[0] != 0)
9798             {
9799               flags=ParseGeometry(argument_list[0].string_reference,
9800                 &geometry_info);
9801               black_point=geometry_info.rho;
9802               if ((flags & SigmaValue) != 0)
9803                 white_point=geometry_info.sigma;
9804               if ((flags & XiValue) != 0)
9805                 gamma=geometry_info.xi;
9806               if ((flags & PercentValue) != 0)
9807                 {
9808                   black_point*=(double) (QuantumRange/100.0);
9809                   white_point*=(double) (QuantumRange/100.0);
9810                 }
9811               if ((flags & SigmaValue) == 0)
9812                 white_point=(double) QuantumRange-black_point;
9813             }
9814           if (attribute_flag[1] != 0)
9815             black_point=argument_list[1].real_reference;
9816           if (attribute_flag[2] != 0)
9817             white_point=argument_list[2].real_reference;
9818           if (attribute_flag[3] != 0)
9819             gamma=argument_list[3].real_reference;
9820           if (attribute_flag[4] != 0)
9821             channel=(ChannelType) argument_list[4].integer_reference;
9822           if (attribute_flag[5] != 0)
9823             {
9824               argument_list[0].real_reference=argument_list[5].real_reference;
9825               attribute_flag[0]=attribute_flag[5];
9826             }
9827           channel_mask=SetImageChannelMask(image,channel);
9828           (void) LevelImage(image,black_point,white_point,gamma,exception);
9829           (void) SetImageChannelMask(image,channel_mask);
9830           break;
9831         }
9832         case 74:  /* Clip */
9833         {
9834           if (attribute_flag[0] == 0)
9835             argument_list[0].string_reference="#1";
9836           if (attribute_flag[1] == 0)
9837             argument_list[1].integer_reference=MagickTrue;
9838           (void) ClipImagePath(image,argument_list[0].string_reference,
9839             argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse,
9840             exception);
9841           break;
9842         }
9843         case 75:  /* AffineTransform */
9844         {
9845           DrawInfo
9846             *draw_info;
9847
9848           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9849             (DrawInfo *) NULL);
9850           if (attribute_flag[0] != 0)
9851             {
9852               AV
9853                 *av;
9854
9855               av=(AV *) argument_list[0].array_reference;
9856               if ((av_len(av) != 3) && (av_len(av) != 5))
9857                 {
9858                   ThrowPerlException(exception,OptionError,
9859                     "affine matrix must have 4 or 6 elements",PackageName);
9860                   goto PerlException;
9861                 }
9862               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9863               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9864               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9865               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9866               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9867                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9868                 {
9869                   ThrowPerlException(exception,OptionError,
9870                     "affine matrix is singular",PackageName);
9871                    goto PerlException;
9872                 }
9873               if (av_len(av) == 5)
9874                 {
9875                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9876                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9877                 }
9878             }
9879           for (j=1; j < 6; j++)
9880           {
9881             if (attribute_flag[j] == 0)
9882               continue;
9883             value=argument_list[j].string_reference;
9884             angle=argument_list[j].real_reference;
9885             current=draw_info->affine;
9886             GetAffineMatrix(&affine);
9887             switch (j)
9888             {
9889               case 1:
9890               {
9891                 /*
9892                   Translate.
9893                 */
9894                 flags=ParseGeometry(value,&geometry_info);
9895                 affine.tx=geometry_info.xi;
9896                 affine.ty=geometry_info.psi;
9897                 if ((flags & PsiValue) == 0)
9898                   affine.ty=affine.tx;
9899                 break;
9900               }
9901               case 2:
9902               {
9903                 /*
9904                   Scale.
9905                 */
9906                 flags=ParseGeometry(value,&geometry_info);
9907                 affine.sx=geometry_info.rho;
9908                 affine.sy=geometry_info.sigma;
9909                 if ((flags & SigmaValue) == 0)
9910                   affine.sy=affine.sx;
9911                 break;
9912               }
9913               case 3:
9914               {
9915                 /*
9916                   Rotate.
9917                 */
9918                 if (angle == 0.0)
9919                   break;
9920                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9921                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9922                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9923                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9924                 break;
9925               }
9926               case 4:
9927               {
9928                 /*
9929                   SkewX.
9930                 */
9931                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9932                 break;
9933               }
9934               case 5:
9935               {
9936                 /*
9937                   SkewY.
9938                 */
9939                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9940                 break;
9941               }
9942             }
9943             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9944             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9945             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9946             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9947             draw_info->affine.tx=
9948               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9949             draw_info->affine.ty=
9950               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9951           }
9952           if (attribute_flag[6] != 0)
9953             image->interpolate=(PixelInterpolateMethod)
9954               argument_list[6].integer_reference;
9955           if (attribute_flag[7] != 0)
9956             QueryColorCompliance(argument_list[7].string_reference,
9957               AllCompliance,&image->background_color,exception);
9958           image=AffineTransformImage(image,&draw_info->affine,exception);
9959           draw_info=DestroyDrawInfo(draw_info);
9960           break;
9961         }
9962         case 76:  /* Difference */
9963         {
9964           if (attribute_flag[0] == 0)
9965             {
9966               ThrowPerlException(exception,OptionError,
9967                 "ReferenceImageRequired",PackageName);
9968               goto PerlException;
9969             }
9970           if (attribute_flag[1] != 0)
9971             image->fuzz=StringToDoubleInterval(
9972               argument_list[1].string_reference,(double) QuantumRange+1.0);
9973           (void) SetImageColorMetric(image,argument_list[0].image_reference,
9974             exception);
9975           break;
9976         }
9977         case 77:  /* AdaptiveThreshold */
9978         {
9979           if (attribute_flag[0] != 0)
9980             {
9981               flags=ParseGeometry(argument_list[0].string_reference,
9982                 &geometry_info);
9983               if ((flags & PercentValue) != 0)
9984                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9985             }
9986           if (attribute_flag[1] != 0)
9987             geometry_info.rho=argument_list[1].integer_reference;
9988           if (attribute_flag[2] != 0)
9989             geometry_info.sigma=argument_list[2].integer_reference;
9990           if (attribute_flag[3] != 0)
9991             geometry_info.xi=argument_list[3].integer_reference;;
9992           image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
9993             (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
9994           break;
9995         }
9996         case 78:  /* Resample */
9997         {
9998           size_t
9999             height,
10000             width;
10001
10002           if (attribute_flag[0] != 0)
10003             {
10004               flags=ParseGeometry(argument_list[0].string_reference,
10005                 &geometry_info);
10006               if ((flags & SigmaValue) == 0)
10007                 geometry_info.sigma=geometry_info.rho;
10008             }
10009           if (attribute_flag[1] != 0)
10010             geometry_info.rho=argument_list[1].real_reference;
10011           if (attribute_flag[2] != 0)
10012             geometry_info.sigma=argument_list[2].real_reference;
10013           if (attribute_flag[3] == 0)
10014             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
10015           if (attribute_flag[4] == 0)
10016             SetImageArtifact(image,"filter:support",
10017               argument_list[4].string_reference);
10018           width=(size_t) (geometry_info.rho*image->columns/
10019             (image->resolution.x == 0.0 ? 72.0 : image->resolution.x)+0.5);
10020           height=(size_t) (geometry_info.sigma*image->rows/
10021             (image->resolution.y == 0.0 ? 72.0 : image->resolution.y)+0.5);
10022           image=ResizeImage(image,width,height,(FilterTypes)
10023             argument_list[3].integer_reference,exception);
10024           if (image != (Image *) NULL)
10025             {
10026               image->resolution.x=geometry_info.rho;
10027               image->resolution.y=geometry_info.sigma;
10028             }
10029           break;
10030         }
10031         case 79:  /* Describe */
10032         {
10033           if (attribute_flag[0] == 0)
10034             argument_list[0].file_reference=(FILE *) NULL;
10035           if (attribute_flag[1] != 0)
10036             (void) SetImageArtifact(image,"identify:features",
10037               argument_list[1].string_reference);
10038           (void) IdentifyImage(image,argument_list[0].file_reference,
10039             MagickTrue,exception);
10040           break;
10041         }
10042         case 80:  /* BlackThreshold */
10043         {
10044           if (attribute_flag[0] == 0)
10045             argument_list[0].string_reference="50%";
10046           if (attribute_flag[2] != 0)
10047             channel=(ChannelType) argument_list[2].integer_reference;
10048           channel_mask=SetImageChannelMask(image,channel);
10049           BlackThresholdImage(image,argument_list[0].string_reference,
10050             exception);
10051           (void) SetImageChannelMask(image,channel_mask);
10052           break;
10053         }
10054         case 81:  /* WhiteThreshold */
10055         {
10056           if (attribute_flag[0] == 0)
10057             argument_list[0].string_reference="50%";
10058           if (attribute_flag[2] != 0)
10059             channel=(ChannelType) argument_list[2].integer_reference;
10060           channel_mask=SetImageChannelMask(image,channel);
10061           WhiteThresholdImage(image,argument_list[0].string_reference,
10062             exception);
10063           (void) SetImageChannelMask(image,channel_mask);
10064           break;
10065         }
10066         case 82:  /* RotationalBlur */
10067         {
10068           if (attribute_flag[0] != 0)
10069             {
10070               flags=ParseGeometry(argument_list[0].string_reference,
10071                 &geometry_info);
10072             }
10073           if (attribute_flag[1] != 0)
10074             geometry_info.rho=argument_list[1].real_reference;
10075           if (attribute_flag[2] != 0)
10076             channel=(ChannelType) argument_list[2].integer_reference;
10077           channel_mask=SetImageChannelMask(image,channel);
10078           image=RotationalBlurImage(image,geometry_info.rho,exception);
10079           if (image != (Image *) NULL)
10080             (void) SetImageChannelMask(image,channel_mask);
10081           break;
10082         }
10083         case 83:  /* Thumbnail */
10084         {
10085           if (attribute_flag[0] != 0)
10086             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10087               &geometry,exception);
10088           if (attribute_flag[1] != 0)
10089             geometry.width=argument_list[1].integer_reference;
10090           if (attribute_flag[2] != 0)
10091             geometry.height=argument_list[2].integer_reference;
10092           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
10093           break;
10094         }
10095         case 84:  /* Strip */
10096         {
10097           (void) StripImage(image,exception);
10098           break;
10099         }
10100         case 85:  /* Tint */
10101         {
10102           PixelInfo
10103             tint;
10104
10105           GetPixelInfo(image,&tint);
10106           if (attribute_flag[0] != 0)
10107             (void) QueryColorCompliance(argument_list[0].string_reference,
10108               AllCompliance,&tint,exception);
10109           if (attribute_flag[1] == 0)
10110             argument_list[1].string_reference="100";
10111           image=TintImage(image,argument_list[1].string_reference,&tint,
10112             exception);
10113           break;
10114         }
10115         case 86:  /* Channel */
10116         {
10117           if (attribute_flag[0] != 0)
10118             channel=(ChannelType) argument_list[0].integer_reference;
10119           image=SeparateImage(image,channel,exception);
10120           break;
10121         }
10122         case 87:  /* Splice */
10123         {
10124           if (attribute_flag[7] != 0)
10125             image->gravity=(GravityType) argument_list[7].integer_reference;
10126           if (attribute_flag[0] != 0)
10127             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
10128               &geometry,exception);
10129           if (attribute_flag[1] != 0)
10130             geometry.width=argument_list[1].integer_reference;
10131           if (attribute_flag[2] != 0)
10132             geometry.height=argument_list[2].integer_reference;
10133           if (attribute_flag[3] != 0)
10134             geometry.x=argument_list[3].integer_reference;
10135           if (attribute_flag[4] != 0)
10136             geometry.y=argument_list[4].integer_reference;
10137           if (attribute_flag[5] != 0)
10138             image->fuzz=StringToDoubleInterval(
10139               argument_list[5].string_reference,(double) QuantumRange+1.0);
10140           if (attribute_flag[6] != 0)
10141             (void) QueryColorCompliance(argument_list[6].string_reference,
10142               AllCompliance,&image->background_color,exception);
10143           image=SpliceImage(image,&geometry,exception);
10144           break;
10145         }
10146         case 88:  /* Posterize */
10147         {
10148           if (attribute_flag[0] == 0)
10149             argument_list[0].integer_reference=3;
10150           if (attribute_flag[1] == 0)
10151             argument_list[1].integer_reference=0;
10152           (void) PosterizeImage(image,argument_list[0].integer_reference,
10153             argument_list[1].integer_reference ? RiemersmaDitherMethod :
10154             NoDitherMethod,exception);
10155           break;
10156         }
10157         case 89:  /* Shadow */
10158         {
10159           if (attribute_flag[0] != 0)
10160             {
10161               flags=ParseGeometry(argument_list[0].string_reference,
10162                 &geometry_info);
10163               if ((flags & SigmaValue) == 0)
10164                 geometry_info.sigma=1.0;
10165               if ((flags & XiValue) == 0)
10166                 geometry_info.xi=4.0;
10167               if ((flags & PsiValue) == 0)
10168                 geometry_info.psi=4.0;
10169             }
10170           if (attribute_flag[1] != 0)
10171             geometry_info.rho=argument_list[1].real_reference;
10172           if (attribute_flag[2] != 0)
10173             geometry_info.sigma=argument_list[2].real_reference;
10174           if (attribute_flag[3] != 0)
10175             geometry_info.xi=argument_list[3].integer_reference;
10176           if (attribute_flag[4] != 0)
10177             geometry_info.psi=argument_list[4].integer_reference;
10178           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
10179             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10180             ceil(geometry_info.psi-0.5),exception);
10181           break;
10182         }
10183         case 90:  /* Identify */
10184         {
10185           if (attribute_flag[0] == 0)
10186             argument_list[0].file_reference=(FILE *) NULL;
10187           if (attribute_flag[1] != 0)
10188             (void) SetImageArtifact(image,"identify:features",
10189               argument_list[1].string_reference);
10190           if ((attribute_flag[2] != 0) &&
10191               (argument_list[2].integer_reference != 0))
10192             (void) SetImageArtifact(image,"identify:unique","true");
10193           (void) IdentifyImage(image,argument_list[0].file_reference,
10194             MagickTrue,exception);
10195           break;
10196         }
10197         case 91:  /* SepiaTone */
10198         {
10199           if (attribute_flag[0] == 0)
10200             argument_list[0].real_reference=80.0*QuantumRange/100.0;
10201           image=SepiaToneImage(image,argument_list[0].real_reference,
10202             exception);
10203           break;
10204         }
10205         case 92:  /* SigmoidalContrast */
10206         {
10207           MagickBooleanType
10208             sharpen;
10209
10210           if (attribute_flag[0] != 0)
10211             {
10212               flags=ParseGeometry(argument_list[0].string_reference,
10213                 &geometry_info);
10214               if ((flags & SigmaValue) == 0)
10215                 geometry_info.sigma=QuantumRange/2.0;
10216               if ((flags & PercentValue) != 0)
10217                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
10218             }
10219           if (attribute_flag[1] != 0)
10220             geometry_info.rho=argument_list[1].real_reference;
10221           if (attribute_flag[2] != 0)
10222             geometry_info.sigma=argument_list[2].real_reference;
10223           if (attribute_flag[3] != 0)
10224             channel=(ChannelType) argument_list[3].integer_reference;
10225           sharpen=MagickTrue;
10226           if (attribute_flag[4] != 0)
10227             sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
10228               MagickFalse;
10229           channel_mask=SetImageChannelMask(image,channel);
10230           (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
10231             geometry_info.sigma,exception);
10232           (void) SetImageChannelMask(image,channel_mask);
10233           break;
10234         }
10235         case 93:  /* Extent */
10236         {
10237           if (attribute_flag[7] != 0)
10238             image->gravity=(GravityType) argument_list[7].integer_reference;
10239           if (attribute_flag[0] != 0)
10240             {
10241               int
10242                 flags;
10243
10244               flags=ParseGravityGeometry(image,
10245                 argument_list[0].string_reference,&geometry,exception);
10246               (void) flags;
10247               if (geometry.width == 0)
10248                 geometry.width=image->columns;
10249               if (geometry.height == 0)
10250                 geometry.height=image->rows;
10251             }
10252           if (attribute_flag[1] != 0)
10253             geometry.width=argument_list[1].integer_reference;
10254           if (attribute_flag[2] != 0)
10255             geometry.height=argument_list[2].integer_reference;
10256           if (attribute_flag[3] != 0)
10257             geometry.x=argument_list[3].integer_reference;
10258           if (attribute_flag[4] != 0)
10259             geometry.y=argument_list[4].integer_reference;
10260           if (attribute_flag[5] != 0)
10261             image->fuzz=StringToDoubleInterval(
10262               argument_list[5].string_reference,(double) QuantumRange+1.0);
10263           if (attribute_flag[6] != 0)
10264             (void) QueryColorCompliance(argument_list[6].string_reference,
10265               AllCompliance,&image->background_color,exception);
10266           image=ExtentImage(image,&geometry,exception);
10267           break;
10268         }
10269         case 94:  /* Vignette */
10270         {
10271           if (attribute_flag[0] != 0)
10272             {
10273               flags=ParseGeometry(argument_list[0].string_reference,
10274                 &geometry_info);
10275               if ((flags & SigmaValue) == 0)
10276                 geometry_info.sigma=1.0;
10277               if ((flags & XiValue) == 0)
10278                 geometry_info.xi=0.1*image->columns;
10279               if ((flags & PsiValue) == 0)
10280                 geometry_info.psi=0.1*image->rows;
10281             }
10282           if (attribute_flag[1] != 0)
10283             geometry_info.rho=argument_list[1].real_reference;
10284           if (attribute_flag[2] != 0)
10285             geometry_info.sigma=argument_list[2].real_reference;
10286           if (attribute_flag[3] != 0)
10287             geometry_info.xi=argument_list[3].integer_reference;
10288           if (attribute_flag[4] != 0)
10289             geometry_info.psi=argument_list[4].integer_reference;
10290           if (attribute_flag[5] != 0)
10291             (void) QueryColorCompliance(argument_list[5].string_reference,
10292               AllCompliance,&image->background_color,exception);
10293           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
10294             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10295             ceil(geometry_info.psi-0.5),exception);
10296           break;
10297         }
10298         case 95:  /* ContrastStretch */
10299         {
10300           double
10301             black_point,
10302             white_point;
10303
10304           black_point=0.0;
10305           white_point=(double) image->columns*image->rows;
10306           if (attribute_flag[0] != 0)
10307             {
10308               flags=ParseGeometry(argument_list[0].string_reference,
10309                 &geometry_info);
10310               black_point=geometry_info.rho;
10311               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
10312                 black_point;
10313               if ((flags & PercentValue) != 0)
10314                 {
10315                   black_point*=(double) image->columns*image->rows/100.0;
10316                   white_point*=(double) image->columns*image->rows/100.0;
10317                 }
10318               white_point=(double) image->columns*image->rows-
10319                 white_point;
10320             }
10321           if (attribute_flag[1] != 0)
10322             black_point=argument_list[1].real_reference;
10323           if (attribute_flag[2] != 0)
10324             white_point=argument_list[2].real_reference;
10325           if (attribute_flag[4] != 0)
10326             channel=(ChannelType) argument_list[4].integer_reference;
10327           channel_mask=SetImageChannelMask(image,channel);
10328           (void) ContrastStretchImage(image,black_point,white_point,exception);
10329           (void) SetImageChannelMask(image,channel_mask);
10330           break;
10331         }
10332         case 96:  /* Sans0 */
10333         {
10334           break;
10335         }
10336         case 97:  /* Sans1 */
10337         {
10338           break;
10339         }
10340         case 98:  /* AdaptiveSharpen */
10341         {
10342           if (attribute_flag[0] != 0)
10343             {
10344               flags=ParseGeometry(argument_list[0].string_reference,
10345                 &geometry_info);
10346               if ((flags & SigmaValue) == 0)
10347                 geometry_info.sigma=1.0;
10348               if ((flags & XiValue) == 0)
10349                 geometry_info.xi=0.0;
10350             }
10351           if (attribute_flag[1] != 0)
10352             geometry_info.rho=argument_list[1].real_reference;
10353           if (attribute_flag[2] != 0)
10354             geometry_info.sigma=argument_list[2].real_reference;
10355           if (attribute_flag[3] != 0)
10356             geometry_info.xi=argument_list[3].real_reference;
10357           if (attribute_flag[4] != 0)
10358             channel=(ChannelType) argument_list[4].integer_reference;
10359           channel_mask=SetImageChannelMask(image,channel);
10360           image=AdaptiveSharpenImage(image,geometry_info.rho,
10361             geometry_info.sigma,exception);
10362           if (image != (Image *) NULL)
10363             (void) SetImageChannelMask(image,channel_mask);
10364           break;
10365         }
10366         case 99:  /* Transpose */
10367         {
10368           image=TransposeImage(image,exception);
10369           break;
10370         }
10371         case 100:  /* Tranverse */
10372         {
10373           image=TransverseImage(image,exception);
10374           break;
10375         }
10376         case 101:  /* AutoOrient */
10377         {
10378           image=AutoOrientImage(image,image->orientation,exception);
10379           break;
10380         }
10381         case 102:  /* AdaptiveBlur */
10382         {
10383           if (attribute_flag[0] != 0)
10384             {
10385               flags=ParseGeometry(argument_list[0].string_reference,
10386                 &geometry_info);
10387               if ((flags & SigmaValue) == 0)
10388                 geometry_info.sigma=1.0;
10389               if ((flags & XiValue) == 0)
10390                 geometry_info.xi=0.0;
10391             }
10392           if (attribute_flag[1] != 0)
10393             geometry_info.rho=argument_list[1].real_reference;
10394           if (attribute_flag[2] != 0)
10395             geometry_info.sigma=argument_list[2].real_reference;
10396           if (attribute_flag[3] != 0)
10397             channel=(ChannelType) argument_list[3].integer_reference;
10398           channel_mask=SetImageChannelMask(image,channel);
10399           image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10400             exception);
10401           if (image != (Image *) NULL)
10402             (void) SetImageChannelMask(image,channel_mask);
10403           break;
10404         }
10405         case 103:  /* Sketch */
10406         {
10407           if (attribute_flag[0] != 0)
10408             {
10409               flags=ParseGeometry(argument_list[0].string_reference,
10410                 &geometry_info);
10411               if ((flags & SigmaValue) == 0)
10412                 geometry_info.sigma=1.0;
10413               if ((flags & XiValue) == 0)
10414                 geometry_info.xi=1.0;
10415             }
10416           if (attribute_flag[1] != 0)
10417             geometry_info.rho=argument_list[1].real_reference;
10418           if (attribute_flag[2] != 0)
10419             geometry_info.sigma=argument_list[2].real_reference;
10420           if (attribute_flag[3] != 0)
10421             geometry_info.xi=argument_list[3].real_reference;
10422           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10423             geometry_info.xi,exception);
10424           break;
10425         }
10426         case 104:  /* UniqueColors */
10427         {
10428           image=UniqueImageColors(image,exception);
10429           break;
10430         }
10431         case 105:  /* AdaptiveResize */
10432         {
10433           if (attribute_flag[0] != 0)
10434             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10435               &geometry,exception);
10436           if (attribute_flag[1] != 0)
10437             geometry.width=argument_list[1].integer_reference;
10438           if (attribute_flag[2] != 0)
10439             geometry.height=argument_list[2].integer_reference;
10440           if (attribute_flag[3] != 0)
10441             image->filter=(FilterTypes) argument_list[4].integer_reference;
10442           if (attribute_flag[4] != 0)
10443             SetImageArtifact(image,"filter:support",
10444               argument_list[4].string_reference);
10445           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10446             exception);
10447           break;
10448         }
10449         case 106:  /* ClipMask */
10450         {
10451           Image
10452             *mask_image;
10453
10454           if (attribute_flag[0] == 0)
10455             {
10456               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10457                 PackageName);
10458               goto PerlException;
10459             }
10460           mask_image=CloneImage(argument_list[0].image_reference,0,0,MagickTrue,
10461             exception);
10462           (void) SetImageMask(image,ReadPixelMask,mask_image,exception);
10463           mask_image=DestroyImage(mask_image);
10464           break;
10465         }
10466         case 107:  /* LinearStretch */
10467         {
10468            double
10469              black_point,
10470              white_point;
10471
10472            black_point=0.0;
10473            white_point=(double) image->columns*image->rows;
10474            if (attribute_flag[0] != 0)
10475              {
10476                flags=ParseGeometry(argument_list[0].string_reference,
10477                  &geometry_info);
10478                if ((flags & SigmaValue) != 0)
10479                   white_point=geometry_info.sigma;
10480                if ((flags & PercentValue) != 0)
10481                  {
10482                    black_point*=(double) image->columns*image->rows/100.0;
10483                    white_point*=(double) image->columns*image->rows/100.0;
10484                  }
10485                if ((flags & SigmaValue) == 0)
10486                  white_point=(double) image->columns*image->rows-black_point;
10487              }
10488           if (attribute_flag[1] != 0)
10489             black_point=argument_list[1].real_reference;
10490           if (attribute_flag[2] != 0)
10491             white_point=argument_list[2].real_reference;
10492           (void) LinearStretchImage(image,black_point,white_point,exception);
10493           break;
10494         }
10495         case 108:  /* ColorMatrix */
10496         {
10497           AV
10498             *av;
10499
10500           double
10501             *color_matrix;
10502
10503           KernelInfo
10504             *kernel_info;
10505
10506           size_t
10507             order;
10508
10509           if (attribute_flag[0] == 0)
10510             break;
10511           av=(AV *) argument_list[0].array_reference;
10512           order=(size_t) sqrt(av_len(av)+1);
10513           color_matrix=(double *) AcquireQuantumMemory(order,order*
10514             sizeof(*color_matrix));
10515           if (color_matrix == (double *) NULL)
10516             {
10517               ThrowPerlException(exception,ResourceLimitFatalError,
10518                 "MemoryAllocationFailed",PackageName);
10519               goto PerlException;
10520            }
10521           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10522             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10523           for ( ; j < (ssize_t) (order*order); j++)
10524             color_matrix[j]=0.0;
10525           kernel_info=AcquireKernelInfo((const char *) NULL,exception);
10526           if (kernel_info == (KernelInfo *) NULL)
10527             break;
10528           kernel_info->width=order;
10529           kernel_info->height=order;
10530           kernel_info->values=(MagickRealType *) AcquireAlignedMemory(order,
10531             order*sizeof(*kernel_info->values));
10532           if (kernel_info->values != (MagickRealType *) NULL)
10533             {
10534               for (i=0; i < (ssize_t) (order*order); i++)
10535                 kernel_info->values[i]=(MagickRealType) color_matrix[i];
10536               image=ColorMatrixImage(image,kernel_info,exception);
10537             }
10538           kernel_info=DestroyKernelInfo(kernel_info);
10539           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10540           break;
10541         }
10542         case 109:  /* Mask */
10543         {
10544           Image
10545             *mask_image;
10546
10547           if (attribute_flag[0] == 0)
10548             {
10549               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10550                 PackageName);
10551               goto PerlException;
10552             }
10553           mask_image=CloneImage(argument_list[0].image_reference,0,0,
10554             MagickTrue,exception);
10555           (void) SetImageMask(image,ReadPixelMask,mask_image,exception);
10556           mask_image=DestroyImage(mask_image);
10557           break;
10558         }
10559         case 110:  /* Polaroid */
10560         {
10561           char
10562             *caption;
10563
10564           DrawInfo
10565             *draw_info;
10566
10567           double
10568             angle;
10569
10570           PixelInterpolateMethod
10571             method;
10572
10573           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10574             (DrawInfo *) NULL);
10575           caption=(char *) NULL;
10576           if (attribute_flag[0] != 0)
10577             caption=InterpretImageProperties(info ? info->image_info :
10578               (ImageInfo *) NULL,image,argument_list[0].string_reference,
10579               exception);
10580           angle=0.0;
10581           if (attribute_flag[1] != 0)
10582             angle=argument_list[1].real_reference;
10583           if (attribute_flag[2] != 0)
10584             (void) CloneString(&draw_info->font,
10585               argument_list[2].string_reference);
10586           if (attribute_flag[3] != 0)
10587             (void) QueryColorCompliance(argument_list[3].string_reference,
10588               AllCompliance,&draw_info->stroke,exception);
10589           if (attribute_flag[4] != 0)
10590             (void) QueryColorCompliance(argument_list[4].string_reference,
10591               AllCompliance,&draw_info->fill,exception);
10592           if (attribute_flag[5] != 0)
10593             draw_info->stroke_width=argument_list[5].real_reference;
10594           if (attribute_flag[6] != 0)
10595             draw_info->pointsize=argument_list[6].real_reference;
10596           if (attribute_flag[7] != 0)
10597             draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10598           if (attribute_flag[8] != 0)
10599             (void) QueryColorCompliance(argument_list[8].string_reference,
10600               AllCompliance,&image->background_color,exception);
10601           method=UndefinedInterpolatePixel;
10602           if (attribute_flag[9] != 0)
10603             method=(PixelInterpolateMethod) argument_list[9].integer_reference;
10604           image=PolaroidImage(image,draw_info,caption,angle,method,exception);
10605           draw_info=DestroyDrawInfo(draw_info);
10606           if (caption != (char *) NULL)
10607             caption=DestroyString(caption);
10608           break;
10609         }
10610         case 111:  /* FloodfillPaint */
10611         {
10612           DrawInfo
10613             *draw_info;
10614
10615           MagickBooleanType
10616             invert;
10617
10618           PixelInfo
10619             target;
10620
10621           draw_info=CloneDrawInfo(info ? info->image_info :
10622             (ImageInfo *) NULL,(DrawInfo *) NULL);
10623           if (attribute_flag[0] != 0)
10624             flags=ParsePageGeometry(image,argument_list[0].string_reference,
10625               &geometry,exception);
10626           if (attribute_flag[1] != 0)
10627             geometry.x=argument_list[1].integer_reference;
10628           if (attribute_flag[2] != 0)
10629             geometry.y=argument_list[2].integer_reference;
10630           if (attribute_flag[3] != 0)
10631             (void) QueryColorCompliance(argument_list[3].string_reference,
10632               AllCompliance,&draw_info->fill,exception);
10633           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
10634             geometry.x,geometry.y,&target,exception);
10635           if (attribute_flag[4] != 0)
10636             QueryColorCompliance(argument_list[4].string_reference,
10637               AllCompliance,&target,exception);
10638           if (attribute_flag[5] != 0)
10639             image->fuzz=StringToDoubleInterval(
10640               argument_list[5].string_reference,(double) QuantumRange+1.0);
10641           if (attribute_flag[6] != 0)
10642             channel=(ChannelType) argument_list[6].integer_reference;
10643           invert=MagickFalse;
10644           if (attribute_flag[7] != 0)
10645             invert=(MagickBooleanType) argument_list[7].integer_reference;
10646           channel_mask=SetImageChannelMask(image,channel);
10647           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10648             geometry.y,invert,exception);
10649           (void) SetImageChannelMask(image,channel_mask);
10650           draw_info=DestroyDrawInfo(draw_info);
10651           break;
10652         }
10653         case 112:  /* Distort */
10654         {
10655           AV
10656             *av;
10657
10658           double
10659             *coordinates;
10660
10661           DistortImageMethod
10662             method;
10663
10664           size_t
10665             number_coordinates;
10666
10667           VirtualPixelMethod
10668             virtual_pixel;
10669
10670           if (attribute_flag[0] == 0)
10671             break;
10672           method=UndefinedDistortion;
10673           if (attribute_flag[1] != 0)
10674             method=(DistortImageMethod) argument_list[1].integer_reference;
10675           av=(AV *) argument_list[0].array_reference;
10676           number_coordinates=(size_t) av_len(av)+1;
10677           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10678             sizeof(*coordinates));
10679           if (coordinates == (double *) NULL)
10680             {
10681               ThrowPerlException(exception,ResourceLimitFatalError,
10682                 "MemoryAllocationFailed",PackageName);
10683               goto PerlException;
10684             }
10685           for (j=0; j < (ssize_t) number_coordinates; j++)
10686             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10687           virtual_pixel=UndefinedVirtualPixelMethod;
10688           if (attribute_flag[2] != 0)
10689             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10690               argument_list[2].integer_reference,exception);
10691           image=DistortImage(image,method,number_coordinates,coordinates,
10692             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10693             exception);
10694           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10695             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10696               exception);
10697           coordinates=(double *) RelinquishMagickMemory(coordinates);
10698           break;
10699         }
10700         case 113:  /* Clut */
10701         {
10702           PixelInterpolateMethod
10703             method;
10704
10705           if (attribute_flag[0] == 0)
10706             {
10707               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10708                 PackageName);
10709               goto PerlException;
10710             }
10711           method=UndefinedInterpolatePixel;
10712           if (attribute_flag[1] != 0)
10713             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
10714           if (attribute_flag[2] != 0)
10715             channel=(ChannelType) argument_list[2].integer_reference;
10716           channel_mask=SetImageChannelMask(image,channel);
10717           (void) ClutImage(image,argument_list[0].image_reference,method,
10718             exception);
10719           (void) SetImageChannelMask(image,channel_mask);
10720           break;
10721         }
10722         case 114:  /* LiquidRescale */
10723         {
10724           if (attribute_flag[0] != 0)
10725             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10726               &geometry,exception);
10727           if (attribute_flag[1] != 0)
10728             geometry.width=argument_list[1].integer_reference;
10729           if (attribute_flag[2] != 0)
10730             geometry.height=argument_list[2].integer_reference;
10731           if (attribute_flag[3] == 0)
10732             argument_list[3].real_reference=1.0;
10733           if (attribute_flag[4] == 0)
10734             argument_list[4].real_reference=0.0;
10735           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10736             argument_list[3].real_reference,argument_list[4].real_reference,
10737             exception);
10738           break;
10739         }
10740         case 115:  /* EncipherImage */
10741         {
10742           (void) EncipherImage(image,argument_list[0].string_reference,
10743             exception);
10744           break;
10745         }
10746         case 116:  /* DecipherImage */
10747         {
10748           (void) DecipherImage(image,argument_list[0].string_reference,
10749             exception);
10750           break;
10751         }
10752         case 117:  /* Deskew */
10753         {
10754           geometry_info.rho=QuantumRange/2.0;
10755           if (attribute_flag[0] != 0)
10756             flags=ParseGeometry(argument_list[0].string_reference,
10757               &geometry_info);
10758           if (attribute_flag[1] != 0)
10759             geometry_info.rho=StringToDoubleInterval(
10760               argument_list[1].string_reference,(double) QuantumRange+1.0);
10761           image=DeskewImage(image,geometry_info.rho,exception);
10762           break;
10763         }
10764         case 118:  /* Remap */
10765         {
10766           QuantizeInfo
10767             *quantize_info;
10768
10769           if (attribute_flag[0] == 0)
10770             {
10771               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10772                 PackageName);
10773               goto PerlException;
10774             }
10775           quantize_info=AcquireQuantizeInfo(info->image_info);
10776           if (attribute_flag[1] != 0)
10777             quantize_info->dither_method=(DitherMethod)
10778               argument_list[1].integer_reference;
10779           (void) RemapImages(quantize_info,image,
10780             argument_list[0].image_reference,exception);
10781           quantize_info=DestroyQuantizeInfo(quantize_info);
10782           break;
10783         }
10784         case 119:  /* SparseColor */
10785         {
10786           AV
10787             *av;
10788
10789           double
10790             *coordinates;
10791
10792           SparseColorMethod
10793             method;
10794
10795           size_t
10796             number_coordinates;
10797
10798           VirtualPixelMethod
10799             virtual_pixel;
10800
10801           if (attribute_flag[0] == 0)
10802             break;
10803           method=UndefinedColorInterpolate;
10804           if (attribute_flag[1] != 0)
10805             method=(SparseColorMethod) argument_list[1].integer_reference;
10806           av=(AV *) argument_list[0].array_reference;
10807           number_coordinates=(size_t) av_len(av)+1;
10808           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10809             sizeof(*coordinates));
10810           if (coordinates == (double *) NULL)
10811             {
10812               ThrowPerlException(exception,ResourceLimitFatalError,
10813                 "MemoryAllocationFailed",PackageName);
10814               goto PerlException;
10815             }
10816           for (j=0; j < (ssize_t) number_coordinates; j++)
10817             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10818           virtual_pixel=UndefinedVirtualPixelMethod;
10819           if (attribute_flag[2] != 0)
10820             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10821               argument_list[2].integer_reference,exception);
10822           if (attribute_flag[3] != 0)
10823             channel=(ChannelType) argument_list[3].integer_reference;
10824           channel_mask=SetImageChannelMask(image,channel);
10825           image=SparseColorImage(image,method,number_coordinates,coordinates,
10826             exception);
10827           if (image != (Image *) NULL)
10828             (void) SetImageChannelMask(image,channel_mask);
10829           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10830             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10831               exception);
10832           coordinates=(double *) RelinquishMagickMemory(coordinates);
10833           break;
10834         }
10835         case 120:  /* Function */
10836         {
10837           AV
10838             *av;
10839
10840           double
10841             *parameters;
10842
10843           MagickFunction
10844             function;
10845
10846           size_t
10847             number_parameters;
10848
10849           VirtualPixelMethod
10850             virtual_pixel;
10851
10852           if (attribute_flag[0] == 0)
10853             break;
10854           function=UndefinedFunction;
10855           if (attribute_flag[1] != 0)
10856             function=(MagickFunction) argument_list[1].integer_reference;
10857           av=(AV *) argument_list[0].array_reference;
10858           number_parameters=(size_t) av_len(av)+1;
10859           parameters=(double *) AcquireQuantumMemory(number_parameters,
10860             sizeof(*parameters));
10861           if (parameters == (double *) NULL)
10862             {
10863               ThrowPerlException(exception,ResourceLimitFatalError,
10864                 "MemoryAllocationFailed",PackageName);
10865               goto PerlException;
10866             }
10867           for (j=0; j < (ssize_t) number_parameters; j++)
10868             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10869           virtual_pixel=UndefinedVirtualPixelMethod;
10870           if (attribute_flag[2] != 0)
10871             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10872               argument_list[2].integer_reference,exception);
10873           (void) FunctionImage(image,function,number_parameters,parameters,
10874             exception);
10875           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10876             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10877               exception);
10878           parameters=(double *) RelinquishMagickMemory(parameters);
10879           break;
10880         }
10881         case 121:  /* SelectiveBlur */
10882         {
10883           if (attribute_flag[0] != 0)
10884             {
10885               flags=ParseGeometry(argument_list[0].string_reference,
10886                 &geometry_info);
10887               if ((flags & SigmaValue) == 0)
10888                 geometry_info.sigma=1.0;
10889               if ((flags & PercentValue) != 0)
10890                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10891             }
10892           if (attribute_flag[1] != 0)
10893             geometry_info.rho=argument_list[1].real_reference;
10894           if (attribute_flag[2] != 0)
10895             geometry_info.sigma=argument_list[2].real_reference;
10896           if (attribute_flag[3] != 0)
10897             geometry_info.xi=argument_list[3].integer_reference;;
10898           if (attribute_flag[5] != 0)
10899             channel=(ChannelType) argument_list[5].integer_reference;
10900           channel_mask=SetImageChannelMask(image,channel);
10901           image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10902             geometry_info.xi,exception);
10903           if (image != (Image *) NULL)
10904             (void) SetImageChannelMask(image,channel_mask);
10905           break;
10906         }
10907         case 122:  /* HaldClut */
10908         {
10909           if (attribute_flag[0] == 0)
10910             {
10911               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10912                 PackageName);
10913               goto PerlException;
10914             }
10915           if (attribute_flag[1] != 0)
10916             channel=(ChannelType) argument_list[1].integer_reference;
10917           channel_mask=SetImageChannelMask(image,channel);
10918           (void) HaldClutImage(image,argument_list[0].image_reference,
10919             exception);
10920           (void) SetImageChannelMask(image,channel_mask);
10921           break;
10922         }
10923         case 123:  /* BlueShift */
10924         {
10925           if (attribute_flag[0] != 0)
10926             (void) ParseGeometry(argument_list[0].string_reference,
10927               &geometry_info);
10928           image=BlueShiftImage(image,geometry_info.rho,exception);
10929           break;
10930         }
10931         case 124:  /* ForwardFourierTransformImage */
10932         {
10933           image=ForwardFourierTransformImage(image,
10934             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10935             exception);
10936           break;
10937         }
10938         case 125:  /* InverseFourierTransformImage */
10939         {
10940           image=InverseFourierTransformImage(image,image->next,
10941             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10942             exception);
10943           break;
10944         }
10945         case 126:  /* ColorDecisionList */
10946         {
10947           if (attribute_flag[0] == 0)
10948             argument_list[0].string_reference=(char *) NULL;
10949           (void) ColorDecisionListImage(image,
10950             argument_list[0].string_reference,exception);
10951           break;
10952         }
10953         case 127:  /* AutoGamma */
10954         {
10955           if (attribute_flag[0] != 0)
10956             channel=(ChannelType) argument_list[0].integer_reference;
10957           channel_mask=SetImageChannelMask(image,channel);
10958           (void) AutoGammaImage(image,exception);
10959           (void) SetImageChannelMask(image,channel_mask);
10960           break;
10961         }
10962         case 128:  /* AutoLevel */
10963         {
10964           if (attribute_flag[0] != 0)
10965             channel=(ChannelType) argument_list[0].integer_reference;
10966           channel_mask=SetImageChannelMask(image,channel);
10967           (void) AutoLevelImage(image,exception);
10968           (void) SetImageChannelMask(image,channel_mask);
10969           break;
10970         }
10971         case 129:  /* LevelColors */
10972         {
10973           PixelInfo
10974             black_point,
10975             white_point;
10976
10977           (void) QueryColorCompliance("#000000",AllCompliance,&black_point,
10978             exception);
10979           (void) QueryColorCompliance("#ffffff",AllCompliance,&white_point,
10980             exception);
10981           if (attribute_flag[1] != 0)
10982              (void) QueryColorCompliance(
10983                argument_list[1].string_reference,AllCompliance,&black_point,
10984                exception);
10985           if (attribute_flag[2] != 0)
10986              (void) QueryColorCompliance(
10987                argument_list[2].string_reference,AllCompliance,&white_point,
10988                exception);
10989           if (attribute_flag[3] != 0)
10990             channel=(ChannelType) argument_list[3].integer_reference;
10991           channel_mask=SetImageChannelMask(image,channel);
10992           (void) LevelImageColors(image,&black_point,&white_point,
10993             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10994             exception);
10995           (void) SetImageChannelMask(image,channel_mask);
10996           break;
10997         }
10998         case 130:  /* Clamp */
10999         {
11000           if (attribute_flag[0] != 0)
11001             channel=(ChannelType) argument_list[0].integer_reference;
11002           channel_mask=SetImageChannelMask(image,channel);
11003           (void) ClampImage(image,exception);
11004           (void) SetImageChannelMask(image,channel_mask);
11005           break;
11006         }
11007         case 131:  /* BrightnessContrast */
11008         {
11009           double
11010             brightness,
11011             contrast;
11012
11013           brightness=0.0;
11014           contrast=0.0;
11015           if (attribute_flag[0] != 0)
11016             {
11017               flags=ParseGeometry(argument_list[0].string_reference,
11018                 &geometry_info);
11019               brightness=geometry_info.rho;
11020               if ((flags & SigmaValue) == 0)
11021                 contrast=geometry_info.sigma;
11022             }
11023           if (attribute_flag[1] != 0)
11024             brightness=argument_list[1].real_reference;
11025           if (attribute_flag[2] != 0)
11026             contrast=argument_list[2].real_reference;
11027           if (attribute_flag[4] != 0)
11028             channel=(ChannelType) argument_list[4].integer_reference;
11029           channel_mask=SetImageChannelMask(image,channel);
11030           (void) BrightnessContrastImage(image,brightness,contrast,exception);
11031           (void) SetImageChannelMask(image,channel_mask);
11032           break;
11033         }
11034         case 132:  /* Morphology */
11035         {
11036           KernelInfo
11037             *kernel;
11038
11039           MorphologyMethod
11040             method;
11041
11042           ssize_t
11043             iterations;
11044
11045           if (attribute_flag[0] == 0)
11046             break;
11047           kernel=AcquireKernelInfo(argument_list[0].string_reference,exception);
11048           if (kernel == (KernelInfo *) NULL)
11049             break;
11050           if (attribute_flag[1] != 0)
11051             channel=(ChannelType) argument_list[1].integer_reference;
11052           method=UndefinedMorphology;
11053           if (attribute_flag[2] != 0)
11054             method=argument_list[2].integer_reference;
11055           iterations=1;
11056           if (attribute_flag[3] != 0)
11057             iterations=argument_list[3].integer_reference;
11058           channel_mask=SetImageChannelMask(image,channel);
11059           image=MorphologyImage(image,method,iterations,kernel,exception);
11060           if (image != (Image *) NULL)
11061             (void) SetImageChannelMask(image,channel_mask);
11062           kernel=DestroyKernelInfo(kernel);
11063           break;
11064         }
11065         case 133:  /* Mode */
11066         {
11067           if (attribute_flag[0] != 0)
11068             {
11069               flags=ParseGeometry(argument_list[0].string_reference,
11070                 &geometry_info);
11071               if ((flags & SigmaValue) == 0)
11072                 geometry_info.sigma=1.0;
11073             }
11074           if (attribute_flag[1] != 0)
11075             geometry_info.rho=argument_list[1].real_reference;
11076           if (attribute_flag[2] != 0)
11077             geometry_info.sigma=argument_list[2].real_reference;
11078           if (attribute_flag[3] != 0)
11079             channel=(ChannelType) argument_list[3].integer_reference;
11080           channel_mask=SetImageChannelMask(image,channel);
11081           image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
11082             (size_t) geometry_info.sigma,exception);
11083           if (image != (Image *) NULL)
11084             (void) SetImageChannelMask(image,channel_mask);
11085           break;
11086         }
11087         case 134:  /* Statistic */
11088         {
11089           StatisticType
11090             statistic;
11091
11092           statistic=UndefinedStatistic;
11093           if (attribute_flag[0] != 0)
11094             {
11095               flags=ParseGeometry(argument_list[0].string_reference,
11096                 &geometry_info);
11097               if ((flags & SigmaValue) == 0)
11098                 geometry_info.sigma=1.0;
11099             }
11100           if (attribute_flag[1] != 0)
11101             geometry_info.rho=argument_list[1].real_reference;
11102           if (attribute_flag[2] != 0)
11103             geometry_info.sigma=argument_list[2].real_reference;
11104           if (attribute_flag[3] != 0)
11105             channel=(ChannelType) argument_list[3].integer_reference;
11106           if (attribute_flag[4] != 0)
11107             statistic=(StatisticType) argument_list[4].integer_reference;
11108           channel_mask=SetImageChannelMask(image,channel);
11109           image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
11110             (size_t) geometry_info.sigma,exception);
11111           if (image != (Image *) NULL)
11112             (void) SetImageChannelMask(image,channel_mask);
11113           break;
11114         }
11115         case 135:  /* Perceptible */
11116         {
11117           double
11118             epsilon;
11119
11120           epsilon=MagickEpsilon;
11121           if (attribute_flag[0] != 0)
11122             epsilon=argument_list[0].real_reference;
11123           if (attribute_flag[1] != 0)
11124             channel=(ChannelType) argument_list[1].integer_reference;
11125           channel_mask=SetImageChannelMask(image,channel);
11126           (void) PerceptibleImage(image,epsilon,exception);
11127           (void) SetImageChannelMask(image,channel_mask);
11128           break;
11129         }
11130         case 136:  /* Poly */
11131         {
11132           AV
11133             *av;
11134
11135           double
11136             *terms;
11137
11138           size_t
11139             number_terms;
11140
11141           if (attribute_flag[0] == 0)
11142             break;
11143           if (attribute_flag[1] != 0)
11144             channel=(ChannelType) argument_list[1].integer_reference;
11145           av=(AV *) argument_list[0].array_reference;
11146           number_terms=(size_t) av_len(av);
11147           terms=(double *) AcquireQuantumMemory(number_terms,sizeof(*terms));
11148           if (terms == (double *) NULL)
11149             {
11150               ThrowPerlException(exception,ResourceLimitFatalError,
11151                 "MemoryAllocationFailed",PackageName);
11152               goto PerlException;
11153             }
11154           for (j=0; j < av_len(av); j++)
11155             terms[j]=(double) SvNV(*(av_fetch(av,j,0)));
11156           image=PolynomialImage(image,number_terms >> 1,terms,exception);
11157           terms=(double *) RelinquishMagickMemory(terms);
11158           break;
11159         }
11160         case 137:  /* Grayscale */
11161         {
11162           PixelIntensityMethod
11163             method;
11164
11165           method=UndefinedPixelIntensityMethod;
11166           if (attribute_flag[0] != 0)
11167             method=(PixelIntensityMethod) argument_list[0].integer_reference;
11168           (void) GrayscaleImage(image,method,exception);
11169           break;
11170         }
11171         case 138:  /* Canny */
11172         {
11173           if (attribute_flag[0] != 0)
11174             {
11175               flags=ParseGeometry(argument_list[0].string_reference,
11176                 &geometry_info);
11177               if ((flags & SigmaValue) == 0)
11178                 geometry_info.sigma=1.0;
11179               if ((flags & XiValue) == 0)
11180                 geometry_info.xi=0.10;
11181               if ((flags & PsiValue) == 0)
11182                 geometry_info.psi=0.30;
11183               if ((flags & PercentValue) != 0)
11184                 {
11185                   geometry_info.xi/=100.0;
11186                   geometry_info.psi/=100.0;
11187                 }
11188             }
11189           if (attribute_flag[1] != 0)
11190             geometry_info.rho=argument_list[1].real_reference;
11191           if (attribute_flag[2] != 0)
11192             geometry_info.sigma=argument_list[2].real_reference;
11193           if (attribute_flag[3] != 0)
11194             geometry_info.xi=argument_list[3].real_reference;
11195           if (attribute_flag[4] != 0)
11196             geometry_info.psi=argument_list[4].real_reference;
11197           if (attribute_flag[5] != 0)
11198             channel=(ChannelType) argument_list[5].integer_reference;
11199           channel_mask=SetImageChannelMask(image,channel);
11200           image=CannyEdgeImage(image,geometry_info.rho,geometry_info.sigma,
11201             geometry_info.xi,geometry_info.psi,exception);
11202           if (image != (Image *) NULL)
11203             (void) SetImageChannelMask(image,channel_mask);
11204           break;
11205         }
11206         case 139:  /* HoughLine */
11207         {
11208           if (attribute_flag[0] != 0)
11209             {
11210               flags=ParseGeometry(argument_list[0].string_reference,
11211                 &geometry_info);
11212               if ((flags & SigmaValue) == 0)
11213                 geometry_info.sigma=geometry_info.rho;
11214               if ((flags & XiValue) == 0)
11215                 geometry_info.xi=40;
11216             }
11217           if (attribute_flag[1] != 0)
11218             geometry_info.rho=(double) argument_list[1].integer_reference;
11219           if (attribute_flag[2] != 0)
11220             geometry_info.sigma=(double) argument_list[2].integer_reference;
11221           if (attribute_flag[3] != 0)
11222             geometry_info.xi=(double) argument_list[3].integer_reference;
11223           image=HoughLineImage(image,(size_t) geometry_info.rho,(size_t)
11224             geometry_info.sigma,(size_t) geometry_info.xi,exception);
11225           break;
11226         }
11227         case 140:  /* MeanShift */
11228         {
11229           if (attribute_flag[0] != 0)
11230             {
11231               flags=ParseGeometry(argument_list[0].string_reference,
11232                 &geometry_info);
11233               if ((flags & SigmaValue) == 0)
11234                 geometry_info.sigma=geometry_info.rho;
11235               if ((flags & XiValue) == 0)
11236                 geometry_info.xi=0.10*QuantumRange;
11237               if ((flags & PercentValue) != 0)
11238                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
11239             }
11240           if (attribute_flag[1] != 0)
11241             geometry_info.rho=(double) argument_list[1].integer_reference;
11242           if (attribute_flag[2] != 0)
11243             geometry_info.sigma=(double) argument_list[2].integer_reference;
11244           if (attribute_flag[3] != 0)
11245             geometry_info.xi=(double) argument_list[3].integer_reference;
11246           image=MeanShiftImage(image,(size_t) geometry_info.rho,(size_t)
11247             geometry_info.sigma,geometry_info.xi,exception);
11248           break;
11249         }
11250         case 141:  /* Kuwahara */
11251         {
11252           if (attribute_flag[0] != 0)
11253             {
11254               flags=ParseGeometry(argument_list[0].string_reference,
11255                 &geometry_info);
11256               if ((flags & SigmaValue) == 0)
11257                 geometry_info.sigma=geometry_info.rho-0.5;
11258             }
11259           if (attribute_flag[1] != 0)
11260             geometry_info.rho=argument_list[1].real_reference;
11261           if (attribute_flag[2] != 0)
11262             geometry_info.sigma=argument_list[2].real_reference;
11263           if (attribute_flag[3] != 0)
11264             channel=(ChannelType) argument_list[3].integer_reference;
11265           channel_mask=SetImageChannelMask(image,channel);
11266           image=KuwaharaImage(image,geometry_info.rho,geometry_info.sigma,
11267             exception);
11268           if (image != (Image *) NULL)
11269             (void) SetImageChannelMask(image,channel_mask);
11270           break;
11271         }
11272         case 142:  /* ConnectedComponent */
11273         {
11274           size_t
11275             connectivity;
11276
11277           connectivity=4;
11278           if (attribute_flag[0] != 0)
11279             connectivity=argument_list[0].integer_reference;
11280           image=ConnectedComponentsImage(image,connectivity,
11281             (CCObjectInfo **) NULL,exception);
11282           break;
11283         }
11284         case 143:  /* Copy */
11285         {
11286           Image
11287             *source_image;
11288
11289           OffsetInfo
11290             offset;
11291
11292           RectangleInfo
11293             offset_geometry;
11294
11295           source_image=image;
11296           if (attribute_flag[0] != 0)
11297             source_image=argument_list[0].image_reference;
11298           SetGeometry(source_image,&geometry);
11299           if (attribute_flag[1] != 0)
11300             flags=ParseGravityGeometry(source_image,
11301               argument_list[1].string_reference,&geometry,exception);
11302           if (attribute_flag[2] != 0)
11303             geometry.width=argument_list[2].integer_reference;
11304           if (attribute_flag[3] != 0)
11305             geometry.height=argument_list[3].integer_reference;
11306           if (attribute_flag[4] != 0)
11307             geometry.x=argument_list[4].integer_reference;
11308           if (attribute_flag[5] != 0)
11309             geometry.y=argument_list[5].integer_reference;
11310           if (attribute_flag[6] != 0)
11311             image->gravity=(GravityType) argument_list[6].integer_reference;
11312           SetGeometry(image,&offset_geometry);
11313           if (attribute_flag[7] != 0)
11314             flags=ParseGravityGeometry(image,argument_list[7].string_reference,
11315               &offset_geometry,exception);
11316           offset.x=offset_geometry.x;
11317           offset.y=offset_geometry.y;
11318           if (attribute_flag[8] != 0)
11319             offset.x=argument_list[8].integer_reference;
11320           if (attribute_flag[9] != 0)
11321             offset.y=argument_list[9].integer_reference;
11322           (void) CopyImagePixels(image,source_image,&geometry,&offset,
11323             exception);
11324           break;
11325         }
11326       }
11327       if (next != (Image *) NULL)
11328         (void) CatchImageException(next);
11329       if (region_image != (Image *) NULL)
11330         {
11331           /*
11332             Composite region.
11333           */
11334           status=CompositeImage(region_image,image,CopyCompositeOp,MagickTrue,
11335             region_info.x,region_info.y,exception);
11336           (void) status;
11337           (void) CatchImageException(region_image);
11338           image=DestroyImage(image);
11339           image=region_image;
11340         }
11341       if (image != (Image *) NULL)
11342         {
11343           number_images++;
11344           if (next && (next != image))
11345             {
11346               image->next=next->next;
11347               if (image->next != (Image *) NULL)
11348                 image->next->previous=image;
11349               DeleteImageFromRegistry(*pv,next);
11350             }
11351           sv_setiv(*pv,PTR2IV(image));
11352           next=image;
11353         }
11354       if (*pv)
11355         pv++;
11356     }
11357
11358   PerlException:
11359     if (reference_vector)
11360       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
11361     InheritPerlException(exception,perl_exception);
11362     exception=DestroyExceptionInfo(exception);
11363     sv_setiv(perl_exception,(IV) number_images);
11364     SvPOK_on(perl_exception);
11365     ST(0)=sv_2mortal(perl_exception);
11366     XSRETURN(1);
11367   }
11368 \f
11369 #
11370 ###############################################################################
11371 #                                                                             #
11372 #                                                                             #
11373 #                                                                             #
11374 #   M o n t a g e                                                             #
11375 #                                                                             #
11376 #                                                                             #
11377 #                                                                             #
11378 ###############################################################################
11379 #
11380 #
11381 void
11382 Montage(ref,...)
11383   Image::Magick ref=NO_INIT
11384   ALIAS:
11385     MontageImage  = 1
11386     montage       = 2
11387     montageimage  = 3
11388   PPCODE:
11389   {
11390     AV
11391       *av;
11392
11393     char
11394       *attribute;
11395
11396     ExceptionInfo
11397       *exception;
11398
11399     HV
11400       *hv;
11401
11402     Image
11403       *image,
11404       *next;
11405
11406     PixelInfo
11407       transparent_color;
11408
11409     MontageInfo
11410       *montage_info;
11411
11412     register ssize_t
11413       i;
11414
11415     ssize_t
11416       sp;
11417
11418     struct PackageInfo
11419       *info;
11420
11421     SV
11422       *av_reference,
11423       *perl_exception,
11424       *reference,
11425       *rv,
11426       *sv;
11427
11428     PERL_UNUSED_VAR(ref);
11429     PERL_UNUSED_VAR(ix);
11430     exception=AcquireExceptionInfo();
11431     perl_exception=newSVpv("",0);
11432     sv=NULL;
11433     attribute=NULL;
11434     if (sv_isobject(ST(0)) == 0)
11435       {
11436         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11437           PackageName);
11438         goto PerlException;
11439       }
11440     reference=SvRV(ST(0));
11441     hv=SvSTASH(reference);
11442     av=newAV();
11443     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11444     SvREFCNT_dec(av);
11445     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11446     if (image == (Image *) NULL)
11447       {
11448         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11449           PackageName);
11450         goto PerlException;
11451       }
11452     /*
11453       Get options.
11454     */
11455     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11456     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
11457     (void) QueryColorCompliance("none",AllCompliance,&transparent_color,
11458       exception);
11459     for (i=2; i < items; i+=2)
11460     {
11461       attribute=(char *) SvPV(ST(i-1),na);
11462       switch (*attribute)
11463       {
11464         case 'B':
11465         case 'b':
11466         {
11467           if (LocaleCompare(attribute,"background") == 0)
11468             {
11469               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11470                 &montage_info->background_color,exception);
11471               for (next=image; next; next=next->next)
11472                 next->background_color=montage_info->background_color;
11473               break;
11474             }
11475           if (LocaleCompare(attribute,"border") == 0)
11476             {
11477               montage_info->border_width=SvIV(ST(i));
11478               break;
11479             }
11480           if (LocaleCompare(attribute,"bordercolor") == 0)
11481             {
11482               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11483                 &montage_info->border_color,exception);
11484               for (next=image; next; next=next->next)
11485                 next->border_color=montage_info->border_color;
11486               break;
11487             }
11488           if (LocaleCompare(attribute,"borderwidth") == 0)
11489             {
11490               montage_info->border_width=SvIV(ST(i));
11491               break;
11492             }
11493           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11494             attribute);
11495           break;
11496         }
11497         case 'C':
11498         case 'c':
11499         {
11500           if (LocaleCompare(attribute,"compose") == 0)
11501             {
11502               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11503                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
11504               if (sp < 0)
11505                 {
11506                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11507                     SvPV(ST(i),na));
11508                   break;
11509                 }
11510               for (next=image; next; next=next->next)
11511                 next->compose=(CompositeOperator) sp;
11512               break;
11513             }
11514           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11515             attribute);
11516           break;
11517         }
11518         case 'F':
11519         case 'f':
11520         {
11521           if (LocaleCompare(attribute,"fill") == 0)
11522             {
11523               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11524                 &montage_info->fill,exception);
11525               break;
11526             }
11527           if (LocaleCompare(attribute,"font") == 0)
11528             {
11529               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
11530               break;
11531             }
11532           if (LocaleCompare(attribute,"frame") == 0)
11533             {
11534               char
11535                 *p;
11536
11537               p=SvPV(ST(i),na);
11538               if (IsGeometry(p) == MagickFalse)
11539                 {
11540                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11541                     p);
11542                   break;
11543                 }
11544               (void) CloneString(&montage_info->frame,p);
11545               if (*p == '\0')
11546                 montage_info->frame=(char *) NULL;
11547               break;
11548             }
11549           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11550             attribute);
11551           break;
11552         }
11553         case 'G':
11554         case 'g':
11555         {
11556           if (LocaleCompare(attribute,"geometry") == 0)
11557             {
11558               char
11559                 *p;
11560
11561               p=SvPV(ST(i),na);
11562               if (IsGeometry(p) == MagickFalse)
11563                 {
11564                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11565                     p);
11566                   break;
11567                 }
11568              (void) CloneString(&montage_info->geometry,p);
11569              if (*p == '\0')
11570                montage_info->geometry=(char *) NULL;
11571              break;
11572            }
11573          if (LocaleCompare(attribute,"gravity") == 0)
11574            {
11575              ssize_t
11576                in;
11577
11578              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11579                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11580              if (in < 0)
11581                {
11582                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
11583                    SvPV(ST(i),na));
11584                  return;
11585                }
11586              montage_info->gravity=(GravityType) in;
11587              for (next=image; next; next=next->next)
11588                next->gravity=(GravityType) in;
11589              break;
11590            }
11591           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11592             attribute);
11593           break;
11594         }
11595         case 'L':
11596         case 'l':
11597         {
11598           if (LocaleCompare(attribute,"label") == 0)
11599             {
11600               for (next=image; next; next=next->next)
11601                 (void) SetImageProperty(next,"label",InterpretImageProperties(
11602                   info ? info->image_info : (ImageInfo *) NULL,next,
11603                   SvPV(ST(i),na),exception),exception);
11604               break;
11605             }
11606           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11607             attribute);
11608           break;
11609         }
11610         case 'M':
11611         case 'm':
11612         {
11613           if (LocaleCompare(attribute,"mattecolor") == 0)
11614             {
11615               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11616                 &montage_info->matte_color,exception);
11617               for (next=image; next; next=next->next)
11618                 next->matte_color=montage_info->matte_color;
11619               break;
11620             }
11621           if (LocaleCompare(attribute,"mode") == 0)
11622             {
11623               ssize_t
11624                 in;
11625
11626               in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11627                 MagickModeOptions,MagickFalse,SvPV(ST(i),na));
11628               switch (in)
11629               {
11630                 default:
11631                 {
11632                   ThrowPerlException(exception,OptionError,
11633                     "UnrecognizedModeType",SvPV(ST(i),na));
11634                   break;
11635                 }
11636                 case FrameMode:
11637                 {
11638                   (void) CloneString(&montage_info->frame,"15x15+3+3");
11639                   montage_info->shadow=MagickTrue;
11640                   break;
11641                 }
11642                 case UnframeMode:
11643                 {
11644                   montage_info->frame=(char *) NULL;
11645                   montage_info->shadow=MagickFalse;
11646                   montage_info->border_width=0;
11647                   break;
11648                 }
11649                 case ConcatenateMode:
11650                 {
11651                   montage_info->frame=(char *) NULL;
11652                   montage_info->shadow=MagickFalse;
11653                   (void) CloneString(&montage_info->geometry,"+0+0");
11654                   montage_info->border_width=0;
11655                 }
11656               }
11657               break;
11658             }
11659           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11660             attribute);
11661           break;
11662         }
11663         case 'P':
11664         case 'p':
11665         {
11666           if (LocaleCompare(attribute,"pointsize") == 0)
11667             {
11668               montage_info->pointsize=SvIV(ST(i));
11669               break;
11670             }
11671           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11672             attribute);
11673           break;
11674         }
11675         case 'S':
11676         case 's':
11677         {
11678           if (LocaleCompare(attribute,"shadow") == 0)
11679             {
11680               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11681                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11682               if (sp < 0)
11683                 {
11684                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11685                     SvPV(ST(i),na));
11686                   break;
11687                 }
11688              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11689              break;
11690             }
11691           if (LocaleCompare(attribute,"stroke") == 0)
11692             {
11693               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11694                 &montage_info->stroke,exception);
11695               break;
11696             }
11697           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11698             attribute);
11699           break;
11700         }
11701         case 'T':
11702         case 't':
11703         {
11704           if (LocaleCompare(attribute,"texture") == 0)
11705             {
11706               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11707               break;
11708             }
11709           if (LocaleCompare(attribute,"tile") == 0)
11710             {
11711               char *p=SvPV(ST(i),na);
11712               if (IsGeometry(p) == MagickFalse)
11713                 {
11714                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11715                     p);
11716                   break;
11717                 }
11718               (void) CloneString(&montage_info->tile,p);
11719               if (*p == '\0')
11720                 montage_info->tile=(char *) NULL;
11721               break;
11722             }
11723           if (LocaleCompare(attribute,"title") == 0)
11724             {
11725               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11726               break;
11727             }
11728           if (LocaleCompare(attribute,"transparent") == 0)
11729             {
11730               PixelInfo
11731                 transparent_color;
11732
11733               QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11734                 &transparent_color,exception);
11735               for (next=image; next; next=next->next)
11736                 (void) TransparentPaintImage(next,&transparent_color,
11737                   TransparentAlpha,MagickFalse,exception);
11738               break;
11739             }
11740           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11741             attribute);
11742           break;
11743         }
11744         default:
11745         {
11746           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11747             attribute);
11748           break;
11749         }
11750       }
11751     }
11752     image=MontageImageList(info->image_info,montage_info,image,exception);
11753     montage_info=DestroyMontageInfo(montage_info);
11754     if (image == (Image *) NULL)
11755       goto PerlException;
11756     if (transparent_color.alpha != TransparentAlpha)
11757       for (next=image; next; next=next->next)
11758         (void) TransparentPaintImage(next,&transparent_color,
11759           TransparentAlpha,MagickFalse,exception);
11760     for (  ; image; image=image->next)
11761     {
11762       AddImageToRegistry(sv,image);
11763       rv=newRV(sv);
11764       av_push(av,sv_bless(rv,hv));
11765       SvREFCNT_dec(sv);
11766     }
11767     exception=DestroyExceptionInfo(exception);
11768     ST(0)=av_reference;
11769     SvREFCNT_dec(perl_exception);
11770     XSRETURN(1);
11771
11772   PerlException:
11773     InheritPerlException(exception,perl_exception);
11774     exception=DestroyExceptionInfo(exception);
11775     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11776     SvPOK_on(perl_exception);
11777     ST(0)=sv_2mortal(perl_exception);
11778     XSRETURN(1);
11779   }
11780 \f
11781 #
11782 ###############################################################################
11783 #                                                                             #
11784 #                                                                             #
11785 #                                                                             #
11786 #   M o r p h                                                                 #
11787 #                                                                             #
11788 #                                                                             #
11789 #                                                                             #
11790 ###############################################################################
11791 #
11792 #
11793 void
11794 Morph(ref,...)
11795   Image::Magick ref=NO_INIT
11796   ALIAS:
11797     MorphImage  = 1
11798     morph       = 2
11799     morphimage  = 3
11800   PPCODE:
11801   {
11802     AV
11803       *av;
11804
11805     char
11806       *attribute;
11807
11808     ExceptionInfo
11809       *exception;
11810
11811     HV
11812       *hv;
11813
11814     Image
11815       *image;
11816
11817     register ssize_t
11818       i;
11819
11820     ssize_t
11821       number_frames;
11822
11823     struct PackageInfo
11824       *info;
11825
11826     SV
11827       *av_reference,
11828       *perl_exception,
11829       *reference,
11830       *rv,
11831       *sv;
11832
11833     PERL_UNUSED_VAR(ref);
11834     PERL_UNUSED_VAR(ix);
11835     exception=AcquireExceptionInfo();
11836     perl_exception=newSVpv("",0);
11837     sv=NULL;
11838     av=NULL;
11839     attribute=NULL;
11840     if (sv_isobject(ST(0)) == 0)
11841       {
11842         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11843           PackageName);
11844         goto PerlException;
11845       }
11846     reference=SvRV(ST(0));
11847     hv=SvSTASH(reference);
11848     av=newAV();
11849     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11850     SvREFCNT_dec(av);
11851     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11852     if (image == (Image *) NULL)
11853       {
11854         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11855           PackageName);
11856         goto PerlException;
11857       }
11858     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11859     /*
11860       Get attribute.
11861     */
11862     number_frames=30;
11863     for (i=2; i < items; i+=2)
11864     {
11865       attribute=(char *) SvPV(ST(i-1),na);
11866       switch (*attribute)
11867       {
11868         case 'F':
11869         case 'f':
11870         {
11871           if (LocaleCompare(attribute,"frames") == 0)
11872             {
11873               number_frames=SvIV(ST(i));
11874               break;
11875             }
11876           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11877             attribute);
11878           break;
11879         }
11880         default:
11881         {
11882           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11883             attribute);
11884           break;
11885         }
11886       }
11887     }
11888     image=MorphImages(image,number_frames,exception);
11889     if (image == (Image *) NULL)
11890       goto PerlException;
11891     for ( ; image; image=image->next)
11892     {
11893       AddImageToRegistry(sv,image);
11894       rv=newRV(sv);
11895       av_push(av,sv_bless(rv,hv));
11896       SvREFCNT_dec(sv);
11897     }
11898     exception=DestroyExceptionInfo(exception);
11899     ST(0)=av_reference;
11900     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11901     XSRETURN(1);
11902
11903   PerlException:
11904     InheritPerlException(exception,perl_exception);
11905     exception=DestroyExceptionInfo(exception);
11906     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11907     SvPOK_on(perl_exception);
11908     ST(0)=sv_2mortal(perl_exception);
11909     XSRETURN(1);
11910   }
11911 \f
11912 #
11913 ###############################################################################
11914 #                                                                             #
11915 #                                                                             #
11916 #                                                                             #
11917 #   M o s a i c                                                               #
11918 #                                                                             #
11919 #                                                                             #
11920 #                                                                             #
11921 ###############################################################################
11922 #
11923 #
11924 void
11925 Mosaic(ref)
11926   Image::Magick ref=NO_INIT
11927   ALIAS:
11928     MosaicImage   = 1
11929     mosaic        = 2
11930     mosaicimage   = 3
11931   PPCODE:
11932   {
11933     AV
11934       *av;
11935
11936     ExceptionInfo
11937       *exception;
11938
11939     HV
11940       *hv;
11941
11942     Image
11943       *image;
11944
11945     struct PackageInfo
11946       *info;
11947
11948     SV
11949       *perl_exception,
11950       *reference,
11951       *rv,
11952       *sv;
11953
11954     PERL_UNUSED_VAR(ref);
11955     PERL_UNUSED_VAR(ix);
11956     exception=AcquireExceptionInfo();
11957     perl_exception=newSVpv("",0);
11958     sv=NULL;
11959     if (sv_isobject(ST(0)) == 0)
11960       {
11961         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11962           PackageName);
11963         goto PerlException;
11964       }
11965     reference=SvRV(ST(0));
11966     hv=SvSTASH(reference);
11967     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11968     if (image == (Image *) NULL)
11969       {
11970         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11971           PackageName);
11972         goto PerlException;
11973       }
11974     image=MergeImageLayers(image,MosaicLayer,exception);
11975     /*
11976       Create blessed Perl array for the returned image.
11977     */
11978     av=newAV();
11979     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11980     SvREFCNT_dec(av);
11981     AddImageToRegistry(sv,image);
11982     rv=newRV(sv);
11983     av_push(av,sv_bless(rv,hv));
11984     SvREFCNT_dec(sv);
11985     (void) CopyMagickString(info->image_info->filename,image->filename,
11986       MagickPathExtent);
11987     SetImageInfo(info->image_info,0,exception);
11988     exception=DestroyExceptionInfo(exception);
11989     SvREFCNT_dec(perl_exception);
11990     XSRETURN(1);
11991
11992   PerlException:
11993     InheritPerlException(exception,perl_exception);
11994     exception=DestroyExceptionInfo(exception);
11995     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11996     SvPOK_on(perl_exception);  /* return messages in string context */
11997     ST(0)=sv_2mortal(perl_exception);
11998     XSRETURN(1);
11999   }
12000 \f
12001 #
12002 ###############################################################################
12003 #                                                                             #
12004 #                                                                             #
12005 #                                                                             #
12006 #   P i n g                                                                   #
12007 #                                                                             #
12008 #                                                                             #
12009 #                                                                             #
12010 ###############################################################################
12011 #
12012 #
12013 void
12014 Ping(ref,...)
12015   Image::Magick ref=NO_INIT
12016   ALIAS:
12017     PingImage  = 1
12018     ping       = 2
12019     pingimage  = 3
12020   PPCODE:
12021   {
12022     AV
12023       *av;
12024
12025     char
12026       **keep,
12027       **list;
12028
12029     ExceptionInfo
12030       *exception;
12031
12032     Image
12033       *image,
12034       *next;
12035
12036     int
12037       n;
12038
12039     MagickBooleanType
12040       status;
12041
12042     register char
12043       **p;
12044
12045     register ssize_t
12046       i;
12047
12048     ssize_t
12049       ac;
12050
12051     STRLEN
12052       *length;
12053
12054     struct PackageInfo
12055       *info,
12056       *package_info;
12057
12058     SV
12059       *perl_exception,
12060       *reference;
12061
12062     size_t
12063       count;
12064
12065     PERL_UNUSED_VAR(ref);
12066     PERL_UNUSED_VAR(ix);
12067     exception=AcquireExceptionInfo();
12068     perl_exception=newSVpv("",0);
12069     package_info=(struct PackageInfo *) NULL;
12070     ac=(items < 2) ? 1 : items-1;
12071     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
12072     keep=list;
12073     length=(STRLEN *) NULL;
12074     if (list == (char **) NULL)
12075       {
12076         ThrowPerlException(exception,ResourceLimitError,
12077           "MemoryAllocationFailed",PackageName);
12078         goto PerlException;
12079       }
12080     keep=list;
12081     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
12082     if (length == (STRLEN *) NULL)
12083       {
12084         ThrowPerlException(exception,ResourceLimitError,
12085           "MemoryAllocationFailed",PackageName);
12086         goto PerlException;
12087       }
12088     if (sv_isobject(ST(0)) == 0)
12089       {
12090         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12091           PackageName);
12092         goto PerlException;
12093       }
12094     reference=SvRV(ST(0));
12095     if (SvTYPE(reference) != SVt_PVAV)
12096       {
12097         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12098           PackageName);
12099         goto PerlException;
12100       }
12101     av=(AV *) reference;
12102     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12103       exception);
12104     package_info=ClonePackageInfo(info,exception);
12105     n=1;
12106     if (items <= 1)
12107       *list=(char *) (*package_info->image_info->filename ?
12108         package_info->image_info->filename : "XC:black");
12109     else
12110       for (n=0, i=0; i < ac; i++)
12111       {
12112         list[n]=(char *) SvPV(ST(i+1),length[n]);
12113         if ((items >= 3) && strEQcase(list[n],"blob"))
12114           {
12115             void
12116               *blob;
12117
12118             i++;
12119             blob=(void *) (SvPV(ST(i+1),length[n]));
12120             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
12121           }
12122         if ((items >= 3) && strEQcase(list[n],"filename"))
12123           continue;
12124         if ((items >= 3) && strEQcase(list[n],"file"))
12125           {
12126             FILE
12127               *file;
12128
12129             PerlIO
12130               *io_info;
12131
12132             i++;
12133             io_info=IoIFP(sv_2io(ST(i+1)));
12134             if (io_info == (PerlIO *) NULL)
12135               {
12136                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12137                   PackageName);
12138                 continue;
12139               }
12140             file=PerlIO_findFILE(io_info);
12141             if (file == (FILE *) NULL)
12142               {
12143                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12144                   PackageName);
12145                 continue;
12146               }
12147             SetImageInfoFile(package_info->image_info,file);
12148           }
12149         if ((items >= 3) && strEQcase(list[n],"magick"))
12150           continue;
12151         n++;
12152       }
12153     list[n]=(char *) NULL;
12154     keep=list;
12155     status=ExpandFilenames(&n,&list);
12156     if (status == MagickFalse)
12157       {
12158         ThrowPerlException(exception,ResourceLimitError,
12159           "MemoryAllocationFailed",PackageName);
12160         goto PerlException;
12161       }
12162     count=0;
12163     for (i=0; i < n; i++)
12164     {
12165       (void) CopyMagickString(package_info->image_info->filename,list[i],
12166         MagickPathExtent);
12167       image=PingImage(package_info->image_info,exception);
12168       if (image == (Image *) NULL)
12169         break;
12170       if ((package_info->image_info->file != (FILE *) NULL) ||
12171           (package_info->image_info->blob != (void *) NULL))
12172         DisassociateImageStream(image);
12173       count+=GetImageListLength(image);
12174       EXTEND(sp,4*count);
12175       for (next=image; next; next=next->next)
12176       {
12177         PUSHs(sv_2mortal(newSViv(next->columns)));
12178         PUSHs(sv_2mortal(newSViv(next->rows)));
12179         PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
12180         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
12181       }
12182       image=DestroyImageList(image);
12183     }
12184     /*
12185       Free resources.
12186     */
12187     for (i=0; i < n; i++)
12188       if (list[i] != (char *) NULL)
12189         for (p=keep; list[i] != *p++; )
12190           if (*p == NULL)
12191             {
12192               list[i]=(char *) RelinquishMagickMemory(list[i]);
12193               break;
12194             }
12195
12196   PerlException:
12197     if (package_info != (struct PackageInfo *) NULL)
12198       DestroyPackageInfo(package_info);
12199     if (list && (list != keep))
12200       list=(char **) RelinquishMagickMemory(list);
12201     if (keep)
12202       keep=(char **) RelinquishMagickMemory(keep);
12203     if (length)
12204       length=(STRLEN *) RelinquishMagickMemory(length);
12205     InheritPerlException(exception,perl_exception);
12206     exception=DestroyExceptionInfo(exception);
12207     SvREFCNT_dec(perl_exception);  /* throw away all errors */
12208   }
12209 \f
12210 #
12211 ###############################################################################
12212 #                                                                             #
12213 #                                                                             #
12214 #                                                                             #
12215 #   P r e v i e w                                                             #
12216 #                                                                             #
12217 #                                                                             #
12218 #                                                                             #
12219 ###############################################################################
12220 #
12221 #
12222 void
12223 Preview(ref,...)
12224   Image::Magick ref=NO_INIT
12225   ALIAS:
12226     PreviewImage = 1
12227     preview      = 2
12228     previewimage = 3
12229   PPCODE:
12230   {
12231     AV
12232       *av;
12233
12234     ExceptionInfo
12235       *exception;
12236
12237     HV
12238       *hv;
12239
12240     Image
12241       *image,
12242       *preview_image;
12243
12244     PreviewType
12245       preview_type;
12246
12247     struct PackageInfo
12248       *info;
12249
12250     SV
12251       *av_reference,
12252       *perl_exception,
12253       *reference,
12254       *rv,
12255       *sv;
12256
12257     PERL_UNUSED_VAR(ref);
12258     PERL_UNUSED_VAR(ix);
12259     exception=AcquireExceptionInfo();
12260     perl_exception=newSVpv("",0);
12261     sv=NULL;
12262     av=NULL;
12263     if (sv_isobject(ST(0)) == 0)
12264       {
12265         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12266           PackageName);
12267         goto PerlException;
12268       }
12269     reference=SvRV(ST(0));
12270     hv=SvSTASH(reference);
12271     av=newAV();
12272     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12273     SvREFCNT_dec(av);
12274     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12275     if (image == (Image *) NULL)
12276       {
12277         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12278           PackageName);
12279         goto PerlException;
12280       }
12281     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
12282     preview_type=GammaPreview;
12283     if (items > 1)
12284       preview_type=(PreviewType)
12285         ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
12286     for ( ; image; image=image->next)
12287     {
12288       preview_image=PreviewImage(image,preview_type,exception);
12289       if (preview_image == (Image *) NULL)
12290         goto PerlException;
12291       AddImageToRegistry(sv,preview_image);
12292       rv=newRV(sv);
12293       av_push(av,sv_bless(rv,hv));
12294       SvREFCNT_dec(sv);
12295     }
12296     exception=DestroyExceptionInfo(exception);
12297     ST(0)=av_reference;
12298     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12299     XSRETURN(1);
12300
12301   PerlException:
12302     InheritPerlException(exception,perl_exception);
12303     exception=DestroyExceptionInfo(exception);
12304     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12305     SvPOK_on(perl_exception);
12306     ST(0)=sv_2mortal(perl_exception);
12307     XSRETURN(1);
12308   }
12309 \f
12310 #
12311 ###############################################################################
12312 #                                                                             #
12313 #                                                                             #
12314 #                                                                             #
12315 #   Q u e r y C o l o r                                                       #
12316 #                                                                             #
12317 #                                                                             #
12318 #                                                                             #
12319 ###############################################################################
12320 #
12321 #
12322 void
12323 QueryColor(ref,...)
12324   Image::Magick ref=NO_INIT
12325   ALIAS:
12326     querycolor = 1
12327   PPCODE:
12328   {
12329     char
12330       *name;
12331
12332     ExceptionInfo
12333       *exception;
12334
12335     PixelInfo
12336       color;
12337
12338     register ssize_t
12339       i;
12340
12341     SV
12342       *perl_exception;
12343
12344     PERL_UNUSED_VAR(ref);
12345     PERL_UNUSED_VAR(ix);
12346     exception=AcquireExceptionInfo();
12347     perl_exception=newSVpv("",0);
12348     if (items == 1)
12349       {
12350         const ColorInfo
12351           **colorlist;
12352
12353         size_t
12354           colors;
12355
12356         colorlist=GetColorInfoList("*",&colors,exception);
12357         EXTEND(sp,colors);
12358         for (i=0; i < (ssize_t) colors; i++)
12359         {
12360           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
12361         }
12362         colorlist=(const ColorInfo **)
12363           RelinquishMagickMemory((ColorInfo **) colorlist);
12364         goto PerlException;
12365       }
12366     EXTEND(sp,5*items);
12367     for (i=1; i < items; i++)
12368     {
12369       name=(char *) SvPV(ST(i),na);
12370       if (QueryColorCompliance(name,AllCompliance,&color,exception) == MagickFalse)
12371         {
12372           PUSHs(&sv_undef);
12373           continue;
12374         }
12375       PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
12376       PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
12377       PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
12378       if (color.colorspace == CMYKColorspace)
12379         PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
12380       if (color.alpha_trait != UndefinedPixelTrait)
12381         PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
12382     }
12383
12384   PerlException:
12385     InheritPerlException(exception,perl_exception);
12386     exception=DestroyExceptionInfo(exception);
12387     SvREFCNT_dec(perl_exception);
12388   }
12389 \f
12390 #
12391 ###############################################################################
12392 #                                                                             #
12393 #                                                                             #
12394 #                                                                             #
12395 #   Q u e r y C o l o r N a m e                                               #
12396 #                                                                             #
12397 #                                                                             #
12398 #                                                                             #
12399 ###############################################################################
12400 #
12401 #
12402 void
12403 QueryColorname(ref,...)
12404   Image::Magick ref=NO_INIT
12405   ALIAS:
12406     querycolorname = 1
12407   PPCODE:
12408   {
12409     AV
12410       *av;
12411
12412     char
12413       message[MagickPathExtent];
12414
12415     ExceptionInfo
12416       *exception;
12417
12418     Image
12419       *image;
12420
12421     PixelInfo
12422       target_color;
12423
12424     register ssize_t
12425       i;
12426
12427     struct PackageInfo
12428       *info;
12429
12430     SV
12431       *perl_exception,
12432       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12433
12434     PERL_UNUSED_VAR(ref);
12435     PERL_UNUSED_VAR(ix);
12436     exception=AcquireExceptionInfo();
12437     perl_exception=newSVpv("",0);
12438     reference=SvRV(ST(0));
12439     av=(AV *) reference;
12440     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12441       exception);
12442     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12443     if (image == (Image *) NULL)
12444       {
12445         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12446           PackageName);
12447         goto PerlException;
12448       }
12449     EXTEND(sp,items);
12450     for (i=1; i < items; i++)
12451     {
12452       (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,&target_color,
12453         exception);
12454       (void) QueryColorname(image,&target_color,SVGCompliance,message,
12455         exception);
12456       PUSHs(sv_2mortal(newSVpv(message,0)));
12457     }
12458
12459   PerlException:
12460     InheritPerlException(exception,perl_exception);
12461     exception=DestroyExceptionInfo(exception);
12462     SvREFCNT_dec(perl_exception);
12463   }
12464 \f
12465 #
12466 ###############################################################################
12467 #                                                                             #
12468 #                                                                             #
12469 #                                                                             #
12470 #   Q u e r y F o n t                                                         #
12471 #                                                                             #
12472 #                                                                             #
12473 #                                                                             #
12474 ###############################################################################
12475 #
12476 #
12477 void
12478 QueryFont(ref,...)
12479   Image::Magick ref=NO_INIT
12480   ALIAS:
12481     queryfont = 1
12482   PPCODE:
12483   {
12484     char
12485       *name,
12486       message[MagickPathExtent];
12487
12488     ExceptionInfo
12489       *exception;
12490
12491     register ssize_t
12492       i;
12493
12494     SV
12495       *perl_exception;
12496
12497     volatile const TypeInfo
12498       *type_info;
12499
12500     PERL_UNUSED_VAR(ref);
12501     PERL_UNUSED_VAR(ix);
12502     exception=AcquireExceptionInfo();
12503     perl_exception=newSVpv("",0);
12504     if (items == 1)
12505       {
12506         const TypeInfo
12507           **typelist;
12508
12509         size_t
12510           types;
12511
12512         typelist=GetTypeInfoList("*",&types,exception);
12513         EXTEND(sp,types);
12514         for (i=0; i < (ssize_t) types; i++)
12515         {
12516           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
12517         }
12518         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
12519           typelist);
12520         goto PerlException;
12521       }
12522     EXTEND(sp,10*items);
12523     for (i=1; i < items; i++)
12524     {
12525       name=(char *) SvPV(ST(i),na);
12526       type_info=GetTypeInfo(name,exception);
12527       if (type_info == (TypeInfo *) NULL)
12528         {
12529           PUSHs(&sv_undef);
12530           continue;
12531         }
12532       if (type_info->name == (char *) NULL)
12533         PUSHs(&sv_undef);
12534       else
12535         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
12536       if (type_info->description == (char *) NULL)
12537         PUSHs(&sv_undef);
12538       else
12539         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
12540       if (type_info->family == (char *) NULL)
12541         PUSHs(&sv_undef);
12542       else
12543         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
12544       if (type_info->style == UndefinedStyle)
12545         PUSHs(&sv_undef);
12546       else
12547         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
12548           type_info->style),0)));
12549       if (type_info->stretch == UndefinedStretch)
12550         PUSHs(&sv_undef);
12551       else
12552         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
12553           type_info->stretch),0)));
12554       (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
12555         type_info->weight);
12556       PUSHs(sv_2mortal(newSVpv(message,0)));
12557       if (type_info->encoding == (char *) NULL)
12558         PUSHs(&sv_undef);
12559       else
12560         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
12561       if (type_info->foundry == (char *) NULL)
12562         PUSHs(&sv_undef);
12563       else
12564         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
12565       if (type_info->format == (char *) NULL)
12566         PUSHs(&sv_undef);
12567       else
12568         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
12569       if (type_info->metrics == (char *) NULL)
12570         PUSHs(&sv_undef);
12571       else
12572         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
12573       if (type_info->glyphs == (char *) NULL)
12574         PUSHs(&sv_undef);
12575       else
12576         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
12577     }
12578
12579   PerlException:
12580     InheritPerlException(exception,perl_exception);
12581     exception=DestroyExceptionInfo(exception);
12582     SvREFCNT_dec(perl_exception);
12583   }
12584 \f
12585 #
12586 ###############################################################################
12587 #                                                                             #
12588 #                                                                             #
12589 #                                                                             #
12590 #   Q u e r y F o n t M e t r i c s                                           #
12591 #                                                                             #
12592 #                                                                             #
12593 #                                                                             #
12594 ###############################################################################
12595 #
12596 #
12597 void
12598 QueryFontMetrics(ref,...)
12599   Image::Magick ref=NO_INIT
12600   ALIAS:
12601     queryfontmetrics = 1
12602   PPCODE:
12603   {
12604     AffineMatrix
12605       affine,
12606       current;
12607
12608     AV
12609       *av;
12610
12611     char
12612       *attribute;
12613
12614     double
12615       x,
12616       y;
12617
12618     DrawInfo
12619       *draw_info;
12620
12621     ExceptionInfo
12622       *exception;
12623
12624     GeometryInfo
12625       geometry_info;
12626
12627     Image
12628       *image;
12629
12630     MagickBooleanType
12631       status;
12632
12633     MagickStatusType
12634       flags;
12635
12636     register ssize_t
12637       i;
12638
12639     ssize_t
12640       type;
12641
12642     struct PackageInfo
12643       *info,
12644       *package_info;
12645
12646     SV
12647       *perl_exception,
12648       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12649
12650     TypeMetric
12651       metrics;
12652
12653     PERL_UNUSED_VAR(ref);
12654     PERL_UNUSED_VAR(ix);
12655     exception=AcquireExceptionInfo();
12656     package_info=(struct PackageInfo *) NULL;
12657     perl_exception=newSVpv("",0);
12658     reference=SvRV(ST(0));
12659     av=(AV *) reference;
12660     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12661       exception);
12662     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12663     if (image == (Image *) NULL)
12664       {
12665         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12666           PackageName);
12667         goto PerlException;
12668       }
12669     package_info=ClonePackageInfo(info,exception);
12670     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12671     CloneString(&draw_info->text,"");
12672     current=draw_info->affine;
12673     GetAffineMatrix(&affine);
12674     x=0.0;
12675     y=0.0;
12676     EXTEND(sp,7*items);
12677     for (i=2; i < items; i+=2)
12678     {
12679       attribute=(char *) SvPV(ST(i-1),na);
12680       switch (*attribute)
12681       {
12682         case 'A':
12683         case 'a':
12684         {
12685           if (LocaleCompare(attribute,"antialias") == 0)
12686             {
12687               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12688                 SvPV(ST(i),na));
12689               if (type < 0)
12690                 {
12691                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12692                     SvPV(ST(i),na));
12693                   break;
12694                 }
12695               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12696               break;
12697             }
12698           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12699             attribute);
12700           break;
12701         }
12702         case 'd':
12703         case 'D':
12704         {
12705           if (LocaleCompare(attribute,"density") == 0)
12706             {
12707               CloneString(&draw_info->density,SvPV(ST(i),na));
12708               break;
12709             }
12710           if (LocaleCompare(attribute,"direction") == 0)
12711             {
12712               draw_info->direction=(DirectionType) ParseCommandOption(
12713                 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12714               break;
12715             }
12716           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12717             attribute);
12718           break;
12719         }
12720         case 'e':
12721         case 'E':
12722         {
12723           if (LocaleCompare(attribute,"encoding") == 0)
12724             {
12725               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12726               break;
12727             }
12728           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12729             attribute);
12730           break;
12731         }
12732         case 'f':
12733         case 'F':
12734         {
12735           if (LocaleCompare(attribute,"family") == 0)
12736             {
12737               CloneString(&draw_info->family,SvPV(ST(i),na));
12738               break;
12739             }
12740           if (LocaleCompare(attribute,"fill") == 0)
12741             {
12742               if (info)
12743                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12744                   &draw_info->fill,exception);
12745               break;
12746             }
12747           if (LocaleCompare(attribute,"font") == 0)
12748             {
12749               CloneString(&draw_info->font,SvPV(ST(i),na));
12750               break;
12751             }
12752           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12753             attribute);
12754           break;
12755         }
12756         case 'g':
12757         case 'G':
12758         {
12759           if (LocaleCompare(attribute,"geometry") == 0)
12760             {
12761               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12762               break;
12763             }
12764           if (LocaleCompare(attribute,"gravity") == 0)
12765             {
12766               draw_info->gravity=(GravityType) ParseCommandOption(
12767                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12768               break;
12769             }
12770           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12771             attribute);
12772           break;
12773         }
12774         case 'i':
12775         case 'I':
12776         {
12777           if (LocaleCompare(attribute,"interline-spacing") == 0)
12778             {
12779               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12780               draw_info->interline_spacing=geometry_info.rho;
12781               break;
12782             }
12783           if (LocaleCompare(attribute,"interword-spacing") == 0)
12784             {
12785               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12786               draw_info->interword_spacing=geometry_info.rho;
12787               break;
12788             }
12789           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12790             attribute);
12791           break;
12792         }
12793         case 'k':
12794         case 'K':
12795         {
12796           if (LocaleCompare(attribute,"kerning") == 0)
12797             {
12798               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12799               draw_info->kerning=geometry_info.rho;
12800               break;
12801             }
12802           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12803             attribute);
12804           break;
12805         }
12806         case 'p':
12807         case 'P':
12808         {
12809           if (LocaleCompare(attribute,"pointsize") == 0)
12810             {
12811               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12812               draw_info->pointsize=geometry_info.rho;
12813               break;
12814             }
12815           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12816             attribute);
12817           break;
12818         }
12819         case 'r':
12820         case 'R':
12821         {
12822           if (LocaleCompare(attribute,"rotate") == 0)
12823             {
12824               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12825               affine.rx=geometry_info.rho;
12826               affine.ry=geometry_info.sigma;
12827               if ((flags & SigmaValue) == 0)
12828                 affine.ry=affine.rx;
12829               break;
12830             }
12831           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12832             attribute);
12833           break;
12834         }
12835         case 's':
12836         case 'S':
12837         {
12838           if (LocaleCompare(attribute,"scale") == 0)
12839             {
12840               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12841               affine.sx=geometry_info.rho;
12842               affine.sy=geometry_info.sigma;
12843               if ((flags & SigmaValue) == 0)
12844                 affine.sy=affine.sx;
12845               break;
12846             }
12847           if (LocaleCompare(attribute,"skew") == 0)
12848             {
12849               double
12850                 x_angle,
12851                 y_angle;
12852
12853               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12854               x_angle=geometry_info.rho;
12855               y_angle=geometry_info.sigma;
12856               if ((flags & SigmaValue) == 0)
12857                 y_angle=x_angle;
12858               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12859               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12860               break;
12861             }
12862           if (LocaleCompare(attribute,"stroke") == 0)
12863             {
12864               if (info)
12865                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12866                   &draw_info->stroke,exception);
12867               break;
12868             }
12869           if (LocaleCompare(attribute,"style") == 0)
12870             {
12871               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12872                 SvPV(ST(i),na));
12873               if (type < 0)
12874                 {
12875                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12876                     SvPV(ST(i),na));
12877                   break;
12878                 }
12879               draw_info->style=(StyleType) type;
12880               break;
12881             }
12882           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12883             attribute);
12884           break;
12885         }
12886         case 't':
12887         case 'T':
12888         {
12889           if (LocaleCompare(attribute,"text") == 0)
12890             {
12891               CloneString(&draw_info->text,SvPV(ST(i),na));
12892               break;
12893             }
12894           if (LocaleCompare(attribute,"translate") == 0)
12895             {
12896               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12897               affine.tx=geometry_info.rho;
12898               affine.ty=geometry_info.sigma;
12899               if ((flags & SigmaValue) == 0)
12900                 affine.ty=affine.tx;
12901               break;
12902             }
12903           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12904             attribute);
12905           break;
12906         }
12907         case 'w':
12908         case 'W':
12909         {
12910           if (LocaleCompare(attribute,"weight") == 0)
12911             {
12912               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12913               draw_info->weight=(size_t) geometry_info.rho;
12914               break;
12915             }
12916           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12917             attribute);
12918           break;
12919         }
12920         case 'x':
12921         case 'X':
12922         {
12923           if (LocaleCompare(attribute,"x") == 0)
12924             {
12925               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12926               x=geometry_info.rho;
12927               break;
12928             }
12929           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12930             attribute);
12931           break;
12932         }
12933         case 'y':
12934         case 'Y':
12935         {
12936           if (LocaleCompare(attribute,"y") == 0)
12937             {
12938               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12939               y=geometry_info.rho;
12940               break;
12941             }
12942           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12943             attribute);
12944           break;
12945         }
12946         default:
12947         {
12948           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12949             attribute);
12950           break;
12951         }
12952       }
12953     }
12954     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12955     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12956     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12957     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12958     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12959     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12960     if (draw_info->geometry == (char *) NULL)
12961       {
12962         draw_info->geometry=AcquireString((char *) NULL);
12963         (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
12964           "%.15g,%.15g",x,y);
12965       }
12966     status=GetTypeMetrics(image,draw_info,&metrics,exception);
12967     (void) CatchImageException(image);
12968     if (status == MagickFalse)
12969       PUSHs(&sv_undef);
12970     else
12971       {
12972         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12973         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12974         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12975         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12976         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12977         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12978         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12979         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12980         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12981         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12982         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12983         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12984         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12985       }
12986     draw_info=DestroyDrawInfo(draw_info);
12987
12988   PerlException:
12989     if (package_info != (struct PackageInfo *) NULL)
12990       DestroyPackageInfo(package_info);
12991     InheritPerlException(exception,perl_exception);
12992     exception=DestroyExceptionInfo(exception);
12993     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12994   }
12995 \f
12996 #
12997 ###############################################################################
12998 #                                                                             #
12999 #                                                                             #
13000 #                                                                             #
13001 #   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                         #
13002 #                                                                             #
13003 #                                                                             #
13004 #                                                                             #
13005 ###############################################################################
13006 #
13007 #
13008 void
13009 QueryMultilineFontMetrics(ref,...)
13010   Image::Magick ref=NO_INIT
13011   ALIAS:
13012     querymultilinefontmetrics = 1
13013   PPCODE:
13014   {
13015     AffineMatrix
13016       affine,
13017       current;
13018
13019     AV
13020       *av;
13021
13022     char
13023       *attribute;
13024
13025     double
13026       x,
13027       y;
13028
13029     DrawInfo
13030       *draw_info;
13031
13032     ExceptionInfo
13033       *exception;
13034
13035     GeometryInfo
13036       geometry_info;
13037
13038     Image
13039       *image;
13040
13041     MagickBooleanType
13042       status;
13043
13044     MagickStatusType
13045       flags;
13046
13047     register ssize_t
13048       i;
13049
13050     ssize_t
13051       type;
13052
13053     struct PackageInfo
13054       *info,
13055       *package_info;
13056
13057     SV
13058       *perl_exception,
13059       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13060
13061     TypeMetric
13062       metrics;
13063
13064     PERL_UNUSED_VAR(ref);
13065     PERL_UNUSED_VAR(ix);
13066     exception=AcquireExceptionInfo();
13067     package_info=(struct PackageInfo *) NULL;
13068     perl_exception=newSVpv("",0);
13069     reference=SvRV(ST(0));
13070     av=(AV *) reference;
13071     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13072       exception);
13073     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13074     if (image == (Image *) NULL)
13075       {
13076         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13077           PackageName);
13078         goto PerlException;
13079       }
13080     package_info=ClonePackageInfo(info,exception);
13081     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
13082     CloneString(&draw_info->text,"");
13083     current=draw_info->affine;
13084     GetAffineMatrix(&affine);
13085     x=0.0;
13086     y=0.0;
13087     EXTEND(sp,7*items);
13088     for (i=2; i < items; i+=2)
13089     {
13090       attribute=(char *) SvPV(ST(i-1),na);
13091       switch (*attribute)
13092       {
13093         case 'A':
13094         case 'a':
13095         {
13096           if (LocaleCompare(attribute,"antialias") == 0)
13097             {
13098               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13099                 SvPV(ST(i),na));
13100               if (type < 0)
13101                 {
13102                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13103                     SvPV(ST(i),na));
13104                   break;
13105                 }
13106               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
13107               break;
13108             }
13109           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13110             attribute);
13111           break;
13112         }
13113         case 'd':
13114         case 'D':
13115         {
13116           if (LocaleCompare(attribute,"density") == 0)
13117             {
13118               CloneString(&draw_info->density,SvPV(ST(i),na));
13119               break;
13120             }
13121           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13122             attribute);
13123           break;
13124         }
13125         case 'e':
13126         case 'E':
13127         {
13128           if (LocaleCompare(attribute,"encoding") == 0)
13129             {
13130               CloneString(&draw_info->encoding,SvPV(ST(i),na));
13131               break;
13132             }
13133           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13134             attribute);
13135           break;
13136         }
13137         case 'f':
13138         case 'F':
13139         {
13140           if (LocaleCompare(attribute,"family") == 0)
13141             {
13142               CloneString(&draw_info->family,SvPV(ST(i),na));
13143               break;
13144             }
13145           if (LocaleCompare(attribute,"fill") == 0)
13146             {
13147               if (info)
13148                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13149                   &draw_info->fill,exception);
13150               break;
13151             }
13152           if (LocaleCompare(attribute,"font") == 0)
13153             {
13154               CloneString(&draw_info->font,SvPV(ST(i),na));
13155               break;
13156             }
13157           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13158             attribute);
13159           break;
13160         }
13161         case 'g':
13162         case 'G':
13163         {
13164           if (LocaleCompare(attribute,"geometry") == 0)
13165             {
13166               CloneString(&draw_info->geometry,SvPV(ST(i),na));
13167               break;
13168             }
13169           if (LocaleCompare(attribute,"gravity") == 0)
13170             {
13171               draw_info->gravity=(GravityType) ParseCommandOption(
13172                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13173               break;
13174             }
13175           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13176             attribute);
13177           break;
13178         }
13179         case 'p':
13180         case 'P':
13181         {
13182           if (LocaleCompare(attribute,"pointsize") == 0)
13183             {
13184               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13185               draw_info->pointsize=geometry_info.rho;
13186               break;
13187             }
13188           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13189             attribute);
13190           break;
13191         }
13192         case 'r':
13193         case 'R':
13194         {
13195           if (LocaleCompare(attribute,"rotate") == 0)
13196             {
13197               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13198               affine.rx=geometry_info.rho;
13199               affine.ry=geometry_info.sigma;
13200               if ((flags & SigmaValue) == 0)
13201                 affine.ry=affine.rx;
13202               break;
13203             }
13204           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13205             attribute);
13206           break;
13207         }
13208         case 's':
13209         case 'S':
13210         {
13211           if (LocaleCompare(attribute,"scale") == 0)
13212             {
13213               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13214               affine.sx=geometry_info.rho;
13215               affine.sy=geometry_info.sigma;
13216               if ((flags & SigmaValue) == 0)
13217                 affine.sy=affine.sx;
13218               break;
13219             }
13220           if (LocaleCompare(attribute,"skew") == 0)
13221             {
13222               double
13223                 x_angle,
13224                 y_angle;
13225
13226               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13227               x_angle=geometry_info.rho;
13228               y_angle=geometry_info.sigma;
13229               if ((flags & SigmaValue) == 0)
13230                 y_angle=x_angle;
13231               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
13232               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
13233               break;
13234             }
13235           if (LocaleCompare(attribute,"stroke") == 0)
13236             {
13237               if (info)
13238                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13239                   &draw_info->stroke,exception);
13240               break;
13241             }
13242           if (LocaleCompare(attribute,"style") == 0)
13243             {
13244               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
13245                 SvPV(ST(i),na));
13246               if (type < 0)
13247                 {
13248                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13249                     SvPV(ST(i),na));
13250                   break;
13251                 }
13252               draw_info->style=(StyleType) type;
13253               break;
13254             }
13255           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13256             attribute);
13257           break;
13258         }
13259         case 't':
13260         case 'T':
13261         {
13262           if (LocaleCompare(attribute,"text") == 0)
13263             {
13264               CloneString(&draw_info->text,SvPV(ST(i),na));
13265               break;
13266             }
13267           if (LocaleCompare(attribute,"translate") == 0)
13268             {
13269               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13270               affine.tx=geometry_info.rho;
13271               affine.ty=geometry_info.sigma;
13272               if ((flags & SigmaValue) == 0)
13273                 affine.ty=affine.tx;
13274               break;
13275             }
13276           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13277             attribute);
13278           break;
13279         }
13280         case 'w':
13281         case 'W':
13282         {
13283           if (LocaleCompare(attribute,"weight") == 0)
13284             {
13285               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13286               draw_info->weight=(size_t) geometry_info.rho;
13287               break;
13288             }
13289           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13290             attribute);
13291           break;
13292         }
13293         case 'x':
13294         case 'X':
13295         {
13296           if (LocaleCompare(attribute,"x") == 0)
13297             {
13298               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13299               x=geometry_info.rho;
13300               break;
13301             }
13302           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13303             attribute);
13304           break;
13305         }
13306         case 'y':
13307         case 'Y':
13308         {
13309           if (LocaleCompare(attribute,"y") == 0)
13310             {
13311               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13312               y=geometry_info.rho;
13313               break;
13314             }
13315           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13316             attribute);
13317           break;
13318         }
13319         default:
13320         {
13321           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13322             attribute);
13323           break;
13324         }
13325       }
13326     }
13327     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
13328     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
13329     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
13330     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
13331     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
13332     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
13333     if (draw_info->geometry == (char *) NULL)
13334       {
13335         draw_info->geometry=AcquireString((char *) NULL);
13336         (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
13337           "%.15g,%.15g",x,y);
13338       }
13339     status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
13340     (void) CatchException(exception);
13341     if (status == MagickFalse)
13342       PUSHs(&sv_undef);
13343     else
13344       {
13345         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
13346         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
13347         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
13348         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13349         PUSHs(sv_2mortal(newSVnv(metrics.width)));
13350         PUSHs(sv_2mortal(newSVnv(metrics.height)));
13351         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13352         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13353         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13354         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13355         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13356         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13357         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13358       }
13359     draw_info=DestroyDrawInfo(draw_info);
13360
13361   PerlException:
13362     if (package_info != (struct PackageInfo *) NULL)
13363       DestroyPackageInfo(package_info);
13364     InheritPerlException(exception,perl_exception);
13365     exception=DestroyExceptionInfo(exception);
13366     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13367   }
13368 \f
13369 #
13370 ###############################################################################
13371 #                                                                             #
13372 #                                                                             #
13373 #                                                                             #
13374 #   Q u e r y F o r m a t                                                     #
13375 #                                                                             #
13376 #                                                                             #
13377 #                                                                             #
13378 ###############################################################################
13379 #
13380 #
13381 void
13382 QueryFormat(ref,...)
13383   Image::Magick ref=NO_INIT
13384   ALIAS:
13385     queryformat = 1
13386   PPCODE:
13387   {
13388     char
13389       *name;
13390
13391     ExceptionInfo
13392       *exception;
13393
13394     register ssize_t
13395       i;
13396
13397     SV
13398       *perl_exception;
13399
13400     volatile const MagickInfo
13401       *magick_info;
13402
13403     PERL_UNUSED_VAR(ref);
13404     PERL_UNUSED_VAR(ix);
13405     exception=AcquireExceptionInfo();
13406     perl_exception=newSVpv("",0);
13407     if (items == 1)
13408       {
13409         char
13410           format[MagickPathExtent];
13411
13412         const MagickInfo
13413           **format_list;
13414
13415         size_t
13416           types;
13417
13418         format_list=GetMagickInfoList("*",&types,exception);
13419         EXTEND(sp,types);
13420         for (i=0; i < (ssize_t) types; i++)
13421         {
13422           (void) CopyMagickString(format,format_list[i]->name,MagickPathExtent);
13423           LocaleLower(format);
13424           PUSHs(sv_2mortal(newSVpv(format,0)));
13425         }
13426         format_list=(const MagickInfo **)
13427           RelinquishMagickMemory((MagickInfo *) format_list);
13428         goto PerlException;
13429       }
13430     EXTEND(sp,8*items);
13431     for (i=1; i < items; i++)
13432     {
13433       name=(char *) SvPV(ST(i),na);
13434       magick_info=GetMagickInfo(name,exception);
13435       if (magick_info == (const MagickInfo *) NULL)
13436         {
13437           PUSHs(&sv_undef);
13438           continue;
13439         }
13440       if (magick_info->description == (char *) NULL)
13441         PUSHs(&sv_undef);
13442       else
13443         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
13444       if (magick_info->module == (char *) NULL)
13445         PUSHs(&sv_undef);
13446       else
13447         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
13448     }
13449
13450   PerlException:
13451     InheritPerlException(exception,perl_exception);
13452     exception=DestroyExceptionInfo(exception);
13453     SvREFCNT_dec(perl_exception);
13454   }
13455 \f
13456 #
13457 ###############################################################################
13458 #                                                                             #
13459 #                                                                             #
13460 #                                                                             #
13461 #   Q u e r y O p t i o n                                                     #
13462 #                                                                             #
13463 #                                                                             #
13464 #                                                                             #
13465 ###############################################################################
13466 #
13467 #
13468 void
13469 QueryOption(ref,...)
13470   Image::Magick ref=NO_INIT
13471   ALIAS:
13472     queryoption = 1
13473   PPCODE:
13474   {
13475     char
13476       **options;
13477
13478     ExceptionInfo
13479       *exception;
13480
13481     register ssize_t
13482       i;
13483
13484     ssize_t
13485       j,
13486       option;
13487
13488     SV
13489       *perl_exception;
13490
13491     PERL_UNUSED_VAR(ref);
13492     PERL_UNUSED_VAR(ix);
13493     exception=AcquireExceptionInfo();
13494     perl_exception=newSVpv("",0);
13495     EXTEND(sp,8*items);
13496     for (i=1; i < items; i++)
13497     {
13498       option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
13499         SvPV(ST(i),na));
13500       options=GetCommandOptions((CommandOption) option);
13501       if (options == (char **) NULL)
13502         PUSHs(&sv_undef);
13503       else
13504         {
13505           for (j=0; options[j] != (char *) NULL; j++)
13506             PUSHs(sv_2mortal(newSVpv(options[j],0)));
13507           options=DestroyStringList(options);
13508         }
13509     }
13510
13511     InheritPerlException(exception,perl_exception);
13512     exception=DestroyExceptionInfo(exception);
13513     SvREFCNT_dec(perl_exception);
13514   }
13515 \f
13516 #
13517 ###############################################################################
13518 #                                                                             #
13519 #                                                                             #
13520 #                                                                             #
13521 #   R e a d                                                                   #
13522 #                                                                             #
13523 #                                                                             #
13524 #                                                                             #
13525 ###############################################################################
13526 #
13527 #
13528 void
13529 Read(ref,...)
13530   Image::Magick ref=NO_INIT
13531   ALIAS:
13532     ReadImage  = 1
13533     read       = 2
13534     readimage  = 3
13535   PPCODE:
13536   {
13537     AV
13538       *av;
13539
13540     char
13541       **keep,
13542       **list;
13543
13544     ExceptionInfo
13545       *exception;
13546
13547     HV
13548       *hv;
13549
13550     Image
13551       *image;
13552
13553     int
13554       n;
13555
13556     MagickBooleanType
13557       status;
13558
13559     register char
13560       **p;
13561
13562     register ssize_t
13563       i;
13564
13565     ssize_t
13566       ac,
13567       number_images;
13568
13569     STRLEN
13570       *length;
13571
13572     struct PackageInfo
13573       *info,
13574       *package_info;
13575
13576     SV
13577       *perl_exception,  /* Perl variable for storing messages */
13578       *reference,
13579       *rv,
13580       *sv;
13581
13582     PERL_UNUSED_VAR(ref);
13583     PERL_UNUSED_VAR(ix);
13584     exception=AcquireExceptionInfo();
13585     perl_exception=newSVpv("",0);
13586     sv=NULL;
13587     package_info=(struct PackageInfo *) NULL;
13588     number_images=0;
13589     ac=(items < 2) ? 1 : items-1;
13590     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
13591     keep=list;
13592     length=(STRLEN *) NULL;
13593     if (list == (char **) NULL)
13594       {
13595         ThrowPerlException(exception,ResourceLimitError,
13596           "MemoryAllocationFailed",PackageName);
13597         goto PerlException;
13598       }
13599     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
13600     if (length == (STRLEN *) NULL)
13601       {
13602         ThrowPerlException(exception,ResourceLimitError,
13603           "MemoryAllocationFailed",PackageName);
13604         goto PerlException;
13605       }
13606     if (sv_isobject(ST(0)) == 0)
13607       {
13608         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13609           PackageName);
13610         goto PerlException;
13611       }
13612     reference=SvRV(ST(0));
13613     hv=SvSTASH(reference);
13614     if (SvTYPE(reference) != SVt_PVAV)
13615       {
13616         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13617           PackageName);
13618         goto PerlException;
13619       }
13620     av=(AV *) reference;
13621     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13622       exception);
13623     package_info=ClonePackageInfo(info,exception);
13624     n=1;
13625     if (items <= 1)
13626       *list=(char *) (*package_info->image_info->filename ?
13627         package_info->image_info->filename : "XC:black");
13628     else
13629       for (n=0, i=0; i < ac; i++)
13630       {
13631         list[n]=(char *) SvPV(ST(i+1),length[n]);
13632         if ((items >= 3) && strEQcase(list[n],"blob"))
13633           {
13634             void
13635               *blob;
13636
13637             i++;
13638             blob=(void *) (SvPV(ST(i+1),length[n]));
13639             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13640           }
13641         if ((items >= 3) && strEQcase(list[n],"filename"))
13642           continue;
13643         if ((items >= 3) && strEQcase(list[n],"file"))
13644           {
13645             FILE
13646               *file;
13647
13648             PerlIO
13649               *io_info;
13650
13651             i++;
13652             io_info=IoIFP(sv_2io(ST(i+1)));
13653             if (io_info == (PerlIO *) NULL)
13654               {
13655                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13656                   PackageName);
13657                 continue;
13658               }
13659             file=PerlIO_findFILE(io_info);
13660             if (file == (FILE *) NULL)
13661               {
13662                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13663                   PackageName);
13664                 continue;
13665               }
13666             SetImageInfoFile(package_info->image_info,file);
13667           }
13668         if ((items >= 3) && strEQcase(list[n],"magick"))
13669           continue;
13670         n++;
13671       }
13672     list[n]=(char *) NULL;
13673     keep=list;
13674     status=ExpandFilenames(&n,&list);
13675     if (status == MagickFalse)
13676       {
13677         ThrowPerlException(exception,ResourceLimitError,
13678           "MemoryAllocationFailed",PackageName);
13679         goto PerlException;
13680       }
13681     number_images=0;
13682     for (i=0; i < n; i++)
13683     {
13684       if ((package_info->image_info->file == (FILE *) NULL) &&
13685           (package_info->image_info->blob == (void *) NULL))
13686         image=ReadImages(package_info->image_info,list[i],exception);
13687       else
13688         {
13689           image=ReadImages(package_info->image_info,
13690             package_info->image_info->filename,exception);
13691           if (image != (Image *) NULL)
13692             DisassociateImageStream(image);
13693         }
13694       if (image == (Image *) NULL)
13695         break;
13696       for ( ; image; image=image->next)
13697       {
13698         AddImageToRegistry(sv,image);
13699         rv=newRV(sv);
13700         av_push(av,sv_bless(rv,hv));
13701         SvREFCNT_dec(sv);
13702         number_images++;
13703       }
13704     }
13705     /*
13706       Free resources.
13707     */
13708     for (i=0; i < n; i++)
13709       if (list[i] != (char *) NULL)
13710         for (p=keep; list[i] != *p++; )
13711           if (*p == (char *) NULL)
13712             {
13713               list[i]=(char *) RelinquishMagickMemory(list[i]);
13714               break;
13715             }
13716
13717   PerlException:
13718     if (package_info != (struct PackageInfo *) NULL)
13719       DestroyPackageInfo(package_info);
13720     if (list && (list != keep))
13721       list=(char **) RelinquishMagickMemory(list);
13722     if (keep)
13723       keep=(char **) RelinquishMagickMemory(keep);
13724     if (length)
13725       length=(STRLEN *) RelinquishMagickMemory(length);
13726     InheritPerlException(exception,perl_exception);
13727     exception=DestroyExceptionInfo(exception);
13728     sv_setiv(perl_exception,(IV) number_images);
13729     SvPOK_on(perl_exception);
13730     ST(0)=sv_2mortal(perl_exception);
13731     XSRETURN(1);
13732   }
13733 \f
13734 #
13735 ###############################################################################
13736 #                                                                             #
13737 #                                                                             #
13738 #                                                                             #
13739 #   R e m o t e                                                               #
13740 #                                                                             #
13741 #                                                                             #
13742 #                                                                             #
13743 ###############################################################################
13744 #
13745 #
13746 void
13747 Remote(ref,...)
13748   Image::Magick ref=NO_INIT
13749   ALIAS:
13750     RemoteCommand  = 1
13751     remote         = 2
13752     remoteCommand  = 3
13753   PPCODE:
13754   {
13755     AV
13756       *av;
13757
13758     ExceptionInfo
13759       *exception;
13760
13761     register ssize_t
13762       i;
13763
13764     SV
13765       *perl_exception,
13766       *reference;
13767
13768     struct PackageInfo
13769       *info;
13770
13771     PERL_UNUSED_VAR(ref);
13772     PERL_UNUSED_VAR(ix);
13773     exception=AcquireExceptionInfo();
13774     perl_exception=newSVpv("",0);
13775     reference=SvRV(ST(0));
13776     av=(AV *) reference;
13777     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13778       exception);
13779     for (i=1; i < items; i++)
13780       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13781         SvPV(ST(i),na),exception);
13782     InheritPerlException(exception,perl_exception);
13783     exception=DestroyExceptionInfo(exception);
13784     SvREFCNT_dec(perl_exception);    /* throw away all errors */
13785   }
13786 \f
13787 #
13788 ###############################################################################
13789 #                                                                             #
13790 #                                                                             #
13791 #                                                                             #
13792 #   S e t                                                                     #
13793 #                                                                             #
13794 #                                                                             #
13795 #                                                                             #
13796 ###############################################################################
13797 #
13798 #
13799 void
13800 Set(ref,...)
13801   Image::Magick ref=NO_INIT
13802   ALIAS:
13803     SetAttributes  = 1
13804     SetAttribute   = 2
13805     set            = 3
13806     setattributes  = 4
13807     setattribute   = 5
13808   PPCODE:
13809   {
13810     ExceptionInfo
13811       *exception;
13812
13813     Image
13814       *image;
13815
13816     register ssize_t
13817       i;
13818
13819     struct PackageInfo
13820       *info;
13821
13822     SV
13823       *perl_exception,
13824       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13825
13826     PERL_UNUSED_VAR(ref);
13827     PERL_UNUSED_VAR(ix);
13828     exception=AcquireExceptionInfo();
13829     perl_exception=newSVpv("",0);
13830     if (sv_isobject(ST(0)) == 0)
13831       {
13832         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13833           PackageName);
13834         goto PerlException;
13835       }
13836     reference=SvRV(ST(0));
13837     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13838     if (items == 2)
13839       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13840     else
13841       for (i=2; i < items; i+=2)
13842         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13843
13844   PerlException:
13845     InheritPerlException(exception,perl_exception);
13846     exception=DestroyExceptionInfo(exception);
13847     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13848     SvPOK_on(perl_exception);
13849     ST(0)=sv_2mortal(perl_exception);
13850     XSRETURN(1);
13851   }
13852 \f
13853 #
13854 ###############################################################################
13855 #                                                                             #
13856 #                                                                             #
13857 #                                                                             #
13858 #   S e t P i x e l                                                           #
13859 #                                                                             #
13860 #                                                                             #
13861 #                                                                             #
13862 ###############################################################################
13863 #
13864 #
13865 void
13866 SetPixel(ref,...)
13867   Image::Magick ref=NO_INIT
13868   ALIAS:
13869     setpixel = 1
13870     setPixel = 2
13871   PPCODE:
13872   {
13873     AV
13874       *av;
13875
13876     char
13877       *attribute;
13878
13879     ChannelType
13880       channel,
13881       channel_mask;
13882
13883     ExceptionInfo
13884       *exception;
13885
13886     Image
13887       *image;
13888
13889     MagickBooleanType
13890       normalize;
13891
13892     RectangleInfo
13893       region;
13894
13895     register ssize_t
13896       i;
13897
13898     register Quantum
13899       *q;
13900
13901     ssize_t
13902       option;
13903
13904     struct PackageInfo
13905       *info;
13906
13907     SV
13908       *perl_exception,
13909       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13910
13911     PERL_UNUSED_VAR(ref);
13912     PERL_UNUSED_VAR(ix);
13913     exception=AcquireExceptionInfo();
13914     perl_exception=newSVpv("",0);
13915     reference=SvRV(ST(0));
13916     av=(AV *) reference;
13917     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13918       exception);
13919     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13920     if (image == (Image *) NULL)
13921       {
13922         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13923           PackageName);
13924         goto PerlException;
13925       }
13926     av=(AV *) NULL;
13927     normalize=MagickTrue;
13928     region.x=0;
13929     region.y=0;
13930     region.width=image->columns;
13931     region.height=1;
13932     if (items == 1)
13933       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13934     channel=DefaultChannels;
13935     for (i=2; i < items; i+=2)
13936     {
13937       attribute=(char *) SvPV(ST(i-1),na);
13938       switch (*attribute)
13939       {
13940         case 'C':
13941         case 'c':
13942         {
13943           if (LocaleCompare(attribute,"channel") == 0)
13944             {
13945               ssize_t
13946                 option;
13947
13948               option=ParseChannelOption(SvPV(ST(i),na));
13949               if (option < 0)
13950                 {
13951                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13952                     SvPV(ST(i),na));
13953                   return;
13954                 }
13955               channel=(ChannelType) option;
13956               break;
13957             }
13958           if (LocaleCompare(attribute,"color") == 0)
13959             {
13960               if (SvTYPE(ST(i)) != SVt_RV)
13961                 {
13962                   char
13963                     message[MagickPathExtent];
13964
13965                   (void) FormatLocaleString(message,MagickPathExtent,
13966                     "invalid %.60s value",attribute);
13967                   ThrowPerlException(exception,OptionError,message,
13968                     SvPV(ST(i),na));
13969                 }
13970               av=(AV *) SvRV(ST(i));
13971               break;
13972             }
13973           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13974             attribute);
13975           break;
13976         }
13977         case 'g':
13978         case 'G':
13979         {
13980           if (LocaleCompare(attribute,"geometry") == 0)
13981             {
13982               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
13983               break;
13984             }
13985           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13986             attribute);
13987           break;
13988         }
13989         case 'N':
13990         case 'n':
13991         {
13992           if (LocaleCompare(attribute,"normalize") == 0)
13993             {
13994               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13995                 SvPV(ST(i),na));
13996               if (option < 0)
13997                 {
13998                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13999                     SvPV(ST(i),na));
14000                   break;
14001                 }
14002              normalize=option != 0 ? MagickTrue : MagickFalse;
14003              break;
14004             }
14005           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14006             attribute);
14007           break;
14008         }
14009         case 'x':
14010         case 'X':
14011         {
14012           if (LocaleCompare(attribute,"x") == 0)
14013             {
14014               region.x=SvIV(ST(i));
14015               break;
14016             }
14017           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14018             attribute);
14019           break;
14020         }
14021         case 'y':
14022         case 'Y':
14023         {
14024           if (LocaleCompare(attribute,"y") == 0)
14025             {
14026               region.y=SvIV(ST(i));
14027               break;
14028             }
14029           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14030             attribute);
14031           break;
14032         }
14033         default:
14034         {
14035           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14036             attribute);
14037           break;
14038         }
14039       }
14040     }
14041     (void) SetImageStorageClass(image,DirectClass,exception);
14042     channel_mask=SetImageChannelMask(image,channel);
14043     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
14044     if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
14045         (SvTYPE(av) != SVt_PVAV))
14046       PUSHs(&sv_undef);
14047     else
14048       {
14049         double
14050           scale;
14051
14052         register ssize_t
14053           i;
14054
14055         i=0;
14056         scale=1.0;
14057         if (normalize != MagickFalse)
14058           scale=QuantumRange;
14059         if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
14060             (i <= av_len(av)))
14061           {
14062             SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
14063               av_fetch(av,i,0)))),q);
14064             i++;
14065           }
14066         if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
14067             (i <= av_len(av)))
14068           {
14069             SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
14070               av_fetch(av,i,0)))),q);
14071             i++;
14072           }
14073         if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
14074             (i <= av_len(av)))
14075           {
14076             SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
14077               av_fetch(av,i,0)))),q);
14078             i++;
14079           }
14080         if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
14081             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
14082           {
14083             SetPixelBlack(image,ClampToQuantum(scale*
14084               SvNV(*(av_fetch(av,i,0)))),q);
14085             i++;
14086           }
14087         if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
14088             (i <= av_len(av)))
14089           {
14090             SetPixelAlpha(image,ClampToQuantum(scale*
14091               SvNV(*(av_fetch(av,i,0)))),q);
14092             i++;
14093           }
14094         (void) SyncAuthenticPixels(image,exception);
14095       }
14096     (void) SetImageChannelMask(image,channel_mask);
14097
14098   PerlException:
14099     InheritPerlException(exception,perl_exception);
14100     exception=DestroyExceptionInfo(exception);
14101     SvREFCNT_dec(perl_exception);
14102   }
14103 \f
14104 #
14105 ###############################################################################
14106 #                                                                             #
14107 #                                                                             #
14108 #                                                                             #
14109 #   S m u s h                                                                 #
14110 #                                                                             #
14111 #                                                                             #
14112 #                                                                             #
14113 ###############################################################################
14114 #
14115 #
14116 void
14117 Smush(ref,...)
14118   Image::Magick ref=NO_INIT
14119   ALIAS:
14120     SmushImage  = 1
14121     smush       = 2
14122     smushimage  = 3
14123   PPCODE:
14124   {
14125     AV
14126       *av;
14127
14128     char
14129       *attribute;
14130
14131     ExceptionInfo
14132       *exception;
14133
14134     HV
14135       *hv;
14136
14137     Image
14138       *image;
14139
14140     register ssize_t
14141       i;
14142
14143     ssize_t
14144       offset,
14145       stack;
14146
14147     struct PackageInfo
14148       *info;
14149
14150     SV
14151       *av_reference,
14152       *perl_exception,
14153       *reference,
14154       *rv,
14155       *sv;
14156
14157     PERL_UNUSED_VAR(ref);
14158     PERL_UNUSED_VAR(ix);
14159     exception=AcquireExceptionInfo();
14160     perl_exception=newSVpv("",0);
14161     sv=NULL;
14162     attribute=NULL;
14163     av=NULL;
14164     if (sv_isobject(ST(0)) == 0)
14165       {
14166         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14167           PackageName);
14168         goto PerlException;
14169       }
14170     reference=SvRV(ST(0));
14171     hv=SvSTASH(reference);
14172     av=newAV();
14173     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14174     SvREFCNT_dec(av);
14175     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14176     if (image == (Image *) NULL)
14177       {
14178         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14179           PackageName);
14180         goto PerlException;
14181       }
14182     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14183     /*
14184       Get options.
14185     */
14186     offset=0;
14187     stack=MagickTrue;
14188     for (i=2; i < items; i+=2)
14189     {
14190       attribute=(char *) SvPV(ST(i-1),na);
14191       switch (*attribute)
14192       {
14193         case 'O':
14194         case 'o':
14195         {
14196           if (LocaleCompare(attribute,"offset") == 0)
14197             {
14198               offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
14199               break;
14200             }
14201           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14202             attribute);
14203           break;
14204         }
14205         case 'S':
14206         case 's':
14207         {
14208           if (LocaleCompare(attribute,"stack") == 0)
14209             {
14210               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14211                 SvPV(ST(i),na));
14212               if (stack < 0)
14213                 {
14214                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
14215                     SvPV(ST(i),na));
14216                   return;
14217                 }
14218               break;
14219             }
14220           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14221             attribute);
14222           break;
14223         }
14224         default:
14225         {
14226           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14227             attribute);
14228           break;
14229         }
14230       }
14231     }
14232     image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
14233       exception);
14234     if (image == (Image *) NULL)
14235       goto PerlException;
14236     for ( ; image; image=image->next)
14237     {
14238       AddImageToRegistry(sv,image);
14239       rv=newRV(sv);
14240       av_push(av,sv_bless(rv,hv));
14241       SvREFCNT_dec(sv);
14242     }
14243     exception=DestroyExceptionInfo(exception);
14244     ST(0)=av_reference;
14245     SvREFCNT_dec(perl_exception);
14246     XSRETURN(1);
14247
14248   PerlException:
14249     InheritPerlException(exception,perl_exception);
14250     exception=DestroyExceptionInfo(exception);
14251     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14252     SvPOK_on(perl_exception);
14253     ST(0)=sv_2mortal(perl_exception);
14254     XSRETURN(1);
14255   }
14256 \f
14257 #
14258 ###############################################################################
14259 #                                                                             #
14260 #                                                                             #
14261 #                                                                             #
14262 #   S t a t i s t i c s                                                       #
14263 #                                                                             #
14264 #                                                                             #
14265 #                                                                             #
14266 ###############################################################################
14267 #
14268 #
14269 void
14270 Statistics(ref,...)
14271   Image::Magick ref=NO_INIT
14272   ALIAS:
14273     StatisticsImage = 1
14274     statistics      = 2
14275     statisticsimage = 3
14276   PPCODE:
14277   {
14278 #define ChannelStatistics(channel) \
14279 { \
14280   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14281     (double) channel_statistics[channel].depth); \
14282   PUSHs(sv_2mortal(newSVpv(message,0))); \
14283   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14284     channel_statistics[channel].minima/scale); \
14285   PUSHs(sv_2mortal(newSVpv(message,0))); \
14286   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14287     channel_statistics[channel].maxima/scale); \
14288   PUSHs(sv_2mortal(newSVpv(message,0))); \
14289   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14290     channel_statistics[channel].mean/scale); \
14291   PUSHs(sv_2mortal(newSVpv(message,0))); \
14292   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14293     channel_statistics[channel].standard_deviation/scale); \
14294   PUSHs(sv_2mortal(newSVpv(message,0))); \
14295   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14296     channel_statistics[channel].kurtosis); \
14297   PUSHs(sv_2mortal(newSVpv(message,0))); \
14298   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14299     channel_statistics[channel].skewness); \
14300   PUSHs(sv_2mortal(newSVpv(message,0))); \
14301   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14302     channel_statistics[channel].entropy); \
14303   PUSHs(sv_2mortal(newSVpv(message,0))); \
14304 }
14305
14306     AV
14307       *av;
14308
14309     char
14310       message[MagickPathExtent];
14311
14312     ChannelStatistics
14313       *channel_statistics;
14314
14315     double
14316       scale;
14317
14318     ExceptionInfo
14319       *exception;
14320
14321     Image
14322       *image;
14323
14324     ssize_t
14325       count;
14326
14327     struct PackageInfo
14328       *info;
14329
14330     SV
14331       *perl_exception,
14332       *reference;
14333
14334     PERL_UNUSED_VAR(ref);
14335     PERL_UNUSED_VAR(ix);
14336     exception=AcquireExceptionInfo();
14337     perl_exception=newSVpv("",0);
14338     av=NULL;
14339     if (sv_isobject(ST(0)) == 0)
14340       {
14341         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14342           PackageName);
14343         goto PerlException;
14344       }
14345     reference=SvRV(ST(0));
14346     av=newAV();
14347     SvREFCNT_dec(av);
14348     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14349     if (image == (Image *) NULL)
14350       {
14351         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14352           PackageName);
14353         goto PerlException;
14354       }
14355     count=0;
14356     for ( ; image; image=image->next)
14357     {
14358       channel_statistics=GetImageStatistics(image,exception);
14359       if (channel_statistics == (ChannelStatistics *) NULL)
14360         continue;
14361       count++;
14362       EXTEND(sp,35*count);
14363       scale=(double) QuantumRange;
14364       ChannelStatistics(RedChannel);
14365       ChannelStatistics(GreenChannel);
14366       ChannelStatistics(BlueChannel);
14367       if (image->colorspace == CMYKColorspace)
14368         ChannelStatistics(BlackChannel);
14369       if (image->alpha_trait != UndefinedPixelTrait)
14370         ChannelStatistics(AlphaChannel);
14371       channel_statistics=(ChannelStatistics *)
14372         RelinquishMagickMemory(channel_statistics);
14373     }
14374
14375   PerlException:
14376     InheritPerlException(exception,perl_exception);
14377     exception=DestroyExceptionInfo(exception);
14378     SvREFCNT_dec(perl_exception);
14379   }
14380 \f
14381 #
14382 ###############################################################################
14383 #                                                                             #
14384 #                                                                             #
14385 #                                                                             #
14386 #   S y n c A u t h e n t i c P i x e l s                                     #
14387 #                                                                             #
14388 #                                                                             #
14389 #                                                                             #
14390 ###############################################################################
14391 #
14392 #
14393 void
14394 SyncAuthenticPixels(ref,...)
14395   Image::Magick ref = NO_INIT
14396   ALIAS:
14397     Syncauthenticpixels = 1
14398     SyncImagePixels = 2
14399     syncimagepixels = 3
14400   CODE:
14401   {
14402     ExceptionInfo
14403       *exception;
14404
14405     Image
14406       *image;
14407
14408     MagickBooleanType
14409       status;
14410
14411     struct PackageInfo
14412       *info;
14413
14414     SV
14415       *perl_exception,
14416       *reference;
14417
14418     PERL_UNUSED_VAR(ref);
14419     PERL_UNUSED_VAR(ix);
14420     exception=AcquireExceptionInfo();
14421     perl_exception=newSVpv("",0);
14422     if (sv_isobject(ST(0)) == 0)
14423       {
14424         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14425           PackageName);
14426         goto PerlException;
14427       }
14428
14429     reference=SvRV(ST(0));
14430     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14431     if (image == (Image *) NULL)
14432       {
14433         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14434           PackageName);
14435         goto PerlException;
14436       }
14437
14438     status=SyncAuthenticPixels(image,exception);
14439     if (status != MagickFalse)
14440       return;
14441
14442   PerlException:
14443     InheritPerlException(exception,perl_exception);
14444     exception=DestroyExceptionInfo(exception);
14445     SvREFCNT_dec(perl_exception);  /* throw away all errors */
14446   }
14447 \f
14448 #
14449 ###############################################################################
14450 #                                                                             #
14451 #                                                                             #
14452 #                                                                             #
14453 #   T r a n s f o r m                                                         #
14454 #                                                                             #
14455 #                                                                             #
14456 #                                                                             #
14457 ###############################################################################
14458 #
14459 #
14460 void
14461 Transform(ref,...)
14462   Image::Magick ref=NO_INIT
14463   ALIAS:
14464     TransformImage = 1
14465     transform      = 2
14466     transformimage = 3
14467   PPCODE:
14468   {
14469     AV
14470       *av;
14471
14472     char
14473       *attribute,
14474       *crop_geometry,
14475       *geometry;
14476
14477     ExceptionInfo
14478       *exception;
14479
14480     HV
14481       *hv;
14482
14483     Image
14484       *clone,
14485       *image;
14486
14487     register ssize_t
14488       i;
14489
14490     struct PackageInfo
14491       *info;
14492
14493     SV
14494       *av_reference,
14495       *perl_exception,
14496       *reference,
14497       *rv,
14498       *sv;
14499
14500     PERL_UNUSED_VAR(ref);
14501     PERL_UNUSED_VAR(ix);
14502     exception=AcquireExceptionInfo();
14503     perl_exception=newSVpv("",0);
14504     sv=NULL;
14505     av=NULL;
14506     attribute=NULL;
14507     if (sv_isobject(ST(0)) == 0)
14508       {
14509         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14510           PackageName);
14511         goto PerlException;
14512       }
14513     reference=SvRV(ST(0));
14514     hv=SvSTASH(reference);
14515     av=newAV();
14516     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14517     SvREFCNT_dec(av);
14518     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14519     if (image == (Image *) NULL)
14520       {
14521         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14522           PackageName);
14523         goto PerlException;
14524       }
14525     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14526     /*
14527       Get attribute.
14528     */
14529     crop_geometry=(char *) NULL;
14530     geometry=(char *) NULL;
14531     for (i=2; i < items; i+=2)
14532     {
14533       attribute=(char *) SvPV(ST(i-1),na);
14534       switch (*attribute)
14535       {
14536         case 'c':
14537         case 'C':
14538         {
14539           if (LocaleCompare(attribute,"crop") == 0)
14540             {
14541               crop_geometry=SvPV(ST(i),na);
14542               break;
14543             }
14544           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14545             attribute);
14546           break;
14547         }
14548         case 'g':
14549         case 'G':
14550         {
14551           if (LocaleCompare(attribute,"geometry") == 0)
14552             {
14553               geometry=SvPV(ST(i),na);
14554               break;
14555             }
14556           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14557             attribute);
14558           break;
14559         }
14560         default:
14561         {
14562           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14563             attribute);
14564           break;
14565         }
14566       }
14567     }
14568     for ( ; image; image=image->next)
14569     {
14570       clone=CloneImage(image,0,0,MagickTrue,exception);
14571       if (clone == (Image *) NULL)
14572         goto PerlException;
14573       TransformImage(&clone,crop_geometry,geometry,exception);
14574       for ( ; clone; clone=clone->next)
14575       {
14576         AddImageToRegistry(sv,clone);
14577         rv=newRV(sv);
14578         av_push(av,sv_bless(rv,hv));
14579         SvREFCNT_dec(sv);
14580       }
14581     }
14582     exception=DestroyExceptionInfo(exception);
14583     ST(0)=av_reference;
14584     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
14585     XSRETURN(1);
14586
14587   PerlException:
14588     InheritPerlException(exception,perl_exception);
14589     exception=DestroyExceptionInfo(exception);
14590     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14591     SvPOK_on(perl_exception);
14592     ST(0)=sv_2mortal(perl_exception);
14593     XSRETURN(1);
14594   }
14595 \f
14596 #
14597 ###############################################################################
14598 #                                                                             #
14599 #                                                                             #
14600 #                                                                             #
14601 #   W r i t e                                                                 #
14602 #                                                                             #
14603 #                                                                             #
14604 #                                                                             #
14605 ###############################################################################
14606 #
14607 #
14608 void
14609 Write(ref,...)
14610   Image::Magick ref=NO_INIT
14611   ALIAS:
14612     WriteImage    = 1
14613     write         = 2
14614     writeimage    = 3
14615   PPCODE:
14616   {
14617     char
14618       filename[MagickPathExtent];
14619
14620     ExceptionInfo
14621       *exception;
14622
14623     Image
14624       *image,
14625       *next;
14626
14627     register ssize_t
14628       i;
14629
14630     ssize_t
14631       number_images,
14632       scene;
14633
14634     struct PackageInfo
14635       *info,
14636       *package_info;
14637
14638     SV
14639       *perl_exception,
14640       *reference;
14641
14642     PERL_UNUSED_VAR(ref);
14643     PERL_UNUSED_VAR(ix);
14644     exception=AcquireExceptionInfo();
14645     perl_exception=newSVpv("",0);
14646     number_images=0;
14647     package_info=(struct PackageInfo *) NULL;
14648     if (sv_isobject(ST(0)) == 0)
14649       {
14650         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14651           PackageName);
14652         goto PerlException;
14653       }
14654     reference=SvRV(ST(0));
14655     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14656     if (image == (Image *) NULL)
14657       {
14658         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14659           PackageName);
14660         goto PerlException;
14661       }
14662     package_info=ClonePackageInfo(info,exception);
14663     if (items == 2)
14664       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14665     else
14666       if (items > 2)
14667         for (i=2; i < items; i+=2)
14668           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14669             exception);
14670     (void) CopyMagickString(filename,package_info->image_info->filename,
14671       MagickPathExtent);
14672     scene=0;
14673     for (next=image; next; next=next->next)
14674     {
14675       (void) CopyMagickString(next->filename,filename,MagickPathExtent);
14676       next->scene=scene++;
14677     }
14678     *package_info->image_info->magick='\0';
14679     SetImageInfo(package_info->image_info,(unsigned int)
14680       GetImageListLength(image),exception);
14681     for (next=image; next; next=next->next)
14682     {
14683       (void) WriteImage(package_info->image_info,next,exception);
14684       number_images++;
14685       if (package_info->image_info->adjoin)
14686         break;
14687     }
14688
14689   PerlException:
14690     if (package_info != (struct PackageInfo *) NULL)
14691       DestroyPackageInfo(package_info);
14692     InheritPerlException(exception,perl_exception);
14693     exception=DestroyExceptionInfo(exception);
14694     sv_setiv(perl_exception,(IV) number_images);
14695     SvPOK_on(perl_exception);
14696     ST(0)=sv_2mortal(perl_exception);
14697     XSRETURN(1);
14698   }