]> granicus.if.org Git - imagemagick/blob - PerlMagick/Magick.xs
(no commit message)
[imagemagick] / PerlMagick / Magick.xs
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                         PPPP   EEEEE  RRRR   L                              %
6 %                         P   P  E      R   R  L                              %
7 %                         PPPP   EEE    RRRR   L                              %
8 %                         P      E      R  R   L                              %
9 %                         P      EEEEE  R   R  LLLLL                          %
10 %                                                                             %
11 %                  M   M   AAA    GGGG  IIIII   CCCC  K   K                   %
12 %                  MM MM  A   A  G        I    C      K  K                    %
13 %                  M M M  AAAAA  G GGG    I    C      KKK                     %
14 %                  M   M  A   A  G   G    I    C      K  K                    %
15 %                  M   M  A   A   GGGG  IIIII   CCCC  K   K                   %
16 %                                                                             %
17 %                                                                             %
18 %                Object-oriented Perl interface to ImageMagick                %
19 %                                                                             %
20 %                            Software Design                                  %
21 %                              Kyle Shorter                                   %
22 %                              John Cristy                                    %
23 %                             February 1997                                   %
24 %                                                                             %
25 %                                                                             %
26 %  Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization      %
27 %  dedicated to making software imaging solutions freely available.           %
28 %                                                                             %
29 %  You may not use this file except in compliance with the License.  You may  %
30 %  obtain a copy of the License at                                            %
31 %                                                                             %
32 %    http://www.imagemagick.org/script/license.php                            %
33 %                                                                             %
34 %  Unless required by applicable law or agreed to in writing, software        %
35 %  distributed under the License is distributed on an "AS IS" BASIS,          %
36 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
37 %  See the License for the specific language governing permissions and        %
38 %  limitations under the License.                                             %
39 %                                                                             %
40 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
41 %
42 %  PerlMagick is an objected-oriented Perl interface to ImageMagick.  Use
43 %  the module to read, manipulate, or write an image or image sequence from
44 %  within a Perl script.  This makes PerlMagick suitable for Web CGI scripts.
45 %
46 */
47 \f
48 /*
49   Include declarations.
50 */
51 #if defined(__cplusplus) || defined(c_plusplus)
52 extern "C" {
53 #endif
54
55 #define PERL_NO_GET_CONTEXT
56 #include "EXTERN.h"
57 #include "perl.h"
58 #include "XSUB.h"
59 #include <math.h>
60 #include <MagickCore/MagickCore.h>
61 #undef tainted
62
63 #if defined(__cplusplus) || defined(c_plusplus)
64 }
65 #endif
66 \f
67 /*
68   Define declarations.
69 */
70 #ifndef aTHX_
71 #define aTHX_
72 #define pTHX_
73 #define dTHX
74 #endif
75 #define DegreesToRadians(x)  (MagickPI*(x)/180.0)
76 #define EndOf(array)  (&array[NumberOf(array)])
77 #define MaxArguments  33
78 #ifndef na
79 #define na  PL_na
80 #endif
81 #define NumberOf(array)  (sizeof(array)/sizeof(*array))
82 #define PackageName   "Image::Magick"
83 #if PERL_VERSION <= 6
84 #define PerlIO  FILE
85 #define PerlIO_importFILE(f, fl)  (f)
86 #define PerlIO_findFILE(f)  NULL
87 #endif
88 #ifndef sv_undef
89 #define sv_undef  PL_sv_undef
90 #endif
91
92 #define AddImageToRegistry(sv,image) \
93 { \
94   if (magick_registry != (SplayTreeInfo *) NULL) \
95     { \
96       (void) AddValueToSplayTree(magick_registry,image,image); \
97       (sv)=newSViv(PTR2IV(image)); \
98     } \
99 }
100
101 #define DeleteImageFromRegistry(reference,image) \
102 { \
103   if (magick_registry != (SplayTreeInfo *) NULL) \
104     { \
105       if (GetImageReferenceCount(image) == 1) \
106        (void) DeleteNodeByValueFromSplayTree(magick_registry,image); \
107       image=DestroyImage(image); \
108       sv_setiv(reference,0); \
109     } \
110 }
111
112 #define InheritPerlException(exception,perl_exception) \
113 { \
114   char \
115     message[MaxTextExtent]; \
116  \
117   if ((exception)->severity != UndefinedException) \
118     { \
119       (void) FormatLocaleString(message,MaxTextExtent,"Exception %d: %s%s%s%s",\
120         (exception)->severity, (exception)->reason ? \
121         GetLocaleExceptionMessage((exception)->severity,(exception)->reason) : \
122         "Unknown", (exception)->description ? " (" : "", \
123         (exception)->description ? GetLocaleExceptionMessage( \
124         (exception)->severity,(exception)->description) : "", \
125         (exception)->description ? ")" : ""); \
126       if ((perl_exception) != (SV *) NULL) \
127         { \
128           if (SvCUR(perl_exception)) \
129             sv_catpv(perl_exception,"\n"); \
130           sv_catpv(perl_exception,message); \
131         } \
132     } \
133 }
134
135 #define ThrowPerlException(exception,severity,tag,reason) \
136   (void) ThrowMagickException(exception,GetMagickModule(),severity, \
137     tag,"`%s'",reason); \
138 \f
139 /*
140   Typedef and structure declarations.
141 */
142 typedef enum
143 {
144   ArrayReference = (~0),
145   RealReference = (~0)-1,
146   FileReference = (~0)-2,
147   ImageReference = (~0)-3,
148   IntegerReference = (~0)-4,
149   StringReference = (~0)-5
150 } MagickReference;
151
152 typedef struct _Arguments
153 {
154   const char
155     *method;
156
157   ssize_t
158     type;
159 } Arguments;
160
161 struct ArgumentList
162 {
163   ssize_t
164     integer_reference;
165
166   double
167     real_reference;
168
169   const char
170     *string_reference;
171
172   Image
173     *image_reference;
174
175   SV
176     *array_reference;
177
178   FILE
179     *file_reference;
180
181   size_t
182     length;
183 };
184
185 struct PackageInfo
186 {
187   ImageInfo
188     *image_info;
189 };
190
191 typedef void
192   *Image__Magick;  /* data type for the Image::Magick package */
193 \f
194 /*
195   Static declarations.
196 */
197 static struct
198   Methods
199   {
200     const char
201       *name;
202
203     Arguments
204       arguments[MaxArguments];
205   } Methods[] =
206   {
207     { "Comment", { {"comment", StringReference} } },
208     { "Label", { {"label", StringReference} } },
209     { "AddNoise", { {"noise", MagickNoiseOptions}, {"attenuate", RealReference},
210       {"channel", MagickChannelOptions} } },
211     { "Colorize", { {"fill", StringReference}, {"blend", StringReference} } },
212     { "Border", { {"geometry", StringReference}, {"width", IntegerReference},
213       {"height", IntegerReference}, {"fill", StringReference},
214       {"bordercolor", StringReference}, {"color", StringReference},
215       {"compose", MagickComposeOptions} } },
216     { "Blur", { {"geometry", StringReference}, {"radius", RealReference},
217       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
218     { "Chop", { {"geometry", StringReference}, {"width", IntegerReference},
219       {"height", IntegerReference}, {"x", IntegerReference},
220       {"y", IntegerReference} } },
221     { "Crop", { {"geometry", StringReference}, {"width", IntegerReference},
222       {"height", IntegerReference}, {"x", IntegerReference},
223       {"y", IntegerReference}, {"fuzz", StringReference},
224       {"gravity", MagickGravityOptions} } },
225     { "Despeckle", },
226     { "Edge", { {"radius", RealReference} } },
227     { "Emboss", { {"geometry", StringReference}, {"radius", RealReference},
228       {"sigma", RealReference} } },
229     { "Enhance", },
230     { "Flip", },
231     { "Flop", },
232     { "Frame", { {"geometry", StringReference}, {"width", IntegerReference},
233       {"height", IntegerReference}, {"inner", IntegerReference},
234       {"outer", IntegerReference}, {"fill", StringReference},
235       {"color", StringReference}, {"compose", MagickComposeOptions} } },
236     { "Implode", { {"amount", RealReference},
237       {"interpolate", MagickInterpolateOptions} } },
238     { "Magnify", },
239     { "MedianFilter", { {"geometry", StringReference},
240       {"width", IntegerReference}, {"height", IntegerReference},
241       {"channel", MagickChannelOptions} } },
242     { "Minify", },
243     { "OilPaint", { {"radius", RealReference}, {"sigma", RealReference} } },
244     { "ReduceNoise", { {"geometry", StringReference},
245       {"width", IntegerReference},{"height", IntegerReference},
246       {"channel", MagickChannelOptions} } },
247     { "Roll", { {"geometry", StringReference}, {"x", IntegerReference},
248       {"y", IntegerReference} } },
249     { "Rotate", { {"degrees", RealReference}, 
250       {"background", StringReference} } },
251     { "Sample", { {"geometry", StringReference}, {"width", IntegerReference},
252       {"height", IntegerReference} } },
253     { "Scale", { {"geometry", StringReference}, {"width", IntegerReference},
254       {"height", IntegerReference} } },
255     { "Shade", { {"geometry", StringReference}, {"azimuth", RealReference},
256       {"elevation", RealReference}, {"gray", MagickBooleanOptions} } },
257     { "Sharpen", { {"geometry", StringReference}, {"radius", RealReference},
258       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
259     { "Shear", { {"geometry", StringReference}, {"x", RealReference},
260       {"y", RealReference}, { "fill", StringReference},
261       {"color", StringReference} } },
262     { "Spread", { {"radius", RealReference},
263       {"interpolate", MagickInterpolateOptions} } },
264     { "Swirl", { {"degrees", RealReference},
265       {"interpolate", MagickInterpolateOptions} } },
266     { "Resize", { {"geometry", StringReference}, {"width", IntegerReference},
267       {"height", IntegerReference}, {"filter", MagickFilterOptions},
268       {"support", StringReference } } },
269     { "Zoom", { {"geometry", StringReference}, {"width", IntegerReference},
270       {"height", IntegerReference}, {"filter", MagickFilterOptions},
271       {"support", RealReference } } },
272     { "Annotate", { {"text", StringReference}, {"font", StringReference},
273       {"pointsize", RealReference}, {"density", StringReference},
274       {"undercolor", StringReference}, {"stroke", StringReference},
275       {"fill", StringReference}, {"geometry", StringReference},
276       {"sans", StringReference}, {"x", RealReference},
277       {"y", RealReference}, {"gravity", MagickGravityOptions},
278       {"translate", StringReference}, {"scale", StringReference},
279       {"rotate", RealReference}, {"skewX", RealReference},
280       {"skewY", RealReference}, {"strokewidth", RealReference},
281       {"antialias", MagickBooleanOptions}, {"family", StringReference},
282       {"style", MagickStyleOptions}, {"stretch", MagickStretchOptions},
283       {"weight", IntegerReference}, {"align", MagickAlignOptions},
284       {"encoding", StringReference}, {"affine", ArrayReference},
285       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
286       {"tile", ImageReference}, {"kerning", RealReference},
287       {"interline-spacing", RealReference},
288       {"interword-spacing", RealReference},
289       {"direction", MagickDirectionOptions} } },
290     { "ColorFloodfill", { {"geometry", StringReference},
291       {"x", IntegerReference}, {"y", IntegerReference},
292       {"fill", StringReference}, {"bordercolor", StringReference},
293       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
294     { "Composite", { {"image", ImageReference},
295       {"compose", MagickComposeOptions}, {"geometry", StringReference},
296       {"x", IntegerReference}, {"y", IntegerReference},
297       {"gravity", MagickGravityOptions}, {"opacity", StringReference},
298       {"tile", MagickBooleanOptions}, {"rotate", RealReference},
299       {"color", StringReference}, {"mask", ImageReference},
300       {"channel", MagickChannelOptions},
301       {"interpolate", MagickInterpolateOptions}, {"args", StringReference},
302       {"blend", StringReference}, {"crop-to-self", MagickBooleanOptions} } },
303     { "Contrast", { {"sharpen", MagickBooleanOptions} } },
304     { "CycleColormap", { {"display", IntegerReference} } },
305     { "Draw", { {"primitive", MagickPrimitiveOptions},
306       {"points", StringReference}, {"method", MagickMethodOptions},
307       {"stroke", StringReference}, {"fill", StringReference},
308       {"strokewidth", RealReference}, {"font", StringReference},
309       {"bordercolor", StringReference}, {"x", RealReference},
310       {"y", RealReference}, {"translate", StringReference},
311       {"scale", StringReference}, {"rotate", RealReference},
312       {"skewX", RealReference}, {"skewY", RealReference},
313       {"tile", ImageReference}, {"pointsize", RealReference},
314       {"antialias", MagickBooleanOptions}, {"density", StringReference},
315       {"linewidth", RealReference}, {"affine", ArrayReference},
316       {"stroke-dashoffset", RealReference},
317       {"stroke-dasharray", ArrayReference},
318       {"interpolate", MagickInterpolateOptions},
319       {"origin", StringReference}, {"text", StringReference},
320       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
321       {"vector-graphics", StringReference}, {"kerning", RealReference},
322       {"interline-spacing", RealReference},
323       {"interword-spacing", RealReference},
324       {"direction", MagickDirectionOptions} } },
325     { "Equalize", { {"channel", MagickChannelOptions} } },
326     { "Gamma", { {"gamma", StringReference}, {"channel", MagickChannelOptions},
327       {"red", RealReference}, {"green", RealReference},
328       {"blue", RealReference} } },
329     { "Map", { {"image", ImageReference},
330       {"dither-method", MagickDitherOptions} } },
331     { "MatteFloodfill", { {"geometry", StringReference},
332       {"x", IntegerReference}, {"y", IntegerReference},
333       {"opacity", StringReference}, {"bordercolor", StringReference},
334       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
335     { "Modulate", { {"factor", StringReference}, {"hue", RealReference},
336       {"saturation", RealReference}, {"whiteness", RealReference},
337       {"brightness", RealReference}, {"lightness", RealReference},
338       {"blackness", RealReference} } },
339     { "Negate", { {"gray", MagickBooleanOptions},
340       {"channel", MagickChannelOptions} } },
341     { "Normalize", { {"channel", MagickChannelOptions} } },
342     { "NumberColors", },
343     { "Opaque", { {"color", StringReference}, {"fill", StringReference},
344       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
345       {"invert", MagickBooleanOptions} } },
346     { "Quantize", { {"colors", IntegerReference},
347       {"treedepth", IntegerReference}, {"colorspace", MagickColorspaceOptions},
348       {"dither", MagickDitherOptions}, {"measure", MagickBooleanOptions},
349       {"global", MagickBooleanOptions}, {"transparent-color", StringReference},
350       {"dither-method", MagickDitherOptions} } },
351     { "Raise", { {"geometry", StringReference}, {"width", IntegerReference},
352       {"height", IntegerReference}, {"raise", MagickBooleanOptions} } },
353     { "Segment", { {"geometry", StringReference},
354       {"cluster-threshold", RealReference},
355       {"smoothing-threshold", RealReference},
356       {"colorspace", MagickColorspaceOptions},
357       {"verbose", MagickBooleanOptions} } },
358     { "Signature", },
359     { "Solarize", { {"geometry", StringReference},
360       {"threshold", StringReference} } },
361     { "Sync", },
362     { "Texture", { {"texture", ImageReference} } },
363     { "Evaluate", { {"value", RealReference},
364       {"operator", MagickEvaluateOptions},
365       {"channel", MagickChannelOptions} } },
366     { "Transparent", { {"color", StringReference}, {"opacity", StringReference},
367       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
368     { "Threshold", { {"threshold", StringReference},
369       {"channel", MagickChannelOptions} } },
370     { "Charcoal", { {"geometry", StringReference}, {"radius", RealReference},
371       {"sigma", RealReference} } },
372     { "Trim", { {"fuzz", StringReference} } },
373     { "Wave", { {"geometry", StringReference}, {"amplitude", RealReference},
374       {"wavelength", RealReference},
375       {"interpolate", MagickInterpolateOptions} } },
376     { "Separate", { {"channel", MagickChannelOptions} } },
377     { "Condense", },
378     { "Stereo", { {"image", ImageReference}, {"x", IntegerReference},
379       {"y", IntegerReference} } },
380     { "Stegano", { {"image", ImageReference}, {"offset", IntegerReference} } },
381     { "Deconstruct", },
382     { "GaussianBlur", { {"geometry", StringReference},
383       {"radius", RealReference}, {"sigma", RealReference},
384       {"channel", MagickChannelOptions} } },
385     { "Convolve", { {"coefficients", ArrayReference},
386       {"channel", MagickChannelOptions}, {"bias", StringReference},
387       {"kernel", StringReference} } },
388     { "Profile", { {"name", StringReference}, {"profile", StringReference},
389       { "rendering-intent", MagickIntentOptions},
390       { "black-point-compensation", MagickBooleanOptions} } },
391     { "UnsharpMask", { {"geometry", StringReference},
392       {"radius", RealReference}, {"sigma", RealReference},
393       {"amount", RealReference}, {"threshold", RealReference},
394       {"channel", MagickChannelOptions} } },
395     { "MotionBlur", { {"geometry", StringReference},
396       {"radius", RealReference}, {"sigma", RealReference},
397       {"angle", RealReference}, {"channel", MagickChannelOptions} } },
398     { "OrderedDither", { {"threshold", StringReference},
399       {"channel", MagickChannelOptions} } },
400     { "Shave", { {"geometry", StringReference}, {"width", IntegerReference},
401       {"height", IntegerReference} } },
402     { "Level", { {"levels", StringReference}, {"black-point", RealReference},
403       {"white-point", RealReference}, {"gamma", RealReference},
404       {"channel", MagickChannelOptions}, {"level", StringReference} } },
405     { "Clip", { {"id", StringReference}, {"inside", MagickBooleanOptions} } },
406     { "AffineTransform", { {"affine", ArrayReference},
407       {"translate", StringReference}, {"scale", StringReference},
408       {"rotate", RealReference}, {"skewX", RealReference},
409       {"skewY", RealReference}, {"interpolate", MagickInterpolateOptions},
410       {"background", StringReference} } },
411     { "Difference", { {"image", ImageReference}, {"fuzz", StringReference} } },
412     { "AdaptiveThreshold", { {"geometry", StringReference},
413       {"width", IntegerReference}, {"height", IntegerReference} } },
414     { "Resample", { {"density", StringReference}, {"x", RealReference},
415       {"y", RealReference}, {"filter", MagickFilterOptions},
416       {"support", RealReference } } },
417     { "Describe", { {"file", FileReference} } },
418     { "BlackThreshold", { {"threshold", StringReference},
419       {"channel", MagickChannelOptions} } },
420     { "WhiteThreshold", { {"threshold", StringReference},
421       {"channel", MagickChannelOptions} } },
422     { "RadialBlur", { {"geometry", StringReference}, {"angle", RealReference},
423       {"channel", MagickChannelOptions} } },
424     { "Thumbnail", { {"geometry", StringReference}, {"width", IntegerReference},
425       {"height", IntegerReference} } },
426     { "Strip", },
427     { "Tint", { {"fill", StringReference}, {"blend", StringReference} } },
428     { "Channel", { {"channel", MagickChannelOptions} } },
429     { "Splice", { {"geometry", StringReference}, {"width", IntegerReference},
430       {"height", IntegerReference}, {"x", IntegerReference},
431       {"y", IntegerReference}, {"fuzz", StringReference},
432       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
433     { "Posterize", { {"levels", IntegerReference},
434       {"dither", MagickBooleanOptions} } },
435     { "Shadow", { {"geometry", StringReference}, {"alpha", RealReference},
436       {"sigma", RealReference}, {"x", IntegerReference},
437       {"y", IntegerReference} } },
438     { "Identify", { {"file", FileReference}, {"features", StringReference},
439       {"unique", MagickBooleanOptions} } },
440     { "SepiaTone", { {"threshold", RealReference} } },
441     { "SigmoidalContrast", { {"geometry", StringReference},
442       {"contrast", RealReference}, {"mid-point", RealReference},
443       {"channel", MagickChannelOptions}, {"sharpen", MagickBooleanOptions} } },
444     { "Extent", { {"geometry", StringReference}, {"width", IntegerReference},
445       {"height", IntegerReference}, {"x", IntegerReference},
446       {"y", IntegerReference}, {"fuzz", StringReference},
447       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
448     { "Vignette", { {"geometry", StringReference}, {"radius", RealReference},
449       {"sigma", RealReference}, {"x", IntegerReference},
450       {"y", IntegerReference}, {"background", StringReference} } },
451     { "ContrastStretch", { {"levels", StringReference},
452       {"black-point", RealReference},{"white-point", RealReference},
453       {"channel", MagickChannelOptions} } },
454     { "Sans0", },
455     { "Sans1", },
456     { "AdaptiveSharpen", { {"geometry", StringReference},
457       {"radius", RealReference}, {"sigma", RealReference},
458       {"bias", RealReference}, {"channel", MagickChannelOptions} } },
459     { "Transpose", },
460     { "Transverse", },
461     { "AutoOrient", },
462     { "AdaptiveBlur", { {"geometry", StringReference},
463       {"radius", RealReference}, {"sigma", RealReference},
464       {"channel", MagickChannelOptions} } },
465     { "Sketch", { {"geometry", StringReference},
466       {"radius", RealReference}, {"sigma", RealReference},
467       {"angle", RealReference} } },
468     { "UniqueColors", },
469     { "AdaptiveResize", { {"geometry", StringReference},
470       {"width", IntegerReference}, {"height", IntegerReference},
471       {"filter", MagickFilterOptions}, {"support", StringReference },
472       {"blur", RealReference } } },
473     { "ClipMask", { {"mask", ImageReference} } },
474     { "LinearStretch", { {"levels", StringReference},
475       {"black-point", RealReference},{"white-point", RealReference} } },
476     { "ColorMatrix", { {"matrix", ArrayReference} } },
477     { "Mask", { {"mask", ImageReference} } },
478     { "Polaroid", { {"caption", StringReference}, {"angle", RealReference},
479       {"font", StringReference}, {"stroke", StringReference},
480       {"fill", StringReference}, {"strokewidth", RealReference},
481       {"pointsize", RealReference}, {"gravity", MagickGravityOptions},
482       {"background", StringReference},
483       {"interpolate", MagickInterpolateOptions} } },
484     { "FloodfillPaint", { {"geometry", StringReference},
485       {"x", IntegerReference}, {"y", IntegerReference},
486       {"fill", StringReference}, {"bordercolor", StringReference},
487       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
488       {"invert", MagickBooleanOptions} } },
489     { "Distort", { {"points", ArrayReference}, {"method", MagickDistortOptions},
490       {"virtual-pixel", MagickVirtualPixelOptions},
491       {"best-fit", MagickBooleanOptions} } },
492     { "Clut", { {"image", ImageReference},
493       {"interpolate", MagickInterpolateOptions},
494       {"channel", MagickChannelOptions} } },
495     { "LiquidRescale", { {"geometry", StringReference},
496       {"width", IntegerReference}, {"height", IntegerReference},
497       {"delta-x", RealReference}, {"rigidity", RealReference } } },
498     { "Encipher", { {"passphrase", StringReference} } },
499     { "Decipher", { {"passphrase", StringReference} } },
500     { "Deskew", { {"geometry", StringReference},
501       {"threshold", StringReference} } },
502     { "Remap", { {"image", ImageReference},
503       {"dither-method", MagickDitherOptions} } },
504     { "SparseColor", { {"points", ArrayReference},
505       {"method", MagickSparseColorOptions},
506       {"virtual-pixel", MagickVirtualPixelOptions},
507       {"channel", MagickChannelOptions} } },
508     { "Function", { {"parameters", ArrayReference},
509       {"function", MagickFunctionOptions},
510       {"virtual-pixel", MagickVirtualPixelOptions} } },
511     { "SelectiveBlur", { {"geometry", StringReference},
512       {"radius", RealReference}, {"sigma", RealReference},
513       {"threshold", RealReference}, {"channel", MagickChannelOptions} } },
514     { "HaldClut", { {"image", ImageReference},
515       {"channel", MagickChannelOptions} } },
516     { "BlueShift", { {"factor", StringReference} } },
517     { "ForwardFourierTransform", { {"magnitude", MagickBooleanOptions} } },
518     { "InverseFourierTransform", { {"magnitude", MagickBooleanOptions} } },
519     { "ColorDecisionList", {
520       {"color-correction-collection", StringReference} } },
521     { "AutoGamma", { {"channel", MagickChannelOptions} } },
522     { "AutoLevel", { {"channel", MagickChannelOptions} } },
523     { "LevelColors", { {"invert", MagickBooleanOptions},
524       {"black-point", StringReference}, {"white-point", StringReference},
525       {"channel", MagickChannelOptions}, {"invert", MagickBooleanOptions} } },
526     { "Clamp", { {"channel", MagickChannelOptions} } },
527     { "BrightnessContrast", { {"levels", StringReference},
528       {"brightness", RealReference},{"contrast", RealReference},
529       {"channel", MagickChannelOptions} } },
530     { "Morphology", { {"kernel", StringReference},
531       {"channel", MagickChannelOptions}, {"method", MagickMorphologyOptions},
532       {"iterations", IntegerReference} } },
533     { "Sans", { {"matrix", ArrayReference} } },
534     { "Color", { {"color", StringReference} } },
535     { "Mode", { {"geometry", StringReference},
536       {"width", IntegerReference},{"height", IntegerReference},
537       {"channel", MagickChannelOptions} } },
538     { "Statistic", { {"geometry", StringReference},
539       {"width", IntegerReference},{"height", IntegerReference},
540       {"channel", MagickChannelOptions}, {"type", MagickStatisticOptions} } }
541   };
542
543 static SplayTreeInfo
544   *magick_registry = (SplayTreeInfo *) NULL;
545 \f
546 /*
547   Forward declarations.
548 */
549 static Image
550   *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
551
552 static ssize_t
553   strEQcase(const char *,const char *);
554 \f
555 /*
556 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
557 %                                                                             %
558 %                                                                             %
559 %                                                                             %
560 %   C l o n e P a c k a g e I n f o                                           %
561 %                                                                             %
562 %                                                                             %
563 %                                                                             %
564 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
565 %
566 %  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
567 %  a new one.
568 %
569 %  The format of the ClonePackageInfo routine is:
570 %
571 %      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
572 %        exception)
573 %
574 %  A description of each parameter follows:
575 %
576 %    o info: a structure of type info.
577 %
578 %    o exception: Return any errors or warnings in this structure.
579 %
580 */
581 static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
582   ExceptionInfo *exception)
583 {
584   struct PackageInfo
585     *clone_info;
586
587   clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
588   if (clone_info == (struct PackageInfo *) NULL)
589     {
590       ThrowPerlException(exception,ResourceLimitError,
591         "UnableToClonePackageInfo",PackageName);
592       return((struct PackageInfo *) NULL);
593     }
594   if (info == (struct PackageInfo *) NULL)
595     {
596       clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
597       return(clone_info);
598     }
599   *clone_info=(*info);
600   clone_info->image_info=CloneImageInfo(info->image_info);
601   return(clone_info);
602 }
603 \f
604 /*
605 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
606 %                                                                             %
607 %                                                                             %
608 %                                                                             %
609 %   c o n s t a n t                                                           %
610 %                                                                             %
611 %                                                                             %
612 %                                                                             %
613 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
614 %
615 %  constant() returns a double value for the specified name.
616 %
617 %  The format of the constant routine is:
618 %
619 %      double constant(char *name,ssize_t sans)
620 %
621 %  A description of each parameter follows:
622 %
623 %    o value: Method constant returns a double value for the specified name.
624 %
625 %    o name: The name of the constant.
626 %
627 %    o sans: This integer value is not used.
628 %
629 */
630 static double constant(char *name,ssize_t sans)
631 {
632   (void) sans;
633   errno=0;
634   switch (*name)
635   {
636     case 'B':
637     {
638       if (strEQ(name,"BlobError"))
639         return(BlobError);
640       if (strEQ(name,"BlobWarning"))
641         return(BlobWarning);
642       break;
643     }
644     case 'C':
645     {
646       if (strEQ(name,"CacheError"))
647         return(CacheError);
648       if (strEQ(name,"CacheWarning"))
649         return(CacheWarning);
650       if (strEQ(name,"CoderError"))
651         return(CoderError);
652       if (strEQ(name,"CoderWarning"))
653         return(CoderWarning);
654       if (strEQ(name,"ConfigureError"))
655         return(ConfigureError);
656       if (strEQ(name,"ConfigureWarning"))
657         return(ConfigureWarning);
658       if (strEQ(name,"CorruptImageError"))
659         return(CorruptImageError);
660       if (strEQ(name,"CorruptImageWarning"))
661         return(CorruptImageWarning);
662       break;
663     }
664     case 'D':
665     {
666       if (strEQ(name,"DelegateError"))
667         return(DelegateError);
668       if (strEQ(name,"DelegateWarning"))
669         return(DelegateWarning);
670       if (strEQ(name,"DrawError"))
671         return(DrawError);
672       if (strEQ(name,"DrawWarning"))
673         return(DrawWarning);
674       break;
675     }
676     case 'E':
677     {
678       if (strEQ(name,"ErrorException"))
679         return(ErrorException);
680       if (strEQ(name,"ExceptionError"))
681         return(CoderError);
682       if (strEQ(name,"ExceptionWarning"))
683         return(CoderWarning);
684       break;
685     }
686     case 'F':
687     {
688       if (strEQ(name,"FatalErrorException"))
689         return(FatalErrorException);
690       if (strEQ(name,"FileOpenError"))
691         return(FileOpenError);
692       if (strEQ(name,"FileOpenWarning"))
693         return(FileOpenWarning);
694       break;
695     }
696     case 'I':
697     {
698       if (strEQ(name,"ImageError"))
699         return(ImageError);
700       if (strEQ(name,"ImageWarning"))
701         return(ImageWarning);
702       break;
703     }
704     case 'M':
705     {
706       if (strEQ(name,"MaxRGB"))
707         return(QuantumRange);
708       if (strEQ(name,"MissingDelegateError"))
709         return(MissingDelegateError);
710       if (strEQ(name,"MissingDelegateWarning"))
711         return(MissingDelegateWarning);
712       if (strEQ(name,"ModuleError"))
713         return(ModuleError);
714       if (strEQ(name,"ModuleWarning"))
715         return(ModuleWarning);
716       break;
717     }
718     case 'O':
719     {
720       if (strEQ(name,"Opaque"))
721         return(OpaqueAlpha);
722       if (strEQ(name,"OptionError"))
723         return(OptionError);
724       if (strEQ(name,"OptionWarning"))
725         return(OptionWarning);
726       break;
727     }
728     case 'Q':
729     {
730       if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
731         return(MAGICKCORE_QUANTUM_DEPTH);
732       if (strEQ(name,"QuantumDepth"))
733         return(MAGICKCORE_QUANTUM_DEPTH);
734       if (strEQ(name,"QuantumRange"))
735         return(QuantumRange);
736       break;
737     }
738     case 'R':
739     {
740       if (strEQ(name,"ResourceLimitError"))
741         return(ResourceLimitError);
742       if (strEQ(name,"ResourceLimitWarning"))
743         return(ResourceLimitWarning);
744       if (strEQ(name,"RegistryError"))
745         return(RegistryError);
746       if (strEQ(name,"RegistryWarning"))
747         return(RegistryWarning);
748       break;
749     }
750     case 'S':
751     {
752       if (strEQ(name,"StreamError"))
753         return(StreamError);
754       if (strEQ(name,"StreamWarning"))
755         return(StreamWarning);
756       if (strEQ(name,"Success"))
757         return(0);
758       break;
759     }
760     case 'T':
761     {
762       if (strEQ(name,"Transparent"))
763         return(TransparentAlpha);
764       if (strEQ(name,"TypeError"))
765         return(TypeError);
766       if (strEQ(name,"TypeWarning"))
767         return(TypeWarning);
768       break;
769     }
770     case 'W':
771     {
772       if (strEQ(name,"WarningException"))
773         return(WarningException);
774       break;
775     }
776     case 'X':
777     {
778       if (strEQ(name,"XServerError"))
779         return(XServerError);
780       if (strEQ(name,"XServerWarning"))
781         return(XServerWarning);
782       break;
783     }
784   }
785   errno=EINVAL;
786   return(0);
787 }
788 \f
789 /*
790 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
791 %                                                                             %
792 %                                                                             %
793 %                                                                             %
794 %   D e s t r o y P a c k a g e I n f o                                       %
795 %                                                                             %
796 %                                                                             %
797 %                                                                             %
798 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
799 %
800 %  Method DestroyPackageInfo frees a previously created info structure.
801 %
802 %  The format of the DestroyPackageInfo routine is:
803 %
804 %      DestroyPackageInfo(struct PackageInfo *info)
805 %
806 %  A description of each parameter follows:
807 %
808 %    o info: a structure of type info.
809 %
810 */
811 static void DestroyPackageInfo(struct PackageInfo *info)
812 {
813   info->image_info=DestroyImageInfo(info->image_info);
814   info=(struct PackageInfo *) RelinquishMagickMemory(info);
815 }
816 \f
817 /*
818 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
819 %                                                                             %
820 %                                                                             %
821 %                                                                             %
822 %   G e t L i s t                                                             %
823 %                                                                             %
824 %                                                                             %
825 %                                                                             %
826 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
827 %
828 %  Method GetList is recursively called by SetupList to traverse the
829 %  Image__Magick reference.  If building an reference_vector (see SetupList),
830 %  *current is the current position in *reference_vector and *last is the final
831 %  entry in *reference_vector.
832 %
833 %  The format of the GetList routine is:
834 %
835 %      GetList(info)
836 %
837 %  A description of each parameter follows:
838 %
839 %    o info: a structure of type info.
840 %
841 */
842 static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
843   ssize_t *current,ssize_t *last,ExceptionInfo *exception)
844 {
845   Image
846     *image;
847
848   if (reference == (SV *) NULL)
849     return(NULL);
850   switch (SvTYPE(reference))
851   {
852     case SVt_PVAV:
853     {
854       AV
855         *av;
856
857       Image
858         *head,
859         *previous;
860
861       register ssize_t
862         i;
863
864       ssize_t
865         n;
866
867       /*
868         Array of images.
869       */
870       previous=(Image *) NULL;
871       head=(Image *) NULL;
872       av=(AV *) reference;
873       n=av_len(av);
874       for (i=0; i <= n; i++)
875       {
876         SV
877           **rv;
878
879         rv=av_fetch(av,i,0);
880         if (rv && *rv && sv_isobject(*rv))
881           {
882             image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
883               exception);
884             if (image == (Image *) NULL)
885               continue;
886             if (image == previous)
887               {
888                 image=CloneImage(image,0,0,MagickTrue,exception);
889                 if (image == (Image *) NULL)
890                   return(NULL);
891               }
892             image->previous=previous;
893             *(previous ? &previous->next : &head)=image;
894             for (previous=image; previous->next; previous=previous->next) ;
895           }
896       }
897       return(head);
898     }
899     case SVt_PVMG:
900     {
901       /*
902         Blessed scalar, one image.
903       */
904       image=INT2PTR(Image *,SvIV(reference));
905       if (image == (Image *) NULL)
906         return(NULL);
907       image->previous=(Image *) NULL;
908       image->next=(Image *) NULL;
909       if (reference_vector)
910         {
911           if (*current == *last)
912             {
913               *last+=256;
914               if (*reference_vector == (SV **) NULL)
915                 *reference_vector=(SV **) AcquireQuantumMemory(*last,
916                   sizeof(*reference_vector));
917               else
918                 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
919                   *last,sizeof(*reference_vector));
920             }
921           if (*reference_vector == (SV **) NULL)
922             {
923               ThrowPerlException(exception,ResourceLimitError,
924                 "MemoryAllocationFailed",PackageName);
925               return((Image *) NULL);
926             }
927           (*reference_vector)[*current]=reference;
928           (*reference_vector)[++(*current)]=NULL;
929         }
930       return(image);
931     }
932     default:
933       break;
934   }
935   (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
936     (double) SvTYPE(reference));
937   return((Image *) NULL);
938 }
939 \f
940 /*
941 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
942 %                                                                             %
943 %                                                                             %
944 %                                                                             %
945 %   G e t P a c k a g e I n f o                                               %
946 %                                                                             %
947 %                                                                             %
948 %                                                                             %
949 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
950 %
951 %  Method GetPackageInfo looks up or creates an info structure for the given
952 %  Image__Magick reference.  If it does create a new one, the information in
953 %  package_info is used to initialize it.
954 %
955 %  The format of the GetPackageInfo routine is:
956 %
957 %      struct PackageInfo *GetPackageInfo(void *reference,
958 %        struct PackageInfo *package_info,ExceptionInfo *exception)
959 %
960 %  A description of each parameter follows:
961 %
962 %    o info: a structure of type info.
963 %
964 %    o exception: Return any errors or warnings in this structure.
965 %
966 */
967 static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
968   struct PackageInfo *package_info,ExceptionInfo *exception)
969 {
970   char
971     message[MaxTextExtent];
972
973   struct PackageInfo
974     *clone_info;
975
976   SV
977     *sv;
978
979   (void) FormatLocaleString(message,MaxTextExtent,"%s::package%s%p",
980     PackageName,XS_VERSION,reference);
981   sv=perl_get_sv(message,(TRUE | 0x02));
982   if (sv == (SV *) NULL)
983     {
984       ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
985         message);
986       return(package_info);
987     }
988   if (SvREFCNT(sv) == 0)
989     (void) SvREFCNT_inc(sv);
990   if (SvIOKp(sv) && (clone_info=INT2PTR(struct PackageInfo *,SvIV(sv))))
991     return(clone_info);
992   clone_info=ClonePackageInfo(package_info,exception);
993   sv_setiv(sv,PTR2IV(clone_info));
994   return(clone_info);
995 }
996 \f
997 /*
998 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
999 %                                                                             %
1000 %                                                                             %
1001 %                                                                             %
1002 %   S e t A t t r i b u t e                                                   %
1003 %                                                                             %
1004 %                                                                             %
1005 %                                                                             %
1006 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1007 %
1008 %  SetAttribute() sets the attribute to the value in sval.  This can change
1009 %  either or both of image or info.
1010 %
1011 %  The format of the SetAttribute routine is:
1012 %
1013 %      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1014 %        SV *sval,ExceptionInfo *exception)
1015 %
1016 %  A description of each parameter follows:
1017 %
1018 %    o list: a list of strings.
1019 %
1020 %    o string: a character string.
1021 %
1022 */
1023
1024 static double SiPrefixToDoubleInterval(const char *string,const double interval)
1025 {
1026   char
1027     *q;
1028
1029   double
1030     value;
1031
1032   value=InterpretSiPrefixValue(string,&q);
1033   if (*q == '%')
1034     value*=interval/100.0;
1035   return(value);
1036 }
1037
1038 static inline double StringToDouble(const char *string,char **sentinal)
1039 {
1040   return(InterpretLocaleValue(string,sentinal));
1041 }
1042
1043 static double StringToDoubleInterval(const char *string,const double interval)
1044 {
1045   char
1046     *q;
1047
1048   double
1049     value;
1050
1051   value=InterpretLocaleValue(string,&q);
1052   if (*q == '%')
1053     value*=interval/100.0;
1054   return(value);
1055 }
1056
1057 static inline ssize_t StringToLong(const char *value)
1058 {
1059   return(strtol(value,(char **) NULL,10));
1060 }
1061
1062 static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1063   const char *attribute,SV *sval,ExceptionInfo *exception)
1064 {
1065   GeometryInfo
1066     geometry_info;
1067
1068   long
1069     x,
1070     y;
1071
1072   PixelInfo
1073     pixel;
1074
1075   MagickStatusType
1076     flags;
1077
1078   PixelInfo
1079     *color,
1080     target_color;
1081
1082   ssize_t
1083     sp;
1084
1085   switch (*attribute)
1086   {
1087     case 'A':
1088     case 'a':
1089     {
1090       if (LocaleCompare(attribute,"adjoin") == 0)
1091         {
1092           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1093             SvPV(sval,na)) : SvIV(sval);
1094           if (sp < 0)
1095             {
1096               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1097                 SvPV(sval,na));
1098               break;
1099             }
1100           if (info)
1101             info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1102           break;
1103         }
1104       if (LocaleCompare(attribute,"alpha") == 0)
1105         {
1106           sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaChannelOptions,MagickFalse,
1107             SvPV(sval,na)) : SvIV(sval);
1108           if (sp < 0)
1109             {
1110               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1111                 SvPV(sval,na));
1112               break;
1113             }
1114           for ( ; image; image=image->next)
1115             (void) SetImageAlphaChannel(image,(AlphaChannelOption) sp,exception);
1116           break;
1117         }
1118       if (LocaleCompare(attribute,"antialias") == 0)
1119         {
1120           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1121             SvPV(sval,na)) : SvIV(sval);
1122           if (sp < 0)
1123             {
1124               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1125                 SvPV(sval,na));
1126               break;
1127             }
1128           if (info)
1129             info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1130           break;
1131         }
1132       if (LocaleCompare(attribute,"area-limit") == 0)
1133         {
1134           MagickSizeType
1135             limit;
1136
1137           limit=MagickResourceInfinity;
1138           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1139             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1140               100.0);
1141           (void) SetMagickResourceLimit(AreaResource,limit);
1142           break;
1143         }
1144       if (LocaleCompare(attribute,"attenuate") == 0)
1145         {
1146           if (info)
1147             (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1148           break;
1149         }
1150       if (LocaleCompare(attribute,"authenticate") == 0)
1151         {
1152           if (info)
1153             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1154           break;
1155         }
1156       if (info)
1157         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1158       for ( ; image; image=image->next)
1159         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1160       break;
1161     }
1162     case 'B':
1163     case 'b':
1164     {
1165       if (LocaleCompare(attribute,"background") == 0)
1166         {
1167           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1168             exception);
1169           if (info)
1170             info->image_info->background_color=target_color;
1171           for ( ; image; image=image->next)
1172             image->background_color=target_color;
1173           break;
1174         }
1175       if (LocaleCompare(attribute,"blue-primary") == 0)
1176         {
1177           for ( ; image; image=image->next)
1178           {
1179             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1180             image->chromaticity.blue_primary.x=geometry_info.rho;
1181             image->chromaticity.blue_primary.y=geometry_info.sigma;
1182             if ((flags & SigmaValue) == 0)
1183               image->chromaticity.blue_primary.y=
1184                 image->chromaticity.blue_primary.x;
1185           }
1186           break;
1187         }
1188       if (LocaleCompare(attribute,"bordercolor") == 0)
1189         {
1190           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1191             exception);
1192           if (info)
1193             info->image_info->border_color=target_color;
1194           for ( ; image; image=image->next)
1195             image->border_color=target_color;
1196           break;
1197         }
1198       if (info)
1199         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1200       for ( ; image; image=image->next)
1201         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1202       break;
1203     }
1204     case 'C':
1205     case 'c':
1206     {
1207       if (LocaleCompare(attribute,"cache-threshold") == 0)
1208         {
1209           (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1210             SiPrefixToDoubleInterval(SvPV(sval,na),100.0));
1211           (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1212             (2.0*SiPrefixToDoubleInterval(SvPV(sval,na),100.0)));
1213           break;
1214         }
1215       if (LocaleCompare(attribute,"clip-mask") == 0)
1216         {
1217           Image
1218             *clip_mask;
1219
1220           clip_mask=(Image *) NULL;
1221           if (SvPOK(sval))
1222             clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1223           for ( ; image; image=image->next)
1224             SetImageMask(image,clip_mask,exception);
1225           break;
1226         }
1227       if (LocaleNCompare(attribute,"colormap",8) == 0)
1228         {
1229           for ( ; image; image=image->next)
1230           {
1231             int
1232               items;
1233
1234             long
1235               i;
1236
1237             if (image->storage_class == DirectClass)
1238               continue;
1239             i=0;
1240             items=sscanf(attribute,"%*[^[][%ld",&i);
1241             (void) items;
1242             if (i > (ssize_t) image->colors)
1243               i%=image->colors;
1244             if ((strchr(SvPV(sval,na),',') == 0) ||
1245                 (strchr(SvPV(sval,na),')') != 0))
1246               QueryColorCompliance(SvPV(sval,na),AllCompliance,
1247                 image->colormap+i,exception);
1248             else
1249               {
1250                 color=image->colormap+i;
1251                 pixel.red=color->red;
1252                 pixel.green=color->green;
1253                 pixel.blue=color->blue;
1254                 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1255                 pixel.red=geometry_info.rho;
1256                 pixel.green=geometry_info.sigma;
1257                 pixel.blue=geometry_info.xi;
1258                 color->red=ClampToQuantum(pixel.red);
1259                 color->green=ClampToQuantum(pixel.green);
1260                 color->blue=ClampToQuantum(pixel.blue);
1261               }
1262           }
1263           break;
1264         }
1265       if (LocaleCompare(attribute,"colorspace") == 0)
1266         {
1267           sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1268             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1269           if (sp < 0)
1270             {
1271               ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1272                 SvPV(sval,na));
1273               break;
1274             }
1275           for ( ; image; image=image->next)
1276             (void) TransformImageColorspace(image,(ColorspaceType) sp,
1277               exception);
1278           break;
1279         }
1280       if (LocaleCompare(attribute,"comment") == 0)
1281         {
1282           for ( ; image; image=image->next)
1283             (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1284               info ? info->image_info : (ImageInfo *) NULL,image,
1285               SvPV(sval,na),exception),exception);
1286           break;
1287         }
1288       if (LocaleCompare(attribute,"compression") == 0)
1289         {
1290           sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1291             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1292           if (sp < 0)
1293             {
1294               ThrowPerlException(exception,OptionError,
1295                 "UnrecognizedImageCompression",SvPV(sval,na));
1296               break;
1297             }
1298           if (info)
1299             info->image_info->compression=(CompressionType) sp;
1300           for ( ; image; image=image->next)
1301             image->compression=(CompressionType) sp;
1302           break;
1303         }
1304       if (info)
1305         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1306       for ( ; image; image=image->next)
1307         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1308       break;
1309     }
1310     case 'D':
1311     case 'd':
1312     {
1313       if (LocaleCompare(attribute,"debug") == 0)
1314         {
1315           SetLogEventMask(SvPV(sval,na));
1316           break;
1317         }
1318       if (LocaleCompare(attribute,"delay") == 0)
1319         {
1320           flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1321           for ( ; image; image=image->next)
1322           {
1323             image->delay=(size_t) floor(geometry_info.rho+0.5);
1324             if ((flags & SigmaValue) != 0)
1325               image->ticks_per_second=(ssize_t)
1326                 floor(geometry_info.sigma+0.5);
1327           }
1328           break;
1329         }
1330       if (LocaleCompare(attribute,"disk-limit") == 0)
1331         {
1332           MagickSizeType
1333             limit;
1334
1335           limit=MagickResourceInfinity;
1336           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1337             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1338               100.0);
1339           (void) SetMagickResourceLimit(DiskResource,limit);
1340           break;
1341         }
1342       if (LocaleCompare(attribute,"density") == 0)
1343         {
1344           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1345             {
1346               ThrowPerlException(exception,OptionError,"MissingGeometry",
1347                 SvPV(sval,na));
1348               break;
1349             }
1350           if (info)
1351             (void) CloneString(&info->image_info->density,SvPV(sval,na));
1352           for ( ; image; image=image->next)
1353           {
1354             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1355             image->resolution.x=geometry_info.rho;
1356             image->resolution.y=geometry_info.sigma;
1357             if ((flags & SigmaValue) == 0)
1358               image->resolution.y=image->resolution.x;
1359           }
1360           break;
1361         }
1362       if (LocaleCompare(attribute,"depth") == 0)
1363         {
1364           if (info)
1365             info->image_info->depth=SvIV(sval);
1366           for ( ; image; image=image->next)
1367             (void) SetImageDepth(image,SvIV(sval),exception);
1368           break;
1369         }
1370       if (LocaleCompare(attribute,"dispose") == 0)
1371         {
1372           sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1373             SvPV(sval,na)) : SvIV(sval);
1374           if (sp < 0)
1375             {
1376               ThrowPerlException(exception,OptionError,
1377                 "UnrecognizedDisposeMethod",SvPV(sval,na));
1378               break;
1379             }
1380           for ( ; image; image=image->next)
1381             image->dispose=(DisposeType) sp;
1382           break;
1383         }
1384       if (LocaleCompare(attribute,"dither") == 0)
1385         {
1386           if (info)
1387             {
1388               sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1389                 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1390               if (sp < 0)
1391                 {
1392                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
1393                     SvPV(sval,na));
1394                   break;
1395                 }
1396               info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1397             }
1398           break;
1399         }
1400       if (LocaleCompare(attribute,"display") == 0)
1401         {
1402           display:
1403           if (info)
1404             (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1405           break;
1406         }
1407       if (info)
1408         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1409       for ( ; image; image=image->next)
1410         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1411       break;
1412     }
1413     case 'E':
1414     case 'e':
1415     {
1416       if (LocaleCompare(attribute,"endian") == 0)
1417         {
1418           sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1419             SvPV(sval,na)) : SvIV(sval);
1420           if (sp < 0)
1421             {
1422               ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1423                 SvPV(sval,na));
1424               break;
1425             }
1426           if (info)
1427             info->image_info->endian=(EndianType) sp;
1428           for ( ; image; image=image->next)
1429             image->endian=(EndianType) sp;
1430           break;
1431         }
1432       if (LocaleCompare(attribute,"extract") == 0)
1433         {
1434           /*
1435             Set image extract geometry.
1436           */
1437           (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1438           break;
1439         }
1440       if (info)
1441         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1442       for ( ; image; image=image->next)
1443         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1444       break;
1445     }
1446     case 'F':
1447     case 'f':
1448     {
1449       if (LocaleCompare(attribute,"filename") == 0)
1450         {
1451           if (info)
1452             (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1453               MaxTextExtent);
1454           for ( ; image; image=image->next)
1455             (void) CopyMagickString(image->filename,SvPV(sval,na),
1456               MaxTextExtent);
1457           break;
1458         }
1459       if (LocaleCompare(attribute,"file") == 0)
1460         {
1461           FILE
1462             *file;
1463
1464           PerlIO
1465             *io_info;
1466
1467           if (info == (struct PackageInfo *) NULL)
1468             break;
1469           io_info=IoIFP(sv_2io(sval));
1470           if (io_info == (PerlIO *) NULL)
1471             {
1472               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1473                 PackageName);
1474               break;
1475             }
1476           file=PerlIO_findFILE(io_info);
1477           if (file == (FILE *) NULL)
1478             {
1479               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1480                 PackageName);
1481               break;
1482             }
1483           SetImageInfoFile(info->image_info,file);
1484           break;
1485         }
1486       if (LocaleCompare(attribute,"fill") == 0)
1487         {
1488           if (info)
1489             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1490           break;
1491         }
1492       if (LocaleCompare(attribute,"font") == 0)
1493         {
1494           if (info)
1495             (void) CloneString(&info->image_info->font,SvPV(sval,na));
1496           break;
1497         }
1498       if (LocaleCompare(attribute,"foreground") == 0)
1499         break;
1500       if (LocaleCompare(attribute,"fuzz") == 0)
1501         {
1502           if (info)
1503             info->image_info->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1504               QuantumRange+1.0);
1505           for ( ; image; image=image->next)
1506             image->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1507               QuantumRange+1.0);
1508           break;
1509         }
1510       if (info)
1511         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1512       for ( ; image; image=image->next)
1513         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1514       break;
1515     }
1516     case 'G':
1517     case 'g':
1518     {
1519       if (LocaleCompare(attribute,"gamma") == 0)
1520         {
1521           for ( ; image; image=image->next)
1522             image->gamma=SvNV(sval);
1523           break;
1524         }
1525       if (LocaleCompare(attribute,"gravity") == 0)
1526         {
1527           sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1528             SvPV(sval,na)) : SvIV(sval);
1529           if (sp < 0)
1530             {
1531               ThrowPerlException(exception,OptionError,
1532                 "UnrecognizedGravityType",SvPV(sval,na));
1533               break;
1534             }
1535           if (info)
1536             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1537           for ( ; image; image=image->next)
1538             image->gravity=(GravityType) sp;
1539           break;
1540         }
1541       if (LocaleCompare(attribute,"green-primary") == 0)
1542         {
1543           for ( ; image; image=image->next)
1544           {
1545             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1546             image->chromaticity.green_primary.x=geometry_info.rho;
1547             image->chromaticity.green_primary.y=geometry_info.sigma;
1548             if ((flags & SigmaValue) == 0)
1549               image->chromaticity.green_primary.y=
1550                 image->chromaticity.green_primary.x;
1551           }
1552           break;
1553         }
1554       if (info)
1555         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1556       for ( ; image; image=image->next)
1557         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1558       break;
1559     }
1560     case 'I':
1561     case 'i':
1562     {
1563       if (LocaleNCompare(attribute,"index",5) == 0)
1564         {
1565           int
1566             items;
1567
1568           long
1569             index;
1570
1571           register Quantum
1572             *q;
1573
1574           CacheView
1575             *image_view;
1576
1577           for ( ; image; image=image->next)
1578           {
1579             if (image->storage_class != PseudoClass)
1580               continue;
1581             x=0;
1582             y=0;
1583             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1584             (void) items;
1585             image_view=AcquireAuthenticCacheView(image,exception);
1586             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1587             if (q != (Quantum *) NULL)
1588               {
1589                 items=sscanf(SvPV(sval,na),"%ld",&index);
1590                 if ((index >= 0) && (index < (ssize_t) image->colors))
1591                   SetPixelIndex(image,index,q);
1592                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1593               }
1594             image_view=DestroyCacheView(image_view);
1595           }
1596           break;
1597         }
1598       if (LocaleCompare(attribute,"iterations") == 0)
1599         {
1600   iterations:
1601           for ( ; image; image=image->next)
1602             image->iterations=SvIV(sval);
1603           break;
1604         }
1605       if (LocaleCompare(attribute,"interlace") == 0)
1606         {
1607           sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1608             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1609           if (sp < 0)
1610             {
1611               ThrowPerlException(exception,OptionError,
1612                 "UnrecognizedInterlaceType",SvPV(sval,na));
1613               break;
1614             }
1615           if (info)
1616             info->image_info->interlace=(InterlaceType) sp;
1617           for ( ; image; image=image->next)
1618             image->interlace=(InterlaceType) sp;
1619           break;
1620         }
1621       if (info)
1622         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1623       for ( ; image; image=image->next)
1624         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1625       break;
1626     }
1627     case 'L':
1628     case 'l':
1629     {
1630       if (LocaleCompare(attribute,"label") == 0)
1631         {
1632           for ( ; image; image=image->next)
1633             (void) SetImageProperty(image,"label",InterpretImageProperties(
1634               info ? info->image_info : (ImageInfo *) NULL,image,
1635               SvPV(sval,na),exception),exception);
1636           break;
1637         }
1638       if (LocaleCompare(attribute,"loop") == 0)
1639         goto iterations;
1640       if (info)
1641         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1642       for ( ; image; image=image->next)
1643         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1644       break;
1645     }
1646     case 'M':
1647     case 'm':
1648     {
1649       if (LocaleCompare(attribute,"magick") == 0)
1650         {
1651           if (info)
1652             (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
1653               "%s:",SvPV(sval,na));
1654           for ( ; image; image=image->next)
1655             (void) CopyMagickString(image->magick,SvPV(sval,na),MaxTextExtent);
1656           break;
1657         }
1658       if (LocaleCompare(attribute,"map-limit") == 0)
1659         {
1660           MagickSizeType
1661             limit;
1662
1663           limit=MagickResourceInfinity;
1664           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1665             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1666               100.0);
1667           (void) SetMagickResourceLimit(MapResource,limit);
1668           break;
1669         }
1670       if (LocaleCompare(attribute,"mask") == 0)
1671         {
1672           Image
1673             *mask;
1674
1675           mask=(Image *) NULL;
1676           if (SvPOK(sval))
1677             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1678           for ( ; image; image=image->next)
1679             SetImageMask(image,mask,exception);
1680           break;
1681         }
1682       if (LocaleCompare(attribute,"mattecolor") == 0)
1683         {
1684           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1685             exception);
1686           if (info)
1687             info->image_info->matte_color=target_color;
1688           for ( ; image; image=image->next)
1689             image->matte_color=target_color;
1690           break;
1691         }
1692       if (LocaleCompare(attribute,"matte") == 0)
1693         {
1694           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1695             SvPV(sval,na)) : SvIV(sval);
1696           if (sp < 0)
1697             {
1698               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1699                 SvPV(sval,na));
1700               break;
1701             }
1702           for ( ; image; image=image->next)
1703             image->alpha_trait=sp != 0 ? BlendPixelTrait : UndefinedPixelTrait;
1704           break;
1705         }
1706       if (LocaleCompare(attribute,"memory-limit") == 0)
1707         {
1708           MagickSizeType
1709             limit;
1710
1711           limit=MagickResourceInfinity;
1712           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1713             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1714               100.0);
1715           (void) SetMagickResourceLimit(MemoryResource,limit);
1716           break;
1717         }
1718       if (LocaleCompare(attribute,"monochrome") == 0)
1719         {
1720           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1721             SvPV(sval,na)) : SvIV(sval);
1722           if (sp < 0)
1723             {
1724               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1725                 SvPV(sval,na));
1726               break;
1727             }
1728           if (info)
1729             info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1730           for ( ; image; image=image->next)
1731             (void) SetImageType(image,BilevelType,exception);
1732           break;
1733         }
1734       if (info)
1735         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1736       for ( ; image; image=image->next)
1737         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1738       break;
1739     }
1740     case 'O':
1741     case 'o':
1742     {
1743       if (LocaleCompare(attribute,"option") == 0)
1744         {
1745           if (info)
1746             DefineImageOption(info->image_info,SvPV(sval,na));
1747           break;
1748         }
1749       if (LocaleCompare(attribute,"orientation") == 0)
1750         {
1751           sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1752             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1753           if (sp < 0)
1754             {
1755               ThrowPerlException(exception,OptionError,
1756                 "UnrecognizedOrientationType",SvPV(sval,na));
1757               break;
1758             }
1759           if (info)
1760             info->image_info->orientation=(OrientationType) sp;
1761           for ( ; image; image=image->next)
1762             image->orientation=(OrientationType) sp;
1763           break;
1764         }
1765       if (info)
1766         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1767       for ( ; image; image=image->next)
1768         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1769       break;
1770     }
1771     case 'P':
1772     case 'p':
1773     {
1774       if (LocaleCompare(attribute,"page") == 0)
1775         {
1776           char
1777             *geometry;
1778
1779           geometry=GetPageGeometry(SvPV(sval,na));
1780           if (info)
1781             (void) CloneString(&info->image_info->page,geometry);
1782           for ( ; image; image=image->next)
1783             (void) ParsePageGeometry(image,geometry,&image->page,exception);
1784           geometry=(char *) RelinquishMagickMemory(geometry);
1785           break;
1786         }
1787       if (LocaleNCompare(attribute,"pixel",5) == 0)
1788         {
1789           int
1790             items;
1791
1792           PixelInfo
1793             pixel;
1794
1795           register Quantum
1796             *q;
1797
1798           CacheView
1799             *image_view;
1800
1801           for ( ; image; image=image->next)
1802           {
1803             if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1804               break;
1805             x=0;
1806             y=0;
1807             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1808             (void) items;
1809             image_view=AcquireVirtualCacheView(image,exception);
1810             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1811             if (q != (Quantum *) NULL)
1812               {
1813                 if ((strchr(SvPV(sval,na),',') == 0) ||
1814                     (strchr(SvPV(sval,na),')') != 0))
1815                   QueryColorCompliance(SvPV(sval,na),AllCompliance,
1816                     &pixel,exception);
1817                 else
1818                   {
1819                     GetPixelInfo(image,&pixel);
1820                     flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1821                     pixel.red=geometry_info.rho;
1822                     if ((flags & SigmaValue) != 0)
1823                       pixel.green=geometry_info.sigma;
1824                     if ((flags & XiValue) != 0)
1825                       pixel.blue=geometry_info.xi;
1826                     if ((flags & PsiValue) != 0)
1827                       pixel.alpha=geometry_info.psi;
1828                     if ((flags & ChiValue) != 0)
1829                       pixel.black=geometry_info.chi;
1830                   }
1831                 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1832                 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1833                 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1834                 if (image->colorspace == CMYKColorspace)
1835                   SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1836                 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1837                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1838               }
1839             image_view=DestroyCacheView(image_view);
1840           }
1841           break;
1842         }
1843       if (LocaleCompare(attribute,"pointsize") == 0)
1844         {
1845           if (info)
1846             {
1847               (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1848               info->image_info->pointsize=geometry_info.rho;
1849             }
1850           break;
1851         }
1852       if (LocaleCompare(attribute,"preview") == 0)
1853         {
1854           sp=SvPOK(sval) ? ParseCommandOption(MagickPreviewOptions,MagickFalse,
1855             SvPV(sval,na)) : SvIV(sval);
1856           if (sp < 0)
1857             {
1858               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1859                 SvPV(sval,na));
1860               break;
1861             }
1862           if (info)
1863             info->image_info->preview_type=(PreviewType) sp;
1864           break;
1865         }
1866       if (info)
1867         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1868       for ( ; image; image=image->next)
1869         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1870       break;
1871     }
1872     case 'Q':
1873     case 'q':
1874     {
1875       if (LocaleCompare(attribute,"quality") == 0)
1876         {
1877           if (info)
1878             info->image_info->quality=SvIV(sval);
1879           for ( ; image; image=image->next)
1880             image->quality=SvIV(sval);
1881           break;
1882         }
1883       if (info)
1884         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1885       for ( ; image; image=image->next)
1886         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1887       break;
1888     }
1889     case 'R':
1890     case 'r':
1891     {
1892       if (LocaleCompare(attribute,"red-primary") == 0)
1893         {
1894           for ( ; image; image=image->next)
1895           {
1896             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1897             image->chromaticity.red_primary.x=geometry_info.rho;
1898             image->chromaticity.red_primary.y=geometry_info.sigma;
1899             if ((flags & SigmaValue) == 0)
1900               image->chromaticity.red_primary.y=
1901                 image->chromaticity.red_primary.x;
1902           }
1903           break;
1904         }
1905       if (LocaleCompare(attribute,"render") == 0)
1906         {
1907           sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1908             SvPV(sval,na)) : SvIV(sval);
1909           if (sp < 0)
1910             {
1911               ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1912                 SvPV(sval,na));
1913               break;
1914             }
1915          for ( ; image; image=image->next)
1916            image->rendering_intent=(RenderingIntent) sp;
1917          break;
1918        }
1919       if (LocaleCompare(attribute,"repage") == 0)
1920         {
1921           RectangleInfo
1922             geometry;
1923
1924           for ( ; image; image=image->next)
1925           {
1926             flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
1927             if ((flags & WidthValue) != 0)
1928               {
1929                 if ((flags & HeightValue) == 0)
1930                   geometry.height=geometry.width;
1931                 image->page.width=geometry.width;
1932                 image->page.height=geometry.height;
1933               }
1934             if ((flags & AspectValue) != 0)
1935               {
1936                 if ((flags & XValue) != 0)
1937                   image->page.x+=geometry.x;
1938                 if ((flags & YValue) != 0)
1939                   image->page.y+=geometry.y;
1940               }
1941             else
1942               {
1943                 if ((flags & XValue) != 0)
1944                   {
1945                     image->page.x=geometry.x;
1946                     if (((flags & WidthValue) != 0) && (geometry.x > 0))
1947                       image->page.width=image->columns+geometry.x;
1948                   }
1949                 if ((flags & YValue) != 0)
1950                   {
1951                     image->page.y=geometry.y;
1952                     if (((flags & HeightValue) != 0) && (geometry.y > 0))
1953                       image->page.height=image->rows+geometry.y;
1954                   }
1955               }
1956           }
1957           break;
1958         }
1959       if (info)
1960         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1961       for ( ; image; image=image->next)
1962         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1963       break;
1964     }
1965     case 'S':
1966     case 's':
1967     {
1968       if (LocaleCompare(attribute,"sampling-factor") == 0)
1969         {
1970           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1971             {
1972               ThrowPerlException(exception,OptionError,"MissingGeometry",
1973                 SvPV(sval,na));
1974               break;
1975             }
1976           if (info)
1977             (void) CloneString(&info->image_info->sampling_factor,
1978               SvPV(sval,na));
1979           break;
1980         }
1981       if (LocaleCompare(attribute,"scene") == 0)
1982         {
1983           for ( ; image; image=image->next)
1984             image->scene=SvIV(sval);
1985           break;
1986         }
1987       if (LocaleCompare(attribute,"server") == 0)
1988         goto display;
1989       if (LocaleCompare(attribute,"size") == 0)
1990         {
1991           if (info)
1992             {
1993               if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1994                 {
1995                   ThrowPerlException(exception,OptionError,"MissingGeometry",
1996                     SvPV(sval,na));
1997                   break;
1998                 }
1999               (void) CloneString(&info->image_info->size,SvPV(sval,na));
2000             }
2001           break;
2002         }
2003       if (LocaleCompare(attribute,"stroke") == 0)
2004         {
2005           if (info)
2006             (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2007           break;
2008         }
2009       if (info)
2010         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2011       for ( ; image; image=image->next)
2012         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2013       break;
2014     }
2015     case 'T':
2016     case 't':
2017     {
2018       if (LocaleCompare(attribute,"texture") == 0)
2019         {
2020           if (info)
2021             (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2022           break;
2023         }
2024       if (LocaleCompare(attribute,"thread-limit") == 0)
2025         {
2026           MagickSizeType
2027             limit;
2028
2029           limit=MagickResourceInfinity;
2030           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2031             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2032               100.0);
2033           (void) SetMagickResourceLimit(ThreadResource,limit);
2034           break;
2035         }
2036       if (LocaleCompare(attribute,"tile-offset") == 0)
2037         {
2038           char
2039             *geometry;
2040
2041           geometry=GetPageGeometry(SvPV(sval,na));
2042           if (info)
2043             (void) CloneString(&info->image_info->page,geometry);
2044           for ( ; image; image=image->next)
2045             (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2046               exception);
2047           geometry=(char *) RelinquishMagickMemory(geometry);
2048           break;
2049         }
2050       if (LocaleCompare(attribute,"time-limit") == 0)
2051         {
2052           MagickSizeType
2053             limit;
2054
2055           limit=MagickResourceInfinity;
2056           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2057             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2058               100.0);
2059           (void) SetMagickResourceLimit(TimeResource,limit);
2060           break;
2061         }
2062       if (LocaleCompare(attribute,"transparent-color") == 0)
2063         {
2064           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
2065             exception);
2066           if (info)
2067             info->image_info->transparent_color=target_color;
2068           for ( ; image; image=image->next)
2069             image->transparent_color=target_color;
2070           break;
2071         }
2072       if (LocaleCompare(attribute,"type") == 0)
2073         {
2074           sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2075             SvPV(sval,na)) : SvIV(sval);
2076           if (sp < 0)
2077             {
2078               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2079                 SvPV(sval,na));
2080               break;
2081             }
2082           if (info)
2083             info->image_info->type=(ImageType) sp;
2084           for ( ; image; image=image->next)
2085             SetImageType(image,(ImageType) sp,exception);
2086           break;
2087         }
2088       if (info)
2089         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2090       for ( ; image; image=image->next)
2091         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2092       break;
2093     }
2094     case 'U':
2095     case 'u':
2096     {
2097       if (LocaleCompare(attribute,"units") == 0)
2098         {
2099           sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2100             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2101           if (sp < 0)
2102             {
2103               ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2104                 SvPV(sval,na));
2105               break;
2106             }
2107           if (info)
2108             info->image_info->units=(ResolutionType) sp;
2109           for ( ; image; image=image->next)
2110           {
2111             ResolutionType
2112               units;
2113
2114             units=(ResolutionType) sp;
2115             if (image->units != units)
2116               switch (image->units)
2117               {
2118                 case UndefinedResolution:
2119                 case PixelsPerInchResolution:
2120                 {
2121                   if (units == PixelsPerCentimeterResolution)
2122                     {
2123                       image->resolution.x*=2.54;
2124                       image->resolution.y*=2.54;
2125                     }
2126                   break;
2127                 }
2128                 case PixelsPerCentimeterResolution:
2129                 {
2130                   if (units == PixelsPerInchResolution)
2131                     {
2132                       image->resolution.x/=2.54;
2133                       image->resolution.y/=2.54;
2134                     }
2135                   break;
2136                 }
2137               }
2138             image->units=units;
2139           }
2140           break;
2141         }
2142       if (info)
2143         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2144       for ( ; image; image=image->next)
2145         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2146       break;
2147     }
2148     case 'V':
2149     case 'v':
2150     {
2151       if (LocaleCompare(attribute,"verbose") == 0)
2152         {
2153           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2154             SvPV(sval,na)) : SvIV(sval);
2155           if (sp < 0)
2156             {
2157               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2158                 SvPV(sval,na));
2159               break;
2160             }
2161           if (info)
2162             info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2163           break;
2164         }
2165       if (LocaleCompare(attribute,"view") == 0)
2166         {
2167           if (info)
2168             (void) CloneString(&info->image_info->view,SvPV(sval,na));
2169           break;
2170         }
2171       if (LocaleCompare(attribute,"virtual-pixel") == 0)
2172         {
2173           sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2174             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2175           if (sp < 0)
2176             {
2177               ThrowPerlException(exception,OptionError,
2178                 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2179               break;
2180             }
2181           for ( ; image; image=image->next)
2182             SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp,exception);
2183           break;
2184         }
2185       if (info)
2186         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2187       for ( ; image; image=image->next)
2188         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2189       break;
2190     }
2191     case 'W':
2192     case 'w':
2193     {
2194       if (LocaleCompare(attribute,"white-point") == 0)
2195         {
2196           for ( ; image; image=image->next)
2197           {
2198             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2199             image->chromaticity.white_point.x=geometry_info.rho;
2200             image->chromaticity.white_point.y=geometry_info.sigma;
2201             if ((flags & SigmaValue) == 0)
2202               image->chromaticity.white_point.y=
2203                 image->chromaticity.white_point.x;
2204           }
2205           break;
2206         }
2207       if (info)
2208         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2209       for ( ; image; image=image->next)
2210         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2211       break;
2212     }
2213     default:
2214     {
2215       if (info)
2216         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2217       for ( ; image; image=image->next)
2218         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2219       break;
2220     }
2221   }
2222 }
2223 \f
2224 /*
2225 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2226 %                                                                             %
2227 %                                                                             %
2228 %                                                                             %
2229 %   S e t u p L i s t                                                         %
2230 %                                                                             %
2231 %                                                                             %
2232 %                                                                             %
2233 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2234 %
2235 %  Method SetupList returns the list of all the images linked by their
2236 %  image->next and image->previous link lists for use with ImageMagick.  If
2237 %  info is non-NULL, an info structure is returned in *info.  If
2238 %  reference_vector is non-NULL,an array of SV* are returned in
2239 %  *reference_vector.  Reference_vector is used when the images are going to be
2240 %  replaced with new Image*'s.
2241 %
2242 %  The format of the SetupList routine is:
2243 %
2244 %      Image *SetupList(SV *reference,struct PackageInfo **info,
2245 %        SV ***reference_vector,ExceptionInfo *exception)
2246 %
2247 %  A description of each parameter follows:
2248 %
2249 %    o list: a list of strings.
2250 %
2251 %    o string: a character string.
2252 %
2253 %    o exception: Return any errors or warnings in this structure.
2254 %
2255 */
2256 static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2257   SV ***reference_vector,ExceptionInfo *exception)
2258 {
2259   Image
2260     *image;
2261
2262   ssize_t
2263     current,
2264     last;
2265
2266   if (reference_vector)
2267     *reference_vector=NULL;
2268   if (info)
2269     *info=NULL;
2270   current=0;
2271   last=0;
2272   image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2273   if (info && (SvTYPE(reference) == SVt_PVAV))
2274     *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2275       exception);
2276   return(image);
2277 }
2278 \f
2279 /*
2280 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2281 %                                                                             %
2282 %                                                                             %
2283 %                                                                             %
2284 %   s t r E Q c a s e                                                         %
2285 %                                                                             %
2286 %                                                                             %
2287 %                                                                             %
2288 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2289 %
2290 %  strEQcase() compares two strings and returns 0 if they are the
2291 %  same or if the second string runs out first.  The comparison is case
2292 %  insensitive.
2293 %
2294 %  The format of the strEQcase routine is:
2295 %
2296 %      ssize_t strEQcase(const char *p,const char *q)
2297 %
2298 %  A description of each parameter follows:
2299 %
2300 %    o p: a character string.
2301 %
2302 %    o q: a character string.
2303 %
2304 %
2305 */
2306 static ssize_t strEQcase(const char *p,const char *q)
2307 {
2308   char
2309     c;
2310
2311   register ssize_t
2312     i;
2313
2314   for (i=0 ; (c=(*q)) != 0; i++)
2315   {
2316     if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2317         (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2318       return(0);
2319     p++;
2320     q++;
2321   }
2322   return(((*q == 0) && (*p == 0)) ? i : 0);
2323 }
2324 \f
2325 /*
2326 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2327 %                                                                             %
2328 %                                                                             %
2329 %                                                                             %
2330 %   I m a g e : : M a g i c k                                                 %
2331 %                                                                             %
2332 %                                                                             %
2333 %                                                                             %
2334 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2335 %
2336 %
2337 */
2338 MODULE = Image::Magick PACKAGE = Image::Magick
2339
2340 PROTOTYPES: ENABLE
2341
2342 BOOT:
2343   MagickCoreGenesis("PerlMagick",MagickFalse);
2344   SetWarningHandler(NULL);
2345   SetErrorHandler(NULL);
2346   magick_registry=NewSplayTree((int (*)(const void *,const void *))
2347     NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2348
2349 void
2350 UNLOAD()
2351   PPCODE:
2352   {
2353     if (magick_registry != (SplayTreeInfo *) NULL)
2354       magick_registry=DestroySplayTree(magick_registry);
2355     MagickCoreTerminus();
2356   }
2357
2358 double
2359 constant(name,argument)
2360   char *name
2361   ssize_t argument
2362 \f
2363 #
2364 ###############################################################################
2365 #                                                                             #
2366 #                                                                             #
2367 #                                                                             #
2368 #   A n i m a t e                                                             #
2369 #                                                                             #
2370 #                                                                             #
2371 #                                                                             #
2372 ###############################################################################
2373 #
2374 #
2375 void
2376 Animate(ref,...)
2377   Image::Magick ref=NO_INIT
2378   ALIAS:
2379     AnimateImage  = 1
2380     animate       = 2
2381     animateimage  = 3
2382   PPCODE:
2383   {
2384     ExceptionInfo
2385       *exception;
2386
2387     Image
2388       *image;
2389
2390     register ssize_t
2391       i;
2392
2393     struct PackageInfo
2394       *info,
2395       *package_info;
2396
2397     SV
2398       *perl_exception,
2399       *reference;
2400
2401     PERL_UNUSED_VAR(ref);
2402     PERL_UNUSED_VAR(ix);
2403     exception=AcquireExceptionInfo();
2404     perl_exception=newSVpv("",0);
2405     package_info=(struct PackageInfo *) NULL;
2406     if (sv_isobject(ST(0)) == 0)
2407       {
2408         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2409           PackageName);
2410         goto PerlException;
2411       }
2412     reference=SvRV(ST(0));
2413     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2414     if (image == (Image *) NULL)
2415       {
2416         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2417           PackageName);
2418         goto PerlException;
2419       }
2420     package_info=ClonePackageInfo(info,exception);
2421     if (items == 2)
2422       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2423     else
2424       if (items > 2)
2425         for (i=2; i < items; i+=2)
2426           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2427             exception);
2428     (void) AnimateImages(package_info->image_info,image,exception);
2429     (void) CatchImageException(image);
2430
2431   PerlException:
2432     if (package_info != (struct PackageInfo *) NULL)
2433       DestroyPackageInfo(package_info);
2434     InheritPerlException(exception,perl_exception);
2435     exception=DestroyExceptionInfo(exception);
2436     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2437     SvPOK_on(perl_exception);
2438     ST(0)=sv_2mortal(perl_exception);
2439     XSRETURN(1);
2440   }
2441 \f
2442 #
2443 ###############################################################################
2444 #                                                                             #
2445 #                                                                             #
2446 #                                                                             #
2447 #   A p p e n d                                                               #
2448 #                                                                             #
2449 #                                                                             #
2450 #                                                                             #
2451 ###############################################################################
2452 #
2453 #
2454 void
2455 Append(ref,...)
2456   Image::Magick ref=NO_INIT
2457   ALIAS:
2458     AppendImage  = 1
2459     append       = 2
2460     appendimage  = 3
2461   PPCODE:
2462   {
2463     AV
2464       *av;
2465
2466     char
2467       *attribute;
2468
2469     ExceptionInfo
2470       *exception;
2471
2472     HV
2473       *hv;
2474
2475     Image
2476       *image;
2477
2478     register ssize_t
2479       i;
2480
2481     ssize_t
2482       stack;
2483
2484     struct PackageInfo
2485       *info;
2486
2487     SV
2488       *av_reference,
2489       *perl_exception,
2490       *reference,
2491       *rv,
2492       *sv;
2493
2494     PERL_UNUSED_VAR(ref);
2495     PERL_UNUSED_VAR(ix);
2496     exception=AcquireExceptionInfo();
2497     perl_exception=newSVpv("",0);
2498     sv=NULL;
2499     attribute=NULL;
2500     av=NULL;
2501     if (sv_isobject(ST(0)) == 0)
2502       {
2503         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2504           PackageName);
2505         goto PerlException;
2506       }
2507     reference=SvRV(ST(0));
2508     hv=SvSTASH(reference);
2509     av=newAV();
2510     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2511     SvREFCNT_dec(av);
2512     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2513     if (image == (Image *) NULL)
2514       {
2515         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2516           PackageName);
2517         goto PerlException;
2518       }
2519     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2520     /*
2521       Get options.
2522     */
2523     stack=MagickTrue;
2524     for (i=2; i < items; i+=2)
2525     {
2526       attribute=(char *) SvPV(ST(i-1),na);
2527       switch (*attribute)
2528       {
2529         case 'S':
2530         case 's':
2531         {
2532           if (LocaleCompare(attribute,"stack") == 0)
2533             {
2534               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2535                 SvPV(ST(i),na));
2536               if (stack < 0)
2537                 {
2538                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
2539                     SvPV(ST(i),na));
2540                   return;
2541                 }
2542               break;
2543             }
2544           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2545             attribute);
2546           break;
2547         }
2548         default:
2549         {
2550           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2551             attribute);
2552           break;
2553         }
2554       }
2555     }
2556     image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2557     if (image == (Image *) NULL)
2558       goto PerlException;
2559     for ( ; image; image=image->next)
2560     {
2561       AddImageToRegistry(sv,image);
2562       rv=newRV(sv);
2563       av_push(av,sv_bless(rv,hv));
2564       SvREFCNT_dec(sv);
2565     }
2566     exception=DestroyExceptionInfo(exception);
2567     ST(0)=av_reference;
2568     SvREFCNT_dec(perl_exception);
2569     XSRETURN(1);
2570
2571   PerlException:
2572     InheritPerlException(exception,perl_exception);
2573     exception=DestroyExceptionInfo(exception);
2574     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2575     SvPOK_on(perl_exception);
2576     ST(0)=sv_2mortal(perl_exception);
2577     XSRETURN(1);
2578   }
2579 \f
2580 #
2581 ###############################################################################
2582 #                                                                             #
2583 #                                                                             #
2584 #                                                                             #
2585 #   A v e r a g e                                                             #
2586 #                                                                             #
2587 #                                                                             #
2588 #                                                                             #
2589 ###############################################################################
2590 #
2591 #
2592 void
2593 Average(ref)
2594   Image::Magick ref=NO_INIT
2595   ALIAS:
2596     AverageImage   = 1
2597     average        = 2
2598     averageimage   = 3
2599   PPCODE:
2600   {
2601     AV
2602       *av;
2603
2604     char
2605       *p;
2606
2607     ExceptionInfo
2608       *exception;
2609
2610     HV
2611       *hv;
2612
2613     Image
2614       *image;
2615
2616     struct PackageInfo
2617       *info;
2618
2619     SV
2620       *perl_exception,
2621       *reference,
2622       *rv,
2623       *sv;
2624
2625     PERL_UNUSED_VAR(ref);
2626     PERL_UNUSED_VAR(ix);
2627     exception=AcquireExceptionInfo();
2628     perl_exception=newSVpv("",0);
2629     sv=NULL;
2630     if (sv_isobject(ST(0)) == 0)
2631       {
2632         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2633           PackageName);
2634         goto PerlException;
2635       }
2636     reference=SvRV(ST(0));
2637     hv=SvSTASH(reference);
2638     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2639     if (image == (Image *) NULL)
2640       {
2641         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2642           PackageName);
2643         goto PerlException;
2644       }
2645     image=EvaluateImages(image,MeanEvaluateOperator,exception);
2646     if (image == (Image *) NULL)
2647       goto PerlException;
2648     /*
2649       Create blessed Perl array for the returned image.
2650     */
2651     av=newAV();
2652     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2653     SvREFCNT_dec(av);
2654     AddImageToRegistry(sv,image);
2655     rv=newRV(sv);
2656     av_push(av,sv_bless(rv,hv));
2657     SvREFCNT_dec(sv);
2658     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2659     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
2660       "average-%.*s",(int) (MaxTextExtent-9),
2661       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2662     (void) CopyMagickString(image->filename,info->image_info->filename,
2663       MaxTextExtent);
2664     SetImageInfo(info->image_info,0,exception);
2665     exception=DestroyExceptionInfo(exception);
2666     SvREFCNT_dec(perl_exception);
2667     XSRETURN(1);
2668
2669   PerlException:
2670     InheritPerlException(exception,perl_exception);
2671     exception=DestroyExceptionInfo(exception);
2672     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2673     SvPOK_on(perl_exception);
2674     ST(0)=sv_2mortal(perl_exception);
2675     XSRETURN(1);
2676   }
2677 \f
2678 #
2679 ###############################################################################
2680 #                                                                             #
2681 #                                                                             #
2682 #                                                                             #
2683 #   B l o b T o I m a g e                                                     #
2684 #                                                                             #
2685 #                                                                             #
2686 #                                                                             #
2687 ###############################################################################
2688 #
2689 #
2690 void
2691 BlobToImage(ref,...)
2692   Image::Magick ref=NO_INIT
2693   ALIAS:
2694     BlobToImage  = 1
2695     blobtoimage  = 2
2696     blobto       = 3
2697   PPCODE:
2698   {
2699     AV
2700       *av;
2701
2702     char
2703       **keep,
2704       **list;
2705
2706     ExceptionInfo
2707       *exception;
2708
2709     HV
2710       *hv;
2711
2712     Image
2713       *image;
2714
2715     register char
2716       **p;
2717
2718     register ssize_t
2719       i;
2720
2721     ssize_t
2722       ac,
2723       n,
2724       number_images;
2725
2726     STRLEN
2727       *length;
2728
2729     struct PackageInfo
2730       *info;
2731
2732     SV
2733       *perl_exception,
2734       *reference,
2735       *rv,
2736       *sv;
2737
2738     PERL_UNUSED_VAR(ref);
2739     PERL_UNUSED_VAR(ix);
2740     exception=AcquireExceptionInfo();
2741     perl_exception=newSVpv("",0);
2742     sv=NULL;
2743     number_images=0;
2744     ac=(items < 2) ? 1 : items-1;
2745     length=(STRLEN *) NULL;
2746     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2747     if (list == (char **) NULL)
2748       {
2749         ThrowPerlException(exception,ResourceLimitError,
2750           "MemoryAllocationFailed",PackageName);
2751         goto PerlException;
2752       }
2753     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2754     if (length == (STRLEN *) NULL)
2755       {
2756         ThrowPerlException(exception,ResourceLimitError,
2757           "MemoryAllocationFailed",PackageName);
2758         goto PerlException;
2759       }
2760     if (sv_isobject(ST(0)) == 0)
2761       {
2762         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2763           PackageName);
2764         goto PerlException;
2765       }
2766     reference=SvRV(ST(0));
2767     hv=SvSTASH(reference);
2768     if (SvTYPE(reference) != SVt_PVAV)
2769       {
2770         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2771           PackageName);
2772         goto PerlException;
2773       }
2774     av=(AV *) reference;
2775     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2776       exception);
2777     n=1;
2778     if (items <= 1)
2779       {
2780         ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2781         goto PerlException;
2782       }
2783     for (n=0, i=0; i < ac; i++)
2784     {
2785       list[n]=(char *) (SvPV(ST(i+1),length[n]));
2786       if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2787         {
2788           list[n]=(char *) (SvPV(ST(i+2),length[n]));
2789           continue;
2790         }
2791       n++;
2792     }
2793     list[n]=(char *) NULL;
2794     keep=list;
2795     for (i=number_images=0; i < n; i++)
2796     {
2797       image=BlobToImage(info->image_info,list[i],length[i],exception);
2798       if (image == (Image *) NULL)
2799         break;
2800       for ( ; image; image=image->next)
2801       {
2802         AddImageToRegistry(sv,image);
2803         rv=newRV(sv);
2804         av_push(av,sv_bless(rv,hv));
2805         SvREFCNT_dec(sv);
2806         number_images++;
2807       }
2808     }
2809     /*
2810       Free resources.
2811     */
2812     for (i=0; i < n; i++)
2813       if (list[i] != (char *) NULL)
2814         for (p=keep; list[i] != *p++; )
2815           if (*p == (char *) NULL)
2816             {
2817               list[i]=(char *) RelinquishMagickMemory(list[i]);
2818               break;
2819             }
2820
2821   PerlException:
2822     if (list)
2823       list=(char **) RelinquishMagickMemory(list);
2824     if (length)
2825       length=(STRLEN *) RelinquishMagickMemory(length);
2826     InheritPerlException(exception,perl_exception);
2827     exception=DestroyExceptionInfo(exception);
2828     sv_setiv(perl_exception,(IV) number_images);
2829     SvPOK_on(perl_exception);
2830     ST(0)=sv_2mortal(perl_exception);
2831     XSRETURN(1);
2832   }
2833 \f
2834 #
2835 ###############################################################################
2836 #                                                                             #
2837 #                                                                             #
2838 #                                                                             #
2839 #   C h a n n e l F x                                                         #
2840 #                                                                             #
2841 #                                                                             #
2842 #                                                                             #
2843 ###############################################################################
2844 #
2845 #
2846 void
2847 ChannelFx(ref,...)
2848   Image::Magick ref=NO_INIT
2849   ALIAS:
2850     ChannelFxImage  = 1
2851     channelfx       = 2
2852     channelfximage  = 3
2853   PPCODE:
2854   {
2855     AV
2856       *av;
2857
2858     char
2859       *attribute,
2860       expression[MaxTextExtent];
2861
2862     ChannelType
2863       channel,
2864       channel_mask;
2865
2866     ExceptionInfo
2867       *exception;
2868
2869     HV
2870       *hv;
2871
2872     Image
2873       *image;
2874
2875     register ssize_t
2876       i;
2877
2878     struct PackageInfo
2879       *info;
2880
2881     SV
2882       *av_reference,
2883       *perl_exception,
2884       *reference,
2885       *rv,
2886       *sv;
2887
2888     PERL_UNUSED_VAR(ref);
2889     PERL_UNUSED_VAR(ix);
2890     exception=AcquireExceptionInfo();
2891     perl_exception=newSVpv("",0);
2892     sv=NULL;
2893     attribute=NULL;
2894     av=NULL;
2895     if (sv_isobject(ST(0)) == 0)
2896       {
2897         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2898           PackageName);
2899         goto PerlException;
2900       }
2901     reference=SvRV(ST(0));
2902     hv=SvSTASH(reference);
2903     av=newAV();
2904     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2905     SvREFCNT_dec(av);
2906     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2907     if (image == (Image *) NULL)
2908       {
2909         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2910           PackageName);
2911         goto PerlException;
2912       }
2913     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2914     /*
2915       Get options.
2916     */
2917     channel=DefaultChannels;
2918     (void) CopyMagickString(expression,"u",MaxTextExtent);
2919     if (items == 2)
2920       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MaxTextExtent);
2921     else
2922       for (i=2; i < items; i+=2)
2923       {
2924         attribute=(char *) SvPV(ST(i-1),na);
2925         switch (*attribute)
2926         {
2927           case 'C':
2928           case 'c':
2929           {
2930             if (LocaleCompare(attribute,"channel") == 0)
2931               {
2932                 ssize_t
2933                   option;
2934
2935                 option=ParseChannelOption(SvPV(ST(i),na));
2936                 if (option < 0)
2937                   {
2938                     ThrowPerlException(exception,OptionError,
2939                       "UnrecognizedType",SvPV(ST(i),na));
2940                     return;
2941                   }
2942                 channel=(ChannelType) option;
2943                 break;
2944               }
2945             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2946               attribute);
2947             break;
2948           }
2949           case 'E':
2950           case 'e':
2951           {
2952             if (LocaleCompare(attribute,"expression") == 0)
2953               {
2954                 (void) CopyMagickString(expression,SvPV(ST(i),na),
2955                   MaxTextExtent);
2956                 break;
2957               }
2958             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2959               attribute);
2960             break;
2961           }
2962           default:
2963           {
2964             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2965               attribute);
2966             break;
2967           }
2968         }
2969       }
2970     channel_mask=SetImageChannelMask(image,channel);
2971     image=ChannelFxImage(image,expression,exception);
2972     if (image != (Image *) NULL)
2973       (void) SetImageChannelMask(image,channel_mask);
2974     if (image == (Image *) NULL)
2975       goto PerlException;
2976     for ( ; image; image=image->next)
2977     {
2978       AddImageToRegistry(sv,image);
2979       rv=newRV(sv);
2980       av_push(av,sv_bless(rv,hv));
2981       SvREFCNT_dec(sv);
2982     }
2983     exception=DestroyExceptionInfo(exception);
2984     ST(0)=av_reference;
2985     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
2986     XSRETURN(1);
2987
2988   PerlException:
2989     InheritPerlException(exception,perl_exception);
2990     exception=DestroyExceptionInfo(exception);
2991     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2992     SvPOK_on(perl_exception);
2993     ST(0)=sv_2mortal(perl_exception);
2994     XSRETURN(1);
2995   }
2996 \f
2997 #
2998 ###############################################################################
2999 #                                                                             #
3000 #                                                                             #
3001 #                                                                             #
3002 #   C l o n e                                                                 #
3003 #                                                                             #
3004 #                                                                             #
3005 #                                                                             #
3006 ###############################################################################
3007 #
3008 #
3009 void
3010 Clone(ref)
3011   Image::Magick ref=NO_INIT
3012   ALIAS:
3013     CopyImage   = 1
3014     copy        = 2
3015     copyimage   = 3
3016     CloneImage  = 4
3017     clone       = 5
3018     cloneimage  = 6
3019     Clone       = 7
3020   PPCODE:
3021   {
3022     AV
3023       *av;
3024
3025     ExceptionInfo
3026       *exception;
3027
3028     HV
3029       *hv;
3030
3031     Image
3032       *clone,
3033       *image;
3034
3035     struct PackageInfo
3036       *info;
3037
3038     SV
3039       *perl_exception,
3040       *reference,
3041       *rv,
3042       *sv;
3043
3044     PERL_UNUSED_VAR(ref);
3045     PERL_UNUSED_VAR(ix);
3046     exception=AcquireExceptionInfo();
3047     perl_exception=newSVpv("",0);
3048     sv=NULL;
3049     if (sv_isobject(ST(0)) == 0)
3050       {
3051         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3052           PackageName);
3053         goto PerlException;
3054       }
3055     reference=SvRV(ST(0));
3056     hv=SvSTASH(reference);
3057     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3058     if (image == (Image *) NULL)
3059       {
3060         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3061           PackageName);
3062         goto PerlException;
3063       }
3064     /*
3065       Create blessed Perl array for the returned image.
3066     */
3067     av=newAV();
3068     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3069     SvREFCNT_dec(av);
3070     for ( ; image; image=image->next)
3071     {
3072       clone=CloneImage(image,0,0,MagickTrue,exception);
3073       if (clone == (Image *) NULL)
3074         break;
3075       AddImageToRegistry(sv,clone);
3076       rv=newRV(sv);
3077       av_push(av,sv_bless(rv,hv));
3078       SvREFCNT_dec(sv);
3079     }
3080     exception=DestroyExceptionInfo(exception);
3081     SvREFCNT_dec(perl_exception);
3082     XSRETURN(1);
3083
3084   PerlException:
3085     InheritPerlException(exception,perl_exception);
3086     exception=DestroyExceptionInfo(exception);
3087     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3088     SvPOK_on(perl_exception);
3089     ST(0)=sv_2mortal(perl_exception);
3090     XSRETURN(1);
3091   }
3092 \f
3093 #
3094 ###############################################################################
3095 #                                                                             #
3096 #                                                                             #
3097 #                                                                             #
3098 #   C L O N E                                                                 #
3099 #                                                                             #
3100 #                                                                             #
3101 #                                                                             #
3102 ###############################################################################
3103 #
3104 #
3105 void
3106 CLONE(ref,...)
3107   SV *ref;
3108   CODE:
3109   {
3110     PERL_UNUSED_VAR(ref);
3111     if (magick_registry != (SplayTreeInfo *) NULL)
3112       {
3113         register Image
3114           *p;
3115
3116         ResetSplayTreeIterator(magick_registry);
3117         p=(Image *) GetNextKeyInSplayTree(magick_registry);
3118         while (p != (Image *) NULL)
3119         {
3120           ReferenceImage(p);
3121           p=(Image *) GetNextKeyInSplayTree(magick_registry);
3122         }
3123       }
3124   }
3125 \f
3126 #
3127 ###############################################################################
3128 #                                                                             #
3129 #                                                                             #
3130 #                                                                             #
3131 #   C o a l e s c e                                                           #
3132 #                                                                             #
3133 #                                                                             #
3134 #                                                                             #
3135 ###############################################################################
3136 #
3137 #
3138 void
3139 Coalesce(ref)
3140   Image::Magick ref=NO_INIT
3141   ALIAS:
3142     CoalesceImage   = 1
3143     coalesce        = 2
3144     coalesceimage   = 3
3145   PPCODE:
3146   {
3147     AV
3148       *av;
3149
3150     ExceptionInfo
3151       *exception;
3152
3153     HV
3154       *hv;
3155
3156     Image
3157       *image;
3158
3159     struct PackageInfo
3160       *info;
3161
3162     SV
3163       *av_reference,
3164       *perl_exception,
3165       *reference,
3166       *rv,
3167       *sv;
3168
3169     PERL_UNUSED_VAR(ref);
3170     PERL_UNUSED_VAR(ix);
3171     exception=AcquireExceptionInfo();
3172     perl_exception=newSVpv("",0);
3173     sv=NULL;
3174     if (sv_isobject(ST(0)) == 0)
3175       {
3176         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3177           PackageName);
3178         goto PerlException;
3179       }
3180     reference=SvRV(ST(0));
3181     hv=SvSTASH(reference);
3182     av=newAV();
3183     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3184     SvREFCNT_dec(av);
3185     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3186     if (image == (Image *) NULL)
3187       {
3188         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3189           PackageName);
3190         goto PerlException;
3191       }
3192     image=CoalesceImages(image,exception);
3193     if (image == (Image *) NULL)
3194       goto PerlException;
3195     for ( ; image; image=image->next)
3196     {
3197       AddImageToRegistry(sv,image);
3198       rv=newRV(sv);
3199       av_push(av,sv_bless(rv,hv));
3200       SvREFCNT_dec(sv);
3201     }
3202     exception=DestroyExceptionInfo(exception);
3203     ST(0)=av_reference;
3204     SvREFCNT_dec(perl_exception);
3205     XSRETURN(1);
3206
3207   PerlException:
3208     InheritPerlException(exception,perl_exception);
3209     exception=DestroyExceptionInfo(exception);
3210     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3211     SvPOK_on(perl_exception);
3212     ST(0)=sv_2mortal(perl_exception);
3213     XSRETURN(1);
3214   }
3215 \f
3216 #
3217 ###############################################################################
3218 #                                                                             #
3219 #                                                                             #
3220 #                                                                             #
3221 #   C o m p a r e                                                             #
3222 #                                                                             #
3223 #                                                                             #
3224 #                                                                             #
3225 ###############################################################################
3226 #
3227 #
3228 void
3229 Compare(ref,...)
3230   Image::Magick ref=NO_INIT
3231   ALIAS:
3232     CompareImages = 1
3233     compare      = 2
3234     compareimage = 3
3235   PPCODE:
3236   {
3237     AV
3238       *av;
3239
3240     char
3241       *attribute;
3242
3243     double
3244       distortion;
3245
3246     ExceptionInfo
3247       *exception;
3248
3249     HV
3250       *hv;
3251
3252     Image
3253       *difference_image,
3254       *image,
3255       *reconstruct_image;
3256
3257     MetricType
3258       metric;
3259
3260     register ssize_t
3261       i;
3262
3263     ssize_t
3264       option;
3265
3266     struct PackageInfo
3267       *info;
3268
3269     SV
3270       *av_reference,
3271       *perl_exception,
3272       *reference,
3273       *rv,
3274       *sv;
3275
3276     PERL_UNUSED_VAR(ref);
3277     PERL_UNUSED_VAR(ix);
3278     exception=AcquireExceptionInfo();
3279     perl_exception=newSVpv("",0);
3280     sv=NULL;
3281     av=NULL;
3282     attribute=NULL;
3283     if (sv_isobject(ST(0)) == 0)
3284       {
3285         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3286           PackageName);
3287         goto PerlException;
3288       }
3289     reference=SvRV(ST(0));
3290     hv=SvSTASH(reference);
3291     av=newAV();
3292     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3293     SvREFCNT_dec(av);
3294     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3295     if (image == (Image *) NULL)
3296       {
3297         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3298           PackageName);
3299         goto PerlException;
3300       }
3301     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3302     /*
3303       Get attribute.
3304     */
3305     reconstruct_image=image;
3306     metric=RootMeanSquaredErrorMetric;
3307     for (i=2; i < items; i+=2)
3308     {
3309       attribute=(char *) SvPV(ST(i-1),na);
3310       switch (*attribute)
3311       {
3312         case 'C':
3313         case 'c':
3314         {
3315           if (LocaleCompare(attribute,"channel") == 0)
3316             {
3317               ssize_t
3318                 option;
3319
3320               option=ParseChannelOption(SvPV(ST(i),na));
3321               if (option < 0)
3322                 {
3323                   ThrowPerlException(exception,OptionError,
3324                     "UnrecognizedType",SvPV(ST(i),na));
3325                   return;
3326                 }
3327               SetPixelChannelMask(image,(ChannelType) option);
3328               break;
3329             }
3330           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3331             attribute);
3332           break;
3333         }
3334         case 'F':
3335         case 'f':
3336         {
3337           if (LocaleCompare(attribute,"fuzz") == 0)
3338             {
3339               image->fuzz=StringToDoubleInterval(SvPV(ST(i),na),100.0);
3340               break;
3341             }
3342           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3343             attribute);
3344           break;
3345         }
3346         case 'I':
3347         case 'i':
3348         {
3349           if (LocaleCompare(attribute,"image") == 0)
3350             {
3351               reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3352                 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3353               break;
3354             }
3355           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3356             attribute);
3357           break;
3358         }
3359         case 'M':
3360         case 'm':
3361         {
3362           if (LocaleCompare(attribute,"metric") == 0)
3363             {
3364               option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3365                 SvPV(ST(i),na));
3366               if (option < 0)
3367                 {
3368                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3369                     SvPV(ST(i),na));
3370                   break;
3371                 }
3372               metric=(MetricType) option;
3373               break;
3374             }
3375           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3376             attribute);
3377           break;
3378         }
3379         default:
3380         {
3381           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3382             attribute);
3383           break;
3384         }
3385       }
3386     }
3387     difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3388       exception);
3389     if (difference_image != (Image *) NULL)
3390       {
3391         difference_image->error.mean_error_per_pixel=distortion;
3392         AddImageToRegistry(sv,difference_image);
3393         rv=newRV(sv);
3394         av_push(av,sv_bless(rv,hv));
3395         SvREFCNT_dec(sv);
3396       }
3397     exception=DestroyExceptionInfo(exception);
3398     ST(0)=av_reference;
3399     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3400     XSRETURN(1);
3401
3402   PerlException:
3403     InheritPerlException(exception,perl_exception);
3404     exception=DestroyExceptionInfo(exception);
3405     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3406     SvPOK_on(perl_exception);
3407     ST(0)=sv_2mortal(perl_exception);
3408     XSRETURN(1);
3409   }
3410 \f
3411 #
3412 ###############################################################################
3413 #                                                                             #
3414 #                                                                             #
3415 #                                                                             #
3416 #   C o m p a r e L a y e r s                                                 #
3417 #                                                                             #
3418 #                                                                             #
3419 #                                                                             #
3420 ###############################################################################
3421 #
3422 #
3423 void
3424 CompareLayers(ref)
3425   Image::Magick ref=NO_INIT
3426   ALIAS:
3427     CompareImagesLayers   = 1
3428     comparelayers        = 2
3429     compareimagelayers   = 3
3430   PPCODE:
3431   {
3432     AV
3433       *av;
3434
3435     char
3436       *attribute;
3437
3438     ExceptionInfo
3439       *exception;
3440
3441     HV
3442       *hv;
3443
3444     Image
3445       *image;
3446
3447     LayerMethod
3448       method;
3449
3450     register ssize_t
3451       i;
3452
3453     ssize_t
3454       option;
3455
3456     struct PackageInfo
3457       *info;
3458
3459     SV
3460       *av_reference,
3461       *perl_exception,
3462       *reference,
3463       *rv,
3464       *sv;
3465
3466     PERL_UNUSED_VAR(ref);
3467     PERL_UNUSED_VAR(ix);
3468     exception=AcquireExceptionInfo();
3469     perl_exception=newSVpv("",0);
3470     sv=NULL;
3471     if (sv_isobject(ST(0)) == 0)
3472       {
3473         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3474           PackageName);
3475         goto PerlException;
3476       }
3477     reference=SvRV(ST(0));
3478     hv=SvSTASH(reference);
3479     av=newAV();
3480     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3481     SvREFCNT_dec(av);
3482     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3483     if (image == (Image *) NULL)
3484       {
3485         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3486           PackageName);
3487         goto PerlException;
3488       }
3489     method=CompareAnyLayer;
3490     for (i=2; i < items; i+=2)
3491     {
3492       attribute=(char *) SvPV(ST(i-1),na);
3493       switch (*attribute)
3494       {
3495         case 'M':
3496         case 'm':
3497         {
3498           if (LocaleCompare(attribute,"method") == 0)
3499             {
3500               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3501                 SvPV(ST(i),na));
3502               if (option < 0)
3503                 {
3504                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3505                     SvPV(ST(i),na));
3506                   break;
3507                 }
3508                method=(LayerMethod) option;
3509               break;
3510             }
3511           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3512             attribute);
3513           break;
3514         }
3515         default:
3516         {
3517           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3518             attribute);
3519           break;
3520         }
3521       }
3522     }
3523     image=CompareImagesLayers(image,method,exception);
3524     if (image == (Image *) NULL)
3525       goto PerlException;
3526     for ( ; image; image=image->next)
3527     {
3528       AddImageToRegistry(sv,image);
3529       rv=newRV(sv);
3530       av_push(av,sv_bless(rv,hv));
3531       SvREFCNT_dec(sv);
3532     }
3533     exception=DestroyExceptionInfo(exception);
3534     ST(0)=av_reference;
3535     SvREFCNT_dec(perl_exception);
3536     XSRETURN(1);
3537
3538   PerlException:
3539     InheritPerlException(exception,perl_exception);
3540     exception=DestroyExceptionInfo(exception);
3541     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3542     SvPOK_on(perl_exception);
3543     ST(0)=sv_2mortal(perl_exception);
3544     XSRETURN(1);
3545   }
3546 \f
3547 #
3548 ###############################################################################
3549 #                                                                             #
3550 #                                                                             #
3551 #                                                                             #
3552 #   D e s t r o y                                                             #
3553 #                                                                             #
3554 #                                                                             #
3555 #                                                                             #
3556 ###############################################################################
3557 #
3558 #
3559 void
3560 DESTROY(ref)
3561   Image::Magick ref=NO_INIT
3562   PPCODE:
3563   {
3564     SV
3565       *reference;
3566
3567     PERL_UNUSED_VAR(ref);
3568     if (sv_isobject(ST(0)) == 0)
3569       croak("ReferenceIsNotMyType");
3570     reference=SvRV(ST(0));
3571     switch (SvTYPE(reference))
3572     {
3573       case SVt_PVAV:
3574       {
3575         char
3576           message[MaxTextExtent];
3577
3578         const SV
3579           *key;
3580
3581         HV
3582           *hv;
3583
3584         GV
3585           **gvp;
3586
3587         struct PackageInfo
3588           *info;
3589
3590         SV
3591           *sv;
3592
3593         /*
3594           Array (AV *) reference
3595         */
3596         (void) FormatLocaleString(message,MaxTextExtent,"package%s%p",
3597           XS_VERSION,reference);
3598         hv=gv_stashpv(PackageName, FALSE);
3599         if (!hv)
3600           break;
3601         gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3602         if (!gvp)
3603           break;
3604         sv=GvSV(*gvp);
3605         if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3606           {
3607             info=INT2PTR(struct PackageInfo *,SvIV(sv));
3608             DestroyPackageInfo(info);
3609           }
3610         key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3611         (void) key;
3612         break;
3613       }
3614       case SVt_PVMG:
3615       {
3616         Image
3617           *image;
3618
3619         /*
3620           Blessed scalar = (Image *) SvIV(reference)
3621         */
3622         image=INT2PTR(Image *,SvIV(reference));
3623         if (image != (Image *) NULL)
3624           DeleteImageFromRegistry(reference,image);
3625         break;
3626       }
3627       default:
3628         break;
3629     }
3630   }
3631 \f
3632 #
3633 ###############################################################################
3634 #                                                                             #
3635 #                                                                             #
3636 #                                                                             #
3637 #   D i s p l a y                                                             #
3638 #                                                                             #
3639 #                                                                             #
3640 #                                                                             #
3641 ###############################################################################
3642 #
3643 #
3644 void
3645 Display(ref,...)
3646   Image::Magick ref=NO_INIT
3647   ALIAS:
3648     DisplayImage  = 1
3649     display       = 2
3650     displayimage  = 3
3651   PPCODE:
3652   {
3653     ExceptionInfo
3654       *exception;
3655
3656     Image
3657       *image;
3658
3659     register ssize_t
3660       i;
3661
3662     struct PackageInfo
3663       *info,
3664       *package_info;
3665
3666     SV
3667       *perl_exception,
3668       *reference;
3669
3670     PERL_UNUSED_VAR(ref);
3671     PERL_UNUSED_VAR(ix);
3672     exception=AcquireExceptionInfo();
3673     perl_exception=newSVpv("",0);
3674     package_info=(struct PackageInfo *) NULL;
3675     if (sv_isobject(ST(0)) == 0)
3676       {
3677         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3678           PackageName);
3679         goto PerlException;
3680       }
3681     reference=SvRV(ST(0));
3682     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3683     if (image == (Image *) NULL)
3684       {
3685         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3686           PackageName);
3687         goto PerlException;
3688       }
3689     package_info=ClonePackageInfo(info,exception);
3690     if (items == 2)
3691       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3692     else
3693       if (items > 2)
3694         for (i=2; i < items; i+=2)
3695           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3696             exception);
3697     (void) DisplayImages(package_info->image_info,image,exception);
3698     (void) CatchImageException(image);
3699
3700   PerlException:
3701     if (package_info != (struct PackageInfo *) NULL)
3702       DestroyPackageInfo(package_info);
3703     InheritPerlException(exception,perl_exception);
3704     exception=DestroyExceptionInfo(exception);
3705     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3706     SvPOK_on(perl_exception);
3707     ST(0)=sv_2mortal(perl_exception);
3708     XSRETURN(1);
3709   }
3710 \f
3711 #
3712 ###############################################################################
3713 #                                                                             #
3714 #                                                                             #
3715 #                                                                             #
3716 #   E v a l u a t e I m a g e s                                               #
3717 #                                                                             #
3718 #                                                                             #
3719 #                                                                             #
3720 ###############################################################################
3721 #
3722 #
3723 void
3724 EvaluateImages(ref)
3725   Image::Magick ref=NO_INIT
3726   ALIAS:
3727     EvaluateImages   = 1
3728     evaluateimages   = 2
3729   PPCODE:
3730   {
3731     AV
3732       *av;
3733
3734     char
3735       *attribute,
3736       *p;
3737
3738     ExceptionInfo
3739       *exception;
3740
3741     HV
3742       *hv;
3743
3744     Image
3745       *image;
3746
3747     MagickEvaluateOperator
3748       op;
3749
3750     register ssize_t
3751       i;
3752
3753     struct PackageInfo
3754       *info;
3755
3756     SV
3757       *perl_exception,
3758       *reference,
3759       *rv,
3760       *sv;
3761
3762     PERL_UNUSED_VAR(ref);
3763     PERL_UNUSED_VAR(ix);
3764     exception=AcquireExceptionInfo();
3765     perl_exception=newSVpv("",0);
3766     sv=NULL;
3767     if (sv_isobject(ST(0)) == 0)
3768       {
3769         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3770           PackageName);
3771         goto PerlException;
3772       }
3773     reference=SvRV(ST(0));
3774     hv=SvSTASH(reference);
3775     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3776     if (image == (Image *) NULL)
3777       {
3778         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3779           PackageName);
3780         goto PerlException;
3781       }
3782     op=MeanEvaluateOperator;
3783     if (items == 2)
3784       {
3785         ssize_t
3786           in;
3787
3788         in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
3789           SvPV(ST(1),na));
3790         if (in < 0)
3791           {
3792             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3793               SvPV(ST(1),na));
3794             return;
3795           }
3796         op=(MagickEvaluateOperator) in;
3797       }
3798     else
3799       for (i=2; i < items; i+=2)
3800       {
3801         attribute=(char *) SvPV(ST(i-1),na);
3802         switch (*attribute)
3803         {
3804           case 'O':
3805           case 'o':
3806           {
3807             if (LocaleCompare(attribute,"operator") == 0)
3808               {
3809                 ssize_t
3810                   in;
3811
3812                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3813                   MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
3814                 if (in < 0)
3815                   {
3816                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3817                       SvPV(ST(i),na));
3818                     return;
3819                   }
3820                 op=(MagickEvaluateOperator) in;
3821                 break;
3822               }
3823             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3824               attribute);
3825             break;
3826           }
3827           default:
3828           {
3829             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3830               attribute);
3831             break;
3832           }
3833         }
3834       }
3835     image=EvaluateImages(image,op,exception);
3836     if (image == (Image *) NULL)
3837       goto PerlException;
3838     /*
3839       Create blessed Perl array for the returned image.
3840     */
3841     av=newAV();
3842     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3843     SvREFCNT_dec(av);
3844     AddImageToRegistry(sv,image);
3845     rv=newRV(sv);
3846     av_push(av,sv_bless(rv,hv));
3847     SvREFCNT_dec(sv);
3848     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3849     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
3850       "evaluate-%.*s",(int) (MaxTextExtent-9),
3851       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3852     (void) CopyMagickString(image->filename,info->image_info->filename,
3853       MaxTextExtent);
3854     SetImageInfo(info->image_info,0,exception);
3855     exception=DestroyExceptionInfo(exception);
3856     SvREFCNT_dec(perl_exception);
3857     XSRETURN(1);
3858
3859   PerlException:
3860     InheritPerlException(exception,perl_exception);
3861     exception=DestroyExceptionInfo(exception);
3862     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3863     SvPOK_on(perl_exception);
3864     ST(0)=sv_2mortal(perl_exception);
3865     XSRETURN(1);
3866   }
3867 \f
3868 #
3869 ###############################################################################
3870 #                                                                             #
3871 #                                                                             #
3872 #                                                                             #
3873 #   F e a t u r e s                                                           #
3874 #                                                                             #
3875 #                                                                             #
3876 #                                                                             #
3877 ###############################################################################
3878 #
3879 #
3880 void
3881 Features(ref,...)
3882   Image::Magick ref=NO_INIT
3883   ALIAS:
3884     FeaturesImage = 1
3885     features      = 2
3886     featuresimage = 3
3887   PPCODE:
3888   {
3889 #define ChannelFeatures(channel,direction) \
3890 { \
3891   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3892     channel_features[channel].angular_second_moment[direction]); \
3893   PUSHs(sv_2mortal(newSVpv(message,0))); \
3894   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3895     channel_features[channel].contrast[direction]); \
3896   PUSHs(sv_2mortal(newSVpv(message,0))); \
3897   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3898     channel_features[channel].contrast[direction]); \
3899   PUSHs(sv_2mortal(newSVpv(message,0))); \
3900   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3901     channel_features[channel].variance_sum_of_squares[direction]); \
3902   PUSHs(sv_2mortal(newSVpv(message,0))); \
3903   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3904     channel_features[channel].inverse_difference_moment[direction]); \
3905   PUSHs(sv_2mortal(newSVpv(message,0))); \
3906   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3907     channel_features[channel].sum_average[direction]); \
3908   PUSHs(sv_2mortal(newSVpv(message,0))); \
3909   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3910     channel_features[channel].sum_variance[direction]); \
3911   PUSHs(sv_2mortal(newSVpv(message,0))); \
3912   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3913     channel_features[channel].sum_entropy[direction]); \
3914   PUSHs(sv_2mortal(newSVpv(message,0))); \
3915   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3916     channel_features[channel].entropy[direction]); \
3917   PUSHs(sv_2mortal(newSVpv(message,0))); \
3918   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3919     channel_features[channel].difference_variance[direction]); \
3920   PUSHs(sv_2mortal(newSVpv(message,0))); \
3921   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3922     channel_features[channel].difference_entropy[direction]); \
3923   PUSHs(sv_2mortal(newSVpv(message,0))); \
3924   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3925     channel_features[channel].measure_of_correlation_1[direction]); \
3926   PUSHs(sv_2mortal(newSVpv(message,0))); \
3927   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3928     channel_features[channel].measure_of_correlation_2[direction]); \
3929   PUSHs(sv_2mortal(newSVpv(message,0))); \
3930   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3931     channel_features[channel].maximum_correlation_coefficient[direction]); \
3932   PUSHs(sv_2mortal(newSVpv(message,0))); \
3933 }
3934
3935     AV
3936       *av;
3937
3938     char
3939       *attribute,
3940       message[MaxTextExtent];
3941
3942     ChannelFeatures
3943       *channel_features;
3944
3945     double
3946       distance;
3947
3948     ExceptionInfo
3949       *exception;
3950
3951     Image
3952       *image;
3953
3954     register ssize_t
3955       i;
3956
3957     ssize_t
3958       count;
3959
3960     struct PackageInfo
3961       *info;
3962
3963     SV
3964       *perl_exception,
3965       *reference;
3966
3967     PERL_UNUSED_VAR(ref);
3968     PERL_UNUSED_VAR(ix);
3969     exception=AcquireExceptionInfo();
3970     perl_exception=newSVpv("",0);
3971     av=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     av=newAV();
3980     SvREFCNT_dec(av);
3981     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3982     if (image == (Image *) NULL)
3983       {
3984         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3985           PackageName);
3986         goto PerlException;
3987       }
3988     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3989     distance=1;
3990     for (i=2; i < items; i+=2)
3991     {
3992       attribute=(char *) SvPV(ST(i-1),na);
3993       switch (*attribute)
3994       {
3995         case 'D':
3996         case 'd':
3997         {
3998           if (LocaleCompare(attribute,"distance") == 0)
3999             {
4000               distance=StringToLong((char *) SvPV(ST(1),na));
4001               break;
4002             }
4003           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4004             attribute);
4005           break;
4006         }
4007         default:
4008         {
4009           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4010             attribute);
4011           break;
4012         }
4013       }
4014     }
4015     count=0;
4016     for ( ; image; image=image->next)
4017     {
4018       channel_features=GetImageFeatures(image,distance,exception);
4019       if (channel_features == (ChannelFeatures *) NULL)
4020         continue;
4021       count++;
4022       EXTEND(sp,75*count);
4023       for (i=0; i < 4; i++)
4024       {
4025         ChannelFeatures(RedChannel,i);
4026         ChannelFeatures(GreenChannel,i);
4027         ChannelFeatures(BlueChannel,i);
4028         if (image->colorspace == CMYKColorspace)
4029           ChannelFeatures(BlackChannel,i);
4030         if (image->alpha_trait == BlendPixelTrait)
4031           ChannelFeatures(AlphaChannel,i);
4032       }
4033       channel_features=(ChannelFeatures *)
4034         RelinquishMagickMemory(channel_features);
4035     }
4036
4037   PerlException:
4038     InheritPerlException(exception,perl_exception);
4039     exception=DestroyExceptionInfo(exception);
4040     SvREFCNT_dec(perl_exception);
4041   }
4042 \f
4043 #
4044 ###############################################################################
4045 #                                                                             #
4046 #                                                                             #
4047 #                                                                             #
4048 #   F l a t t e n                                                             #
4049 #                                                                             #
4050 #                                                                             #
4051 #                                                                             #
4052 ###############################################################################
4053 #
4054 #
4055 void
4056 Flatten(ref)
4057   Image::Magick ref=NO_INIT
4058   ALIAS:
4059     FlattenImage   = 1
4060     flatten        = 2
4061     flattenimage   = 3
4062   PPCODE:
4063   {
4064     AV
4065       *av;
4066
4067     char
4068       *attribute,
4069       *p;
4070
4071     ExceptionInfo
4072       *exception;
4073
4074     HV
4075       *hv;
4076
4077     Image
4078       *image;
4079
4080     PixelInfo
4081       background_color;
4082
4083     register ssize_t
4084       i;
4085
4086     struct PackageInfo
4087       *info;
4088
4089     SV
4090       *perl_exception,
4091       *reference,
4092       *rv,
4093       *sv;
4094
4095     PERL_UNUSED_VAR(ref);
4096     PERL_UNUSED_VAR(ix);
4097     exception=AcquireExceptionInfo();
4098     perl_exception=newSVpv("",0);
4099     sv=NULL;
4100     if (sv_isobject(ST(0)) == 0)
4101       {
4102         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4103           PackageName);
4104         goto PerlException;
4105       }
4106     reference=SvRV(ST(0));
4107     hv=SvSTASH(reference);
4108     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4109     if (image == (Image *) NULL)
4110       {
4111         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4112           PackageName);
4113         goto PerlException;
4114       }
4115     background_color=image->background_color;
4116     if (items == 2)
4117       (void) QueryColorCompliance((char *) SvPV(ST(1),na),AllCompliance,
4118         &background_color,exception);
4119     else
4120       for (i=2; i < items; i+=2)
4121       {
4122         attribute=(char *) SvPV(ST(i-1),na);
4123         switch (*attribute)
4124         {
4125           case 'B':
4126           case 'b':
4127           {
4128             if (LocaleCompare(attribute,"background") == 0)
4129               {
4130                 (void) QueryColorCompliance((char *) SvPV(ST(1),na),
4131                   AllCompliance,&background_color,exception);
4132                 break;
4133               }
4134             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4135               attribute);
4136             break;
4137           }
4138           default:
4139           {
4140             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4141               attribute);
4142             break;
4143           }
4144         }
4145       }
4146     image->background_color=background_color;
4147     image=MergeImageLayers(image,FlattenLayer,exception);
4148     if (image == (Image *) NULL)
4149       goto PerlException;
4150     /*
4151       Create blessed Perl array for the returned image.
4152     */
4153     av=newAV();
4154     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4155     SvREFCNT_dec(av);
4156     AddImageToRegistry(sv,image);
4157     rv=newRV(sv);
4158     av_push(av,sv_bless(rv,hv));
4159     SvREFCNT_dec(sv);
4160     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4161     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
4162       "flatten-%.*s",(int) (MaxTextExtent-9),
4163       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4164     (void) CopyMagickString(image->filename,info->image_info->filename,
4165       MaxTextExtent);
4166     SetImageInfo(info->image_info,0,exception);
4167     exception=DestroyExceptionInfo(exception);
4168     SvREFCNT_dec(perl_exception);
4169     XSRETURN(1);
4170
4171   PerlException:
4172     InheritPerlException(exception,perl_exception);
4173     exception=DestroyExceptionInfo(exception);
4174     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4175     SvPOK_on(perl_exception);  /* return messages in string context */
4176     ST(0)=sv_2mortal(perl_exception);
4177     XSRETURN(1);
4178   }
4179 \f
4180 #
4181 ###############################################################################
4182 #                                                                             #
4183 #                                                                             #
4184 #                                                                             #
4185 #   F x                                                                       #
4186 #                                                                             #
4187 #                                                                             #
4188 #                                                                             #
4189 ###############################################################################
4190 #
4191 #
4192 void
4193 Fx(ref,...)
4194   Image::Magick ref=NO_INIT
4195   ALIAS:
4196     FxImage  = 1
4197     fx       = 2
4198     fximage  = 3
4199   PPCODE:
4200   {
4201     AV
4202       *av;
4203
4204     char
4205       *attribute,
4206       expression[MaxTextExtent];
4207
4208     ChannelType
4209       channel,
4210       channel_mask;
4211
4212     ExceptionInfo
4213       *exception;
4214
4215     HV
4216       *hv;
4217
4218     Image
4219       *image;
4220
4221     register ssize_t
4222       i;
4223
4224     struct PackageInfo
4225       *info;
4226
4227     SV
4228       *av_reference,
4229       *perl_exception,
4230       *reference,
4231       *rv,
4232       *sv;
4233
4234     PERL_UNUSED_VAR(ref);
4235     PERL_UNUSED_VAR(ix);
4236     exception=AcquireExceptionInfo();
4237     perl_exception=newSVpv("",0);
4238     sv=NULL;
4239     attribute=NULL;
4240     av=NULL;
4241     if (sv_isobject(ST(0)) == 0)
4242       {
4243         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4244           PackageName);
4245         goto PerlException;
4246       }
4247     reference=SvRV(ST(0));
4248     hv=SvSTASH(reference);
4249     av=newAV();
4250     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4251     SvREFCNT_dec(av);
4252     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4253     if (image == (Image *) NULL)
4254       {
4255         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4256           PackageName);
4257         goto PerlException;
4258       }
4259     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4260     /*
4261       Get options.
4262     */
4263     channel=DefaultChannels;
4264     (void) CopyMagickString(expression,"u",MaxTextExtent);
4265     if (items == 2)
4266       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MaxTextExtent);
4267     else
4268       for (i=2; i < items; i+=2)
4269       {
4270         attribute=(char *) SvPV(ST(i-1),na);
4271         switch (*attribute)
4272         {
4273           case 'C':
4274           case 'c':
4275           {
4276             if (LocaleCompare(attribute,"channel") == 0)
4277               {
4278                 ssize_t
4279                   option;
4280
4281                 option=ParseChannelOption(SvPV(ST(i),na));
4282                 if (option < 0)
4283                   {
4284                     ThrowPerlException(exception,OptionError,
4285                       "UnrecognizedType",SvPV(ST(i),na));
4286                     return;
4287                   }
4288                 channel=(ChannelType) option;
4289                 break;
4290               }
4291             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4292               attribute);
4293             break;
4294           }
4295           case 'E':
4296           case 'e':
4297           {
4298             if (LocaleCompare(attribute,"expression") == 0)
4299               {
4300                 (void) CopyMagickString(expression,SvPV(ST(i),na),
4301                   MaxTextExtent);
4302                 break;
4303               }
4304             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4305               attribute);
4306             break;
4307           }
4308           default:
4309           {
4310             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4311               attribute);
4312             break;
4313           }
4314         }
4315       }
4316     channel_mask=SetImageChannelMask(image,channel);
4317     image=FxImage(image,expression,exception);
4318     if (image != (Image *) NULL)
4319       (void) SetImageChannelMask(image,channel_mask);
4320     if (image == (Image *) NULL)
4321       goto PerlException;
4322     for ( ; image; image=image->next)
4323     {
4324       AddImageToRegistry(sv,image);
4325       rv=newRV(sv);
4326       av_push(av,sv_bless(rv,hv));
4327       SvREFCNT_dec(sv);
4328     }
4329     exception=DestroyExceptionInfo(exception);
4330     ST(0)=av_reference;
4331     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4332     XSRETURN(1);
4333
4334   PerlException:
4335     InheritPerlException(exception,perl_exception);
4336     exception=DestroyExceptionInfo(exception);
4337     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4338     SvPOK_on(perl_exception);
4339     ST(0)=sv_2mortal(perl_exception);
4340     XSRETURN(1);
4341   }
4342 \f
4343 #
4344 ###############################################################################
4345 #                                                                             #
4346 #                                                                             #
4347 #                                                                             #
4348 #   G e t                                                                     #
4349 #                                                                             #
4350 #                                                                             #
4351 #                                                                             #
4352 ###############################################################################
4353 #
4354 #
4355 void
4356 Get(ref,...)
4357   Image::Magick ref=NO_INIT
4358   ALIAS:
4359     GetAttributes = 1
4360     GetAttribute  = 2
4361     get           = 3
4362     getattributes = 4
4363     getattribute  = 5
4364   PPCODE:
4365   {
4366     char
4367       *attribute,
4368       color[MaxTextExtent];
4369
4370     const char
4371       *value;
4372
4373     ExceptionInfo
4374       *exception;
4375
4376     Image
4377       *image;
4378
4379     long
4380       j;
4381
4382     register ssize_t
4383       i;
4384
4385     struct PackageInfo
4386       *info;
4387
4388     SV
4389       *perl_exception,
4390       *reference,
4391       *s;
4392
4393     PERL_UNUSED_VAR(ref);
4394     PERL_UNUSED_VAR(ix);
4395     exception=AcquireExceptionInfo();
4396     perl_exception=newSVpv("",0);
4397     if (sv_isobject(ST(0)) == 0)
4398       {
4399         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4400           PackageName);
4401         XSRETURN_EMPTY;
4402       }
4403     reference=SvRV(ST(0));
4404     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4405     if (image == (Image *) NULL && !info)
4406       XSRETURN_EMPTY;
4407     EXTEND(sp,items);
4408     for (i=1; i < items; i++)
4409     {
4410       attribute=(char *) SvPV(ST(i),na);
4411       s=NULL;
4412       switch (*attribute)
4413       {
4414         case 'A':
4415         case 'a':
4416         {
4417           if (LocaleCompare(attribute,"adjoin") == 0)
4418             {
4419               if (info)
4420                 s=newSViv((ssize_t) info->image_info->adjoin);
4421               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4422               continue;
4423             }
4424           if (LocaleCompare(attribute,"antialias") == 0)
4425             {
4426               if (info)
4427                 s=newSViv((ssize_t) info->image_info->antialias);
4428               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4429               continue;
4430             }
4431           if (LocaleCompare(attribute,"area") == 0)
4432             {
4433               s=newSViv(GetMagickResource(AreaResource));
4434               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4435               continue;
4436             }
4437           if (LocaleCompare(attribute,"attenuate") == 0)
4438             {
4439               const char
4440                 *value;
4441
4442               value=GetImageProperty(image,attribute,exception);
4443               if (value != (const char *) NULL)
4444                 s=newSVpv(value,0);
4445               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4446               continue;
4447             }
4448           if (LocaleCompare(attribute,"authenticate") == 0)
4449             {
4450               if (info)
4451                 {
4452                   const char
4453                     *option;
4454
4455                   option=GetImageOption(info->image_info,attribute);
4456                   if (option != (const char *) NULL)
4457                     s=newSVpv(option,0);
4458                 }
4459               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4460               continue;
4461             }
4462           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4463             attribute);
4464           break;
4465         }
4466         case 'B':
4467         case 'b':
4468         {
4469           if (LocaleCompare(attribute,"background") == 0)
4470             {
4471               if (image == (Image *) NULL)
4472                 break;
4473               (void) FormatLocaleString(color,MaxTextExtent,
4474                 "%.20g,%.20g,%.20g,%.20g",image->background_color.red,
4475                 image->background_color.green,image->background_color.blue,
4476                 image->background_color.alpha);
4477               s=newSVpv(color,0);
4478               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4479               continue;
4480             }
4481           if (LocaleCompare(attribute,"base-columns") == 0)
4482             {
4483               if (image != (Image *) NULL)
4484                 s=newSViv((ssize_t) image->magick_columns);
4485               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4486               continue;
4487             }
4488           if (LocaleCompare(attribute,"base-filename") == 0)
4489             {
4490               if (image != (Image *) NULL)
4491                 s=newSVpv(image->magick_filename,0);
4492               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4493               continue;
4494             }
4495           if (LocaleCompare(attribute,"base-height") == 0)
4496             {
4497               if (image != (Image *) NULL)
4498                 s=newSViv((ssize_t) image->magick_rows);
4499               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4500               continue;
4501             }
4502           if (LocaleCompare(attribute,"base-rows") == 0)
4503             {
4504               if (image != (Image *) NULL)
4505                 s=newSViv((ssize_t) image->magick_rows);
4506               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4507               continue;
4508             }
4509           if (LocaleCompare(attribute,"base-width") == 0)
4510             {
4511               if (image != (Image *) NULL)
4512                 s=newSViv((ssize_t) image->magick_columns);
4513               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4514               continue;
4515             }
4516           if (LocaleCompare(attribute,"blue-primary") == 0)
4517             {
4518               if (image == (Image *) NULL)
4519                 break;
4520               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4521                 image->chromaticity.blue_primary.x,
4522                 image->chromaticity.blue_primary.y);
4523               s=newSVpv(color,0);
4524               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4525               continue;
4526             }
4527           if (LocaleCompare(attribute,"bordercolor") == 0)
4528             {
4529               if (image == (Image *) NULL)
4530                 break;
4531               (void) FormatLocaleString(color,MaxTextExtent,
4532                 "%.20g,%.20g,%.20g,%.20g",image->border_color.red,
4533                 image->border_color.green,image->border_color.blue,
4534                 image->border_color.alpha);
4535               s=newSVpv(color,0);
4536               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4537               continue;
4538             }
4539           if (LocaleCompare(attribute,"bounding-box") == 0)
4540             {
4541               char
4542                 geometry[MaxTextExtent];
4543
4544               RectangleInfo
4545                 page;
4546
4547               if (image == (Image *) NULL)
4548                 break;
4549               page=GetImageBoundingBox(image,exception);
4550               (void) FormatLocaleString(geometry,MaxTextExtent,
4551                 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4552                 page.height,(double) page.x,(double) page.y);
4553               s=newSVpv(geometry,0);
4554               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4555               continue;
4556             }
4557           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4558             attribute);
4559           break;
4560         }
4561         case 'C':
4562         case 'c':
4563         {
4564           if (LocaleCompare(attribute,"class") == 0)
4565             {
4566               if (image == (Image *) NULL)
4567                 break;
4568               s=newSViv(image->storage_class);
4569               (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4570                 image->storage_class));
4571               SvIOK_on(s);
4572               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4573               continue;
4574             }
4575           if (LocaleCompare(attribute,"clip-mask") == 0)
4576             {
4577               if (image != (Image *) NULL)
4578                 {
4579                   Image
4580                     *mask_image;
4581
4582                   SV
4583                     *sv;
4584
4585                   sv=NULL;
4586                   if (image->mask == MagickFalse)
4587                     ClipImage(image,exception);
4588                   mask_image=GetImageMask(image,exception);
4589                   if (mask_image != (Image *) NULL)
4590                     {
4591                       AddImageToRegistry(sv,mask_image);
4592                       s=sv_bless(newRV(sv),SvSTASH(reference));
4593                     }
4594                 }
4595               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4596               continue;
4597             }
4598           if (LocaleCompare(attribute,"clip-path") == 0)
4599             {
4600               if (image != (Image *) NULL)
4601                 {
4602                   Image
4603                     *mask_image;
4604
4605                   SV
4606                     *sv;
4607
4608                   sv=NULL;
4609                   if (image->mask != MagickFalse)
4610                     ClipImage(image,exception);
4611                   mask_image=GetImageMask(image,exception);
4612                   if (mask_image != (Image *) NULL)
4613                     {
4614                       AddImageToRegistry(sv,mask_image);
4615                       s=sv_bless(newRV(sv),SvSTASH(reference));
4616                     }
4617                 }
4618               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4619               continue;
4620             }
4621           if (LocaleCompare(attribute,"compression") == 0)
4622             {
4623               j=info ? info->image_info->compression : image ?
4624                 image->compression : UndefinedCompression;
4625               if (info)
4626                 if (info->image_info->compression == UndefinedCompression)
4627                   j=image->compression;
4628               s=newSViv(j);
4629               (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4630                 j));
4631               SvIOK_on(s);
4632               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4633               continue;
4634             }
4635           if (LocaleCompare(attribute,"colorspace") == 0)
4636             {
4637               j=image ? image->colorspace : RGBColorspace;
4638               s=newSViv(j);
4639               (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4640                 j));
4641               SvIOK_on(s);
4642               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4643               continue;
4644             }
4645           if (LocaleCompare(attribute,"colors") == 0)
4646             {
4647               if (image != (Image *) NULL)
4648                 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4649                   exception));
4650               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4651               continue;
4652             }
4653           if (LocaleNCompare(attribute,"colormap",8) == 0)
4654             {
4655               int
4656                 items;
4657
4658               if (image == (Image *) NULL || !image->colormap)
4659                 break;
4660               j=0;
4661               items=sscanf(attribute,"%*[^[][%ld",&j);
4662               (void) items;
4663               if (j > (ssize_t) image->colors)
4664                 j%=image->colors;
4665               (void) FormatLocaleString(color,MaxTextExtent,
4666                 "%.20g,%.20g,%.20g,%.20g",image->colormap[j].red,
4667                 image->colormap[j].green,image->colormap[j].blue,
4668                 image->colormap[j].alpha);
4669               s=newSVpv(color,0);
4670               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4671               continue;
4672             }
4673           if (LocaleCompare(attribute,"columns") == 0)
4674             {
4675               if (image != (Image *) NULL)
4676                 s=newSViv((ssize_t) image->columns);
4677               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4678               continue;
4679             }
4680           if (LocaleCompare(attribute,"comment") == 0)
4681             {
4682               const char
4683                 *value;
4684
4685               value=GetImageProperty(image,attribute,exception);
4686               if (value != (const char *) NULL)
4687                 s=newSVpv(value,0);
4688               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4689               continue;
4690             }
4691           if (LocaleCompare(attribute,"copyright") == 0)
4692             {
4693               s=newSVpv(GetMagickCopyright(),0);
4694               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4695               continue;
4696             }
4697           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4698             attribute);
4699           break;
4700         }
4701         case 'D':
4702         case 'd':
4703         {
4704           if (LocaleCompare(attribute,"density") == 0)
4705             {
4706               char
4707                 geometry[MaxTextExtent];
4708
4709               if (image == (Image *) NULL)
4710                 break;
4711               (void) FormatLocaleString(geometry,MaxTextExtent,"%.15gx%.15g",
4712                 image->resolution.x,image->resolution.y);
4713               s=newSVpv(geometry,0);
4714               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4715               continue;
4716             }
4717           if (LocaleCompare(attribute,"delay") == 0)
4718             {
4719               if (image != (Image *) NULL)
4720                 s=newSViv((ssize_t) image->delay);
4721               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4722               continue;
4723             }
4724           if (LocaleCompare(attribute,"depth") == 0)
4725             {
4726               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4727               if (image != (Image *) NULL)
4728                 s=newSViv((ssize_t) GetImageDepth(image,exception));
4729               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4730               continue;
4731             }
4732           if (LocaleCompare(attribute,"directory") == 0)
4733             {
4734               if (image && image->directory)
4735                 s=newSVpv(image->directory,0);
4736               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4737               continue;
4738             }
4739           if (LocaleCompare(attribute,"dispose") == 0)
4740             {
4741               if (image == (Image *) NULL)
4742                 break;
4743
4744               s=newSViv(image->dispose);
4745               (void) sv_setpv(s,
4746                 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
4747               SvIOK_on(s);
4748               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4749               continue;
4750             }
4751           if (LocaleCompare(attribute,"disk") == 0)
4752             {
4753               s=newSViv(GetMagickResource(DiskResource));
4754               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4755               continue;
4756             }
4757           if (LocaleCompare(attribute,"dither") == 0)
4758             {
4759               if (info)
4760                 s=newSViv((ssize_t) info->image_info->dither);
4761               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4762               continue;
4763             }
4764           if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4765             {
4766               if (info && info->image_info->server_name)
4767                 s=newSVpv(info->image_info->server_name,0);
4768               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4769               continue;
4770             }
4771           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4772             attribute);
4773           break;
4774         }
4775         case 'E':
4776         case 'e':
4777         {
4778           if (LocaleCompare(attribute,"elapsed-time") == 0)
4779             {
4780               if (image != (Image *) NULL)
4781                 s=newSVnv(GetElapsedTime(&image->timer));
4782               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4783               continue;
4784             }
4785           if (LocaleCompare(attribute,"endian") == 0)
4786             {
4787               j=info ? info->image_info->endian : image ? image->endian :
4788                 UndefinedEndian;
4789               s=newSViv(j);
4790               (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
4791               SvIOK_on(s);
4792               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4793               continue;
4794             }
4795           if (LocaleCompare(attribute,"error") == 0)
4796             {
4797               if (image != (Image *) NULL)
4798                 s=newSVnv(image->error.mean_error_per_pixel);
4799               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4800               continue;
4801             }
4802           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4803             attribute);
4804           break;
4805         }
4806         case 'F':
4807         case 'f':
4808         {
4809           if (LocaleCompare(attribute,"filesize") == 0)
4810             {
4811               if (image != (Image *) NULL)
4812                 s=newSViv((ssize_t) GetBlobSize(image));
4813               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4814               continue;
4815             }
4816           if (LocaleCompare(attribute,"filename") == 0)
4817             {
4818               if (info && info->image_info->filename &&
4819                   *info->image_info->filename)
4820                 s=newSVpv(info->image_info->filename,0);
4821               if (image != (Image *) NULL)
4822                 s=newSVpv(image->filename,0);
4823               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4824               continue;
4825             }
4826           if (LocaleCompare(attribute,"filter") == 0)
4827             {
4828               s=image ? newSViv(image->filter) : newSViv(0);
4829               (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
4830                 image->filter));
4831               SvIOK_on(s);
4832               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4833               continue;
4834             }
4835           if (LocaleCompare(attribute,"font") == 0)
4836             {
4837               if (info && info->image_info->font)
4838                 s=newSVpv(info->image_info->font,0);
4839               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4840               continue;
4841             }
4842           if (LocaleCompare(attribute,"foreground") == 0)
4843             continue;
4844           if (LocaleCompare(attribute,"format") == 0)
4845             {
4846               const MagickInfo
4847                 *magick_info;
4848
4849               magick_info=(const MagickInfo *) NULL;
4850               if (info && (*info->image_info->magick != '\0'))
4851                 magick_info=GetMagickInfo(info->image_info->magick,exception);
4852               if (image != (Image *) NULL)
4853                 magick_info=GetMagickInfo(image->magick,exception);
4854               if ((magick_info != (const MagickInfo *) NULL) &&
4855                   (*magick_info->description != '\0'))
4856                 s=newSVpv((char *) magick_info->description,0);
4857               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4858               continue;
4859             }
4860           if (LocaleCompare(attribute,"fuzz") == 0)
4861             {
4862               if (info)
4863                 s=newSVnv(info->image_info->fuzz);
4864               if (image != (Image *) NULL)
4865                 s=newSVnv(image->fuzz);
4866               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4867               continue;
4868             }
4869           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4870             attribute);
4871           break;
4872         }
4873         case 'G':
4874         case 'g':
4875         {
4876           if (LocaleCompare(attribute,"gamma") == 0)
4877             {
4878               if (image != (Image *) NULL)
4879                 s=newSVnv(image->gamma);
4880               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4881               continue;
4882             }
4883           if (LocaleCompare(attribute,"geometry") == 0)
4884             {
4885               if (image && image->geometry)
4886                 s=newSVpv(image->geometry,0);
4887               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4888               continue;
4889             }
4890           if (LocaleCompare(attribute,"gravity") == 0)
4891             {
4892               s=image ? newSViv(image->gravity) : newSViv(0);
4893               (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
4894                 image->gravity));
4895               SvIOK_on(s);
4896               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4897               continue;
4898             }
4899           if (LocaleCompare(attribute,"green-primary") == 0)
4900             {
4901               if (image == (Image *) NULL)
4902                 break;
4903               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4904                 image->chromaticity.green_primary.x,
4905                 image->chromaticity.green_primary.y);
4906               s=newSVpv(color,0);
4907               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4908               continue;
4909             }
4910           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4911             attribute);
4912           break;
4913         }
4914         case 'H':
4915         case 'h':
4916         {
4917           if (LocaleCompare(attribute,"height") == 0)
4918             {
4919               if (image != (Image *) NULL)
4920                 s=newSViv((ssize_t) image->rows);
4921               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4922               continue;
4923             }
4924           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4925             attribute);
4926           break;
4927         }
4928         case 'I':
4929         case 'i':
4930         {
4931           if (LocaleCompare(attribute,"icc") == 0)
4932             {
4933               if (image != (Image *) NULL)
4934                 {
4935                   const StringInfo
4936                     *profile;
4937
4938                   profile=GetImageProfile(image,"icc");
4939                   if (profile != (StringInfo *) NULL)
4940                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4941                       GetStringInfoLength(profile));
4942                 }
4943               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4944               continue;
4945             }
4946           if (LocaleCompare(attribute,"icm") == 0)
4947             {
4948               if (image != (Image *) NULL)
4949                 {
4950                   const StringInfo
4951                     *profile;
4952
4953                   profile=GetImageProfile(image,"icm");
4954                   if (profile != (const StringInfo *) NULL)
4955                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4956                       GetStringInfoLength(profile));
4957                 }
4958               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4959               continue;
4960             }
4961           if (LocaleCompare(attribute,"id") == 0)
4962             {
4963               if (image != (Image *) NULL)
4964                 {
4965                   char
4966                     key[MaxTextExtent];
4967
4968                   MagickBooleanType
4969                     status;
4970
4971                   static ssize_t
4972                     id = 0;
4973
4974                   (void) FormatLocaleString(key,MaxTextExtent,"%.20g\n",(double)
4975                     id);
4976                   status=SetImageRegistry(ImageRegistryType,key,image,
4977                     exception);
4978                   (void) status;
4979                   s=newSViv(id++);
4980                 }
4981               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4982               continue;
4983             }
4984           if (LocaleNCompare(attribute,"index",5) == 0)
4985             {
4986               char
4987                 name[MaxTextExtent];
4988
4989               int
4990                 items;
4991
4992               long
4993                 x,
4994                 y;
4995
4996               register const Quantum
4997                 *p;
4998
4999               CacheView
5000                 *image_view;
5001
5002               if (image == (Image *) NULL)
5003                 break;
5004               if (image->storage_class != PseudoClass)
5005                 break;
5006               x=0;
5007               y=0;
5008               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5009               (void) items;
5010               image_view=AcquireVirtualCacheView(image,exception);
5011               p=GetCacheViewVirtualPixels(image_view,x,y,1,1,exception);
5012               if (p != (const Quantum *) NULL)
5013                 {
5014                   (void) FormatLocaleString(name,MaxTextExtent,QuantumFormat,
5015                     GetPixelIndex(image,p));
5016                   s=newSVpv(name,0);
5017                   PUSHs(s ? sv_2mortal(s) : &sv_undef);
5018                 }
5019               image_view=DestroyCacheView(image_view);
5020               continue;
5021             }
5022           if (LocaleCompare(attribute,"iptc") == 0)
5023             {
5024               if (image != (Image *) NULL)
5025                 {
5026                   const StringInfo
5027                     *profile;
5028
5029                   profile=GetImageProfile(image,"iptc");
5030                   if (profile != (const StringInfo *) NULL)
5031                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5032                       GetStringInfoLength(profile));
5033                 }
5034               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5035               continue;
5036             }
5037           if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
5038             {
5039               if (image != (Image *) NULL)
5040                 s=newSViv((ssize_t) image->iterations);
5041               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5042               continue;
5043             }
5044           if (LocaleCompare(attribute,"interlace") == 0)
5045             {
5046               j=info ? info->image_info->interlace : image ? image->interlace :
5047                 UndefinedInterlace;
5048               s=newSViv(j);
5049               (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
5050                 j));
5051               SvIOK_on(s);
5052               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5053               continue;
5054             }
5055           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5056             attribute);
5057           break;
5058         }
5059         case 'L':
5060         case 'l':
5061         {
5062           if (LocaleCompare(attribute,"label") == 0)
5063             {
5064               const char
5065                 *value;
5066
5067               if (image == (Image *) NULL)
5068                 break;
5069               value=GetImageProperty(image,"Label",exception);
5070               if (value != (const char *) NULL)
5071                 s=newSVpv(value,0);
5072               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5073               continue;
5074             }
5075           if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
5076             {
5077               if (image != (Image *) NULL)
5078                 s=newSViv((ssize_t) image->iterations);
5079               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5080               continue;
5081             }
5082           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5083             attribute);
5084           break;
5085         }
5086         case 'M':
5087         case 'm':
5088         {
5089           if (LocaleCompare(attribute,"magick") == 0)
5090             {
5091               if (info && *info->image_info->magick)
5092                 s=newSVpv(info->image_info->magick,0);
5093               if (image != (Image *) NULL)
5094                 s=newSVpv(image->magick,0);
5095               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5096               continue;
5097             }
5098           if (LocaleCompare(attribute,"map") == 0)
5099             {
5100               s=newSViv(GetMagickResource(MapResource));
5101               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5102               continue;
5103             }
5104           if (LocaleCompare(attribute,"maximum-error") == 0)
5105             {
5106               if (image != (Image *) NULL)
5107                 s=newSVnv(image->error.normalized_maximum_error);
5108               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5109               continue;
5110             }
5111           if (LocaleCompare(attribute,"memory") == 0)
5112             {
5113               s=newSViv(GetMagickResource(MemoryResource));
5114               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5115               continue;
5116             }
5117           if (LocaleCompare(attribute,"mean-error") == 0)
5118             {
5119               if (image != (Image *) NULL)
5120                 s=newSVnv(image->error.normalized_mean_error);
5121               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5122               continue;
5123             }
5124           if (LocaleCompare(attribute,"mime") == 0)
5125             {
5126               if (info && *info->image_info->magick)
5127                 s=newSVpv(MagickToMime(info->image_info->magick),0);
5128               if (image != (Image *) NULL)
5129                 s=newSVpv(MagickToMime(image->magick),0);
5130               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5131               continue;
5132             }
5133           if (LocaleCompare(attribute,"mattecolor") == 0)
5134             {
5135               if (image == (Image *) NULL)
5136                 break;
5137               (void) FormatLocaleString(color,MaxTextExtent,
5138                 "%.20g,%.20g,%.20g,%.20g",image->matte_color.red,
5139                 image->matte_color.green,image->matte_color.blue,
5140                 image->matte_color.alpha);
5141               s=newSVpv(color,0);
5142               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5143               continue;
5144             }
5145           if (LocaleCompare(attribute,"matte") == 0)
5146             {
5147               if (image != (Image *) NULL)
5148                 s=newSViv((ssize_t) image->alpha_trait == BlendPixelTrait ?
5149                   1 : 0);
5150               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5151               continue;
5152             }
5153           if (LocaleCompare(attribute,"mime") == 0)
5154             {
5155               const char
5156                 *magick;
5157
5158               magick=NULL;
5159               if (info && *info->image_info->magick)
5160                 magick=info->image_info->magick;
5161               if (image != (Image *) NULL)
5162                 magick=image->magick;
5163               if (magick)
5164                 {
5165                   char
5166                     *mime;
5167
5168                   mime=MagickToMime(magick);
5169                   s=newSVpv(mime,0);
5170                   mime=(char *) RelinquishMagickMemory(mime);
5171                 }
5172               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5173               continue;
5174             }
5175           if (LocaleCompare(attribute,"monochrome") == 0)
5176             {
5177               if (image == (Image *) NULL)
5178                 continue;
5179               j=info ? info->image_info->monochrome :
5180                 IsImageMonochrome(image,exception);
5181               s=newSViv(j);
5182               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5183               continue;
5184             }
5185           if (LocaleCompare(attribute,"montage") == 0)
5186             {
5187               if (image && image->montage)
5188                 s=newSVpv(image->montage,0);
5189               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5190               continue;
5191             }
5192           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5193             attribute);
5194           break;
5195         }
5196         case 'O':
5197         case 'o':
5198         {
5199           if (LocaleCompare(attribute,"orientation") == 0)
5200             {
5201               j=info ? info->image_info->orientation : image ?
5202                 image->orientation : UndefinedOrientation;
5203               s=newSViv(j);
5204               (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5205                 j));
5206               SvIOK_on(s);
5207               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5208               continue;
5209             }
5210           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5211             attribute);
5212           break;
5213         }
5214         case 'P':
5215         case 'p':
5216         {
5217           if (LocaleCompare(attribute,"page") == 0)
5218             {
5219               if (info && info->image_info->page)
5220                 s=newSVpv(info->image_info->page,0);
5221               if (image != (Image *) NULL)
5222                 {
5223                   char
5224                     geometry[MaxTextExtent];
5225
5226                   (void) FormatLocaleString(geometry,MaxTextExtent,
5227                     "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5228                     (double) image->page.height,(double) image->page.x,(double)
5229                     image->page.y);
5230                   s=newSVpv(geometry,0);
5231                 }
5232               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5233               continue;
5234             }
5235           if (LocaleCompare(attribute,"page.x") == 0)
5236             {
5237               if (image != (Image *) NULL)
5238                 s=newSViv((ssize_t) image->page.x);
5239               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5240               continue;
5241             }
5242           if (LocaleCompare(attribute,"page.y") == 0)
5243             {
5244               if (image != (Image *) NULL)
5245                 s=newSViv((ssize_t) image->page.y);
5246               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5247               continue;
5248             }
5249           if (LocaleNCompare(attribute,"pixel",5) == 0)
5250             {
5251               char
5252                 tuple[MaxTextExtent];
5253
5254               int
5255                 items;
5256
5257               long
5258                 x,
5259                 y;
5260
5261               register const Quantum
5262                 *p;
5263
5264               if (image == (Image *) NULL)
5265                 break;
5266               x=0;
5267               y=0;
5268               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5269               (void) items;
5270               p=GetVirtualPixels(image,x,y,1,1,exception);
5271               if (image->colorspace != CMYKColorspace)
5272                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5273                   QuantumFormat "," QuantumFormat "," QuantumFormat,
5274                   GetPixelRed(image,p),GetPixelGreen(image,p),
5275                   GetPixelBlue(image,p),GetPixelAlpha(image,p));
5276               else
5277                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5278                   QuantumFormat "," QuantumFormat "," QuantumFormat ","
5279                   QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5280                   GetPixelBlue(image,p),GetPixelBlack(image,p),
5281                   GetPixelAlpha(image,p));
5282               s=newSVpv(tuple,0);
5283               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5284               continue;
5285             }
5286           if (LocaleCompare(attribute,"pointsize") == 0)
5287             {
5288               if (info)
5289                 s=newSViv((ssize_t) info->image_info->pointsize);
5290               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5291               continue;
5292             }
5293           if (LocaleCompare(attribute,"preview") == 0)
5294             {
5295               s=newSViv(info->image_info->preview_type);
5296               (void) sv_setpv(s,CommandOptionToMnemonic(MagickPreviewOptions,
5297                 info->image_info->preview_type));
5298               SvIOK_on(s);
5299               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5300               continue;
5301             }
5302           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5303             attribute);
5304           break;
5305         }
5306         case 'Q':
5307         case 'q':
5308         {
5309           if (LocaleCompare(attribute,"quality") == 0)
5310             {
5311               if (info)
5312                 s=newSViv((ssize_t) info->image_info->quality);
5313               if (image != (Image *) NULL)
5314                 s=newSViv((ssize_t) image->quality);
5315               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5316               continue;
5317             }
5318           if (LocaleCompare(attribute,"quantum") == 0)
5319             {
5320               if (info)
5321                 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5322               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5323               continue;
5324             }
5325           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5326             attribute);
5327           break;
5328         }
5329         case 'R':
5330         case 'r':
5331         {
5332           if (LocaleCompare(attribute,"rendering-intent") == 0)
5333             {
5334               s=newSViv(image->rendering_intent);
5335               (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5336                 image->rendering_intent));
5337               SvIOK_on(s);
5338               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5339               continue;
5340             }
5341           if (LocaleCompare(attribute,"red-primary") == 0)
5342             {
5343               if (image == (Image *) NULL)
5344                 break;
5345               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5346                 image->chromaticity.red_primary.x,
5347                 image->chromaticity.red_primary.y);
5348               s=newSVpv(color,0);
5349               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5350               continue;
5351             }
5352           if (LocaleCompare(attribute,"rows") == 0)
5353             {
5354               if (image != (Image *) NULL)
5355                 s=newSViv((ssize_t) image->rows);
5356               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5357               continue;
5358             }
5359           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5360             attribute);
5361           break;
5362         }
5363         case 'S':
5364         case 's':
5365         {
5366           if (LocaleCompare(attribute,"sampling-factor") == 0)
5367             {
5368               if (info && info->image_info->sampling_factor)
5369                 s=newSVpv(info->image_info->sampling_factor,0);
5370               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5371               continue;
5372             }
5373           if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5374             {
5375               if (info && info->image_info->server_name)
5376                 s=newSVpv(info->image_info->server_name,0);
5377               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5378               continue;
5379             }
5380           if (LocaleCompare(attribute,"size") == 0)
5381             {
5382               if (info && info->image_info->size)
5383                 s=newSVpv(info->image_info->size,0);
5384               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5385               continue;
5386             }
5387           if (LocaleCompare(attribute,"scene") == 0)
5388             {
5389               if (image != (Image *) NULL)
5390                 s=newSViv((ssize_t) image->scene);
5391               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5392               continue;
5393             }
5394           if (LocaleCompare(attribute,"scenes") == 0)
5395             {
5396               if (image != (Image *) NULL)
5397                 s=newSViv((ssize_t) info->image_info->number_scenes);
5398               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5399               continue;
5400             }
5401           if (LocaleCompare(attribute,"signature") == 0)
5402             {
5403               const char
5404                 *value;
5405
5406               if (image == (Image *) NULL)
5407                 break;
5408               (void) SignatureImage(image,exception);
5409               value=GetImageProperty(image,"Signature",exception);
5410               if (value != (const char *) NULL)
5411                 s=newSVpv(value,0);
5412               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5413               continue;
5414             }
5415           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5416             attribute);
5417           break;
5418         }
5419         case 'T':
5420         case 't':
5421         {
5422           if (LocaleCompare(attribute,"taint") == 0)
5423             {
5424               if (image != (Image *) NULL)
5425                 s=newSViv((ssize_t) IsTaintImage(image));
5426               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5427               continue;
5428             }
5429           if (LocaleCompare(attribute,"texture") == 0)
5430             {
5431               if (info && info->image_info->texture)
5432                 s=newSVpv(info->image_info->texture,0);
5433               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5434               continue;
5435             }
5436           if (LocaleCompare(attribute,"total-ink-density") == 0)
5437             {
5438               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5439               if (image != (Image *) NULL)
5440                 s=newSVnv(GetImageTotalInkDensity(image,exception));
5441               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5442               continue;
5443             }
5444           if (LocaleCompare(attribute,"transparent-color") == 0)
5445             {
5446               if (image == (Image *) NULL)
5447                 break;
5448               (void) FormatLocaleString(color,MaxTextExtent,
5449                 "%.20g,%.20g,%.20g,%.20g",image->transparent_color.red,
5450                 image->transparent_color.green,image->transparent_color.blue,
5451                 image->transparent_color.alpha);
5452               s=newSVpv(color,0);
5453               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5454               continue;
5455             }
5456           if (LocaleCompare(attribute,"type") == 0)
5457             {
5458               if (image == (Image *) NULL)
5459                 break;
5460               j=(ssize_t) GetImageType(image,exception);
5461               s=newSViv(j);
5462               (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5463               SvIOK_on(s);
5464               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5465               continue;
5466             }
5467           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5468             attribute);
5469           break;
5470         }
5471         case 'U':
5472         case 'u':
5473         {
5474           if (LocaleCompare(attribute,"units") == 0)
5475             {
5476               j=info ? info->image_info->units : image ? image->units :
5477                 UndefinedResolution;
5478               if (info && (info->image_info->units == UndefinedResolution))
5479                 if (image)
5480                   j=image->units;
5481               if (j == UndefinedResolution)
5482                 s=newSVpv("undefined units",0);
5483               else
5484                 if (j == PixelsPerInchResolution)
5485                   s=newSVpv("pixels / inch",0);
5486                 else
5487                   s=newSVpv("pixels / centimeter",0);
5488               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5489               continue;
5490             }
5491           if (LocaleCompare(attribute,"user-time") == 0)
5492             {
5493               if (image != (Image *) NULL)
5494                 s=newSVnv(GetUserTime(&image->timer));
5495               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5496               continue;
5497             }
5498           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5499             attribute);
5500           break;
5501         }
5502         case 'V':
5503         case 'v':
5504         {
5505           if (LocaleCompare(attribute,"verbose") == 0)
5506             {
5507               if (info)
5508                 s=newSViv((ssize_t) info->image_info->verbose);
5509               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5510               continue;
5511             }
5512           if (LocaleCompare(attribute,"version") == 0)
5513             {
5514               s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5515               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5516               continue;
5517             }
5518           if (LocaleCompare(attribute,"view") == 0)
5519             {
5520               if (info && info->image_info->view)
5521                 s=newSVpv(info->image_info->view,0);
5522               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5523               continue;
5524             }
5525           if (LocaleCompare(attribute,"virtual-pixel") == 0)
5526             {
5527               if (image == (Image *) NULL)
5528                 break;
5529               j=(ssize_t) GetImageVirtualPixelMethod(image);
5530               s=newSViv(j);
5531               (void) sv_setpv(s,CommandOptionToMnemonic(
5532                 MagickVirtualPixelOptions,j));
5533               SvIOK_on(s);
5534               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5535               continue;
5536             }
5537           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5538             attribute);
5539           break;
5540         }
5541         case 'W':
5542         case 'w':
5543         {
5544           if (LocaleCompare(attribute,"white-point") == 0)
5545             {
5546               if (image == (Image *) NULL)
5547                 break;
5548               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5549                 image->chromaticity.white_point.x,
5550                 image->chromaticity.white_point.y);
5551               s=newSVpv(color,0);
5552               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5553               continue;
5554             }
5555           if (LocaleCompare(attribute,"width") == 0)
5556             {
5557               if (image != (Image *) NULL)
5558                 s=newSViv((ssize_t) image->columns);
5559               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5560               continue;
5561             }
5562           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5563              attribute);
5564           break;
5565         }
5566         case 'X':
5567         case 'x':
5568         {
5569           if (LocaleCompare(attribute,"x-resolution") == 0)
5570             {
5571               if (image != (Image *) NULL)
5572                 s=newSVnv(image->resolution.x);
5573               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5574               continue;
5575             }
5576           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5577             attribute);
5578           break;
5579         }
5580         case 'Y':
5581         case 'y':
5582         {
5583           if (LocaleCompare(attribute,"y-resolution") == 0)
5584             {
5585               if (image != (Image *) NULL)
5586                 s=newSVnv(image->resolution.y);
5587               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5588               continue;
5589             }
5590           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5591             attribute);
5592           break;
5593         }
5594         default:
5595           break;
5596       }
5597       if (image == (Image *) NULL)
5598         ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5599           attribute)
5600       else
5601         {
5602           value=GetImageProperty(image,attribute,exception);
5603           if (value != (const char *) NULL)
5604             {
5605               s=newSVpv(value,0);
5606               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5607             }
5608           else
5609             if (*attribute != '%')
5610               ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5611                 attribute)
5612             else
5613               {
5614                  char
5615                    *meta;
5616
5617                  meta=InterpretImageProperties(info ? info->image_info :
5618                    (ImageInfo *) NULL,image,attribute,exception);
5619                  s=newSVpv(meta,0);
5620                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5621                  meta=(char *) RelinquishMagickMemory(meta);
5622               }
5623         }
5624     }
5625     exception=DestroyExceptionInfo(exception);
5626     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5627   }
5628 \f
5629 #
5630 ###############################################################################
5631 #                                                                             #
5632 #                                                                             #
5633 #                                                                             #
5634 #   G e t A u t h e n t i c P i x e l s                                       #
5635 #                                                                             #
5636 #                                                                             #
5637 #                                                                             #
5638 ###############################################################################
5639 #
5640 #
5641 void *
5642 GetAuthenticPixels(ref,...)
5643   Image::Magick ref = NO_INIT
5644   ALIAS:
5645     getauthenticpixels = 1
5646     GetImagePixels = 2
5647     getimagepixels = 3
5648   CODE:
5649   {
5650     char
5651       *attribute;
5652
5653     ExceptionInfo
5654       *exception;
5655
5656     Image
5657       *image;
5658
5659     RectangleInfo
5660       region;
5661
5662     ssize_t
5663       i;
5664
5665     struct PackageInfo
5666       *info;
5667
5668     SV
5669       *perl_exception,
5670       *reference;
5671
5672     void
5673       *blob = NULL;
5674
5675     PERL_UNUSED_VAR(ref);
5676     PERL_UNUSED_VAR(ix);
5677     exception=AcquireExceptionInfo();
5678     perl_exception=newSVpv("",0);
5679     if (sv_isobject(ST(0)) == 0)
5680       {
5681         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5682           PackageName);
5683         goto PerlException;
5684       }
5685     reference=SvRV(ST(0));
5686
5687     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5688     if (image == (Image *) NULL)
5689       {
5690         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5691           PackageName);
5692         goto PerlException;
5693       }
5694
5695     region.x=0;
5696     region.y=0;
5697     region.width=image->columns;
5698     region.height=1;
5699     if (items == 1)
5700       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5701     for (i=2; i < items; i+=2)
5702     {
5703       attribute=(char *) SvPV(ST(i-1),na);
5704       switch (*attribute)
5705       {
5706         case 'g':
5707         case 'G':
5708         {
5709           if (LocaleCompare(attribute,"geometry") == 0)
5710             {
5711               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5712               break;
5713             }
5714           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5715             attribute);
5716           break;
5717         }
5718         case 'H':
5719         case 'h':
5720         {
5721           if (LocaleCompare(attribute,"height") == 0)
5722             {
5723               region.height=SvIV(ST(i));
5724               continue;
5725             }
5726           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5727             attribute);
5728           break;
5729         }
5730         case 'X':
5731         case 'x':
5732         {
5733           if (LocaleCompare(attribute,"x") == 0)
5734             {
5735               region.x=SvIV(ST(i));
5736               continue;
5737             }
5738           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5739             attribute);
5740           break;
5741         }
5742         case 'Y':
5743         case 'y':
5744         {
5745           if (LocaleCompare(attribute,"y") == 0)
5746             {
5747               region.y=SvIV(ST(i));
5748               continue;
5749             }
5750           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5751             attribute);
5752           break;
5753         }
5754         case 'W':
5755         case 'w':
5756         {
5757           if (LocaleCompare(attribute,"width") == 0)
5758             {
5759               region.width=SvIV(ST(i));
5760               continue;
5761             }
5762           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5763             attribute);
5764           break;
5765         }
5766       }
5767     }
5768     blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5769       region.height,exception);
5770     if (blob != (void *) NULL)
5771       goto PerlEnd;
5772
5773   PerlException:
5774     InheritPerlException(exception,perl_exception);
5775     exception=DestroyExceptionInfo(exception);
5776     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5777
5778   PerlEnd:
5779     RETVAL = blob;
5780   }
5781   OUTPUT:
5782     RETVAL
5783 \f
5784 #
5785 ###############################################################################
5786 #                                                                             #
5787 #                                                                             #
5788 #                                                                             #
5789 #   G e t V i r t u a l P i x e l s                                           #
5790 #                                                                             #
5791 #                                                                             #
5792 #                                                                             #
5793 ###############################################################################
5794 #
5795 #
5796 void *
5797 GetVirtualPixels(ref,...)
5798   Image::Magick ref = NO_INIT
5799   ALIAS:
5800     getvirtualpixels = 1
5801     AcquireImagePixels = 2
5802     acquireimagepixels = 3
5803   CODE:
5804   {
5805     char
5806       *attribute;
5807
5808     const void
5809       *blob = NULL;
5810
5811     ExceptionInfo
5812       *exception;
5813
5814     Image
5815       *image;
5816
5817     RectangleInfo
5818       region;
5819
5820     ssize_t
5821       i;
5822
5823     struct PackageInfo
5824       *info;
5825
5826     SV
5827       *perl_exception,
5828       *reference;
5829
5830     PERL_UNUSED_VAR(ref);
5831     PERL_UNUSED_VAR(ix);
5832     exception=AcquireExceptionInfo();
5833     perl_exception=newSVpv("",0);
5834     if (sv_isobject(ST(0)) == 0)
5835       {
5836         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5837           PackageName);
5838         goto PerlException;
5839       }
5840     reference=SvRV(ST(0));
5841
5842     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5843     if (image == (Image *) NULL)
5844       {
5845         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5846           PackageName);
5847         goto PerlException;
5848       }
5849
5850     region.x=0;
5851     region.y=0;
5852     region.width=image->columns;
5853     region.height=1;
5854     if (items == 1)
5855       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5856     for (i=2; i < items; i+=2)
5857     {
5858       attribute=(char *) SvPV(ST(i-1),na);
5859       switch (*attribute)
5860       {
5861         case 'g':
5862         case 'G':
5863         {
5864           if (LocaleCompare(attribute,"geometry") == 0)
5865             {
5866               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5867               break;
5868             }
5869           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5870             attribute);
5871           break;
5872         }
5873         case 'H':
5874         case 'h':
5875         {
5876           if (LocaleCompare(attribute,"height") == 0)
5877             {
5878               region.height=SvIV(ST(i));
5879               continue;
5880             }
5881           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5882             attribute);
5883           break;
5884         }
5885         case 'X':
5886         case 'x':
5887         {
5888           if (LocaleCompare(attribute,"x") == 0)
5889             {
5890               region.x=SvIV(ST(i));
5891               continue;
5892             }
5893           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5894             attribute);
5895           break;
5896         }
5897         case 'Y':
5898         case 'y':
5899         {
5900           if (LocaleCompare(attribute,"y") == 0)
5901             {
5902               region.y=SvIV(ST(i));
5903               continue;
5904             }
5905           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5906             attribute);
5907           break;
5908         }
5909         case 'W':
5910         case 'w':
5911         {
5912           if (LocaleCompare(attribute,"width") == 0)
5913             {
5914               region.width=SvIV(ST(i));
5915               continue;
5916             }
5917           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5918             attribute);
5919           break;
5920         }
5921       }
5922     }
5923     blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
5924       region.height,exception);
5925     if (blob != (void *) NULL)
5926       goto PerlEnd;
5927
5928   PerlException:
5929     InheritPerlException(exception,perl_exception);
5930     exception=DestroyExceptionInfo(exception);
5931     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5932
5933   PerlEnd:
5934     RETVAL = (void *) blob;
5935   }
5936   OUTPUT:
5937     RETVAL
5938 \f
5939 #
5940 ###############################################################################
5941 #                                                                             #
5942 #                                                                             #
5943 #                                                                             #
5944 #   G e t A u t h e n t i c M e t a c o n t e n t                             #
5945 #                                                                             #
5946 #                                                                             #
5947 #                                                                             #
5948 ###############################################################################
5949 #
5950 #
5951 void *
5952 GetAuthenticMetacontent(ref,...)
5953   Image::Magick ref = NO_INIT
5954   ALIAS:
5955     getauthenticmetacontent = 1
5956     GetMetacontent = 2
5957     getmetacontent = 3
5958   CODE:
5959   {
5960     ExceptionInfo
5961       *exception;
5962
5963     Image
5964       *image;
5965
5966     struct PackageInfo
5967       *info;
5968
5969     SV
5970       *perl_exception,
5971       *reference;
5972
5973     void
5974       *blob = NULL;
5975
5976     PERL_UNUSED_VAR(ref);
5977     PERL_UNUSED_VAR(ix);
5978     exception=AcquireExceptionInfo();
5979     perl_exception=newSVpv("",0);
5980     if (sv_isobject(ST(0)) == 0)
5981       {
5982         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5983           PackageName);
5984         goto PerlException;
5985       }
5986     reference=SvRV(ST(0));
5987
5988     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5989     if (image == (Image *) NULL)
5990       {
5991         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5992           PackageName);
5993         goto PerlException;
5994       }
5995
5996     blob=(void *) GetAuthenticMetacontent(image);
5997     if (blob != (void *) NULL)
5998       goto PerlEnd;
5999
6000   PerlException:
6001     InheritPerlException(exception,perl_exception);
6002     exception=DestroyExceptionInfo(exception);
6003     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6004
6005   PerlEnd:
6006     RETVAL = blob;
6007   }
6008   OUTPUT:
6009     RETVAL
6010 \f
6011 #
6012 ###############################################################################
6013 #                                                                             #
6014 #                                                                             #
6015 #                                                                             #
6016 #   G e t V i r t u a l M e t a c o n t e n t                                 #
6017 #                                                                             #
6018 #                                                                             #
6019 #                                                                             #
6020 ###############################################################################
6021 #
6022 #
6023 void *
6024 GetVirtualMetacontent(ref,...)
6025   Image::Magick ref = NO_INIT
6026   ALIAS:
6027     getvirtualmetacontent = 1
6028   CODE:
6029   {
6030     ExceptionInfo
6031       *exception;
6032
6033     Image
6034       *image;
6035
6036     struct PackageInfo
6037       *info;
6038
6039     SV
6040       *perl_exception,
6041       *reference;
6042
6043     void
6044       *blob = NULL;
6045
6046     PERL_UNUSED_VAR(ref);
6047     PERL_UNUSED_VAR(ix);
6048     exception=AcquireExceptionInfo();
6049     perl_exception=newSVpv("",0);
6050     if (sv_isobject(ST(0)) == 0)
6051       {
6052         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6053           PackageName);
6054         goto PerlException;
6055       }
6056     reference=SvRV(ST(0));
6057
6058     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6059     if (image == (Image *) NULL)
6060       {
6061         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6062           PackageName);
6063         goto PerlException;
6064       }
6065
6066     blob=(void *) GetVirtualMetacontent(image);
6067     if (blob != (void *) NULL)
6068       goto PerlEnd;
6069
6070   PerlException:
6071     InheritPerlException(exception,perl_exception);
6072     exception=DestroyExceptionInfo(exception);
6073     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6074
6075   PerlEnd:
6076     RETVAL = blob;
6077   }
6078   OUTPUT:
6079     RETVAL
6080 \f
6081 #
6082 ###############################################################################
6083 #                                                                             #
6084 #                                                                             #
6085 #                                                                             #
6086 #   H i s t o g r a m                                                         #
6087 #                                                                             #
6088 #                                                                             #
6089 #                                                                             #
6090 ###############################################################################
6091 #
6092 #
6093 void
6094 Histogram(ref,...)
6095   Image::Magick ref=NO_INIT
6096   ALIAS:
6097     HistogramImage = 1
6098     histogram      = 2
6099     histogramimage = 3
6100   PPCODE:
6101   {
6102     AV
6103       *av;
6104
6105     char
6106       message[MaxTextExtent];
6107
6108     PixelInfo
6109       *histogram;
6110
6111     ExceptionInfo
6112       *exception;
6113
6114     Image
6115       *image;
6116
6117     register ssize_t
6118       i;
6119
6120     ssize_t
6121       count;
6122
6123     struct PackageInfo
6124       *info;
6125
6126     SV
6127       *perl_exception,
6128       *reference;
6129
6130     size_t
6131       number_colors;
6132
6133     PERL_UNUSED_VAR(ref);
6134     PERL_UNUSED_VAR(ix);
6135     exception=AcquireExceptionInfo();
6136     perl_exception=newSVpv("",0);
6137     av=NULL;
6138     if (sv_isobject(ST(0)) == 0)
6139       {
6140         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6141           PackageName);
6142         goto PerlException;
6143       }
6144     reference=SvRV(ST(0));
6145     av=newAV();
6146     SvREFCNT_dec(av);
6147     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6148     if (image == (Image *) NULL)
6149       {
6150         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6151           PackageName);
6152         goto PerlException;
6153       }
6154     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
6155     count=0;
6156     for ( ; image; image=image->next)
6157     {
6158       histogram=GetImageHistogram(image,&number_colors,exception);
6159       if (histogram == (PixelInfo *) NULL)
6160         continue;
6161       count+=(ssize_t) number_colors;
6162       EXTEND(sp,6*count);
6163       for (i=0; i < (ssize_t) number_colors; i++)
6164       {
6165         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6166           histogram[i].red);
6167         PUSHs(sv_2mortal(newSVpv(message,0)));
6168         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6169           histogram[i].green);
6170         PUSHs(sv_2mortal(newSVpv(message,0)));
6171         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6172           histogram[i].blue);
6173         PUSHs(sv_2mortal(newSVpv(message,0)));
6174         if (image->colorspace == CMYKColorspace)
6175           {
6176             (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6177               histogram[i].black);
6178             PUSHs(sv_2mortal(newSVpv(message,0)));
6179           }
6180         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6181           histogram[i].alpha);
6182         PUSHs(sv_2mortal(newSVpv(message,0)));
6183         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
6184           histogram[i].count);
6185         PUSHs(sv_2mortal(newSVpv(message,0)));
6186       }
6187       histogram=(PixelInfo *) RelinquishMagickMemory(histogram);
6188     }
6189
6190   PerlException:
6191     InheritPerlException(exception,perl_exception);
6192     exception=DestroyExceptionInfo(exception);
6193     SvREFCNT_dec(perl_exception);
6194   }
6195 \f
6196 #
6197 ###############################################################################
6198 #                                                                             #
6199 #                                                                             #
6200 #                                                                             #
6201 #   G e t P i x e l                                                           #
6202 #                                                                             #
6203 #                                                                             #
6204 #                                                                             #
6205 ###############################################################################
6206 #
6207 #
6208 void
6209 GetPixel(ref,...)
6210   Image::Magick ref=NO_INIT
6211   ALIAS:
6212     getpixel = 1
6213     getPixel = 2
6214   PPCODE:
6215   {
6216     AV
6217       *av;
6218
6219     char
6220       *attribute;
6221
6222     ExceptionInfo
6223       *exception;
6224
6225     Image
6226       *image;
6227
6228     MagickBooleanType
6229       normalize;
6230
6231     RectangleInfo
6232       region;
6233
6234     register const Quantum
6235       *p;
6236
6237     register ssize_t
6238       i;
6239
6240     ssize_t
6241       option;
6242
6243     struct PackageInfo
6244       *info;
6245
6246     SV
6247       *perl_exception,
6248       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6249
6250     PERL_UNUSED_VAR(ref);
6251     PERL_UNUSED_VAR(ix);
6252     exception=AcquireExceptionInfo();
6253     perl_exception=newSVpv("",0);
6254     reference=SvRV(ST(0));
6255     av=(AV *) reference;
6256     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6257       exception);
6258     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6259     if (image == (Image *) NULL)
6260       {
6261         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6262           PackageName);
6263         goto PerlException;
6264       }
6265     normalize=MagickTrue;
6266     region.x=0;
6267     region.y=0;
6268     region.width=image->columns;
6269     region.height=1;
6270     if (items == 1)
6271       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6272     for (i=2; i < items; i+=2)
6273     {
6274       attribute=(char *) SvPV(ST(i-1),na);
6275       switch (*attribute)
6276       {
6277         case 'C':
6278         case 'c':
6279         {
6280           if (LocaleCompare(attribute,"channel") == 0)
6281             {
6282               ssize_t
6283                 option;
6284
6285               option=ParseChannelOption(SvPV(ST(i),na));
6286               if (option < 0)
6287                 {
6288                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6289                     SvPV(ST(i),na));
6290                   return;
6291                 }
6292               SetPixelChannelMask(image,(ChannelType) option);
6293               break;
6294             }
6295           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6296             attribute);
6297           break;
6298         }
6299         case 'g':
6300         case 'G':
6301         {
6302           if (LocaleCompare(attribute,"geometry") == 0)
6303             {
6304               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6305               break;
6306             }
6307           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6308             attribute);
6309           break;
6310         }
6311         case 'N':
6312         case 'n':
6313         {
6314           if (LocaleCompare(attribute,"normalize") == 0)
6315             {
6316               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6317                 SvPV(ST(i),na));
6318               if (option < 0)
6319                 {
6320                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6321                     SvPV(ST(i),na));
6322                   break;
6323                 }
6324              normalize=option != 0 ? MagickTrue : MagickFalse;
6325              break;
6326             }
6327           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6328             attribute);
6329           break;
6330         }
6331         case 'x':
6332         case 'X':
6333         {
6334           if (LocaleCompare(attribute,"x") == 0)
6335             {
6336               region.x=SvIV(ST(i));
6337               break;
6338             }
6339           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6340             attribute);
6341           break;
6342         }
6343         case 'y':
6344         case 'Y':
6345         {
6346           if (LocaleCompare(attribute,"y") == 0)
6347             {
6348               region.y=SvIV(ST(i));
6349               break;
6350             }
6351           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6352             attribute);
6353           break;
6354         }
6355         default:
6356         {
6357           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6358             attribute);
6359           break;
6360         }
6361       }
6362     }
6363     p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6364     if (p == (const Quantum *) NULL)
6365       PUSHs(&sv_undef);
6366     else
6367       {
6368         double
6369           scale;
6370
6371         scale=1.0;
6372         if (normalize != MagickFalse)
6373           scale=1.0/QuantumRange;
6374         if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
6375           PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6376         if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6377           PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6378         if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6379           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6380         if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6381             (image->colorspace == CMYKColorspace))
6382           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6383         if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
6384           PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6385       }
6386
6387   PerlException:
6388     InheritPerlException(exception,perl_exception);
6389     exception=DestroyExceptionInfo(exception);
6390     SvREFCNT_dec(perl_exception);
6391   }
6392 \f
6393 #
6394 ###############################################################################
6395 #                                                                             #
6396 #                                                                             #
6397 #                                                                             #
6398 #   G e t P i x e l s                                                         #
6399 #                                                                             #
6400 #                                                                             #
6401 #                                                                             #
6402 ###############################################################################
6403 #
6404 #
6405 void
6406 GetPixels(ref,...)
6407   Image::Magick ref=NO_INIT
6408   ALIAS:
6409     getpixels = 1
6410     getPixels = 2
6411   PPCODE:
6412   {
6413     AV
6414       *av;
6415
6416     char
6417       *attribute;
6418
6419     const char
6420       *map;
6421
6422     ExceptionInfo
6423       *exception;
6424
6425     Image
6426       *image;
6427
6428     MagickBooleanType
6429       normalize,
6430       status;
6431
6432     RectangleInfo
6433       region;
6434
6435     register ssize_t
6436       i;
6437
6438     ssize_t
6439       option;
6440
6441     struct PackageInfo
6442       *info;
6443
6444     SV
6445       *perl_exception,
6446       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6447
6448     PERL_UNUSED_VAR(ref);
6449     PERL_UNUSED_VAR(ix);
6450     exception=AcquireExceptionInfo();
6451     perl_exception=newSVpv("",0);
6452     reference=SvRV(ST(0));
6453     av=(AV *) reference;
6454     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6455       exception);
6456     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6457     if (image == (Image *) NULL)
6458       {
6459         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6460           PackageName);
6461         goto PerlException;
6462       }
6463     map="RGB";
6464     if (image->alpha_trait == BlendPixelTrait)
6465       map="RGBA";
6466     if (image->colorspace == CMYKColorspace)
6467       {
6468         map="CMYK";
6469         if (image->alpha_trait == BlendPixelTrait)
6470           map="CMYKA";
6471       }
6472     normalize=MagickFalse;
6473     region.x=0;
6474     region.y=0;
6475     region.width=image->columns;
6476     region.height=1;
6477     if (items == 1)
6478       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6479     for (i=2; i < items; i+=2)
6480     {
6481       attribute=(char *) SvPV(ST(i-1),na);
6482       switch (*attribute)
6483       {
6484         case 'g':
6485         case 'G':
6486         {
6487           if (LocaleCompare(attribute,"geometry") == 0)
6488             {
6489               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6490               break;
6491             }
6492           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6493             attribute);
6494           break;
6495         }
6496         case 'H':
6497         case 'h':
6498         {
6499           if (LocaleCompare(attribute,"height") == 0)
6500             {
6501               region.height=SvIV(ST(i));
6502               break;
6503             }
6504           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6505             attribute);
6506           break;
6507         }
6508         case 'M':
6509         case 'm':
6510         {
6511           if (LocaleCompare(attribute,"map") == 0)
6512             {
6513               map=SvPV(ST(i),na);
6514               break;
6515             }
6516           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6517             attribute);
6518           break;
6519         }
6520         case 'N':
6521         case 'n':
6522         {
6523           if (LocaleCompare(attribute,"normalize") == 0)
6524             {
6525               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6526                 SvPV(ST(i),na));
6527               if (option < 0)
6528                 {
6529                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6530                     SvPV(ST(i),na));
6531                   break;
6532                 }
6533              normalize=option != 0 ? MagickTrue : MagickFalse;
6534              break;
6535             }
6536           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6537             attribute);
6538           break;
6539         }
6540         case 'W':
6541         case 'w':
6542         {
6543           if (LocaleCompare(attribute,"width") == 0)
6544             {
6545               region.width=SvIV(ST(i));
6546               break;
6547             }
6548           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6549             attribute);
6550           break;
6551         }
6552         case 'x':
6553         case 'X':
6554         {
6555           if (LocaleCompare(attribute,"x") == 0)
6556             {
6557               region.x=SvIV(ST(i));
6558               break;
6559             }
6560           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6561             attribute);
6562           break;
6563         }
6564         case 'y':
6565         case 'Y':
6566         {
6567           if (LocaleCompare(attribute,"y") == 0)
6568             {
6569               region.y=SvIV(ST(i));
6570               break;
6571             }
6572           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6573             attribute);
6574           break;
6575         }
6576         default:
6577         {
6578           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6579             attribute);
6580           break;
6581         }
6582       }
6583     }
6584     if (normalize != MagickFalse)
6585       {
6586         float
6587           *pixels;
6588
6589         pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6590           region.height*sizeof(*pixels));
6591         if (pixels == (float *) NULL)
6592           {
6593             ThrowPerlException(exception,ResourceLimitError,
6594               "MemoryAllocationFailed",PackageName);
6595             goto PerlException;
6596           }
6597         status=ExportImagePixels(image,region.x,region.y,region.width,
6598           region.height,map,FloatPixel,pixels,exception);
6599         if (status == MagickFalse)
6600           PUSHs(&sv_undef);
6601         else
6602           {
6603             EXTEND(sp,strlen(map)*region.width*region.height);
6604             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6605               PUSHs(sv_2mortal(newSVnv(pixels[i])));
6606           }
6607         pixels=(float *) RelinquishMagickMemory(pixels);
6608       }
6609     else
6610       {
6611         Quantum
6612           *pixels;
6613
6614         pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6615           region.height*sizeof(*pixels));
6616         if (pixels == (Quantum *) NULL)
6617           {
6618             ThrowPerlException(exception,ResourceLimitError,
6619               "MemoryAllocationFailed",PackageName);
6620             goto PerlException;
6621           }
6622         status=ExportImagePixels(image,region.x,region.y,region.width,
6623           region.height,map,QuantumPixel,pixels,exception);
6624         if (status == MagickFalse)
6625           PUSHs(&sv_undef);
6626         else
6627           {
6628             EXTEND(sp,strlen(map)*region.width*region.height);
6629             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6630               PUSHs(sv_2mortal(newSViv(pixels[i])));
6631           }
6632         pixels=(Quantum *) RelinquishMagickMemory(pixels);
6633       }
6634
6635   PerlException:
6636     InheritPerlException(exception,perl_exception);
6637     exception=DestroyExceptionInfo(exception);
6638     SvREFCNT_dec(perl_exception);
6639   }
6640 \f
6641 #
6642 ###############################################################################
6643 #                                                                             #
6644 #                                                                             #
6645 #                                                                             #
6646 #   I m a g e T o B l o b                                                     #
6647 #                                                                             #
6648 #                                                                             #
6649 #                                                                             #
6650 ###############################################################################
6651 #
6652 #
6653 void
6654 ImageToBlob(ref,...)
6655   Image::Magick ref=NO_INIT
6656   ALIAS:
6657     ImageToBlob  = 1
6658     imagetoblob  = 2
6659     toblob       = 3
6660     blob         = 4
6661   PPCODE:
6662   {
6663     char
6664       filename[MaxTextExtent];
6665
6666     ExceptionInfo
6667       *exception;
6668
6669     Image
6670       *image,
6671       *next;
6672
6673     register ssize_t
6674       i;
6675
6676     struct PackageInfo
6677       *info,
6678       *package_info;
6679
6680     size_t
6681       length;
6682
6683     ssize_t
6684       scene;
6685
6686     SV
6687       *perl_exception,
6688       *reference;
6689
6690     void
6691       *blob;
6692
6693     PERL_UNUSED_VAR(ref);
6694     PERL_UNUSED_VAR(ix);
6695     exception=AcquireExceptionInfo();
6696     perl_exception=newSVpv("",0);
6697     package_info=(struct PackageInfo *) NULL;
6698     if (sv_isobject(ST(0)) == 0)
6699       {
6700         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6701           PackageName);
6702         goto PerlException;
6703       }
6704     reference=SvRV(ST(0));
6705     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6706     if (image == (Image *) NULL)
6707       {
6708         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6709           PackageName);
6710         goto PerlException;
6711       }
6712     package_info=ClonePackageInfo(info,exception);
6713     for (i=2; i < items; i+=2)
6714       SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6715     (void) CopyMagickString(filename,package_info->image_info->filename,
6716       MaxTextExtent);
6717     scene=0;
6718     for (next=image; next; next=next->next)
6719     {
6720       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
6721       next->scene=scene++;
6722     }
6723     SetImageInfo(package_info->image_info,(unsigned int)
6724       GetImageListLength(image),exception);
6725     EXTEND(sp,(ssize_t) GetImageListLength(image));
6726     for ( ; image; image=image->next)
6727     {
6728       length=0;
6729       blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6730       if (blob != (char *) NULL)
6731         {
6732           PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6733           blob=(unsigned char *) RelinquishMagickMemory(blob);
6734         }
6735       if (package_info->image_info->adjoin)
6736         break;
6737     }
6738
6739   PerlException:
6740     if (package_info != (struct PackageInfo *) NULL)
6741       DestroyPackageInfo(package_info);
6742     InheritPerlException(exception,perl_exception);
6743     exception=DestroyExceptionInfo(exception);
6744     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6745   }
6746 \f
6747 #
6748 ###############################################################################
6749 #                                                                             #
6750 #                                                                             #
6751 #                                                                             #
6752 #   L a y e r s                                                               #
6753 #                                                                             #
6754 #                                                                             #
6755 #                                                                             #
6756 ###############################################################################
6757 #
6758 #
6759 void
6760 Layers(ref,...)
6761   Image::Magick ref=NO_INIT
6762   ALIAS:
6763     Layers                = 1
6764     layers           = 2
6765     OptimizeImageLayers   = 3
6766     optimizelayers        = 4
6767     optimizeimagelayers   = 5
6768   PPCODE:
6769   {
6770     AV
6771       *av;
6772
6773     char
6774       *attribute;
6775
6776     CompositeOperator
6777       compose;
6778
6779     ExceptionInfo
6780       *exception;
6781
6782     HV
6783       *hv;
6784
6785     Image
6786       *image,
6787       *layers;
6788
6789     LayerMethod
6790       method;
6791
6792     register ssize_t
6793       i;
6794
6795     ssize_t
6796       option,
6797       sp;
6798
6799     struct PackageInfo
6800       *info;
6801
6802     SV
6803       *av_reference,
6804       *perl_exception,
6805       *reference,
6806       *rv,
6807       *sv;
6808
6809     PERL_UNUSED_VAR(ref);
6810     PERL_UNUSED_VAR(ix);
6811     exception=AcquireExceptionInfo();
6812     perl_exception=newSVpv("",0);
6813     sv=NULL;
6814     if (sv_isobject(ST(0)) == 0)
6815       {
6816         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6817           PackageName);
6818         goto PerlException;
6819       }
6820     reference=SvRV(ST(0));
6821     hv=SvSTASH(reference);
6822     av=newAV();
6823     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
6824     SvREFCNT_dec(av);
6825     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6826     if (image == (Image *) NULL)
6827       {
6828         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6829           PackageName);
6830         goto PerlException;
6831       }
6832     compose=image->compose;
6833     method=OptimizeLayer;
6834     for (i=2; i < items; i+=2)
6835     {
6836       attribute=(char *) SvPV(ST(i-1),na);
6837       switch (*attribute)
6838       {
6839         case 'C':
6840         case 'c':
6841         {
6842           if (LocaleCompare(attribute,"compose") == 0)
6843             {
6844               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
6845                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
6846               if (sp < 0)
6847                 {
6848                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6849                     SvPV(ST(i),na));
6850                   break;
6851                 }
6852               compose=(CompositeOperator) sp;
6853               break;
6854             }
6855           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6856             attribute);
6857           break;
6858         }
6859         case 'M':
6860         case 'm':
6861         {
6862           if (LocaleCompare(attribute,"method") == 0)
6863             {
6864               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
6865                 SvPV(ST(i),na));
6866               if (option < 0)
6867                 {
6868                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6869                     SvPV(ST(i),na));
6870                   break;
6871                 }
6872               method=(LayerMethod) option;
6873               break;
6874             }
6875           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6876             attribute);
6877           break;
6878         }
6879         default:
6880         {
6881           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6882             attribute);
6883           break;
6884         }
6885       }
6886     }
6887     layers=(Image *) NULL;
6888     switch (method)
6889     {
6890       case CompareAnyLayer:
6891       case CompareClearLayer:
6892       case CompareOverlayLayer:
6893       default:
6894       {
6895         layers=CompareImagesLayers(image,method,exception);
6896         break;
6897       }
6898       case MergeLayer:
6899       case FlattenLayer:
6900       case MosaicLayer:
6901       {
6902         layers=MergeImageLayers(image,method,exception);
6903         break;
6904       }
6905       case DisposeLayer:
6906       {
6907         layers=DisposeImages(image,exception);
6908         break;
6909       }
6910       case OptimizeImageLayer:
6911       {
6912         layers=OptimizeImageLayers(image,exception);
6913         break;
6914       }
6915       case OptimizePlusLayer:
6916       {
6917         layers=OptimizePlusImageLayers(image,exception);
6918         break;
6919       }
6920       case OptimizeTransLayer:
6921       {
6922         OptimizeImageTransparency(image,exception);
6923         break;
6924       }
6925       case RemoveDupsLayer:
6926       {
6927         RemoveDuplicateLayers(&image,exception);
6928         break;
6929       }
6930       case RemoveZeroLayer:
6931       {
6932         RemoveZeroDelayLayers(&image,exception);
6933         break;
6934       }
6935       case OptimizeLayer:
6936       {
6937         QuantizeInfo
6938           *quantize_info;
6939
6940         /*
6941           General Purpose, GIF Animation Optimizer.
6942         */
6943         layers=CoalesceImages(image,exception);
6944         if (layers == (Image *) NULL)
6945           break;
6946         image=layers;
6947         layers=OptimizeImageLayers(image,exception);
6948         if (layers == (Image *) NULL)
6949           break;
6950         image=DestroyImageList(image);
6951         image=layers;
6952         layers=(Image *) NULL;
6953         OptimizeImageTransparency(image,exception);
6954         quantize_info=AcquireQuantizeInfo(info->image_info);
6955         (void) RemapImages(quantize_info,image,(Image *) NULL,exception);
6956         quantize_info=DestroyQuantizeInfo(quantize_info);
6957         break;
6958       }
6959       case CompositeLayer:
6960       {
6961         Image
6962           *source;
6963
6964         RectangleInfo
6965           geometry;
6966
6967         /*
6968           Split image sequence at the first 'NULL:' image.
6969         */
6970         source=image;
6971         while (source != (Image *) NULL)
6972         {
6973           source=GetNextImageInList(source);
6974           if ((source != (Image *) NULL) &&
6975               (LocaleCompare(source->magick,"NULL") == 0))
6976             break;
6977         }
6978         if (source != (Image *) NULL)
6979           {
6980             if ((GetPreviousImageInList(source) == (Image *) NULL) ||
6981                 (GetNextImageInList(source) == (Image *) NULL))
6982               source=(Image *) NULL;
6983             else
6984               {
6985                 /*
6986                   Separate the two lists, junk the null: image.
6987                 */
6988                 source=SplitImageList(source->previous);
6989                 DeleteImageFromList(&source);
6990               }
6991           }
6992         if (source == (Image *) NULL)
6993           {
6994             (void) ThrowMagickException(exception,GetMagickModule(),
6995               OptionError,"MissingNullSeparator","layers Composite");
6996             break;
6997           }
6998         /*
6999           Adjust offset with gravity and virtual canvas.
7000         */
7001         SetGeometry(image,&geometry);
7002         (void) ParseAbsoluteGeometry(image->geometry,&geometry);
7003         geometry.width=source->page.width != 0 ? source->page.width :
7004           source->columns;
7005         geometry.height=source->page.height != 0 ? source->page.height :
7006           source->rows;
7007         GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
7008           image->columns,image->page.height != 0 ? image->page.height :
7009           image->rows,image->gravity,&geometry);
7010         CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
7011         source=DestroyImageList(source);
7012         break;
7013       }
7014     }
7015     if (layers != (Image *) NULL)
7016       image=layers;
7017     if (image == (Image *) NULL)
7018       goto PerlException;
7019     for ( ; image; image=image->next)
7020     {
7021       AddImageToRegistry(sv,image);
7022       rv=newRV(sv);
7023       av_push(av,sv_bless(rv,hv));
7024       SvREFCNT_dec(sv);
7025     }
7026     exception=DestroyExceptionInfo(exception);
7027     ST(0)=av_reference;
7028     SvREFCNT_dec(perl_exception);
7029     XSRETURN(1);
7030
7031   PerlException:
7032     InheritPerlException(exception,perl_exception);
7033     exception=DestroyExceptionInfo(exception);
7034     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
7035     SvPOK_on(perl_exception);
7036     ST(0)=sv_2mortal(perl_exception);
7037     XSRETURN(1);
7038   }
7039 \f
7040 #
7041 ###############################################################################
7042 #                                                                             #
7043 #                                                                             #
7044 #                                                                             #
7045 #   M a g i c k T o M i m e                                                   #
7046 #                                                                             #
7047 #                                                                             #
7048 #                                                                             #
7049 ###############################################################################
7050 #
7051 #
7052 SV *
7053 MagickToMime(ref,name)
7054   Image::Magick ref=NO_INIT
7055   char *name
7056   ALIAS:
7057     magicktomime = 1
7058   CODE:
7059   {
7060     char
7061       *mime;
7062
7063     PERL_UNUSED_VAR(ref);
7064     PERL_UNUSED_VAR(ix);
7065     mime=MagickToMime(name);
7066     RETVAL=newSVpv(mime,0);
7067     mime=(char *) RelinquishMagickMemory(mime);
7068   }
7069   OUTPUT:
7070     RETVAL
7071 \f
7072 #
7073 ###############################################################################
7074 #                                                                             #
7075 #                                                                             #
7076 #                                                                             #
7077 #   M o g r i f y                                                             #
7078 #                                                                             #
7079 #                                                                             #
7080 #                                                                             #
7081 ###############################################################################
7082 #
7083 #
7084 void
7085 Mogrify(ref,...)
7086   Image::Magick ref=NO_INIT
7087   ALIAS:
7088     Comment            =   1
7089     CommentImage       =   2
7090     Label              =   3
7091     LabelImage         =   4
7092     AddNoise           =   5
7093     AddNoiseImage      =   6
7094     Colorize           =   7
7095     ColorizeImage      =   8
7096     Border             =   9
7097     BorderImage        =  10
7098     Blur               =  11
7099     BlurImage          =  12
7100     Chop               =  13
7101     ChopImage          =  14
7102     Crop               =  15
7103     CropImage          =  16
7104     Despeckle          =  17
7105     DespeckleImage     =  18
7106     Edge               =  19
7107     EdgeImage          =  20
7108     Emboss             =  21
7109     EmbossImage        =  22
7110     Enhance            =  23
7111     EnhanceImage       =  24
7112     Flip               =  25
7113     FlipImage          =  26
7114     Flop               =  27
7115     FlopImage          =  28
7116     Frame              =  29
7117     FrameImage         =  30
7118     Implode            =  31
7119     ImplodeImage       =  32
7120     Magnify            =  33
7121     MagnifyImage       =  34
7122     MedianFilter       =  35
7123     MedianConvolveImage  =  36
7124     Minify             =  37
7125     MinifyImage        =  38
7126     OilPaint           =  39
7127     OilPaintImage      =  40
7128     ReduceNoise        =  41
7129     ReduceNoiseImage   =  42
7130     Roll               =  43
7131     RollImage          =  44
7132     Rotate             =  45
7133     RotateImage        =  46
7134     Sample             =  47
7135     SampleImage        =  48
7136     Scale              =  49
7137     ScaleImage         =  50
7138     Shade              =  51
7139     ShadeImage         =  52
7140     Sharpen            =  53
7141     SharpenImage       =  54
7142     Shear              =  55
7143     ShearImage         =  56
7144     Spread             =  57
7145     SpreadImage        =  58
7146     Swirl              =  59
7147     SwirlImage         =  60
7148     Resize             =  61
7149     ResizeImage        =  62
7150     Zoom               =  63
7151     ZoomImage          =  64
7152     Annotate           =  65
7153     AnnotateImage      =  66
7154     ColorFloodfill     =  67
7155     ColorFloodfillImage=  68
7156     Composite          =  69
7157     CompositeImage     =  70
7158     Contrast           =  71
7159     ContrastImage      =  72
7160     CycleColormap      =  73
7161     CycleColormapImage =  74
7162     Draw               =  75
7163     DrawImage          =  76
7164     Equalize           =  77
7165     EqualizeImage      =  78
7166     Gamma              =  79
7167     GammaImage         =  80
7168     Map                =  81
7169     MapImage           =  82
7170     MatteFloodfill     =  83
7171     MatteFloodfillImage=  84
7172     Modulate           =  85
7173     ModulateImage      =  86
7174     Negate             =  87
7175     NegateImage        =  88
7176     Normalize          =  89
7177     NormalizeImage     =  90
7178     NumberColors       =  91
7179     NumberColorsImage  =  92
7180     Opaque             =  93
7181     OpaqueImage        =  94
7182     Quantize           =  95
7183     QuantizeImage      =  96
7184     Raise              =  97
7185     RaiseImage         =  98
7186     Segment            =  99
7187     SegmentImage       = 100
7188     Signature          = 101
7189     SignatureImage     = 102
7190     Solarize           = 103
7191     SolarizeImage      = 104
7192     Sync               = 105
7193     SyncImage          = 106
7194     Texture            = 107
7195     TextureImage       = 108
7196     Evaluate           = 109
7197     EvaluateImage      = 110
7198     Transparent        = 111
7199     TransparentImage   = 112
7200     Threshold          = 113
7201     ThresholdImage     = 114
7202     Charcoal           = 115
7203     CharcoalImage      = 116
7204     Trim               = 117
7205     TrimImage          = 118
7206     Wave               = 119
7207     WaveImage          = 120
7208     Separate           = 121
7209     SeparateImage      = 122
7210     Stereo             = 125
7211     StereoImage        = 126
7212     Stegano            = 127
7213     SteganoImage       = 128
7214     Deconstruct        = 129
7215     DeconstructImage   = 130
7216     GaussianBlur       = 131
7217     GaussianBlurImage  = 132
7218     Convolve           = 133
7219     ConvolveImage      = 134
7220     Profile            = 135
7221     ProfileImage       = 136
7222     UnsharpMask        = 137
7223     UnsharpMaskImage   = 138
7224     MotionBlur         = 139
7225     MotionBlurImage    = 140
7226     OrderedDither      = 141
7227     OrderedDitherImage = 142
7228     Shave              = 143
7229     ShaveImage         = 144
7230     Level              = 145
7231     LevelImage         = 146
7232     Clip               = 147
7233     ClipImage          = 148
7234     AffineTransform    = 149
7235     AffineTransformImage = 150
7236     Difference         = 151
7237     DifferenceImage    = 152
7238     AdaptiveThreshold  = 153
7239     AdaptiveThresholdImage = 154
7240     Resample           = 155
7241     ResampleImage      = 156
7242     Describe           = 157
7243     DescribeImage      = 158
7244     BlackThreshold     = 159
7245     BlackThresholdImage= 160
7246     WhiteThreshold     = 161
7247     WhiteThresholdImage= 162
7248     RadialBlur         = 163
7249     RadialBlurImage    = 164
7250     Thumbnail          = 165
7251     ThumbnailImage     = 166
7252     Strip              = 167
7253     StripImage         = 168
7254     Tint               = 169
7255     TintImage          = 170
7256     Channel            = 171
7257     ChannelImage       = 172
7258     Splice             = 173
7259     SpliceImage        = 174
7260     Posterize          = 175
7261     PosterizeImage     = 176
7262     Shadow             = 177
7263     ShadowImage        = 178
7264     Identify           = 179
7265     IdentifyImage      = 180
7266     SepiaTone          = 181
7267     SepiaToneImage     = 182
7268     SigmoidalContrast  = 183
7269     SigmoidalContrastImage = 184
7270     Extent             = 185
7271     ExtentImage        = 186
7272     Vignette           = 187
7273     VignetteImage      = 188
7274     ContrastStretch    = 189
7275     ContrastStretchImage = 190
7276     Sans0              = 191
7277     Sans0Image         = 192
7278     Sans1              = 193
7279     Sans1Image         = 194
7280     AdaptiveSharpen    = 195
7281     AdaptiveSharpenImage = 196
7282     Transpose          = 197
7283     TransposeImage     = 198
7284     Transverse         = 199
7285     TransverseImage    = 200
7286     AutoOrient         = 201
7287     AutoOrientImage    = 202
7288     AdaptiveBlur       = 203
7289     AdaptiveBlurImage  = 204
7290     Sketch             = 205
7291     SketchImage        = 206
7292     UniqueColors       = 207
7293     UniqueColorsImage  = 208
7294     AdaptiveResize     = 209
7295     AdaptiveResizeImage= 210
7296     ClipMask           = 211
7297     ClipMaskImage      = 212
7298     LinearStretch      = 213
7299     LinearStretchImage = 214
7300     ColorMatrix        = 215
7301     ColorMatrixImage   = 216
7302     Mask               = 217
7303     MaskImage          = 218
7304     Polaroid           = 219
7305     PolaroidImage      = 220
7306     FloodfillPaint     = 221
7307     FloodfillPaintImage= 222
7308     Distort            = 223
7309     DistortImage       = 224
7310     Clut               = 225
7311     ClutImage          = 226
7312     LiquidRescale      = 227
7313     LiquidRescaleImage = 228
7314     Encipher           = 229
7315     EncipherImage      = 230
7316     Decipher           = 231
7317     DecipherImage      = 232
7318     Deskew             = 233
7319     DeskewImage        = 234
7320     Remap              = 235
7321     RemapImage         = 236
7322     SparseColor        = 237
7323     SparseColorImage   = 238
7324     Function           = 239
7325     FunctionImage      = 240
7326     SelectiveBlur      = 241
7327     SelectiveBlurImage = 242
7328     HaldClut           = 243
7329     HaldClutImage      = 244
7330     BlueShift          = 245
7331     BlueShiftImage     = 246
7332     ForwardFourierTransform  = 247
7333     ForwardFourierTransformImage = 248
7334     InverseFourierTransform = 249
7335     InverseFourierTransformImage = 250
7336     ColorDecisionList  = 251
7337     ColorDecisionListImage = 252
7338     AutoGamma          = 253
7339     AutoGammaImage     = 254
7340     AutoLevel          = 255
7341     AutoLevelImage     = 256
7342     LevelColors        = 257
7343     LevelImageColors   = 258
7344     Clamp              = 259
7345     ClampImage         = 260
7346     BrightnessContrast = 261
7347     BrightnessContrastImage = 262
7348     Morphology         = 263
7349     MorphologyImage    = 264
7350     Color              = 265
7351     ColorImage         = 266
7352     Mode               = 267
7353     ModeImage          = 268
7354     Statistic          = 269
7355     StatisticImage     = 270
7356     MogrifyRegion      = 666
7357   PPCODE:
7358   {
7359     AffineMatrix
7360       affine,
7361       current;
7362
7363     char
7364       attribute_flag[MaxArguments],
7365       message[MaxTextExtent];
7366
7367     ChannelType
7368       channel,
7369       channel_mask;
7370
7371     CompositeOperator
7372       compose;
7373
7374     const char
7375       *attribute,
7376       *value;
7377
7378     double
7379       angle;
7380
7381     ExceptionInfo
7382       *exception;
7383
7384     GeometryInfo
7385       geometry_info;
7386
7387     Image
7388       *image,
7389       *next,
7390       *region_image;
7391
7392     MagickBooleanType
7393       status;
7394
7395     MagickStatusType
7396       flags;
7397
7398     PixelInfo
7399       fill_color;
7400
7401     RectangleInfo
7402       geometry,
7403       region_info;
7404
7405     register ssize_t
7406       i;
7407
7408     ssize_t
7409       base,
7410       j,
7411       number_images;
7412
7413     struct Methods
7414       *rp;
7415
7416     struct PackageInfo
7417       *info;
7418
7419     SV
7420       *perl_exception,
7421       **pv,
7422       *reference,
7423       **reference_vector;
7424
7425     struct ArgumentList
7426       argument_list[MaxArguments];
7427
7428     PERL_UNUSED_VAR(ref);
7429     PERL_UNUSED_VAR(ix);
7430     exception=AcquireExceptionInfo();
7431     perl_exception=newSVpv("",0);
7432     reference_vector=NULL;
7433     region_image=NULL;
7434     number_images=0;
7435     base=2;
7436     if (sv_isobject(ST(0)) == 0)
7437       {
7438         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7439           PackageName);
7440         goto PerlException;
7441       }
7442     reference=SvRV(ST(0));
7443     region_info.width=0;
7444     region_info.height=0;
7445     region_info.x=0;
7446     region_info.y=0;
7447     region_image=(Image *) NULL;
7448     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7449     if (ix && (ix != 666))
7450       {
7451         /*
7452           Called as Method(...)
7453         */
7454         ix=(ix+1)/2;
7455         rp=(&Methods[ix-1]);
7456         attribute=rp->name;
7457       }
7458     else
7459       {
7460         /*
7461           Called as Mogrify("Method",...)
7462         */
7463         attribute=(char *) SvPV(ST(1),na);
7464         if (ix)
7465           {
7466             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7467             attribute=(char *) SvPV(ST(2),na);
7468             base++;
7469           }
7470         for (rp=Methods; ; rp++)
7471         {
7472           if (rp >= EndOf(Methods))
7473             {
7474               ThrowPerlException(exception,OptionError,
7475                 "UnrecognizedPerlMagickMethod",attribute);
7476               goto PerlException;
7477             }
7478           if (strEQcase(attribute,rp->name))
7479             break;
7480         }
7481         ix=rp-Methods+1;
7482         base++;
7483       }
7484     if (image == (Image *) NULL)
7485       {
7486         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7487         goto PerlException;
7488       }
7489     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7490     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7491     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7492     {
7493       Arguments
7494         *pp,
7495         *qq;
7496
7497       ssize_t
7498         ssize_test;
7499
7500       struct ArgumentList
7501         *al;
7502
7503       SV
7504         *sv;
7505
7506       sv=NULL;
7507       ssize_test=0;
7508       pp=(Arguments *) NULL;
7509       qq=rp->arguments;
7510       if (i == items)
7511         {
7512           pp=rp->arguments,
7513           sv=ST(i-1);
7514         }
7515       else
7516         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7517         {
7518           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7519             break;
7520           if (strEQcase(attribute,qq->method) > ssize_test)
7521             {
7522               pp=qq;
7523               ssize_test=strEQcase(attribute,qq->method);
7524             }
7525         }
7526       if (pp == (Arguments *) NULL)
7527         {
7528           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7529             attribute);
7530           goto continue_outer_loop;
7531         }
7532       al=(&argument_list[pp-rp->arguments]);
7533       switch (pp->type)
7534       {
7535         case ArrayReference:
7536         {
7537           if (SvTYPE(sv) != SVt_RV)
7538             {
7539               (void) FormatLocaleString(message,MaxTextExtent,
7540                 "invalid %.60s value",pp->method);
7541               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7542               goto continue_outer_loop;
7543             }
7544           al->array_reference=SvRV(sv);
7545           break;
7546         }
7547         case RealReference:
7548         {
7549           al->real_reference=SvNV(sv);
7550           break;
7551         }
7552         case FileReference:
7553         {
7554           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7555           break;
7556         }
7557         case ImageReference:
7558         {
7559           if (!sv_isobject(sv) ||
7560               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7561                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7562             {
7563               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7564                 PackageName);
7565               goto PerlException;
7566             }
7567           break;
7568         }
7569         case IntegerReference:
7570         {
7571           al->integer_reference=SvIV(sv);
7572           break;
7573         }
7574         case StringReference:
7575         {
7576           al->string_reference=(char *) SvPV(sv,al->length);
7577           if (sv_isobject(sv))
7578             al->image_reference=SetupList(aTHX_ SvRV(sv),
7579               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7580           break;
7581         }
7582         default:
7583         {
7584           /*
7585             Is a string; look up name.
7586           */
7587           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7588             {
7589               al->string_reference=(char *) SvPV(sv,al->length);
7590               al->integer_reference=(-1);
7591               break;
7592             }
7593           al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7594             MagickFalse,SvPV(sv,na));
7595           if (pp->type == MagickChannelOptions)
7596             al->integer_reference=ParseChannelOption(SvPV(sv,na));
7597           if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7598             {
7599               (void) FormatLocaleString(message,MaxTextExtent,
7600                 "invalid %.60s value",pp->method);
7601               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7602               goto continue_outer_loop;
7603             }
7604           break;
7605         }
7606       }
7607       attribute_flag[pp-rp->arguments]++;
7608       continue_outer_loop: ;
7609     }
7610     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7611     pv=reference_vector;
7612     SetGeometryInfo(&geometry_info);
7613     channel=DefaultChannels;
7614     for (next=image; next; next=next->next)
7615     {
7616       image=next;
7617       SetGeometry(image,&geometry);
7618       if ((region_info.width*region_info.height) != 0)
7619         {
7620           region_image=image;
7621           image=CropImage(image,&region_info,exception);
7622         }
7623       switch (ix)
7624       {
7625         default:
7626         {
7627           (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double) ix);
7628           ThrowPerlException(exception,OptionError,
7629             "UnrecognizedPerlMagickMethod",message);
7630           goto PerlException;
7631         }
7632         case 1:  /* Comment */
7633         {
7634           if (attribute_flag[0] == 0)
7635             argument_list[0].string_reference=(char *) NULL;
7636           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7637             info ? info->image_info : (ImageInfo *) NULL,image,
7638             argument_list[0].string_reference,exception),exception);
7639           break;
7640         }
7641         case 2:  /* Label */
7642         {
7643           if (attribute_flag[0] == 0)
7644             argument_list[0].string_reference=(char *) NULL;
7645           (void) SetImageProperty(image,"label",InterpretImageProperties(
7646             info ? info->image_info : (ImageInfo *) NULL,image,
7647             argument_list[0].string_reference,exception),exception);
7648           break;
7649         }
7650         case 3:  /* AddNoise */
7651         {
7652           double
7653             attenuate;
7654
7655           if (attribute_flag[0] == 0)
7656             argument_list[0].integer_reference=UniformNoise;
7657           attenuate=1.0;
7658           if (attribute_flag[1] != 0)
7659             attenuate=argument_list[1].real_reference;
7660           if (attribute_flag[2] != 0)
7661             channel=(ChannelType) argument_list[2].integer_reference;
7662           channel_mask=SetImageChannelMask(image,channel);
7663           image=AddNoiseImage(image,(NoiseType)
7664             argument_list[0].integer_reference,attenuate,exception);
7665           if (image != (Image *) NULL)
7666             (void) SetImageChannelMask(image,channel_mask);
7667           break;
7668         }
7669         case 4:  /* Colorize */
7670         {
7671           PixelInfo
7672             target;
7673
7674           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
7675             0,0,&target,exception);
7676           if (attribute_flag[0] != 0)
7677             (void) QueryColorCompliance(argument_list[0].string_reference,
7678               AllCompliance,&target,exception);
7679           if (attribute_flag[1] == 0)
7680             argument_list[1].string_reference="100%";
7681           image=ColorizeImage(image,argument_list[1].string_reference,&target,
7682             exception);
7683           break;
7684         }
7685         case 5:  /* Border */
7686         {
7687           CompositeOperator
7688             compose;
7689
7690           geometry.width=0;
7691           geometry.height=0;
7692           if (attribute_flag[0] != 0)
7693             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7694               &geometry,exception);
7695           if (attribute_flag[1] != 0)
7696             geometry.width=argument_list[1].integer_reference;
7697           if (attribute_flag[2] != 0)
7698             geometry.height=argument_list[2].integer_reference;
7699           if (attribute_flag[3] != 0)
7700             QueryColorCompliance(argument_list[3].string_reference,
7701               AllCompliance,&image->border_color,exception);
7702           if (attribute_flag[4] != 0)
7703             QueryColorCompliance(argument_list[4].string_reference,
7704               AllCompliance,&image->border_color,exception);
7705           if (attribute_flag[5] != 0)
7706             QueryColorCompliance(argument_list[5].string_reference,
7707               AllCompliance,&image->border_color,exception);
7708           compose=image->compose;
7709           if (attribute_flag[6] != 0)
7710             compose=(CompositeOperator) argument_list[6].integer_reference;
7711           image=BorderImage(image,&geometry,compose,exception);
7712           break;
7713         }
7714         case 6:  /* Blur */
7715         {
7716           if (attribute_flag[0] != 0)
7717             {
7718               flags=ParseGeometry(argument_list[0].string_reference,
7719                 &geometry_info);
7720               if ((flags & SigmaValue) == 0)
7721                 geometry_info.sigma=1.0;
7722             }
7723           if (attribute_flag[1] != 0)
7724             geometry_info.rho=argument_list[1].real_reference;
7725           if (attribute_flag[2] != 0)
7726             geometry_info.sigma=argument_list[2].real_reference;
7727           if (attribute_flag[3] != 0)
7728             channel=(ChannelType) argument_list[3].integer_reference;
7729           channel_mask=SetImageChannelMask(image,channel);
7730           image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
7731             exception);
7732           if (image != (Image *) NULL)
7733             (void) SetImageChannelMask(image,channel_mask);
7734           break;
7735         }
7736         case 7:  /* Chop */
7737         {
7738           if (attribute_flag[0] != 0)
7739             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7740               &geometry,exception);
7741           if (attribute_flag[1] != 0)
7742             geometry.width=argument_list[1].integer_reference;
7743           if (attribute_flag[2] != 0)
7744             geometry.height=argument_list[2].integer_reference;
7745           if (attribute_flag[3] != 0)
7746             geometry.x=argument_list[3].integer_reference;
7747           if (attribute_flag[4] != 0)
7748             geometry.y=argument_list[4].integer_reference;
7749           image=ChopImage(image,&geometry,exception);
7750           break;
7751         }
7752         case 8:  /* Crop */
7753         {
7754           if (attribute_flag[6] != 0)
7755             image->gravity=(GravityType) argument_list[6].integer_reference;
7756           if (attribute_flag[0] != 0)
7757             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7758               &geometry,exception);
7759           if (attribute_flag[1] != 0)
7760             geometry.width=argument_list[1].integer_reference;
7761           if (attribute_flag[2] != 0)
7762             geometry.height=argument_list[2].integer_reference;
7763           if (attribute_flag[3] != 0)
7764             geometry.x=argument_list[3].integer_reference;
7765           if (attribute_flag[4] != 0)
7766             geometry.y=argument_list[4].integer_reference;
7767           if (attribute_flag[5] != 0)
7768             image->fuzz=StringToDoubleInterval(
7769               argument_list[5].string_reference,(double) QuantumRange+1.0);
7770           image=CropImage(image,&geometry,exception);
7771           break;
7772         }
7773         case 9:  /* Despeckle */
7774         {
7775           image=DespeckleImage(image,exception);
7776           break;
7777         }
7778         case 10:  /* Edge */
7779         {
7780           if (attribute_flag[0] != 0)
7781             geometry_info.rho=argument_list[0].real_reference;
7782           image=EdgeImage(image,geometry_info.rho,geometry_info.sigma,
7783             exception);
7784           break;
7785         }
7786         case 11:  /* Emboss */
7787         {
7788           if (attribute_flag[0] != 0)
7789             {
7790               flags=ParseGeometry(argument_list[0].string_reference,
7791                 &geometry_info);
7792               if ((flags & SigmaValue) == 0)
7793                 geometry_info.sigma=1.0;
7794             }
7795           if (attribute_flag[1] != 0)
7796             geometry_info.rho=argument_list[1].real_reference;
7797           if (attribute_flag[2] != 0)
7798             geometry_info.sigma=argument_list[2].real_reference;
7799           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
7800             exception);
7801           break;
7802         }
7803         case 12:  /* Enhance */
7804         {
7805           image=EnhanceImage(image,exception);
7806           break;
7807         }
7808         case 13:  /* Flip */
7809         {
7810           image=FlipImage(image,exception);
7811           break;
7812         }
7813         case 14:  /* Flop */
7814         {
7815           image=FlopImage(image,exception);
7816           break;
7817         }
7818         case 15:  /* Frame */
7819         {
7820           CompositeOperator
7821             compose;
7822
7823           FrameInfo
7824             frame_info;
7825
7826           if (attribute_flag[0] != 0)
7827             {
7828               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7829                 &geometry,exception);
7830               frame_info.width=geometry.width;
7831               frame_info.height=geometry.height;
7832               frame_info.outer_bevel=geometry.x;
7833               frame_info.inner_bevel=geometry.y;
7834             }
7835           if (attribute_flag[1] != 0)
7836             frame_info.width=argument_list[1].integer_reference;
7837           if (attribute_flag[2] != 0)
7838             frame_info.height=argument_list[2].integer_reference;
7839           if (attribute_flag[3] != 0)
7840             frame_info.inner_bevel=argument_list[3].integer_reference;
7841           if (attribute_flag[4] != 0)
7842             frame_info.outer_bevel=argument_list[4].integer_reference;
7843           if (attribute_flag[5] != 0)
7844             QueryColorCompliance(argument_list[5].string_reference,
7845               AllCompliance,&fill_color,exception);
7846           if (attribute_flag[6] != 0)
7847             QueryColorCompliance(argument_list[6].string_reference,
7848               AllCompliance,&fill_color,exception);
7849           frame_info.x=(ssize_t) frame_info.width;
7850           frame_info.y=(ssize_t) frame_info.height;
7851           frame_info.width=image->columns+2*frame_info.x;
7852           frame_info.height=image->rows+2*frame_info.y;
7853           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
7854             image->matte_color=fill_color;
7855           compose=image->compose;
7856           if (attribute_flag[7] != 0)
7857             compose=(CompositeOperator) argument_list[7].integer_reference;
7858           image=FrameImage(image,&frame_info,compose,exception);
7859           break;
7860         }
7861         case 16:  /* Implode */
7862         {
7863           PixelInterpolateMethod
7864             method;
7865
7866           if (attribute_flag[0] == 0)
7867             argument_list[0].real_reference=0.5;
7868           method=UndefinedInterpolatePixel;
7869           if (attribute_flag[1] != 0)
7870             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
7871           image=ImplodeImage(image,argument_list[0].real_reference,
7872             method,exception);
7873           break;
7874         }
7875         case 17:  /* Magnify */
7876         {
7877           image=MagnifyImage(image,exception);
7878           break;
7879         }
7880         case 18:  /* MedianFilter */
7881         {
7882           if (attribute_flag[0] != 0)
7883             {
7884               flags=ParseGeometry(argument_list[0].string_reference,
7885                 &geometry_info);
7886               if ((flags & SigmaValue) == 0)
7887                 geometry_info.sigma=geometry_info.rho;
7888             }
7889           if (attribute_flag[1] != 0)
7890             geometry_info.rho=argument_list[1].real_reference;
7891           if (attribute_flag[2] != 0)
7892             geometry_info.sigma=argument_list[2].real_reference;
7893           if (attribute_flag[3] != 0)
7894             channel=(ChannelType) argument_list[3].integer_reference;
7895           channel_mask=SetImageChannelMask(image,channel);
7896           image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
7897             (size_t) geometry_info.sigma,exception);
7898           if (image != (Image *) NULL)
7899             (void) SetImageChannelMask(image,channel_mask);
7900           break;
7901         }
7902         case 19:  /* Minify */
7903         {
7904           image=MinifyImage(image,exception);
7905           break;
7906         }
7907         case 20:  /* OilPaint */
7908         {
7909           if (attribute_flag[0] == 0)
7910             argument_list[0].real_reference=0.0;
7911           if (attribute_flag[1] == 0)
7912             argument_list[1].real_reference=1.0;
7913           image=OilPaintImage(image,argument_list[0].real_reference,
7914             argument_list[1].real_reference,exception);
7915           break;
7916         }
7917         case 21:  /* ReduceNoise */
7918         {
7919           if (attribute_flag[0] != 0)
7920             {
7921               flags=ParseGeometry(argument_list[0].string_reference,
7922                 &geometry_info);
7923               if ((flags & SigmaValue) == 0)
7924                 geometry_info.sigma=1.0;
7925             }
7926           if (attribute_flag[1] != 0)
7927             geometry_info.rho=argument_list[1].real_reference;
7928           if (attribute_flag[2] != 0)
7929             geometry_info.sigma=argument_list[2].real_reference;
7930           if (attribute_flag[3] != 0)
7931             channel=(ChannelType) argument_list[3].integer_reference;
7932           channel_mask=SetImageChannelMask(image,channel);
7933           image=StatisticImage(image,NonpeakStatistic,(size_t)
7934             geometry_info.rho,(size_t) geometry_info.sigma,exception);
7935           if (image != (Image *) NULL)
7936             (void) SetImageChannelMask(image,channel_mask);
7937           break;
7938         }
7939         case 22:  /* Roll */
7940         {
7941           if (attribute_flag[0] != 0)
7942             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7943               &geometry,exception);
7944           if (attribute_flag[1] != 0)
7945             geometry.x=argument_list[1].integer_reference;
7946           if (attribute_flag[2] != 0)
7947             geometry.y=argument_list[2].integer_reference;
7948           image=RollImage(image,geometry.x,geometry.y,exception);
7949           break;
7950         }
7951         case 23:  /* Rotate */
7952         {
7953           if (attribute_flag[0] == 0)
7954             argument_list[0].real_reference=90.0;
7955           if (attribute_flag[1] != 0)
7956             {
7957               QueryColorCompliance(argument_list[1].string_reference,
7958                 AllCompliance,&image->background_color,exception);
7959               if ((image->background_color.alpha_trait == BlendPixelTrait) &&
7960                   (image->alpha_trait != BlendPixelTrait))
7961                 (void) SetImageAlpha(image,OpaqueAlpha,exception);
7962             }
7963           image=RotateImage(image,argument_list[0].real_reference,exception);
7964           break;
7965         }
7966         case 24:  /* Sample */
7967         {
7968           if (attribute_flag[0] != 0)
7969             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7970               &geometry,exception);
7971           if (attribute_flag[1] != 0)
7972             geometry.width=argument_list[1].integer_reference;
7973           if (attribute_flag[2] != 0)
7974             geometry.height=argument_list[2].integer_reference;
7975           image=SampleImage(image,geometry.width,geometry.height,exception);
7976           break;
7977         }
7978         case 25:  /* Scale */
7979         {
7980           if (attribute_flag[0] != 0)
7981             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7982               &geometry,exception);
7983           if (attribute_flag[1] != 0)
7984             geometry.width=argument_list[1].integer_reference;
7985           if (attribute_flag[2] != 0)
7986             geometry.height=argument_list[2].integer_reference;
7987           image=ScaleImage(image,geometry.width,geometry.height,exception);
7988           break;
7989         }
7990         case 26:  /* Shade */
7991         {
7992           if (attribute_flag[0] != 0)
7993             {
7994               flags=ParseGeometry(argument_list[0].string_reference,
7995                 &geometry_info);
7996               if ((flags & SigmaValue) == 0)
7997                 geometry_info.sigma=0.0;
7998             }
7999           if (attribute_flag[1] != 0)
8000             geometry_info.rho=argument_list[1].real_reference;
8001           if (attribute_flag[2] != 0)
8002             geometry_info.sigma=argument_list[2].real_reference;
8003           image=ShadeImage(image,
8004             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8005             geometry_info.rho,geometry_info.sigma,exception);
8006           break;
8007         }
8008         case 27:  /* Sharpen */
8009         {
8010           if (attribute_flag[0] != 0)
8011             {
8012               flags=ParseGeometry(argument_list[0].string_reference,
8013                 &geometry_info);
8014               if ((flags & SigmaValue) == 0)
8015                 geometry_info.sigma=1.0;
8016             }
8017           if (attribute_flag[1] != 0)
8018             geometry_info.rho=argument_list[1].real_reference;
8019           if (attribute_flag[2] != 0)
8020             geometry_info.sigma=argument_list[2].real_reference;
8021           if (attribute_flag[3] != 0)
8022             channel=(ChannelType) argument_list[3].integer_reference;
8023           channel_mask=SetImageChannelMask(image,channel);
8024           image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
8025             exception);
8026           if (image != (Image *) NULL)
8027             (void) SetImageChannelMask(image,channel_mask);
8028           break;
8029         }
8030         case 28:  /* Shear */
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=geometry_info.rho;
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           if (attribute_flag[3] != 0)
8044             QueryColorCompliance(argument_list[3].string_reference,
8045               AllCompliance,&image->background_color,exception);
8046           if (attribute_flag[4] != 0)
8047             QueryColorCompliance(argument_list[4].string_reference,
8048               AllCompliance,&image->background_color,exception);
8049           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
8050             exception);
8051           break;
8052         }
8053         case 29:  /* Spread */
8054         {
8055           PixelInterpolateMethod
8056             method;
8057
8058           if (attribute_flag[0] == 0)
8059             argument_list[0].real_reference=1.0;
8060           method=UndefinedInterpolatePixel;
8061           if (attribute_flag[1] != 0)
8062             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8063           image=SpreadImage(image,argument_list[0].real_reference,method,
8064             exception);
8065           break;
8066         }
8067         case 30:  /* Swirl */
8068         {
8069           PixelInterpolateMethod
8070             method;
8071
8072           if (attribute_flag[0] == 0)
8073             argument_list[0].real_reference=50.0;
8074           method=UndefinedInterpolatePixel;
8075           if (attribute_flag[1] != 0)
8076             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8077           image=SwirlImage(image,argument_list[0].real_reference,
8078             method,exception);
8079           break;
8080         }
8081         case 31:  /* Resize */
8082         case 32:  /* Zoom */
8083         {
8084           if (attribute_flag[0] != 0)
8085             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8086               &geometry,exception);
8087           if (attribute_flag[1] != 0)
8088             geometry.width=argument_list[1].integer_reference;
8089           if (attribute_flag[2] != 0)
8090             geometry.height=argument_list[2].integer_reference;
8091           if (attribute_flag[3] == 0)
8092             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
8093           if (attribute_flag[4] != 0)
8094             SetImageArtifact(image,"filter:support",
8095               argument_list[4].string_reference);
8096           image=ResizeImage(image,geometry.width,geometry.height,
8097             (FilterTypes) argument_list[3].integer_reference,
8098             exception);
8099           break;
8100         }
8101         case 33:  /* Annotate */
8102         {
8103           DrawInfo
8104             *draw_info;
8105
8106           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8107             (DrawInfo *) NULL);
8108           if (attribute_flag[0] != 0)
8109             {
8110               char
8111                 *text;
8112
8113               text=InterpretImageProperties(info ? info->image_info :
8114                 (ImageInfo *) NULL,image,argument_list[0].string_reference,
8115                 exception);
8116               (void) CloneString(&draw_info->text,text);
8117               text=DestroyString(text);
8118             }
8119           if (attribute_flag[1] != 0)
8120             (void) CloneString(&draw_info->font,
8121               argument_list[1].string_reference);
8122           if (attribute_flag[2] != 0)
8123             draw_info->pointsize=argument_list[2].real_reference;
8124           if (attribute_flag[3] != 0)
8125             (void) CloneString(&draw_info->density,
8126               argument_list[3].string_reference);
8127           if (attribute_flag[4] != 0)
8128             (void) QueryColorCompliance(argument_list[4].string_reference,
8129               AllCompliance,&draw_info->undercolor,exception);
8130           if (attribute_flag[5] != 0)
8131             {
8132               (void) QueryColorCompliance(argument_list[5].string_reference,
8133                 AllCompliance,&draw_info->stroke,exception);
8134               if (argument_list[5].image_reference != (Image *) NULL)
8135                 draw_info->stroke_pattern=CloneImage(
8136                   argument_list[5].image_reference,0,0,MagickTrue,exception);
8137             }
8138           if (attribute_flag[6] != 0)
8139             {
8140               (void) QueryColorCompliance(argument_list[6].string_reference,
8141                 AllCompliance,&draw_info->fill,exception);
8142               if (argument_list[6].image_reference != (Image *) NULL)
8143                 draw_info->fill_pattern=CloneImage(
8144                   argument_list[6].image_reference,0,0,MagickTrue,exception);
8145             }
8146           if (attribute_flag[7] != 0)
8147             {
8148               (void) CloneString(&draw_info->geometry,
8149                 argument_list[7].string_reference);
8150               flags=ParsePageGeometry(image,argument_list[7].string_reference,
8151                 &geometry,exception);
8152               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8153                 geometry_info.sigma=geometry_info.xi;
8154             }
8155           if (attribute_flag[8] != 0)
8156             (void) QueryColorCompliance(argument_list[8].string_reference,
8157               AllCompliance,&draw_info->fill,exception);
8158           if (attribute_flag[11] != 0)
8159             draw_info->gravity=(GravityType)
8160               argument_list[11].integer_reference;
8161           if (attribute_flag[25] != 0)
8162             {
8163               AV
8164                 *av;
8165
8166               av=(AV *) argument_list[25].array_reference;
8167               if ((av_len(av) != 3) && (av_len(av) != 5))
8168                 {
8169                   ThrowPerlException(exception,OptionError,
8170                     "affine matrix must have 4 or 6 elements",PackageName);
8171                   goto PerlException;
8172                 }
8173               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8174               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8175               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8176               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8177               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8178                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8179                 {
8180                   ThrowPerlException(exception,OptionError,
8181                     "affine matrix is singular",PackageName);
8182                    goto PerlException;
8183                 }
8184               if (av_len(av) == 5)
8185                 {
8186                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8187                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8188                 }
8189             }
8190           for (j=12; j < 17; j++)
8191           {
8192             if (attribute_flag[j] == 0)
8193               continue;
8194             value=argument_list[j].string_reference;
8195             angle=argument_list[j].real_reference;
8196             current=draw_info->affine;
8197             GetAffineMatrix(&affine);
8198             switch (j)
8199             {
8200               case 12:
8201               {
8202                 /*
8203                   Translate.
8204                 */
8205                 flags=ParseGeometry(value,&geometry_info);
8206                 affine.tx=geometry_info.xi;
8207                 affine.ty=geometry_info.psi;
8208                 if ((flags & PsiValue) == 0)
8209                   affine.ty=affine.tx;
8210                 break;
8211               }
8212               case 13:
8213               {
8214                 /*
8215                   Scale.
8216                 */
8217                 flags=ParseGeometry(value,&geometry_info);
8218                 affine.sx=geometry_info.rho;
8219                 affine.sy=geometry_info.sigma;
8220                 if ((flags & SigmaValue) == 0)
8221                   affine.sy=affine.sx;
8222                 break;
8223               }
8224               case 14:
8225               {
8226                 /*
8227                   Rotate.
8228                 */
8229                 if (angle == 0.0)
8230                   break;
8231                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8232                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8233                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8234                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8235                 break;
8236               }
8237               case 15:
8238               {
8239                 /*
8240                   SkewX.
8241                 */
8242                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8243                 break;
8244               }
8245               case 16:
8246               {
8247                 /*
8248                   SkewY.
8249                 */
8250                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8251                 break;
8252               }
8253             }
8254             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8255             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8256             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8257             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8258             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8259               current.tx;
8260             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8261               current.ty;
8262           }
8263           if (attribute_flag[9] == 0)
8264             argument_list[9].real_reference=0.0;
8265           if (attribute_flag[10] == 0)
8266             argument_list[10].real_reference=0.0;
8267           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8268             {
8269               char
8270                 geometry[MaxTextExtent];
8271
8272               (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
8273                 (double) argument_list[9].real_reference+draw_info->affine.tx,
8274                 (double) argument_list[10].real_reference+draw_info->affine.ty);
8275               (void) CloneString(&draw_info->geometry,geometry);
8276             }
8277           if (attribute_flag[17] != 0)
8278             draw_info->stroke_width=argument_list[17].real_reference;
8279           if (attribute_flag[18] != 0)
8280             {
8281               draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8282                 MagickTrue : MagickFalse;
8283               draw_info->stroke_antialias=draw_info->text_antialias;
8284             }
8285           if (attribute_flag[19] != 0)
8286             (void) CloneString(&draw_info->family,
8287               argument_list[19].string_reference);
8288           if (attribute_flag[20] != 0)
8289             draw_info->style=(StyleType) argument_list[20].integer_reference;
8290           if (attribute_flag[21] != 0)
8291             draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8292           if (attribute_flag[22] != 0)
8293             draw_info->weight=argument_list[22].integer_reference;
8294           if (attribute_flag[23] != 0)
8295             draw_info->align=(AlignType) argument_list[23].integer_reference;
8296           if (attribute_flag[24] != 0)
8297             (void) CloneString(&draw_info->encoding,
8298               argument_list[24].string_reference);
8299           if (attribute_flag[25] != 0)
8300             draw_info->fill_pattern=CloneImage(
8301               argument_list[25].image_reference,0,0,MagickTrue,exception);
8302           if (attribute_flag[26] != 0)
8303             draw_info->fill_pattern=CloneImage(
8304               argument_list[26].image_reference,0,0,MagickTrue,exception);
8305           if (attribute_flag[27] != 0)
8306             draw_info->stroke_pattern=CloneImage(
8307               argument_list[27].image_reference,0,0,MagickTrue,exception);
8308           if (attribute_flag[29] != 0)
8309             draw_info->kerning=argument_list[29].real_reference;
8310           if (attribute_flag[30] != 0)
8311             draw_info->interline_spacing=argument_list[30].real_reference;
8312           if (attribute_flag[31] != 0)
8313             draw_info->interword_spacing=argument_list[31].real_reference;
8314           if (attribute_flag[32] != 0)
8315             draw_info->direction=(DirectionType)
8316               argument_list[32].integer_reference;
8317           (void) AnnotateImage(image,draw_info,exception);
8318           draw_info=DestroyDrawInfo(draw_info);
8319           break;
8320         }
8321         case 34:  /* ColorFloodfill */
8322         {
8323           DrawInfo
8324             *draw_info;
8325
8326           MagickBooleanType
8327             invert;
8328
8329           PixelInfo
8330             target;
8331
8332           draw_info=CloneDrawInfo(info ? info->image_info :
8333             (ImageInfo *) NULL,(DrawInfo *) NULL);
8334           if (attribute_flag[0] != 0)
8335             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8336               &geometry,exception);
8337           if (attribute_flag[1] != 0)
8338             geometry.x=argument_list[1].integer_reference;
8339           if (attribute_flag[2] != 0)
8340             geometry.y=argument_list[2].integer_reference;
8341           if (attribute_flag[3] != 0)
8342             (void) QueryColorCompliance(argument_list[3].string_reference,
8343               AllCompliance,&draw_info->fill,exception);
8344           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
8345             geometry.x,geometry.y,&target,exception);
8346           invert=MagickFalse;
8347           if (attribute_flag[4] != 0)
8348             {
8349               QueryColorCompliance(argument_list[4].string_reference,
8350                 AllCompliance,&target,exception);
8351               invert=MagickTrue;
8352             }
8353           if (attribute_flag[5] != 0)
8354             image->fuzz=StringToDoubleInterval(
8355               argument_list[5].string_reference,(double) QuantumRange+1.0);
8356           if (attribute_flag[6] != 0)
8357             invert=(MagickBooleanType) argument_list[6].integer_reference;
8358           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8359             geometry.y,invert,exception);
8360           draw_info=DestroyDrawInfo(draw_info);
8361           break;
8362         }
8363         case 35:  /* Composite */
8364         {
8365           char
8366             composite_geometry[MaxTextExtent];
8367
8368           Image
8369             *composite_image,
8370             *rotate_image;
8371
8372           MagickBooleanType
8373             clip_to_self;
8374
8375           compose=OverCompositeOp;
8376           if (attribute_flag[0] != 0)
8377             composite_image=argument_list[0].image_reference;
8378           else
8379             {
8380               ThrowPerlException(exception,OptionError,
8381                 "CompositeImageRequired",PackageName);
8382               goto PerlException;
8383             }
8384           /*
8385             Parameter Handling used for BOTH normal and tiled composition.
8386           */
8387           if (attribute_flag[1] != 0) /* compose */
8388             compose=(CompositeOperator) argument_list[1].integer_reference;
8389           if (attribute_flag[6] != 0) /* opacity  */
8390             {
8391               if (compose != DissolveCompositeOp)
8392                 (void) SetImageAlpha(composite_image,(Quantum)
8393                   StringToDoubleInterval(argument_list[6].string_reference,
8394                   (double) QuantumRange+1.0),exception);
8395               else
8396                 {
8397                   CacheView
8398                     *composite_view;
8399
8400                   double
8401                     opacity;
8402
8403                   MagickBooleanType
8404                     sync;
8405
8406                   register ssize_t
8407                     x;
8408
8409                   register Quantum
8410                     *q;
8411
8412                   ssize_t
8413                     y;
8414
8415                   /*
8416                     Handle dissolve composite operator (patch by
8417                     Kevin A. McGrail).
8418                   */
8419                   (void) CloneString(&image->geometry,
8420                     argument_list[6].string_reference);
8421                   opacity=(Quantum) StringToDoubleInterval(
8422                     argument_list[6].string_reference,(double) QuantumRange+
8423                     1.0);
8424                   if (composite_image->alpha_trait == BlendPixelTrait)
8425                     (void) SetImageAlpha(composite_image,OpaqueAlpha,exception);
8426                   composite_view=AcquireAuthenticCacheView(composite_image,
8427                     exception);
8428                   for (y=0; y < (ssize_t) composite_image->rows ; y++)
8429                   {
8430                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8431                       composite_image->columns,1,exception);
8432                     for (x=0; x < (ssize_t) composite_image->columns; x++)
8433                     {
8434                       if (GetPixelAlpha(image,q) == OpaqueAlpha)
8435                         SetPixelAlpha(composite_image,ClampToQuantum(opacity),
8436                           q);
8437                       q+=GetPixelChannels(composite_image);
8438                     }
8439                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8440                     if (sync == MagickFalse)
8441                       break;
8442                   }
8443                   composite_view=DestroyCacheView(composite_view);
8444                 }
8445             }
8446           if (attribute_flag[9] != 0)    /* "color=>" */
8447             QueryColorCompliance(argument_list[9].string_reference,
8448               AllCompliance,&composite_image->background_color,exception);
8449           if (attribute_flag[12] != 0) /* "interpolate=>" */
8450             image->interpolate=(PixelInterpolateMethod)
8451               argument_list[12].integer_reference;
8452           if (attribute_flag[13] != 0)   /* "args=>" */
8453             (void) SetImageArtifact(composite_image,"compose:args",
8454               argument_list[13].string_reference);
8455           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8456             (void) SetImageArtifact(composite_image,"compose:args",
8457               argument_list[14].string_reference);
8458           clip_to_self=MagickTrue;
8459           if (attribute_flag[15] != 0)
8460             clip_to_self=(MagickBooleanType)
8461               argument_list[15].integer_reference;
8462           /*
8463             Tiling Composition (with orthogonal rotate).
8464           */
8465           rotate_image=(Image *) NULL;
8466           if (attribute_flag[8] != 0)   /* "rotate=>" */
8467             {
8468                /*
8469                  Rotate image.
8470                */
8471                rotate_image=RotateImage(composite_image,
8472                  argument_list[8].real_reference,exception);
8473                if (rotate_image == (Image *) NULL)
8474                  break;
8475             }
8476           if ((attribute_flag[7] != 0) &&
8477               (argument_list[7].integer_reference != 0)) /* tile */
8478             {
8479               ssize_t
8480                 x,
8481                 y;
8482
8483               /*
8484                 Tile the composite image.
8485               */
8486              if (attribute_flag[8] != 0)   /* "tile=>" */
8487                (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8488                  "false");
8489              else
8490                (void) SetImageArtifact(composite_image,
8491                  "compose:outside-overlay","false");
8492              for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8493                 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8494                 {
8495                   if (attribute_flag[8] != 0) /* rotate */
8496                     (void) CompositeImage(image,rotate_image,compose,
8497                       MagickTrue,x,y,exception);
8498                   else
8499                     (void) CompositeImage(image,composite_image,compose,
8500                       MagickTrue,x,y,exception);
8501                 }
8502               if (attribute_flag[8] != 0) /* rotate */
8503                 rotate_image=DestroyImage(rotate_image);
8504               break;
8505             }
8506           /*
8507             Parameter Handling used used ONLY for normal composition.
8508           */
8509           if (attribute_flag[5] != 0) /* gravity */
8510             image->gravity=(GravityType) argument_list[5].integer_reference;
8511           if (attribute_flag[2] != 0) /* geometry offset */
8512             {
8513               SetGeometry(image,&geometry);
8514               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8515                 &geometry);
8516               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8517                 &geometry);
8518             }
8519           if (attribute_flag[3] != 0) /* x offset */
8520             geometry.x=argument_list[3].integer_reference;
8521           if (attribute_flag[4] != 0) /* y offset */
8522             geometry.y=argument_list[4].integer_reference;
8523           if (attribute_flag[10] != 0) /* mask */
8524             {
8525               if ((image->compose == DisplaceCompositeOp) ||
8526                   (image->compose == DistortCompositeOp))
8527                 {
8528                   /*
8529                     Merge Y displacement into X displacement image.
8530                   */
8531                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8532                     exception);
8533                   (void) CompositeImage(composite_image,
8534                     argument_list[10].image_reference,CopyGreenCompositeOp,
8535                     MagickTrue,0,0,exception);
8536                 }
8537               else
8538                 {
8539                   Image
8540                     *mask_image;
8541
8542                   /*
8543                     Set a blending mask for the composition.
8544                   */
8545                   mask_image=CloneImage(argument_list[10].image_reference,0,0,
8546                     MagickTrue,exception);
8547                   (void) NegateImage(mask_image,MagickFalse,exception);
8548                   (void) SetImageMask(composite_image,mask_image,exception);
8549                   mask_image=DestroyImage(mask_image);
8550                 }
8551             }
8552           if (attribute_flag[11] != 0) /* channel */
8553             channel=(ChannelType) argument_list[11].integer_reference;
8554           /*
8555             Composite two images (normal composition).
8556           */
8557           (void) FormatLocaleString(composite_geometry,MaxTextExtent,
8558             "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8559             (double) composite_image->rows,(double) geometry.x,(double)
8560             geometry.y);
8561           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8562             exception);
8563           channel_mask=SetImageChannelMask(image,channel);
8564           if (attribute_flag[8] == 0) /* no rotate */
8565             CompositeImage(image,composite_image,compose,clip_to_self,
8566               geometry.x,geometry.y,exception);
8567           else
8568             {
8569               /*
8570                 Position adjust rotated image then composite.
8571               */
8572               geometry.x-=(ssize_t) (rotate_image->columns-
8573                 composite_image->columns)/2;
8574               geometry.y-=(ssize_t) (rotate_image->rows-
8575                 composite_image->rows)/2;
8576               CompositeImage(image,rotate_image,compose,clip_to_self,geometry.x,
8577                 geometry.y,exception);
8578               rotate_image=DestroyImage(rotate_image);
8579             }
8580           if (attribute_flag[10] != 0) /* mask */
8581             {
8582               if ((image->compose == DisplaceCompositeOp) ||
8583                   (image->compose == DistortCompositeOp))
8584                 composite_image=DestroyImage(composite_image);
8585               else
8586                 (void) SetImageMask(image,(Image *) NULL,exception);
8587             }
8588           (void) SetImageChannelMask(image,channel_mask);
8589           break;
8590         }
8591         case 36:  /* Contrast */
8592         {
8593           if (attribute_flag[0] == 0)
8594             argument_list[0].integer_reference=0;
8595           (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8596             MagickTrue : MagickFalse,exception);
8597           break;
8598         }
8599         case 37:  /* CycleColormap */
8600         {
8601           if (attribute_flag[0] == 0)
8602             argument_list[0].integer_reference=6;
8603           (void) CycleColormapImage(image,argument_list[0].integer_reference,
8604             exception);
8605           break;
8606         }
8607         case 38:  /* Draw */
8608         {
8609           DrawInfo
8610             *draw_info;
8611
8612           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8613             (DrawInfo *) NULL);
8614           (void) CloneString(&draw_info->primitive,"point");
8615           if (attribute_flag[0] != 0)
8616             {
8617               if (argument_list[0].integer_reference < 0)
8618                 (void) CloneString(&draw_info->primitive,
8619                   argument_list[0].string_reference);
8620               else
8621                 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8622                   MagickPrimitiveOptions,argument_list[0].integer_reference));
8623             }
8624           if (attribute_flag[1] != 0)
8625             {
8626               if (LocaleCompare(draw_info->primitive,"path") == 0)
8627                 {
8628                   (void) ConcatenateString(&draw_info->primitive," '");
8629                   ConcatenateString(&draw_info->primitive,
8630                     argument_list[1].string_reference);
8631                   (void) ConcatenateString(&draw_info->primitive,"'");
8632                 }
8633               else
8634                 {
8635                   (void) ConcatenateString(&draw_info->primitive," ");
8636                   ConcatenateString(&draw_info->primitive,
8637                     argument_list[1].string_reference);
8638                 }
8639             }
8640           if (attribute_flag[2] != 0)
8641             {
8642               (void) ConcatenateString(&draw_info->primitive," ");
8643               (void) ConcatenateString(&draw_info->primitive,
8644                 CommandOptionToMnemonic(MagickMethodOptions,
8645                 argument_list[2].integer_reference));
8646             }
8647           if (attribute_flag[3] != 0)
8648             {
8649               (void) QueryColorCompliance(argument_list[3].string_reference,
8650                 AllCompliance,&draw_info->stroke,exception);
8651               if (argument_list[3].image_reference != (Image *) NULL)
8652                 draw_info->stroke_pattern=CloneImage(
8653                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8654             }
8655           if (attribute_flag[4] != 0)
8656             {
8657               (void) QueryColorCompliance(argument_list[4].string_reference,
8658                 AllCompliance,&draw_info->fill,exception);
8659               if (argument_list[4].image_reference != (Image *) NULL)
8660                 draw_info->fill_pattern=CloneImage(
8661                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8662             }
8663           if (attribute_flag[5] != 0)
8664             draw_info->stroke_width=argument_list[5].real_reference;
8665           if (attribute_flag[6] != 0)
8666             (void) CloneString(&draw_info->font,
8667               argument_list[6].string_reference);
8668           if (attribute_flag[7] != 0)
8669             (void) QueryColorCompliance(argument_list[7].string_reference,
8670               AllCompliance,&draw_info->border_color,exception);
8671           if (attribute_flag[8] != 0)
8672             draw_info->affine.tx=argument_list[8].real_reference;
8673           if (attribute_flag[9] != 0)
8674             draw_info->affine.ty=argument_list[9].real_reference;
8675           if (attribute_flag[20] != 0)
8676             {
8677               AV
8678                 *av;
8679
8680               av=(AV *) argument_list[20].array_reference;
8681               if ((av_len(av) != 3) && (av_len(av) != 5))
8682                 {
8683                   ThrowPerlException(exception,OptionError,
8684                     "affine matrix must have 4 or 6 elements",PackageName);
8685                   goto PerlException;
8686                 }
8687               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8688               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8689               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8690               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8691               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8692                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8693                 {
8694                   ThrowPerlException(exception,OptionError,
8695                     "affine matrix is singular",PackageName);
8696                    goto PerlException;
8697                 }
8698               if (av_len(av) == 5)
8699                 {
8700                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8701                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8702                 }
8703             }
8704           for (j=10; j < 15; j++)
8705           {
8706             if (attribute_flag[j] == 0)
8707               continue;
8708             value=argument_list[j].string_reference;
8709             angle=argument_list[j].real_reference;
8710             current=draw_info->affine;
8711             GetAffineMatrix(&affine);
8712             switch (j)
8713             {
8714               case 10:
8715               {
8716                 /*
8717                   Translate.
8718                 */
8719                 flags=ParseGeometry(value,&geometry_info);
8720                 affine.tx=geometry_info.xi;
8721                 affine.ty=geometry_info.psi;
8722                 if ((flags & PsiValue) == 0)
8723                   affine.ty=affine.tx;
8724                 break;
8725               }
8726               case 11:
8727               {
8728                 /*
8729                   Scale.
8730                 */
8731                 flags=ParseGeometry(value,&geometry_info);
8732                 affine.sx=geometry_info.rho;
8733                 affine.sy=geometry_info.sigma;
8734                 if ((flags & SigmaValue) == 0)
8735                   affine.sy=affine.sx;
8736                 break;
8737               }
8738               case 12:
8739               {
8740                 /*
8741                   Rotate.
8742                 */
8743                 if (angle == 0.0)
8744                   break;
8745                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8746                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8747                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8748                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8749                 break;
8750               }
8751               case 13:
8752               {
8753                 /*
8754                   SkewX.
8755                 */
8756                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8757                 break;
8758               }
8759               case 14:
8760               {
8761                 /*
8762                   SkewY.
8763                 */
8764                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8765                 break;
8766               }
8767             }
8768             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8769             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8770             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8771             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8772             draw_info->affine.tx=
8773               current.sx*affine.tx+current.ry*affine.ty+current.tx;
8774             draw_info->affine.ty=
8775               current.rx*affine.tx+current.sy*affine.ty+current.ty;
8776           }
8777           if (attribute_flag[15] != 0)
8778             draw_info->fill_pattern=CloneImage(
8779               argument_list[15].image_reference,0,0,MagickTrue,exception);
8780           if (attribute_flag[16] != 0)
8781             draw_info->pointsize=argument_list[16].real_reference;
8782           if (attribute_flag[17] != 0)
8783             {
8784               draw_info->stroke_antialias=argument_list[17].integer_reference != 0
8785                 ? MagickTrue : MagickFalse;
8786               draw_info->text_antialias=draw_info->stroke_antialias;
8787             }
8788           if (attribute_flag[18] != 0)
8789             (void) CloneString(&draw_info->density,
8790               argument_list[18].string_reference);
8791           if (attribute_flag[19] != 0)
8792             draw_info->stroke_width=argument_list[19].real_reference;
8793           if (attribute_flag[21] != 0)
8794             draw_info->dash_offset=argument_list[21].real_reference;
8795           if (attribute_flag[22] != 0)
8796             {
8797               AV
8798                 *av;
8799
8800               av=(AV *) argument_list[22].array_reference;
8801               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
8802                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
8803               if (draw_info->dash_pattern != (double *) NULL)
8804                 {
8805                   for (i=0; i <= av_len(av); i++)
8806                     draw_info->dash_pattern[i]=(double)
8807                       SvNV(*(av_fetch(av,i,0)));
8808                   draw_info->dash_pattern[i]=0.0;
8809                 }
8810             }
8811           if (attribute_flag[23] != 0)
8812             image->interpolate=(PixelInterpolateMethod)
8813               argument_list[23].integer_reference;
8814           if ((attribute_flag[24] != 0) &&
8815               (draw_info->fill_pattern != (Image *) NULL))
8816             flags=ParsePageGeometry(draw_info->fill_pattern,
8817               argument_list[24].string_reference,
8818               &draw_info->fill_pattern->tile_offset,exception);
8819           if (attribute_flag[25] != 0)
8820             {
8821               (void) ConcatenateString(&draw_info->primitive," '");
8822               (void) ConcatenateString(&draw_info->primitive,
8823                 argument_list[25].string_reference);
8824               (void) ConcatenateString(&draw_info->primitive,"'");
8825             }
8826           if (attribute_flag[26] != 0)
8827             draw_info->fill_pattern=CloneImage(
8828               argument_list[26].image_reference,0,0,MagickTrue,exception);
8829           if (attribute_flag[27] != 0)
8830             draw_info->stroke_pattern=CloneImage(
8831               argument_list[27].image_reference,0,0,MagickTrue,exception);
8832           if (attribute_flag[28] != 0)
8833             (void) CloneString(&draw_info->primitive,
8834               argument_list[28].string_reference);
8835           if (attribute_flag[29] != 0)
8836             draw_info->kerning=argument_list[29].real_reference;
8837           if (attribute_flag[30] != 0)
8838             draw_info->interline_spacing=argument_list[30].real_reference;
8839           if (attribute_flag[31] != 0)
8840             draw_info->interword_spacing=argument_list[31].real_reference;
8841           if (attribute_flag[32] != 0)
8842             draw_info->direction=(DirectionType)
8843               argument_list[32].integer_reference;
8844           DrawImage(image,draw_info,exception);
8845           draw_info=DestroyDrawInfo(draw_info);
8846           break;
8847         }
8848         case 39:  /* Equalize */
8849         {
8850           if (attribute_flag[0] != 0)
8851             channel=(ChannelType) argument_list[0].integer_reference;
8852           channel_mask=SetImageChannelMask(image,channel);
8853           EqualizeImage(image,exception);
8854           (void) SetImageChannelMask(image,channel_mask);
8855           break;
8856         }
8857         case 40:  /* Gamma */
8858         {
8859           if (attribute_flag[1] != 0)
8860             channel=(ChannelType) argument_list[1].integer_reference;
8861           if (attribute_flag[2] == 0)
8862             argument_list[2].real_reference=1.0;
8863           if (attribute_flag[3] == 0)
8864             argument_list[3].real_reference=1.0;
8865           if (attribute_flag[4] == 0)
8866             argument_list[4].real_reference=1.0;
8867           if (attribute_flag[0] == 0)
8868             {
8869               (void) FormatLocaleString(message,MaxTextExtent,
8870                 "%.15g,%.15g,%.15g",(double) argument_list[2].real_reference,
8871                 (double) argument_list[3].real_reference,
8872                 (double) argument_list[4].real_reference);
8873               argument_list[0].string_reference=message;
8874             }
8875           (void) GammaImage(image,StringToDouble(
8876             argument_list[0].string_reference,(char **) NULL),exception);
8877           break;
8878         }
8879         case 41:  /* Map */
8880         {
8881           QuantizeInfo
8882             *quantize_info;
8883
8884           if (attribute_flag[0] == 0)
8885             {
8886               ThrowPerlException(exception,OptionError,"MapImageRequired",
8887                 PackageName);
8888               goto PerlException;
8889             }
8890           quantize_info=AcquireQuantizeInfo(info->image_info);
8891           if (attribute_flag[1] != 0)
8892             quantize_info->dither_method=(DitherMethod)
8893               argument_list[1].integer_reference;
8894           (void) RemapImages(quantize_info,image,
8895             argument_list[0].image_reference,exception);
8896           quantize_info=DestroyQuantizeInfo(quantize_info);
8897           break;
8898         }
8899         case 42:  /* MatteFloodfill */
8900         {
8901           DrawInfo
8902             *draw_info;
8903
8904           MagickBooleanType
8905             invert;
8906
8907           PixelInfo
8908             target;
8909
8910           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8911             (DrawInfo *) NULL);
8912           if (attribute_flag[0] != 0)
8913             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8914               &geometry,exception);
8915           if (attribute_flag[1] != 0)
8916             geometry.x=argument_list[1].integer_reference;
8917           if (attribute_flag[2] != 0)
8918             geometry.y=argument_list[2].integer_reference;
8919           if (image->alpha_trait != BlendPixelTrait)
8920             (void) SetImageAlpha(image,OpaqueAlpha,exception);
8921           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
8922             geometry.x,geometry.y,&target,exception);
8923           if (attribute_flag[4] != 0)
8924             QueryColorCompliance(argument_list[4].string_reference,
8925               AllCompliance,&target,exception);
8926           if (attribute_flag[3] != 0)
8927             target.alpha=StringToDoubleInterval(
8928               argument_list[3].string_reference,(double) (double) QuantumRange+
8929               1.0);
8930           if (attribute_flag[5] != 0)
8931             image->fuzz=StringToDoubleInterval(
8932               argument_list[5].string_reference,(double) QuantumRange+1.0);
8933           invert=MagickFalse;
8934           if (attribute_flag[6] != 0)
8935             invert=(MagickBooleanType) argument_list[6].integer_reference;
8936           channel_mask=SetImageChannelMask(image,AlphaChannel);
8937           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8938             geometry.y,invert,exception);
8939           (void) SetImageChannelMask(image,channel_mask);
8940           draw_info=DestroyDrawInfo(draw_info);
8941           break;
8942         }
8943         case 43:  /* Modulate */
8944         {
8945           char
8946             modulate[MaxTextExtent];
8947
8948           geometry_info.rho=100.0;
8949           geometry_info.sigma=100.0;
8950           geometry_info.xi=100.0;
8951           if (attribute_flag[0] != 0)
8952             (void)ParseGeometry(argument_list[0].string_reference,
8953               &geometry_info);
8954           if (attribute_flag[1] != 0)
8955             geometry_info.xi=argument_list[1].real_reference;
8956           if (attribute_flag[2] != 0)
8957             geometry_info.sigma=argument_list[2].real_reference;
8958           if (attribute_flag[3] != 0)
8959             {
8960               geometry_info.sigma=argument_list[3].real_reference;
8961               SetImageArtifact(image,"modulate:colorspace","HWB");
8962             }
8963           if (attribute_flag[4] != 0)
8964             {
8965               geometry_info.rho=argument_list[4].real_reference;
8966               SetImageArtifact(image,"modulate:colorspace","HSB");
8967             }
8968           if (attribute_flag[5] != 0)
8969             {
8970               geometry_info.sigma=argument_list[5].real_reference;
8971               SetImageArtifact(image,"modulate:colorspace","HSL");
8972             }
8973           if (attribute_flag[6] != 0)
8974             {
8975               geometry_info.rho=argument_list[6].real_reference;
8976               SetImageArtifact(image,"modulate:colorspace","HWB");
8977             }
8978           (void) FormatLocaleString(modulate,MaxTextExtent,"%.15g,%.15g,%.15g",
8979             geometry_info.rho,geometry_info.sigma,geometry_info.xi);
8980           (void) ModulateImage(image,modulate,exception);
8981           break;
8982         }
8983         case 44:  /* Negate */
8984         {
8985           if (attribute_flag[0] == 0)
8986             argument_list[0].integer_reference=0;
8987           if (attribute_flag[1] != 0)
8988             channel=(ChannelType) argument_list[1].integer_reference;
8989           channel_mask=SetImageChannelMask(image,channel);
8990           (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
8991             MagickTrue : MagickFalse,exception);
8992           (void) SetImageChannelMask(image,channel_mask);
8993           break;
8994         }
8995         case 45:  /* Normalize */
8996         {
8997           if (attribute_flag[0] != 0)
8998             channel=(ChannelType) argument_list[0].integer_reference;
8999           channel_mask=SetImageChannelMask(image,channel);
9000           NormalizeImage(image,exception);
9001           (void) SetImageChannelMask(image,channel_mask);
9002           break;
9003         }
9004         case 46:  /* NumberColors */
9005           break;
9006         case 47:  /* Opaque */
9007         {
9008           MagickBooleanType
9009             invert;
9010
9011           PixelInfo
9012             fill_color,
9013             target;
9014
9015           (void) QueryColorCompliance("none",AllCompliance,&target,
9016              exception);
9017           (void) QueryColorCompliance("none",AllCompliance,&fill_color,
9018             exception);
9019           if (attribute_flag[0] != 0)
9020             (void) QueryColorCompliance(argument_list[0].string_reference,
9021               AllCompliance,&target,exception);
9022           if (attribute_flag[1] != 0)
9023             (void) QueryColorCompliance(argument_list[1].string_reference,
9024               AllCompliance,&fill_color,exception);
9025           if (attribute_flag[2] != 0)
9026             image->fuzz=StringToDoubleInterval(
9027               argument_list[2].string_reference,(double) QuantumRange+1.0);
9028           if (attribute_flag[3] != 0)
9029             channel=(ChannelType) argument_list[3].integer_reference;
9030           invert=MagickFalse;
9031           if (attribute_flag[4] != 0)
9032             invert=(MagickBooleanType) argument_list[4].integer_reference;
9033           channel_mask=SetImageChannelMask(image,channel);
9034           (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
9035           (void) SetImageChannelMask(image,channel_mask);
9036           break;
9037         }
9038         case 48:  /* Quantize */
9039         {
9040           QuantizeInfo
9041             *quantize_info;
9042
9043           quantize_info=AcquireQuantizeInfo(info->image_info);
9044           if (attribute_flag[0] != 0)
9045             quantize_info->number_colors=(size_t)
9046               argument_list[0].integer_reference;
9047           if (attribute_flag[1] != 0)
9048             quantize_info->tree_depth=(size_t)
9049               argument_list[1].integer_reference;
9050           if (attribute_flag[2] != 0)
9051             quantize_info->colorspace=(ColorspaceType)
9052               argument_list[2].integer_reference;
9053           if (attribute_flag[3] != 0)
9054             quantize_info->dither_method=(DitherMethod)
9055               argument_list[3].integer_reference;
9056           if (attribute_flag[4] != 0)
9057             quantize_info->measure_error=argument_list[4].integer_reference !=
9058               0 ? MagickTrue : MagickFalse;
9059           if (attribute_flag[5] != 0)
9060             (void) QueryColorCompliance(argument_list[5].string_reference,
9061               AllCompliance,&image->transparent_color,exception);
9062           if (attribute_flag[5] && argument_list[5].integer_reference)
9063             {
9064               (void) QuantizeImages(quantize_info,image,exception);
9065               goto PerlException;
9066             }
9067           if (attribute_flag[6] != 0)
9068             quantize_info->dither_method=(DitherMethod)
9069               argument_list[6].integer_reference;
9070           if ((image->storage_class == DirectClass) ||
9071               (image->colors > quantize_info->number_colors) ||
9072               (quantize_info->colorspace == GRAYColorspace))
9073             (void) QuantizeImage(quantize_info,image,exception);
9074           else
9075             CompressImageColormap(image,exception);
9076           quantize_info=DestroyQuantizeInfo(quantize_info);
9077           break;
9078         }
9079         case 49:  /* Raise */
9080         {
9081           if (attribute_flag[0] != 0)
9082             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9083               &geometry,exception);
9084           if (attribute_flag[1] != 0)
9085             geometry.width=argument_list[1].integer_reference;
9086           if (attribute_flag[2] != 0)
9087             geometry.height=argument_list[2].integer_reference;
9088           if (attribute_flag[3] == 0)
9089             argument_list[3].integer_reference=1;
9090           (void) RaiseImage(image,&geometry,
9091             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
9092             exception);
9093           break;
9094         }
9095         case 50:  /* Segment */
9096         {
9097           ColorspaceType
9098             colorspace;
9099
9100           double
9101             cluster_threshold,
9102             smoothing_threshold;
9103
9104           MagickBooleanType
9105             verbose;
9106
9107           cluster_threshold=1.0;
9108           smoothing_threshold=1.5;
9109           colorspace=sRGBColorspace;
9110           verbose=MagickFalse;
9111           if (attribute_flag[0] != 0)
9112             {
9113               flags=ParseGeometry(argument_list[0].string_reference,
9114                 &geometry_info);
9115               cluster_threshold=geometry_info.rho;
9116               if (flags & SigmaValue)
9117                 smoothing_threshold=geometry_info.sigma;
9118             }
9119           if (attribute_flag[1] != 0)
9120             cluster_threshold=argument_list[1].real_reference;
9121           if (attribute_flag[2] != 0)
9122             smoothing_threshold=argument_list[2].real_reference;
9123           if (attribute_flag[3] != 0)
9124             colorspace=(ColorspaceType) argument_list[3].integer_reference;
9125           if (attribute_flag[4] != 0)
9126             verbose=argument_list[4].integer_reference != 0 ?
9127               MagickTrue : MagickFalse;
9128           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
9129             smoothing_threshold,exception);
9130           break;
9131         }
9132         case 51:  /* Signature */
9133         {
9134           (void) SignatureImage(image,exception);
9135           break;
9136         }
9137         case 52:  /* Solarize */
9138         {
9139           geometry_info.rho=QuantumRange/2.0;
9140           if (attribute_flag[0] != 0)
9141             flags=ParseGeometry(argument_list[0].string_reference,
9142               &geometry_info);
9143           if (attribute_flag[1] != 0)
9144             geometry_info.rho=StringToDoubleInterval(
9145               argument_list[1].string_reference,(double) QuantumRange+1.0);
9146           (void) SolarizeImage(image,geometry_info.rho,exception);
9147           break;
9148         }
9149         case 53:  /* Sync */
9150         {
9151           (void) SyncImage(image,exception);
9152           break;
9153         }
9154         case 54:  /* Texture */
9155         {
9156           if (attribute_flag[0] == 0)
9157             break;
9158           TextureImage(image,argument_list[0].image_reference,exception);
9159           break;
9160         }
9161         case 55:  /* Evalute */
9162         {
9163           MagickEvaluateOperator
9164             op;
9165
9166           op=SetEvaluateOperator;
9167           if (attribute_flag[0] == MagickFalse)
9168             argument_list[0].real_reference=0.0;
9169           if (attribute_flag[1] != MagickFalse)
9170             op=(MagickEvaluateOperator) argument_list[1].integer_reference;
9171           if (attribute_flag[2] != MagickFalse)
9172             channel=(ChannelType) argument_list[2].integer_reference;
9173           channel_mask=SetImageChannelMask(image,channel);
9174           (void) EvaluateImage(image,op,argument_list[0].real_reference,
9175             exception);
9176           (void) SetImageChannelMask(image,channel_mask);
9177           break;
9178         }
9179         case 56:  /* Transparent */
9180         {
9181           double
9182             opacity;
9183
9184           MagickBooleanType
9185             invert;
9186
9187           PixelInfo
9188             target;
9189
9190           (void) QueryColorCompliance("none",AllCompliance,&target,
9191             exception);
9192           if (attribute_flag[0] != 0)
9193             (void) QueryColorCompliance(argument_list[0].string_reference,
9194               AllCompliance,&target,exception);
9195           opacity=TransparentAlpha;
9196           if (attribute_flag[1] != 0)
9197             opacity=StringToDoubleInterval(argument_list[1].string_reference,
9198               (double) QuantumRange+1.0);
9199           if (attribute_flag[2] != 0)
9200             image->fuzz=StringToDoubleInterval(
9201               argument_list[2].string_reference,(double) QuantumRange+1.0);
9202           if (attribute_flag[3] == 0)
9203             argument_list[3].integer_reference=0;
9204           invert=MagickFalse;
9205           if (attribute_flag[3] != 0)
9206             invert=(MagickBooleanType) argument_list[3].integer_reference;
9207           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9208             invert,exception);
9209           break;
9210         }
9211         case 57:  /* Threshold */
9212         {
9213           double
9214             threshold;
9215
9216           if (attribute_flag[0] == 0)
9217             argument_list[0].string_reference="50%";
9218           if (attribute_flag[1] != 0)
9219             channel=(ChannelType) argument_list[1].integer_reference;
9220           threshold=StringToDoubleInterval(argument_list[0].string_reference,
9221             (double) QuantumRange+1.0);
9222           channel_mask=SetImageChannelMask(image,channel);
9223           (void) BilevelImage(image,threshold,exception);
9224           (void) SetImageChannelMask(image,channel_mask);
9225           break;
9226         }
9227         case 58:  /* Charcoal */
9228         {
9229           if (attribute_flag[0] != 0)
9230             {
9231               flags=ParseGeometry(argument_list[0].string_reference,
9232                 &geometry_info);
9233               if ((flags & SigmaValue) == 0)
9234                 geometry_info.sigma=1.0;
9235             }
9236           if (attribute_flag[1] != 0)
9237             geometry_info.rho=argument_list[1].real_reference;
9238           if (attribute_flag[2] != 0)
9239             geometry_info.sigma=argument_list[2].real_reference;
9240           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9241             exception);
9242           break;
9243         }
9244         case 59:  /* Trim */
9245         {
9246           if (attribute_flag[0] != 0)
9247             image->fuzz=StringToDoubleInterval(
9248               argument_list[0].string_reference,(double) QuantumRange+1.0);
9249           image=TrimImage(image,exception);
9250           break;
9251         }
9252         case 60:  /* Wave */
9253         {
9254           PixelInterpolateMethod
9255             method;
9256
9257           if (attribute_flag[0] != 0)
9258             {
9259               flags=ParseGeometry(argument_list[0].string_reference,
9260                 &geometry_info);
9261               if ((flags & SigmaValue) == 0)
9262                 geometry_info.sigma=1.0;
9263             }
9264           if (attribute_flag[1] != 0)
9265             geometry_info.rho=argument_list[1].real_reference;
9266           if (attribute_flag[2] != 0)
9267             geometry_info.sigma=argument_list[2].real_reference;
9268           method=UndefinedInterpolatePixel;
9269           if (attribute_flag[3] != 0)
9270             method=(PixelInterpolateMethod) argument_list[3].integer_reference;
9271           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9272             method,exception);
9273           break;
9274         }
9275         case 61:  /* Separate */
9276         {
9277           if (attribute_flag[0] != 0)
9278             channel=(ChannelType) argument_list[0].integer_reference;
9279           image=SeparateImage(image,channel,exception);
9280           break;
9281         }
9282         case 63:  /* Stereo */
9283         {
9284           if (attribute_flag[0] == 0)
9285             {
9286               ThrowPerlException(exception,OptionError,"StereoImageRequired",
9287                 PackageName);
9288               goto PerlException;
9289             }
9290           if (attribute_flag[1] != 0)
9291             geometry.x=argument_list[1].integer_reference;
9292           if (attribute_flag[2] != 0)
9293             geometry.y=argument_list[2].integer_reference;
9294           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9295             geometry.x,geometry.y,exception);
9296           break;
9297         }
9298         case 64:  /* Stegano */
9299         {
9300           if (attribute_flag[0] == 0)
9301             {
9302               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9303                 PackageName);
9304               goto PerlException;
9305             }
9306           if (attribute_flag[1] == 0)
9307             argument_list[1].integer_reference=0;
9308           image->offset=argument_list[1].integer_reference;
9309           image=SteganoImage(image,argument_list[0].image_reference,exception);
9310           break;
9311         }
9312         case 65:  /* Deconstruct */
9313         {
9314           image=CompareImagesLayers(image,CompareAnyLayer,exception);
9315           break;
9316         }
9317         case 66:  /* GaussianBlur */
9318         {
9319           if (attribute_flag[0] != 0)
9320             {
9321               flags=ParseGeometry(argument_list[0].string_reference,
9322                 &geometry_info);
9323               if ((flags & SigmaValue) == 0)
9324                 geometry_info.sigma=1.0;
9325             }
9326           if (attribute_flag[1] != 0)
9327             geometry_info.rho=argument_list[1].real_reference;
9328           if (attribute_flag[2] != 0)
9329             geometry_info.sigma=argument_list[2].real_reference;
9330           if (attribute_flag[3] != 0)
9331             channel=(ChannelType) argument_list[3].integer_reference;
9332           channel_mask=SetImageChannelMask(image,channel);
9333           image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9334             exception);
9335           if (image != (Image *) NULL)
9336             (void) SetImageChannelMask(image,channel_mask);
9337           break;
9338         }
9339         case 67:  /* Convolve */
9340         {
9341           KernelInfo
9342             *kernel;
9343
9344           kernel=(KernelInfo *) NULL;
9345           if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9346             break;
9347           if (attribute_flag[0] != 0)
9348             {
9349               AV
9350                 *av;
9351
9352               size_t
9353                 order;
9354
9355               kernel=AcquireKernelInfo((const char *) NULL);
9356               if (kernel == (KernelInfo *) NULL)
9357                 break;
9358               av=(AV *) argument_list[0].array_reference;
9359               order=(size_t) sqrt(av_len(av)+1);
9360               kernel->width=order;
9361               kernel->height=order;
9362               kernel->values=(MagickRealType *) AcquireAlignedMemory(order,
9363                 order*sizeof(*kernel->values));
9364               if (kernel->values == (MagickRealType *) NULL)
9365                 {
9366                   kernel=DestroyKernelInfo(kernel);
9367                   ThrowPerlException(exception,ResourceLimitFatalError,
9368                     "MemoryAllocationFailed",PackageName);
9369                   goto PerlException;
9370                 }
9371               for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9372                 kernel->values[j]=(MagickRealType) SvNV(*(av_fetch(av,j,0)));
9373               for ( ; j < (ssize_t) (order*order); j++)
9374                 kernel->values[j]=0.0;
9375             }
9376           if (attribute_flag[1] != 0)
9377             channel=(ChannelType) argument_list[1].integer_reference;
9378           if (attribute_flag[2] != 0)
9379             SetImageArtifact(image,"filter:blur",
9380               argument_list[2].string_reference);
9381           if (attribute_flag[3] != 0)
9382             {
9383               kernel=AcquireKernelInfo(argument_list[3].string_reference);
9384               if (kernel == (KernelInfo *) NULL)
9385                 break;
9386             }
9387           channel_mask=SetImageChannelMask(image,channel);
9388           image=ConvolveImage(image,kernel,exception);
9389           if (image != (Image *) NULL)
9390             (void) SetImageChannelMask(image,channel_mask);
9391           kernel=DestroyKernelInfo(kernel);
9392           break;
9393         }
9394         case 68:  /* Profile */
9395         {
9396           const char
9397             *name;
9398
9399           Image
9400             *profile_image;
9401
9402           ImageInfo
9403             *profile_info;
9404
9405           StringInfo
9406             *profile;
9407
9408           name="*";
9409           if (attribute_flag[0] != 0)
9410             name=argument_list[0].string_reference;
9411           if (attribute_flag[2] != 0)
9412             image->rendering_intent=(RenderingIntent)
9413               argument_list[2].integer_reference;
9414           if (attribute_flag[3] != 0)
9415             image->black_point_compensation=
9416               argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9417           if (attribute_flag[1] != 0)
9418             {
9419               if (argument_list[1].length == 0)
9420                 {
9421                   /*
9422                     Remove a profile from the image.
9423                   */
9424                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9425                     exception);
9426                   break;
9427                 }
9428               /*
9429                 Associate user supplied profile with the image.
9430               */
9431               profile=AcquireStringInfo(argument_list[1].length);
9432               SetStringInfoDatum(profile,(const unsigned char *)
9433                 argument_list[1].string_reference);
9434               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9435                 (size_t) GetStringInfoLength(profile),exception);
9436               profile=DestroyStringInfo(profile);
9437               break;
9438             }
9439           /*
9440             Associate a profile with the image.
9441           */
9442           profile_info=CloneImageInfo(info ? info->image_info :
9443             (ImageInfo *) NULL);
9444           profile_image=ReadImages(profile_info,name,exception);
9445           if (profile_image == (Image *) NULL)
9446             break;
9447           ResetImageProfileIterator(profile_image);
9448           name=GetNextImageProfile(profile_image);
9449           while (name != (const char *) NULL)
9450           {
9451             const StringInfo
9452               *profile;
9453
9454             profile=GetImageProfile(profile_image,name);
9455             if (profile != (const StringInfo *) NULL)
9456               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9457                 (size_t) GetStringInfoLength(profile),exception);
9458             name=GetNextImageProfile(profile_image);
9459           }
9460           profile_image=DestroyImage(profile_image);
9461           profile_info=DestroyImageInfo(profile_info);
9462           break;
9463         }
9464         case 69:  /* UnsharpMask */
9465         {
9466           if (attribute_flag[0] != 0)
9467             {
9468               flags=ParseGeometry(argument_list[0].string_reference,
9469                 &geometry_info);
9470               if ((flags & SigmaValue) == 0)
9471                 geometry_info.sigma=1.0;
9472               if ((flags & XiValue) == 0)
9473                 geometry_info.xi=1.0;
9474               if ((flags & PsiValue) == 0)
9475                 geometry_info.psi=0.5;
9476             }
9477           if (attribute_flag[1] != 0)
9478             geometry_info.rho=argument_list[1].real_reference;
9479           if (attribute_flag[2] != 0)
9480             geometry_info.sigma=argument_list[2].real_reference;
9481           if (attribute_flag[3] != 0)
9482             geometry_info.xi=argument_list[3].real_reference;
9483           if (attribute_flag[4] != 0)
9484             geometry_info.psi=argument_list[4].real_reference;
9485           if (attribute_flag[5] != 0)
9486             channel=(ChannelType) argument_list[5].integer_reference;
9487           channel_mask=SetImageChannelMask(image,channel);
9488           image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9489             geometry_info.xi,geometry_info.psi,exception);
9490           if (image != (Image *) NULL)
9491             (void) SetImageChannelMask(image,channel_mask);
9492           break;
9493         }
9494         case 70:  /* MotionBlur */
9495         {
9496           if (attribute_flag[0] != 0)
9497             {
9498               flags=ParseGeometry(argument_list[0].string_reference,
9499                 &geometry_info);
9500               if ((flags & SigmaValue) == 0)
9501                 geometry_info.sigma=1.0;
9502               if ((flags & XiValue) == 0)
9503                 geometry_info.xi=1.0;
9504             }
9505           if (attribute_flag[1] != 0)
9506             geometry_info.rho=argument_list[1].real_reference;
9507           if (attribute_flag[2] != 0)
9508             geometry_info.sigma=argument_list[2].real_reference;
9509           if (attribute_flag[3] != 0)
9510             geometry_info.xi=argument_list[3].real_reference;
9511           if (attribute_flag[4] != 0)
9512             channel=(ChannelType) argument_list[4].integer_reference;
9513           channel_mask=SetImageChannelMask(image,channel);
9514           image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9515             geometry_info.xi,exception);
9516           if (image != (Image *) NULL)
9517             (void) SetImageChannelMask(image,channel_mask);
9518           break;
9519         }
9520         case 71:  /* OrderedDither */
9521         {
9522           if (attribute_flag[0] == 0)
9523             argument_list[0].string_reference="o8x8";
9524           if (attribute_flag[1] != 0)
9525             channel=(ChannelType) argument_list[1].integer_reference;
9526           channel_mask=SetImageChannelMask(image,channel);
9527           (void) OrderedPosterizeImage(image,argument_list[0].string_reference,
9528             exception);
9529           (void) SetImageChannelMask(image,channel_mask);
9530           break;
9531         }
9532         case 72:  /* Shave */
9533         {
9534           if (attribute_flag[0] != 0)
9535             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9536               &geometry,exception);
9537           if (attribute_flag[1] != 0)
9538             geometry.width=argument_list[1].integer_reference;
9539           if (attribute_flag[2] != 0)
9540             geometry.height=argument_list[2].integer_reference;
9541           image=ShaveImage(image,&geometry,exception);
9542           break;
9543         }
9544         case 73:  /* Level */
9545         {
9546           double
9547             black_point,
9548             gamma,
9549             white_point;
9550
9551           black_point=0.0;
9552           white_point=(double) image->columns*image->rows;
9553           gamma=1.0;
9554           if (attribute_flag[0] != 0)
9555             {
9556               flags=ParseGeometry(argument_list[0].string_reference,
9557                 &geometry_info);
9558               black_point=geometry_info.rho;
9559               if ((flags & SigmaValue) != 0)
9560                 white_point=geometry_info.sigma;
9561               if ((flags & XiValue) != 0)
9562                 gamma=geometry_info.xi;
9563               if ((flags & PercentValue) != 0)
9564                 {
9565                   black_point*=(double) (QuantumRange/100.0);
9566                   white_point*=(double) (QuantumRange/100.0);
9567                 }
9568               if ((flags & SigmaValue) == 0)
9569                 white_point=(double) QuantumRange-black_point;
9570             }
9571           if (attribute_flag[1] != 0)
9572             black_point=argument_list[1].real_reference;
9573           if (attribute_flag[2] != 0)
9574             white_point=argument_list[2].real_reference;
9575           if (attribute_flag[3] != 0)
9576             gamma=argument_list[3].real_reference;
9577           if (attribute_flag[4] != 0)
9578             channel=(ChannelType) argument_list[4].integer_reference;
9579           if (attribute_flag[5] != 0)
9580             {
9581               argument_list[0].real_reference=argument_list[5].real_reference;
9582               attribute_flag[0]=attribute_flag[5];
9583             }
9584           channel_mask=SetImageChannelMask(image,channel);
9585           (void) LevelImage(image,black_point,white_point,gamma,exception);
9586           (void) SetImageChannelMask(image,channel_mask);
9587           break;
9588         }
9589         case 74:  /* Clip */
9590         {
9591           if (attribute_flag[0] == 0)
9592             argument_list[0].string_reference="#1";
9593           if (attribute_flag[1] == 0)
9594             argument_list[1].integer_reference=MagickTrue;
9595           (void) ClipImagePath(image,argument_list[0].string_reference,
9596             argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse,
9597             exception);
9598           break;
9599         }
9600         case 75:  /* AffineTransform */
9601         {
9602           DrawInfo
9603             *draw_info;
9604
9605           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9606             (DrawInfo *) NULL);
9607           if (attribute_flag[0] != 0)
9608             {
9609               AV
9610                 *av;
9611
9612               av=(AV *) argument_list[0].array_reference;
9613               if ((av_len(av) != 3) && (av_len(av) != 5))
9614                 {
9615                   ThrowPerlException(exception,OptionError,
9616                     "affine matrix must have 4 or 6 elements",PackageName);
9617                   goto PerlException;
9618                 }
9619               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9620               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9621               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9622               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9623               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9624                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9625                 {
9626                   ThrowPerlException(exception,OptionError,
9627                     "affine matrix is singular",PackageName);
9628                    goto PerlException;
9629                 }
9630               if (av_len(av) == 5)
9631                 {
9632                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9633                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9634                 }
9635             }
9636           for (j=1; j < 6; j++)
9637           {
9638             if (attribute_flag[j] == 0)
9639               continue;
9640             value=argument_list[j].string_reference;
9641             angle=argument_list[j].real_reference;
9642             current=draw_info->affine;
9643             GetAffineMatrix(&affine);
9644             switch (j)
9645             {
9646               case 1:
9647               {
9648                 /*
9649                   Translate.
9650                 */
9651                 flags=ParseGeometry(value,&geometry_info);
9652                 affine.tx=geometry_info.xi;
9653                 affine.ty=geometry_info.psi;
9654                 if ((flags & PsiValue) == 0)
9655                   affine.ty=affine.tx;
9656                 break;
9657               }
9658               case 2:
9659               {
9660                 /*
9661                   Scale.
9662                 */
9663                 flags=ParseGeometry(value,&geometry_info);
9664                 affine.sx=geometry_info.rho;
9665                 affine.sy=geometry_info.sigma;
9666                 if ((flags & SigmaValue) == 0)
9667                   affine.sy=affine.sx;
9668                 break;
9669               }
9670               case 3:
9671               {
9672                 /*
9673                   Rotate.
9674                 */
9675                 if (angle == 0.0)
9676                   break;
9677                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9678                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9679                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9680                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9681                 break;
9682               }
9683               case 4:
9684               {
9685                 /*
9686                   SkewX.
9687                 */
9688                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9689                 break;
9690               }
9691               case 5:
9692               {
9693                 /*
9694                   SkewY.
9695                 */
9696                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9697                 break;
9698               }
9699             }
9700             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9701             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9702             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9703             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9704             draw_info->affine.tx=
9705               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9706             draw_info->affine.ty=
9707               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9708           }
9709           if (attribute_flag[6] != 0)
9710             image->interpolate=(PixelInterpolateMethod)
9711               argument_list[6].integer_reference;
9712           if (attribute_flag[7] != 0)
9713             QueryColorCompliance(argument_list[7].string_reference,
9714               AllCompliance,&image->background_color,exception);
9715           image=AffineTransformImage(image,&draw_info->affine,exception);
9716           draw_info=DestroyDrawInfo(draw_info);
9717           break;
9718         }
9719         case 76:  /* Difference */
9720         {
9721           if (attribute_flag[0] == 0)
9722             {
9723               ThrowPerlException(exception,OptionError,
9724                 "ReferenceImageRequired",PackageName);
9725               goto PerlException;
9726             }
9727           if (attribute_flag[1] != 0)
9728             image->fuzz=StringToDoubleInterval(
9729               argument_list[1].string_reference,(double) QuantumRange+1.0);
9730           (void) IsImagesEqual(image,argument_list[0].image_reference,
9731             exception);
9732           break;
9733         }
9734         case 77:  /* AdaptiveThreshold */
9735         {
9736           if (attribute_flag[0] != 0)
9737             {
9738               flags=ParseGeometry(argument_list[0].string_reference,
9739                 &geometry_info);
9740               if ((flags & PercentValue) != 0)
9741                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9742             }
9743           if (attribute_flag[1] != 0)
9744             geometry_info.rho=argument_list[1].integer_reference;
9745           if (attribute_flag[2] != 0)
9746             geometry_info.sigma=argument_list[2].integer_reference;
9747           if (attribute_flag[3] != 0)
9748             geometry_info.xi=argument_list[3].integer_reference;;
9749           image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
9750             (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
9751           break;
9752         }
9753         case 78:  /* Resample */
9754         {
9755           size_t
9756             height,
9757             width;
9758
9759           if (attribute_flag[0] != 0)
9760             {
9761               flags=ParseGeometry(argument_list[0].string_reference,
9762                 &geometry_info);
9763               if ((flags & SigmaValue) == 0)
9764                 geometry_info.sigma=geometry_info.rho;
9765             }
9766           if (attribute_flag[1] != 0)
9767             geometry_info.rho=argument_list[1].real_reference;
9768           if (attribute_flag[2] != 0)
9769             geometry_info.sigma=argument_list[2].real_reference;
9770           if (attribute_flag[3] == 0)
9771             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
9772           if (attribute_flag[4] == 0)
9773             SetImageArtifact(image,"filter:support",
9774               argument_list[4].string_reference);
9775           width=(size_t) (geometry_info.rho*image->columns/
9776             (image->resolution.x == 0.0 ? 72.0 : image->resolution.x)+0.5);
9777           height=(size_t) (geometry_info.sigma*image->rows/
9778             (image->resolution.y == 0.0 ? 72.0 : image->resolution.y)+0.5);
9779           image=ResizeImage(image,width,height,(FilterTypes)
9780             argument_list[3].integer_reference,exception);
9781           if (image != (Image *) NULL)
9782             {
9783               image->resolution.x=geometry_info.rho;
9784               image->resolution.y=geometry_info.sigma;
9785             }
9786           break;
9787         }
9788         case 79:  /* Describe */
9789         {
9790           if (attribute_flag[0] == 0)
9791             argument_list[0].file_reference=(FILE *) NULL;
9792           if (attribute_flag[1] != 0)
9793             (void) SetImageArtifact(image,"identify:features",
9794               argument_list[1].string_reference);
9795           (void) IdentifyImage(image,argument_list[0].file_reference,
9796             MagickTrue,exception);
9797           break;
9798         }
9799         case 80:  /* BlackThreshold */
9800         {
9801           if (attribute_flag[0] == 0)
9802             argument_list[0].string_reference="50%";
9803           if (attribute_flag[2] != 0)
9804             channel=(ChannelType) argument_list[2].integer_reference;
9805           channel_mask=SetImageChannelMask(image,channel);
9806           BlackThresholdImage(image,argument_list[0].string_reference,
9807             exception);
9808           (void) SetImageChannelMask(image,channel_mask);
9809           break;
9810         }
9811         case 81:  /* WhiteThreshold */
9812         {
9813           if (attribute_flag[0] == 0)
9814             argument_list[0].string_reference="50%";
9815           if (attribute_flag[2] != 0)
9816             channel=(ChannelType) argument_list[2].integer_reference;
9817           channel_mask=SetImageChannelMask(image,channel);
9818           WhiteThresholdImage(image,argument_list[0].string_reference,
9819             exception);
9820           (void) SetImageChannelMask(image,channel_mask);
9821           break;
9822         }
9823         case 82:  /* RadialBlur */
9824         {
9825           if (attribute_flag[0] != 0)
9826             {
9827               flags=ParseGeometry(argument_list[0].string_reference,
9828                 &geometry_info);
9829             }
9830           if (attribute_flag[1] != 0)
9831             geometry_info.rho=argument_list[1].real_reference;
9832           if (attribute_flag[2] != 0)
9833             channel=(ChannelType) argument_list[2].integer_reference;
9834           channel_mask=SetImageChannelMask(image,channel);
9835           image=RadialBlurImage(image,geometry_info.rho,exception);
9836           if (image != (Image *) NULL)
9837             (void) SetImageChannelMask(image,channel_mask);
9838           break;
9839         }
9840         case 83:  /* Thumbnail */
9841         {
9842           if (attribute_flag[0] != 0)
9843             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
9844               &geometry,exception);
9845           if (attribute_flag[1] != 0)
9846             geometry.width=argument_list[1].integer_reference;
9847           if (attribute_flag[2] != 0)
9848             geometry.height=argument_list[2].integer_reference;
9849           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
9850           break;
9851         }
9852         case 84:  /* Strip */
9853         {
9854           (void) StripImage(image,exception);
9855           break;
9856         }
9857         case 85:  /* Tint */
9858         {
9859           PixelInfo
9860             tint;
9861
9862           GetPixelInfo(image,&tint);
9863           if (attribute_flag[0] != 0)
9864             (void) QueryColorCompliance(argument_list[0].string_reference,
9865               AllCompliance,&tint,exception);
9866           if (attribute_flag[1] == 0)
9867             argument_list[1].string_reference="100";
9868           image=TintImage(image,argument_list[1].string_reference,&tint,
9869             exception);
9870           break;
9871         }
9872         case 86:  /* Channel */
9873         {
9874           if (attribute_flag[0] != 0)
9875             channel=(ChannelType) argument_list[0].integer_reference;
9876           image=SeparateImage(image,channel,exception);
9877           break;
9878         }
9879         case 87:  /* Splice */
9880         {
9881           if (attribute_flag[0] != 0)
9882             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
9883               &geometry,exception);
9884           if (attribute_flag[1] != 0)
9885             geometry.width=argument_list[1].integer_reference;
9886           if (attribute_flag[2] != 0)
9887             geometry.height=argument_list[2].integer_reference;
9888           if (attribute_flag[3] != 0)
9889             geometry.x=argument_list[3].integer_reference;
9890           if (attribute_flag[4] != 0)
9891             geometry.y=argument_list[4].integer_reference;
9892           if (attribute_flag[5] != 0)
9893             image->fuzz=StringToDoubleInterval(
9894               argument_list[5].string_reference,(double) QuantumRange+1.0);
9895           if (attribute_flag[6] != 0)
9896             (void) QueryColorCompliance(argument_list[6].string_reference,
9897               AllCompliance,&image->background_color,exception);
9898           if (attribute_flag[7] != 0)
9899             image->gravity=(GravityType) argument_list[7].integer_reference;
9900           image=SpliceImage(image,&geometry,exception);
9901           break;
9902         }
9903         case 88:  /* Posterize */
9904         {
9905           if (attribute_flag[0] == 0)
9906             argument_list[0].integer_reference=3;
9907           if (attribute_flag[1] == 0)
9908             argument_list[1].integer_reference=0;
9909           (void) PosterizeImage(image,argument_list[0].integer_reference,
9910             argument_list[1].integer_reference ? RiemersmaDitherMethod :
9911             NoDitherMethod,exception);
9912           break;
9913         }
9914         case 89:  /* Shadow */
9915         {
9916           if (attribute_flag[0] != 0)
9917             {
9918               flags=ParseGeometry(argument_list[0].string_reference,
9919                 &geometry_info);
9920               if ((flags & SigmaValue) == 0)
9921                 geometry_info.sigma=1.0;
9922               if ((flags & XiValue) == 0)
9923                 geometry_info.xi=4.0;
9924               if ((flags & PsiValue) == 0)
9925                 geometry_info.psi=4.0;
9926             }
9927           if (attribute_flag[1] != 0)
9928             geometry_info.rho=argument_list[1].real_reference;
9929           if (attribute_flag[2] != 0)
9930             geometry_info.sigma=argument_list[2].real_reference;
9931           if (attribute_flag[3] != 0)
9932             geometry_info.xi=argument_list[3].integer_reference;
9933           if (attribute_flag[4] != 0)
9934             geometry_info.psi=argument_list[4].integer_reference;
9935           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
9936             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
9937             ceil(geometry_info.psi-0.5),exception);
9938           break;
9939         }
9940         case 90:  /* Identify */
9941         {
9942           if (attribute_flag[0] == 0)
9943             argument_list[0].file_reference=(FILE *) NULL;
9944           if (attribute_flag[1] != 0)
9945             (void) SetImageArtifact(image,"identify:features",
9946               argument_list[1].string_reference);
9947           if ((attribute_flag[2] != 0) &&
9948               (argument_list[2].integer_reference != 0))
9949             (void) SetImageArtifact(image,"identify:unique","true");
9950           (void) IdentifyImage(image,argument_list[0].file_reference,
9951             MagickTrue,exception);
9952           break;
9953         }
9954         case 91:  /* SepiaTone */
9955         {
9956           if (attribute_flag[0] == 0)
9957             argument_list[0].real_reference=80.0*QuantumRange/100.0;
9958           image=SepiaToneImage(image,argument_list[0].real_reference,
9959             exception);
9960           break;
9961         }
9962         case 92:  /* SigmoidalContrast */
9963         {
9964           MagickBooleanType
9965             sharpen;
9966
9967           if (attribute_flag[0] != 0)
9968             {
9969               flags=ParseGeometry(argument_list[0].string_reference,
9970                 &geometry_info);
9971               if ((flags & SigmaValue) == 0)
9972                 geometry_info.sigma=QuantumRange/2.0;
9973               if ((flags & PercentValue) != 0)
9974                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
9975             }
9976           if (attribute_flag[1] != 0)
9977             geometry_info.rho=argument_list[1].real_reference;
9978           if (attribute_flag[2] != 0)
9979             geometry_info.sigma=argument_list[2].real_reference;
9980           if (attribute_flag[3] != 0)
9981             channel=(ChannelType) argument_list[3].integer_reference;
9982           sharpen=MagickTrue;
9983           if (attribute_flag[4] != 0)
9984             sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
9985               MagickFalse;
9986           channel_mask=SetImageChannelMask(image,channel);
9987           (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
9988             geometry_info.sigma,exception);
9989           (void) SetImageChannelMask(image,channel_mask);
9990           break;
9991         }
9992         case 93:  /* Extent */
9993         {
9994           if (attribute_flag[7] != 0)
9995             image->gravity=(GravityType) argument_list[7].integer_reference;
9996           if (attribute_flag[0] != 0)
9997             {
9998               int
9999                 flags;
10000
10001               flags=ParseGravityGeometry(image,
10002                 argument_list[0].string_reference,&geometry,exception);
10003               (void) flags;
10004               if (geometry.width == 0)
10005                 geometry.width=image->columns;
10006               if (geometry.height == 0)
10007                 geometry.height=image->rows;
10008             }
10009           if (attribute_flag[1] != 0)
10010             geometry.width=argument_list[1].integer_reference;
10011           if (attribute_flag[2] != 0)
10012             geometry.height=argument_list[2].integer_reference;
10013           if (attribute_flag[3] != 0)
10014             geometry.x=argument_list[3].integer_reference;
10015           if (attribute_flag[4] != 0)
10016             geometry.y=argument_list[4].integer_reference;
10017           if (attribute_flag[5] != 0)
10018             image->fuzz=StringToDoubleInterval(
10019               argument_list[5].string_reference,(double) QuantumRange+1.0);
10020           if (attribute_flag[6] != 0)
10021             (void) QueryColorCompliance(argument_list[6].string_reference,
10022               AllCompliance,&image->background_color,exception);
10023           image=ExtentImage(image,&geometry,exception);
10024           break;
10025         }
10026         case 94:  /* Vignette */
10027         {
10028           if (attribute_flag[0] != 0)
10029             {
10030               flags=ParseGeometry(argument_list[0].string_reference,
10031                 &geometry_info);
10032               if ((flags & SigmaValue) == 0)
10033                 geometry_info.sigma=1.0;
10034               if ((flags & XiValue) == 0)
10035                 geometry_info.xi=0.1*image->columns;
10036               if ((flags & PsiValue) == 0)
10037                 geometry_info.psi=0.1*image->rows;
10038             }
10039           if (attribute_flag[1] != 0)
10040             geometry_info.rho=argument_list[1].real_reference;
10041           if (attribute_flag[2] != 0)
10042             geometry_info.sigma=argument_list[2].real_reference;
10043           if (attribute_flag[3] != 0)
10044             geometry_info.xi=argument_list[3].integer_reference;
10045           if (attribute_flag[4] != 0)
10046             geometry_info.psi=argument_list[4].integer_reference;
10047           if (attribute_flag[5] != 0)
10048             (void) QueryColorCompliance(argument_list[5].string_reference,
10049               AllCompliance,&image->background_color,exception);
10050           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
10051             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10052             ceil(geometry_info.psi-0.5),exception);
10053           break;
10054         }
10055         case 95:  /* ContrastStretch */
10056         {
10057           double
10058             black_point,
10059             white_point;
10060
10061           black_point=0.0;
10062           white_point=(double) image->columns*image->rows;
10063           if (attribute_flag[0] != 0)
10064             {
10065               flags=ParseGeometry(argument_list[0].string_reference,
10066                 &geometry_info);
10067               black_point=geometry_info.rho;
10068               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
10069                 black_point;
10070               if ((flags & PercentValue) != 0)
10071                 {
10072                   black_point*=(double) image->columns*image->rows/100.0;
10073                   white_point*=(double) image->columns*image->rows/100.0;
10074                 }
10075               white_point=(double) image->columns*image->rows-
10076                 white_point;
10077             }
10078           if (attribute_flag[1] != 0)
10079             black_point=argument_list[1].real_reference;
10080           if (attribute_flag[2] != 0)
10081             white_point=argument_list[2].real_reference;
10082           if (attribute_flag[4] != 0)
10083             channel=(ChannelType) argument_list[4].integer_reference;
10084           channel_mask=SetImageChannelMask(image,channel);
10085           (void) ContrastStretchImage(image,black_point,white_point,exception);
10086           (void) SetImageChannelMask(image,channel_mask);
10087           break;
10088         }
10089         case 96:  /* Sans0 */
10090         {
10091           break;
10092         }
10093         case 97:  /* Sans1 */
10094         {
10095           break;
10096         }
10097         case 98:  /* AdaptiveSharpen */
10098         {
10099           if (attribute_flag[0] != 0)
10100             {
10101               flags=ParseGeometry(argument_list[0].string_reference,
10102                 &geometry_info);
10103               if ((flags & SigmaValue) == 0)
10104                 geometry_info.sigma=1.0;
10105               if ((flags & XiValue) == 0)
10106                 geometry_info.xi=0.0;
10107             }
10108           if (attribute_flag[1] != 0)
10109             geometry_info.rho=argument_list[1].real_reference;
10110           if (attribute_flag[2] != 0)
10111             geometry_info.sigma=argument_list[2].real_reference;
10112           if (attribute_flag[3] != 0)
10113             geometry_info.xi=argument_list[3].real_reference;
10114           if (attribute_flag[4] != 0)
10115             channel=(ChannelType) argument_list[4].integer_reference;
10116           channel_mask=SetImageChannelMask(image,channel);
10117           image=AdaptiveSharpenImage(image,geometry_info.rho,
10118             geometry_info.sigma,exception);
10119           if (image != (Image *) NULL)
10120             (void) SetImageChannelMask(image,channel_mask);
10121           break;
10122         }
10123         case 99:  /* Transpose */
10124         {
10125           image=TransposeImage(image,exception);
10126           break;
10127         }
10128         case 100:  /* Tranverse */
10129         {
10130           image=TransverseImage(image,exception);
10131           break;
10132         }
10133         case 101:  /* AutoOrient */
10134         {
10135           switch (image->orientation)
10136           {
10137             case TopRightOrientation:
10138             {
10139               image=FlopImage(image,exception);
10140               break;
10141             }
10142             case BottomRightOrientation:
10143             {
10144               image=RotateImage(image,180.0,exception);
10145               break;
10146             }
10147             case BottomLeftOrientation:
10148             {
10149               image=FlipImage(image,exception);
10150               break;
10151             }
10152             case LeftTopOrientation:
10153             {
10154               image=TransposeImage(image,exception);
10155               break;
10156             }
10157             case RightTopOrientation:
10158             {
10159               image=RotateImage(image,90.0,exception);
10160               break;
10161             }
10162             case RightBottomOrientation:
10163             {
10164               image=TransverseImage(image,exception);
10165               break;
10166             }
10167             case LeftBottomOrientation:
10168             {
10169               image=RotateImage(image,270.0,exception);
10170               break;
10171             }
10172             default:
10173               break;
10174           }
10175           break;
10176         }
10177         case 102:  /* AdaptiveBlur */
10178         {
10179           if (attribute_flag[0] != 0)
10180             {
10181               flags=ParseGeometry(argument_list[0].string_reference,
10182                 &geometry_info);
10183               if ((flags & SigmaValue) == 0)
10184                 geometry_info.sigma=1.0;
10185               if ((flags & XiValue) == 0)
10186                 geometry_info.xi=0.0;
10187             }
10188           if (attribute_flag[1] != 0)
10189             geometry_info.rho=argument_list[1].real_reference;
10190           if (attribute_flag[2] != 0)
10191             geometry_info.sigma=argument_list[2].real_reference;
10192           if (attribute_flag[3] != 0)
10193             channel=(ChannelType) argument_list[3].integer_reference;
10194           channel_mask=SetImageChannelMask(image,channel);
10195           image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10196             exception);
10197           if (image != (Image *) NULL)
10198             (void) SetImageChannelMask(image,channel_mask);
10199           break;
10200         }
10201         case 103:  /* Sketch */
10202         {
10203           if (attribute_flag[0] != 0)
10204             {
10205               flags=ParseGeometry(argument_list[0].string_reference,
10206                 &geometry_info);
10207               if ((flags & SigmaValue) == 0)
10208                 geometry_info.sigma=1.0;
10209               if ((flags & XiValue) == 0)
10210                 geometry_info.xi=1.0;
10211             }
10212           if (attribute_flag[1] != 0)
10213             geometry_info.rho=argument_list[1].real_reference;
10214           if (attribute_flag[2] != 0)
10215             geometry_info.sigma=argument_list[2].real_reference;
10216           if (attribute_flag[3] != 0)
10217             geometry_info.xi=argument_list[3].real_reference;
10218           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10219             geometry_info.xi,exception);
10220           break;
10221         }
10222         case 104:  /* UniqueColors */
10223         {
10224           image=UniqueImageColors(image,exception);
10225           break;
10226         }
10227         case 105:  /* AdaptiveResize */
10228         {
10229           if (attribute_flag[0] != 0)
10230             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10231               &geometry,exception);
10232           if (attribute_flag[1] != 0)
10233             geometry.width=argument_list[1].integer_reference;
10234           if (attribute_flag[2] != 0)
10235             geometry.height=argument_list[2].integer_reference;
10236           if (attribute_flag[3] != 0)
10237             image->filter=(FilterTypes) argument_list[4].integer_reference;
10238           if (attribute_flag[4] != 0)
10239             SetImageArtifact(image,"filter:support",
10240               argument_list[4].string_reference);
10241           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10242             exception);
10243           break;
10244         }
10245         case 106:  /* ClipMask */
10246         {
10247           Image
10248             *mask_image;
10249
10250           if (attribute_flag[0] == 0)
10251             {
10252               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10253                 PackageName);
10254               goto PerlException;
10255             }
10256           mask_image=CloneImage(argument_list[0].image_reference,0,0,MagickTrue,
10257             exception);
10258           (void) NegateImage(mask_image,MagickFalse,exception);
10259           (void) SetImageMask(image,mask_image,exception);
10260           mask_image=DestroyImage(mask_image);
10261           break;
10262         }
10263         case 107:  /* LinearStretch */
10264         {
10265            double
10266              black_point,
10267              white_point;
10268
10269            black_point=0.0;
10270            white_point=(double) image->columns*image->rows;
10271            if (attribute_flag[0] != 0)
10272              {
10273                flags=ParseGeometry(argument_list[0].string_reference,
10274                  &geometry_info);
10275                if ((flags & SigmaValue) != 0)
10276                   white_point=geometry_info.sigma;
10277                if ((flags & PercentValue) != 0)
10278                  {
10279                    black_point*=(double) image->columns*image->rows/100.0;
10280                    white_point*=(double) image->columns*image->rows/100.0;
10281                  }
10282                if ((flags & SigmaValue) == 0)
10283                  white_point=(double) image->columns*image->rows-black_point;
10284              }
10285           if (attribute_flag[1] != 0)
10286             black_point=argument_list[1].real_reference;
10287           if (attribute_flag[2] != 0)
10288             white_point=argument_list[2].real_reference;
10289           (void) LinearStretchImage(image,black_point,white_point,exception);
10290           break;
10291         }
10292         case 108:  /* ColorMatrix */
10293         {
10294           AV
10295             *av;
10296
10297           double
10298             *color_matrix;
10299
10300           KernelInfo
10301             *kernel_info;
10302
10303           size_t
10304             order;
10305
10306           if (attribute_flag[0] == 0)
10307             break;
10308           av=(AV *) argument_list[0].array_reference;
10309           order=(size_t) sqrt(av_len(av)+1);
10310           color_matrix=(double *) AcquireQuantumMemory(order,order*
10311             sizeof(*color_matrix));
10312           if (color_matrix == (double *) NULL)
10313             {
10314               ThrowPerlException(exception,ResourceLimitFatalError,
10315                 "MemoryAllocationFailed",PackageName);
10316               goto PerlException;
10317            }
10318           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10319             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10320           for ( ; j < (ssize_t) (order*order); j++)
10321             color_matrix[j]=0.0;
10322           kernel_info=AcquireKernelInfo((const char *) NULL);
10323           if (kernel_info == (KernelInfo *) NULL)
10324             break;
10325           kernel_info->width=order;
10326           kernel_info->height=order;
10327           kernel_info->values=(MagickRealType *) AcquireAlignedMemory(order,
10328             order*sizeof(*kernel_info->values));
10329           if (kernel_info->values != (MagickRealType *) NULL)
10330             {
10331               for (i=0; i < (ssize_t) (order*order); i++)
10332                 kernel_info->values[i]=(MagickRealType) color_matrix[i];
10333               image=ColorMatrixImage(image,kernel_info,exception);
10334             }
10335           kernel_info=DestroyKernelInfo(kernel_info);
10336           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10337           break;
10338         }
10339         case 109:  /* Mask */
10340         {
10341           Image
10342             *mask_image;
10343
10344           if (attribute_flag[0] == 0)
10345             {
10346               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10347                 PackageName);
10348               goto PerlException;
10349             }
10350           mask_image=CloneImage(argument_list[0].image_reference,0,0,
10351             MagickTrue,exception);
10352           (void) NegateImage(mask_image,MagickFalse,exception);
10353           (void) SetImageMask(image,mask_image,exception);
10354           mask_image=DestroyImage(mask_image);
10355           break;
10356         }
10357         case 110:  /* Polaroid */
10358         {
10359           char
10360             *caption;
10361
10362           DrawInfo
10363             *draw_info;
10364
10365           double
10366             angle;
10367
10368           PixelInterpolateMethod
10369             method;
10370
10371           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10372             (DrawInfo *) NULL);
10373           caption=(char *) NULL;
10374           if (attribute_flag[0] != 0)
10375             caption=InterpretImageProperties(info ? info->image_info :
10376               (ImageInfo *) NULL,image,argument_list[0].string_reference,
10377               exception);
10378           angle=0.0;
10379           if (attribute_flag[1] != 0)
10380             angle=argument_list[1].real_reference;
10381           if (attribute_flag[2] != 0)
10382             (void) CloneString(&draw_info->font,
10383               argument_list[2].string_reference);
10384           if (attribute_flag[3] != 0)
10385             (void) QueryColorCompliance(argument_list[3].string_reference,
10386               AllCompliance,&draw_info->stroke,exception);
10387           if (attribute_flag[4] != 0)
10388             (void) QueryColorCompliance(argument_list[4].string_reference,
10389               AllCompliance,&draw_info->fill,exception);
10390           if (attribute_flag[5] != 0)
10391             draw_info->stroke_width=argument_list[5].real_reference;
10392           if (attribute_flag[6] != 0)
10393             draw_info->pointsize=argument_list[6].real_reference;
10394           if (attribute_flag[7] != 0)
10395             draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10396           if (attribute_flag[8] != 0)
10397             (void) QueryColorCompliance(argument_list[8].string_reference,
10398               AllCompliance,&image->background_color,exception);
10399           method=UndefinedInterpolatePixel;
10400           if (attribute_flag[9] != 0)
10401             method=(PixelInterpolateMethod) argument_list[9].integer_reference;
10402           image=PolaroidImage(image,draw_info,caption,angle,method,exception);
10403           draw_info=DestroyDrawInfo(draw_info);
10404           if (caption != (char *) NULL)
10405             caption=DestroyString(caption);
10406           break;
10407         }
10408         case 111:  /* FloodfillPaint */
10409         {
10410           DrawInfo
10411             *draw_info;
10412
10413           MagickBooleanType
10414             invert;
10415
10416           PixelInfo
10417             target;
10418
10419           draw_info=CloneDrawInfo(info ? info->image_info :
10420             (ImageInfo *) NULL,(DrawInfo *) NULL);
10421           if (attribute_flag[0] != 0)
10422             flags=ParsePageGeometry(image,argument_list[0].string_reference,
10423               &geometry,exception);
10424           if (attribute_flag[1] != 0)
10425             geometry.x=argument_list[1].integer_reference;
10426           if (attribute_flag[2] != 0)
10427             geometry.y=argument_list[2].integer_reference;
10428           if (attribute_flag[3] != 0)
10429             (void) QueryColorCompliance(argument_list[3].string_reference,
10430               AllCompliance,&draw_info->fill,exception);
10431           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
10432             geometry.x,geometry.y,&target,exception);
10433           if (attribute_flag[4] != 0)
10434             QueryColorCompliance(argument_list[4].string_reference,
10435               AllCompliance,&target,exception);
10436           if (attribute_flag[5] != 0)
10437             image->fuzz=StringToDoubleInterval(
10438               argument_list[5].string_reference,(double) QuantumRange+1.0);
10439           if (attribute_flag[6] != 0)
10440             channel=(ChannelType) argument_list[6].integer_reference;
10441           invert=MagickFalse;
10442           if (attribute_flag[7] != 0)
10443             invert=(MagickBooleanType) argument_list[7].integer_reference;
10444           channel_mask=SetImageChannelMask(image,channel);
10445           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10446             geometry.y,invert,exception);
10447           (void) SetImageChannelMask(image,channel_mask);
10448           draw_info=DestroyDrawInfo(draw_info);
10449           break;
10450         }
10451         case 112:  /* Distort */
10452         {
10453           AV
10454             *av;
10455
10456           double
10457             *coordinates;
10458
10459           DistortImageMethod
10460             method;
10461
10462           size_t
10463             number_coordinates;
10464
10465           VirtualPixelMethod
10466             virtual_pixel;
10467
10468           if (attribute_flag[0] == 0)
10469             break;
10470           method=UndefinedDistortion;
10471           if (attribute_flag[1] != 0)
10472             method=(DistortImageMethod) argument_list[1].integer_reference;
10473           av=(AV *) argument_list[0].array_reference;
10474           number_coordinates=(size_t) av_len(av)+1;
10475           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10476             sizeof(*coordinates));
10477           if (coordinates == (double *) NULL)
10478             {
10479               ThrowPerlException(exception,ResourceLimitFatalError,
10480                 "MemoryAllocationFailed",PackageName);
10481               goto PerlException;
10482             }
10483           for (j=0; j < (ssize_t) number_coordinates; j++)
10484             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10485           virtual_pixel=UndefinedVirtualPixelMethod;
10486           if (attribute_flag[2] != 0)
10487             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10488               argument_list[2].integer_reference,exception);
10489           image=DistortImage(image,method,number_coordinates,coordinates,
10490             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10491             exception);
10492           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10493             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10494               exception);
10495           coordinates=(double *) RelinquishMagickMemory(coordinates);
10496           break;
10497         }
10498         case 113:  /* Clut */
10499         {
10500           PixelInterpolateMethod
10501             method;
10502
10503           if (attribute_flag[0] == 0)
10504             {
10505               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10506                 PackageName);
10507               goto PerlException;
10508             }
10509           method=UndefinedInterpolatePixel;
10510           if (attribute_flag[1] != 0)
10511             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
10512           if (attribute_flag[2] != 0)
10513             channel=(ChannelType) argument_list[2].integer_reference;
10514           channel_mask=SetImageChannelMask(image,channel);
10515           (void) ClutImage(image,argument_list[0].image_reference,method,
10516             exception);
10517           (void) SetImageChannelMask(image,channel_mask);
10518           break;
10519         }
10520         case 114:  /* LiquidRescale */
10521         {
10522           if (attribute_flag[0] != 0)
10523             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10524               &geometry,exception);
10525           if (attribute_flag[1] != 0)
10526             geometry.width=argument_list[1].integer_reference;
10527           if (attribute_flag[2] != 0)
10528             geometry.height=argument_list[2].integer_reference;
10529           if (attribute_flag[3] == 0)
10530             argument_list[3].real_reference=1.0;
10531           if (attribute_flag[4] == 0)
10532             argument_list[4].real_reference=0.0;
10533           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10534             argument_list[3].real_reference,argument_list[4].real_reference,
10535             exception);
10536           break;
10537         }
10538         case 115:  /* EncipherImage */
10539         {
10540           (void) EncipherImage(image,argument_list[0].string_reference,
10541             exception);
10542           break;
10543         }
10544         case 116:  /* DecipherImage */
10545         {
10546           (void) DecipherImage(image,argument_list[0].string_reference,
10547             exception);
10548           break;
10549         }
10550         case 117:  /* Deskew */
10551         {
10552           geometry_info.rho=QuantumRange/2.0;
10553           if (attribute_flag[0] != 0)
10554             flags=ParseGeometry(argument_list[0].string_reference,
10555               &geometry_info);
10556           if (attribute_flag[1] != 0)
10557             geometry_info.rho=StringToDoubleInterval(
10558               argument_list[1].string_reference,(double) QuantumRange+1.0);
10559           image=DeskewImage(image,geometry_info.rho,exception);
10560           break;
10561         }
10562         case 118:  /* Remap */
10563         {
10564           QuantizeInfo
10565             *quantize_info;
10566
10567           if (attribute_flag[0] == 0)
10568             {
10569               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10570                 PackageName);
10571               goto PerlException;
10572             }
10573           quantize_info=AcquireQuantizeInfo(info->image_info);
10574           if (attribute_flag[1] != 0)
10575             quantize_info->dither_method=(DitherMethod)
10576               argument_list[1].integer_reference;
10577           (void) RemapImages(quantize_info,image,
10578             argument_list[0].image_reference,exception);
10579           quantize_info=DestroyQuantizeInfo(quantize_info);
10580           break;
10581         }
10582         case 119:  /* SparseColor */
10583         {
10584           AV
10585             *av;
10586
10587           double
10588             *coordinates;
10589
10590           SparseColorMethod
10591             method;
10592
10593           size_t
10594             number_coordinates;
10595
10596           VirtualPixelMethod
10597             virtual_pixel;
10598
10599           if (attribute_flag[0] == 0)
10600             break;
10601           method=UndefinedColorInterpolate;
10602           if (attribute_flag[1] != 0)
10603             method=(SparseColorMethod) argument_list[1].integer_reference;
10604           av=(AV *) argument_list[0].array_reference;
10605           number_coordinates=(size_t) av_len(av)+1;
10606           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10607             sizeof(*coordinates));
10608           if (coordinates == (double *) NULL)
10609             {
10610               ThrowPerlException(exception,ResourceLimitFatalError,
10611                 "MemoryAllocationFailed",PackageName);
10612               goto PerlException;
10613             }
10614           for (j=0; j < (ssize_t) number_coordinates; j++)
10615             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10616           virtual_pixel=UndefinedVirtualPixelMethod;
10617           if (attribute_flag[2] != 0)
10618             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10619               argument_list[2].integer_reference,exception);
10620           if (attribute_flag[3] != 0)
10621             channel=(ChannelType) argument_list[3].integer_reference;
10622           channel_mask=SetImageChannelMask(image,channel);
10623           image=SparseColorImage(image,method,number_coordinates,coordinates,
10624             exception);
10625           if (image != (Image *) NULL)
10626             (void) SetImageChannelMask(image,channel_mask);
10627           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10628             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10629               exception);
10630           coordinates=(double *) RelinquishMagickMemory(coordinates);
10631           break;
10632         }
10633         case 120:  /* Function */
10634         {
10635           AV
10636             *av;
10637
10638           double
10639             *parameters;
10640
10641           MagickFunction
10642             function;
10643
10644           size_t
10645             number_parameters;
10646
10647           VirtualPixelMethod
10648             virtual_pixel;
10649
10650           if (attribute_flag[0] == 0)
10651             break;
10652           function=UndefinedFunction;
10653           if (attribute_flag[1] != 0)
10654             function=(MagickFunction) argument_list[1].integer_reference;
10655           av=(AV *) argument_list[0].array_reference;
10656           number_parameters=(size_t) av_len(av)+1;
10657           parameters=(double *) AcquireQuantumMemory(number_parameters,
10658             sizeof(*parameters));
10659           if (parameters == (double *) NULL)
10660             {
10661               ThrowPerlException(exception,ResourceLimitFatalError,
10662                 "MemoryAllocationFailed",PackageName);
10663               goto PerlException;
10664             }
10665           for (j=0; j < (ssize_t) number_parameters; j++)
10666             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10667           virtual_pixel=UndefinedVirtualPixelMethod;
10668           if (attribute_flag[2] != 0)
10669             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10670               argument_list[2].integer_reference,exception);
10671           (void) FunctionImage(image,function,number_parameters,parameters,
10672             exception);
10673           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10674             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10675               exception);
10676           parameters=(double *) RelinquishMagickMemory(parameters);
10677           break;
10678         }
10679         case 121:  /* SelectiveBlur */
10680         {
10681           if (attribute_flag[0] != 0)
10682             {
10683               flags=ParseGeometry(argument_list[0].string_reference,
10684                 &geometry_info);
10685               if ((flags & SigmaValue) == 0)
10686                 geometry_info.sigma=1.0;
10687               if ((flags & PercentValue) != 0)
10688                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10689             }
10690           if (attribute_flag[1] != 0)
10691             geometry_info.rho=argument_list[1].real_reference;
10692           if (attribute_flag[2] != 0)
10693             geometry_info.sigma=argument_list[2].real_reference;
10694           if (attribute_flag[3] != 0)
10695             geometry_info.xi=argument_list[3].integer_reference;;
10696           if (attribute_flag[5] != 0)
10697             channel=(ChannelType) argument_list[5].integer_reference;
10698           channel_mask=SetImageChannelMask(image,channel);
10699           image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10700             geometry_info.xi,exception);
10701           if (image != (Image *) NULL)
10702             (void) SetImageChannelMask(image,channel_mask);
10703           break;
10704         }
10705         case 122:  /* HaldClut */
10706         {
10707           if (attribute_flag[0] == 0)
10708             {
10709               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10710                 PackageName);
10711               goto PerlException;
10712             }
10713           if (attribute_flag[1] != 0)
10714             channel=(ChannelType) argument_list[1].integer_reference;
10715           channel_mask=SetImageChannelMask(image,channel);
10716           (void) HaldClutImage(image,argument_list[0].image_reference,
10717             exception);
10718           (void) SetImageChannelMask(image,channel_mask);
10719           break;
10720         }
10721         case 123:  /* BlueShift */
10722         {
10723           if (attribute_flag[0] != 0)
10724             (void) ParseGeometry(argument_list[0].string_reference,
10725               &geometry_info);
10726           image=BlueShiftImage(image,geometry_info.rho,exception);
10727           break;
10728         }
10729         case 124:  /* ForwardFourierTransformImage */
10730         {
10731           image=ForwardFourierTransformImage(image,
10732             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10733             exception);
10734           break;
10735         }
10736         case 125:  /* InverseFourierTransformImage */
10737         {
10738           image=InverseFourierTransformImage(image,image->next,
10739             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10740             exception);
10741           break;
10742         }
10743         case 126:  /* ColorDecisionList */
10744         {
10745           if (attribute_flag[0] == 0)
10746             argument_list[0].string_reference=(char *) NULL;
10747           (void) ColorDecisionListImage(image,
10748             argument_list[0].string_reference,exception);
10749           break;
10750         }
10751         case 127:  /* AutoGamma */
10752         {
10753           if (attribute_flag[0] != 0)
10754             channel=(ChannelType) argument_list[0].integer_reference;
10755           channel_mask=SetImageChannelMask(image,channel);
10756           (void) AutoGammaImage(image,exception);
10757           (void) SetImageChannelMask(image,channel_mask);
10758           break;
10759         }
10760         case 128:  /* AutoLevel */
10761         {
10762           if (attribute_flag[0] != 0)
10763             channel=(ChannelType) argument_list[0].integer_reference;
10764           channel_mask=SetImageChannelMask(image,channel);
10765           (void) AutoLevelImage(image,exception);
10766           (void) SetImageChannelMask(image,channel_mask);
10767           break;
10768         }
10769         case 129:  /* LevelColors */
10770         {
10771           PixelInfo
10772             black_point,
10773             white_point;
10774
10775           (void) QueryColorCompliance("#000000",AllCompliance,&black_point,
10776             exception);
10777           (void) QueryColorCompliance("#ffffff",AllCompliance,&white_point,
10778             exception);
10779           if (attribute_flag[1] != 0)
10780              (void) QueryColorCompliance(
10781                argument_list[1].string_reference,AllCompliance,&black_point,
10782                exception);
10783           if (attribute_flag[2] != 0)
10784              (void) QueryColorCompliance(
10785                argument_list[2].string_reference,AllCompliance,&white_point,
10786                exception);
10787           if (attribute_flag[3] != 0)
10788             channel=(ChannelType) argument_list[3].integer_reference;
10789           channel_mask=SetImageChannelMask(image,channel);
10790           (void) LevelImageColors(image,&black_point,&white_point,
10791             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10792             exception);
10793           (void) SetImageChannelMask(image,channel_mask);
10794           break;
10795         }
10796         case 130:  /* Clamp */
10797         {
10798           if (attribute_flag[0] != 0)
10799             channel=(ChannelType) argument_list[0].integer_reference;
10800           channel_mask=SetImageChannelMask(image,channel);
10801           (void) ClampImage(image,exception);
10802           (void) SetImageChannelMask(image,channel_mask);
10803           break;
10804         }
10805         case 131:  /* BrightnessContrast */
10806         {
10807           double
10808             brightness,
10809             contrast;
10810
10811           brightness=0.0;
10812           contrast=0.0;
10813           if (attribute_flag[0] != 0)
10814             {
10815               flags=ParseGeometry(argument_list[0].string_reference,
10816                 &geometry_info);
10817               brightness=geometry_info.rho;
10818               if ((flags & SigmaValue) == 0)
10819                 contrast=geometry_info.sigma;
10820             }
10821           if (attribute_flag[1] != 0)
10822             brightness=argument_list[1].real_reference;
10823           if (attribute_flag[2] != 0)
10824             contrast=argument_list[2].real_reference;
10825           if (attribute_flag[4] != 0)
10826             channel=(ChannelType) argument_list[4].integer_reference;
10827           channel_mask=SetImageChannelMask(image,channel);
10828           (void) BrightnessContrastImage(image,brightness,contrast,exception);
10829           (void) SetImageChannelMask(image,channel_mask);
10830           break;
10831         }
10832         case 132:  /* Morphology */
10833         {
10834           KernelInfo
10835             *kernel;
10836
10837           MorphologyMethod
10838             method;
10839
10840           ssize_t
10841             iterations;
10842
10843           if (attribute_flag[0] == 0)
10844             break;
10845           kernel=AcquireKernelInfo(argument_list[0].string_reference);
10846           if (kernel == (KernelInfo *) NULL)
10847             break;
10848           if (attribute_flag[1] != 0)
10849             channel=(ChannelType) argument_list[1].integer_reference;
10850           method=UndefinedMorphology;
10851           if (attribute_flag[2] != 0)
10852             method=argument_list[2].integer_reference;
10853           iterations=1;
10854           if (attribute_flag[3] != 0)
10855             iterations=argument_list[3].integer_reference;
10856           channel_mask=SetImageChannelMask(image,channel);
10857           image=MorphologyImage(image,method,iterations,kernel,exception);
10858           if (image != (Image *) NULL)
10859             (void) SetImageChannelMask(image,channel_mask);
10860           kernel=DestroyKernelInfo(kernel);
10861           break;
10862         }
10863         case 133:  /* Mode */
10864         {
10865           if (attribute_flag[0] != 0)
10866             {
10867               flags=ParseGeometry(argument_list[0].string_reference,
10868                 &geometry_info);
10869               if ((flags & SigmaValue) == 0)
10870                 geometry_info.sigma=1.0;
10871             }
10872           if (attribute_flag[1] != 0)
10873             geometry_info.rho=argument_list[1].real_reference;
10874           if (attribute_flag[2] != 0)
10875             geometry_info.sigma=argument_list[2].real_reference;
10876           if (attribute_flag[3] != 0)
10877             channel=(ChannelType) argument_list[3].integer_reference;
10878           channel_mask=SetImageChannelMask(image,channel);
10879           image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
10880             (size_t) geometry_info.sigma,exception);
10881           if (image != (Image *) NULL)
10882             (void) SetImageChannelMask(image,channel_mask);
10883           break;
10884         }
10885         case 134:  /* Statistic */
10886         {
10887           StatisticType
10888             statistic;
10889
10890           statistic=UndefinedStatistic;
10891           if (attribute_flag[0] != 0)
10892             {
10893               flags=ParseGeometry(argument_list[0].string_reference,
10894                 &geometry_info);
10895               if ((flags & SigmaValue) == 0)
10896                 geometry_info.sigma=1.0;
10897             }
10898           if (attribute_flag[1] != 0)
10899             geometry_info.rho=argument_list[1].real_reference;
10900           if (attribute_flag[2] != 0)
10901             geometry_info.sigma=argument_list[2].real_reference;
10902           if (attribute_flag[3] != 0)
10903             channel=(ChannelType) argument_list[3].integer_reference;
10904           if (attribute_flag[4] != 0)
10905             statistic=(StatisticType) argument_list[4].integer_reference;
10906           channel_mask=SetImageChannelMask(image,channel);
10907           image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
10908             (size_t) geometry_info.sigma,exception);
10909           if (image != (Image *) NULL)
10910             (void) SetImageChannelMask(image,channel_mask);
10911           break;
10912         }
10913       }
10914       if (next != (Image *) NULL)
10915         (void) CatchImageException(next);
10916       if (region_image != (Image *) NULL)
10917         {
10918           /*
10919             Composite region.
10920           */ 
10921           status=CompositeImage(region_image,image,CopyCompositeOp,MagickTrue,
10922             region_info.x,region_info.y,exception);
10923           (void) status;
10924           (void) CatchImageException(region_image);
10925           image=DestroyImage(image);
10926           image=region_image;
10927         }
10928       if (image != (Image *) NULL)
10929         {
10930           number_images++;
10931           if (next && (next != image))
10932             {
10933               image->next=next->next;
10934               if (image->next != (Image *) NULL)
10935                 image->next->previous=image;
10936               DeleteImageFromRegistry(*pv,next);
10937             }
10938           sv_setiv(*pv,PTR2IV(image));
10939           next=image;
10940         }
10941       if (*pv)
10942         pv++;
10943     }
10944
10945   PerlException:
10946     if (reference_vector)
10947       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
10948     InheritPerlException(exception,perl_exception);
10949     exception=DestroyExceptionInfo(exception);
10950     sv_setiv(perl_exception,(IV) number_images);
10951     SvPOK_on(perl_exception);
10952     ST(0)=sv_2mortal(perl_exception);
10953     XSRETURN(1);
10954   }
10955 \f
10956 #
10957 ###############################################################################
10958 #                                                                             #
10959 #                                                                             #
10960 #                                                                             #
10961 #   M o n t a g e                                                             #
10962 #                                                                             #
10963 #                                                                             #
10964 #                                                                             #
10965 ###############################################################################
10966 #
10967 #
10968 void
10969 Montage(ref,...)
10970   Image::Magick ref=NO_INIT
10971   ALIAS:
10972     MontageImage  = 1
10973     montage       = 2
10974     montageimage  = 3
10975   PPCODE:
10976   {
10977     AV
10978       *av;
10979
10980     char
10981       *attribute;
10982
10983     ExceptionInfo
10984       *exception;
10985
10986     HV
10987       *hv;
10988
10989     Image
10990       *image,
10991       *next;
10992
10993     PixelInfo
10994       transparent_color;
10995
10996     MontageInfo
10997       *montage_info;
10998
10999     register ssize_t
11000       i;
11001
11002     ssize_t
11003       sp;
11004
11005     struct PackageInfo
11006       *info;
11007
11008     SV
11009       *av_reference,
11010       *perl_exception,
11011       *reference,
11012       *rv,
11013       *sv;
11014
11015     PERL_UNUSED_VAR(ref);
11016     PERL_UNUSED_VAR(ix);
11017     exception=AcquireExceptionInfo();
11018     perl_exception=newSVpv("",0);
11019     sv=NULL;
11020     attribute=NULL;
11021     if (sv_isobject(ST(0)) == 0)
11022       {
11023         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11024           PackageName);
11025         goto PerlException;
11026       }
11027     reference=SvRV(ST(0));
11028     hv=SvSTASH(reference);
11029     av=newAV();
11030     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11031     SvREFCNT_dec(av);
11032     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11033     if (image == (Image *) NULL)
11034       {
11035         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11036           PackageName);
11037         goto PerlException;
11038       }
11039     /*
11040       Get options.
11041     */
11042     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11043     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
11044     (void) QueryColorCompliance("none",AllCompliance,&transparent_color,
11045       exception);
11046     for (i=2; i < items; i+=2)
11047     {
11048       attribute=(char *) SvPV(ST(i-1),na);
11049       switch (*attribute)
11050       {
11051         case 'B':
11052         case 'b':
11053         {
11054           if (LocaleCompare(attribute,"background") == 0)
11055             {
11056               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11057                 &montage_info->background_color,exception);
11058               for (next=image; next; next=next->next)
11059                 next->background_color=montage_info->background_color;
11060               break;
11061             }
11062           if (LocaleCompare(attribute,"border") == 0)
11063             {
11064               montage_info->border_width=SvIV(ST(i));
11065               break;
11066             }
11067           if (LocaleCompare(attribute,"bordercolor") == 0)
11068             {
11069               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11070                 &montage_info->border_color,exception);
11071               for (next=image; next; next=next->next)
11072                 next->border_color=montage_info->border_color;
11073               break;
11074             }
11075           if (LocaleCompare(attribute,"borderwidth") == 0)
11076             {
11077               montage_info->border_width=SvIV(ST(i));
11078               break;
11079             }
11080           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11081             attribute);
11082           break;
11083         }
11084         case 'C':
11085         case 'c':
11086         {
11087           if (LocaleCompare(attribute,"compose") == 0)
11088             {
11089               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11090                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
11091               if (sp < 0)
11092                 {
11093                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11094                     SvPV(ST(i),na));
11095                   break;
11096                 }
11097               for (next=image; next; next=next->next)
11098                 next->compose=(CompositeOperator) sp;
11099               break;
11100             }
11101           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11102             attribute);
11103           break;
11104         }
11105         case 'F':
11106         case 'f':
11107         {
11108           if (LocaleCompare(attribute,"fill") == 0)
11109             {
11110               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11111                 &montage_info->fill,exception);
11112               break;
11113             }
11114           if (LocaleCompare(attribute,"font") == 0)
11115             {
11116               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
11117               break;
11118             }
11119           if (LocaleCompare(attribute,"frame") == 0)
11120             {
11121               char
11122                 *p;
11123
11124               p=SvPV(ST(i),na);
11125               if (IsGeometry(p) == MagickFalse)
11126                 {
11127                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11128                     p);
11129                   break;
11130                 }
11131               (void) CloneString(&montage_info->frame,p);
11132               if (*p == '\0')
11133                 montage_info->frame=(char *) NULL;
11134               break;
11135             }
11136           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11137             attribute);
11138           break;
11139         }
11140         case 'G':
11141         case 'g':
11142         {
11143           if (LocaleCompare(attribute,"geometry") == 0)
11144             {
11145               char
11146                 *p;
11147
11148               p=SvPV(ST(i),na);
11149               if (IsGeometry(p) == MagickFalse)
11150                 {
11151                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11152                     p);
11153                   break;
11154                 }
11155              (void) CloneString(&montage_info->geometry,p);
11156              if (*p == '\0')
11157                montage_info->geometry=(char *) NULL;
11158              break;
11159            }
11160          if (LocaleCompare(attribute,"gravity") == 0)
11161            {
11162              ssize_t
11163                in;
11164
11165              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11166                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11167              if (in < 0)
11168                {
11169                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
11170                    SvPV(ST(i),na));
11171                  return;
11172                }
11173              montage_info->gravity=(GravityType) in;
11174              for (next=image; next; next=next->next)
11175                next->gravity=(GravityType) in;
11176              break;
11177            }
11178           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11179             attribute);
11180           break;
11181         }
11182         case 'L':
11183         case 'l':
11184         {
11185           if (LocaleCompare(attribute,"label") == 0)
11186             {
11187               for (next=image; next; next=next->next)
11188                 (void) SetImageProperty(next,"label",InterpretImageProperties(
11189                   info ? info->image_info : (ImageInfo *) NULL,next,
11190                   SvPV(ST(i),na),exception),exception);
11191               break;
11192             }
11193           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11194             attribute);
11195           break;
11196         }
11197         case 'M':
11198         case 'm':
11199         {
11200           if (LocaleCompare(attribute,"mattecolor") == 0)
11201             {
11202               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11203                 &montage_info->matte_color,exception);
11204               for (next=image; next; next=next->next)
11205                 next->matte_color=montage_info->matte_color;
11206               break;
11207             }
11208           if (LocaleCompare(attribute,"mode") == 0)
11209             {
11210               ssize_t
11211                 in;
11212
11213               in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11214                 MagickModeOptions,MagickFalse,SvPV(ST(i),na));
11215               switch (in)
11216               {
11217                 default:
11218                 {
11219                   ThrowPerlException(exception,OptionError,
11220                     "UnrecognizedModeType",SvPV(ST(i),na));
11221                   break;
11222                 }
11223                 case FrameMode:
11224                 {
11225                   (void) CloneString(&montage_info->frame,"15x15+3+3");
11226                   montage_info->shadow=MagickTrue;
11227                   break;
11228                 }
11229                 case UnframeMode:
11230                 {
11231                   montage_info->frame=(char *) NULL;
11232                   montage_info->shadow=MagickFalse;
11233                   montage_info->border_width=0;
11234                   break;
11235                 }
11236                 case ConcatenateMode:
11237                 {
11238                   montage_info->frame=(char *) NULL;
11239                   montage_info->shadow=MagickFalse;
11240                   (void) CloneString(&montage_info->geometry,"+0+0");
11241                   montage_info->border_width=0;
11242                 }
11243               }
11244               break;
11245             }
11246           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11247             attribute);
11248           break;
11249         }
11250         case 'P':
11251         case 'p':
11252         {
11253           if (LocaleCompare(attribute,"pointsize") == 0)
11254             {
11255               montage_info->pointsize=SvIV(ST(i));
11256               break;
11257             }
11258           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11259             attribute);
11260           break;
11261         }
11262         case 'S':
11263         case 's':
11264         {
11265           if (LocaleCompare(attribute,"shadow") == 0)
11266             {
11267               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11268                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11269               if (sp < 0)
11270                 {
11271                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11272                     SvPV(ST(i),na));
11273                   break;
11274                 }
11275              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11276              break;
11277             }
11278           if (LocaleCompare(attribute,"stroke") == 0)
11279             {
11280               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11281                 &montage_info->stroke,exception);
11282               break;
11283             }
11284           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11285             attribute);
11286           break;
11287         }
11288         case 'T':
11289         case 't':
11290         {
11291           if (LocaleCompare(attribute,"texture") == 0)
11292             {
11293               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11294               break;
11295             }
11296           if (LocaleCompare(attribute,"tile") == 0)
11297             {
11298               char *p=SvPV(ST(i),na);
11299               if (IsGeometry(p) == MagickFalse)
11300                 {
11301                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11302                     p);
11303                   break;
11304                 }
11305               (void) CloneString(&montage_info->tile,p);
11306               if (*p == '\0')
11307                 montage_info->tile=(char *) NULL;
11308               break;
11309             }
11310           if (LocaleCompare(attribute,"title") == 0)
11311             {
11312               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11313               break;
11314             }
11315           if (LocaleCompare(attribute,"transparent") == 0)
11316             {
11317               PixelInfo
11318                 transparent_color;
11319
11320               QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11321                 &transparent_color,exception);
11322               for (next=image; next; next=next->next)
11323                 (void) TransparentPaintImage(next,&transparent_color,
11324                   TransparentAlpha,MagickFalse,exception);
11325               break;
11326             }
11327           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11328             attribute);
11329           break;
11330         }
11331         default:
11332         {
11333           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11334             attribute);
11335           break;
11336         }
11337       }
11338     }
11339     image=MontageImageList(info->image_info,montage_info,image,exception);
11340     montage_info=DestroyMontageInfo(montage_info);
11341     if (image == (Image *) NULL)
11342       goto PerlException;
11343     if (transparent_color.alpha != TransparentAlpha)
11344       for (next=image; next; next=next->next)
11345         (void) TransparentPaintImage(next,&transparent_color,
11346           TransparentAlpha,MagickFalse,exception);
11347     for (  ; image; image=image->next)
11348     {
11349       AddImageToRegistry(sv,image);
11350       rv=newRV(sv);
11351       av_push(av,sv_bless(rv,hv));
11352       SvREFCNT_dec(sv);
11353     }
11354     exception=DestroyExceptionInfo(exception);
11355     ST(0)=av_reference;
11356     SvREFCNT_dec(perl_exception);
11357     XSRETURN(1);
11358
11359   PerlException:
11360     InheritPerlException(exception,perl_exception);
11361     exception=DestroyExceptionInfo(exception);
11362     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11363     SvPOK_on(perl_exception);
11364     ST(0)=sv_2mortal(perl_exception);
11365     XSRETURN(1);
11366   }
11367 \f
11368 #
11369 ###############################################################################
11370 #                                                                             #
11371 #                                                                             #
11372 #                                                                             #
11373 #   M o r p h                                                                 #
11374 #                                                                             #
11375 #                                                                             #
11376 #                                                                             #
11377 ###############################################################################
11378 #
11379 #
11380 void
11381 Morph(ref,...)
11382   Image::Magick ref=NO_INIT
11383   ALIAS:
11384     MorphImage  = 1
11385     morph       = 2
11386     morphimage  = 3
11387   PPCODE:
11388   {
11389     AV
11390       *av;
11391
11392     char
11393       *attribute;
11394
11395     ExceptionInfo
11396       *exception;
11397
11398     HV
11399       *hv;
11400
11401     Image
11402       *image;
11403
11404     register ssize_t
11405       i;
11406
11407     ssize_t
11408       number_frames;
11409
11410     struct PackageInfo
11411       *info;
11412
11413     SV
11414       *av_reference,
11415       *perl_exception,
11416       *reference,
11417       *rv,
11418       *sv;
11419
11420     PERL_UNUSED_VAR(ref);
11421     PERL_UNUSED_VAR(ix);
11422     exception=AcquireExceptionInfo();
11423     perl_exception=newSVpv("",0);
11424     sv=NULL;
11425     av=NULL;
11426     attribute=NULL;
11427     if (sv_isobject(ST(0)) == 0)
11428       {
11429         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11430           PackageName);
11431         goto PerlException;
11432       }
11433     reference=SvRV(ST(0));
11434     hv=SvSTASH(reference);
11435     av=newAV();
11436     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11437     SvREFCNT_dec(av);
11438     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11439     if (image == (Image *) NULL)
11440       {
11441         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11442           PackageName);
11443         goto PerlException;
11444       }
11445     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11446     /*
11447       Get attribute.
11448     */
11449     number_frames=30;
11450     for (i=2; i < items; i+=2)
11451     {
11452       attribute=(char *) SvPV(ST(i-1),na);
11453       switch (*attribute)
11454       {
11455         case 'F':
11456         case 'f':
11457         {
11458           if (LocaleCompare(attribute,"frames") == 0)
11459             {
11460               number_frames=SvIV(ST(i));
11461               break;
11462             }
11463           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11464             attribute);
11465           break;
11466         }
11467         default:
11468         {
11469           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11470             attribute);
11471           break;
11472         }
11473       }
11474     }
11475     image=MorphImages(image,number_frames,exception);
11476     if (image == (Image *) NULL)
11477       goto PerlException;
11478     for ( ; image; image=image->next)
11479     {
11480       AddImageToRegistry(sv,image);
11481       rv=newRV(sv);
11482       av_push(av,sv_bless(rv,hv));
11483       SvREFCNT_dec(sv);
11484     }
11485     exception=DestroyExceptionInfo(exception);
11486     ST(0)=av_reference;
11487     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11488     XSRETURN(1);
11489
11490   PerlException:
11491     InheritPerlException(exception,perl_exception);
11492     exception=DestroyExceptionInfo(exception);
11493     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11494     SvPOK_on(perl_exception);
11495     ST(0)=sv_2mortal(perl_exception);
11496     XSRETURN(1);
11497   }
11498 \f
11499 #
11500 ###############################################################################
11501 #                                                                             #
11502 #                                                                             #
11503 #                                                                             #
11504 #   M o s a i c                                                               #
11505 #                                                                             #
11506 #                                                                             #
11507 #                                                                             #
11508 ###############################################################################
11509 #
11510 #
11511 void
11512 Mosaic(ref)
11513   Image::Magick ref=NO_INIT
11514   ALIAS:
11515     MosaicImage   = 1
11516     mosaic        = 2
11517     mosaicimage   = 3
11518   PPCODE:
11519   {
11520     AV
11521       *av;
11522
11523     ExceptionInfo
11524       *exception;
11525
11526     HV
11527       *hv;
11528
11529     Image
11530       *image;
11531
11532     struct PackageInfo
11533       *info;
11534
11535     SV
11536       *perl_exception,
11537       *reference,
11538       *rv,
11539       *sv;
11540
11541     PERL_UNUSED_VAR(ref);
11542     PERL_UNUSED_VAR(ix);
11543     exception=AcquireExceptionInfo();
11544     perl_exception=newSVpv("",0);
11545     sv=NULL;
11546     if (sv_isobject(ST(0)) == 0)
11547       {
11548         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11549           PackageName);
11550         goto PerlException;
11551       }
11552     reference=SvRV(ST(0));
11553     hv=SvSTASH(reference);
11554     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11555     if (image == (Image *) NULL)
11556       {
11557         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11558           PackageName);
11559         goto PerlException;
11560       }
11561     image=MergeImageLayers(image,MosaicLayer,exception);
11562     /*
11563       Create blessed Perl array for the returned image.
11564     */
11565     av=newAV();
11566     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11567     SvREFCNT_dec(av);
11568     AddImageToRegistry(sv,image);
11569     rv=newRV(sv);
11570     av_push(av,sv_bless(rv,hv));
11571     SvREFCNT_dec(sv);
11572     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11573     (void) CopyMagickString(info->image_info->filename,image->filename,
11574       MaxTextExtent);
11575     SetImageInfo(info->image_info,0,exception);
11576     exception=DestroyExceptionInfo(exception);
11577     SvREFCNT_dec(perl_exception);
11578     XSRETURN(1);
11579
11580   PerlException:
11581     InheritPerlException(exception,perl_exception);
11582     exception=DestroyExceptionInfo(exception);
11583     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11584     SvPOK_on(perl_exception);  /* return messages in string context */
11585     ST(0)=sv_2mortal(perl_exception);
11586     XSRETURN(1);
11587   }
11588 \f
11589 #
11590 ###############################################################################
11591 #                                                                             #
11592 #                                                                             #
11593 #                                                                             #
11594 #   P i n g                                                                   #
11595 #                                                                             #
11596 #                                                                             #
11597 #                                                                             #
11598 ###############################################################################
11599 #
11600 #
11601 void
11602 Ping(ref,...)
11603   Image::Magick ref=NO_INIT
11604   ALIAS:
11605     PingImage  = 1
11606     ping       = 2
11607     pingimage  = 3
11608   PPCODE:
11609   {
11610     AV
11611       *av;
11612
11613     char
11614       **keep,
11615       **list;
11616
11617     ExceptionInfo
11618       *exception;
11619
11620     Image
11621       *image,
11622       *next;
11623
11624     int
11625       n;
11626
11627     MagickBooleanType
11628       status;
11629
11630     register char
11631       **p;
11632
11633     register ssize_t
11634       i;
11635
11636     ssize_t
11637       ac;
11638
11639     STRLEN
11640       *length;
11641
11642     struct PackageInfo
11643       *info,
11644       *package_info;
11645
11646     SV
11647       *perl_exception,
11648       *reference;
11649
11650     size_t
11651       count;
11652
11653     PERL_UNUSED_VAR(ref);
11654     PERL_UNUSED_VAR(ix);
11655     exception=AcquireExceptionInfo();
11656     perl_exception=newSVpv("",0);
11657     package_info=(struct PackageInfo *) NULL;
11658     ac=(items < 2) ? 1 : items-1;
11659     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
11660     keep=list;
11661     length=(STRLEN *) NULL;
11662     if (list == (char **) NULL)
11663       {
11664         ThrowPerlException(exception,ResourceLimitError,
11665           "MemoryAllocationFailed",PackageName);
11666         goto PerlException;
11667       }
11668     keep=list;
11669     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
11670     if (length == (STRLEN *) NULL)
11671       {
11672         ThrowPerlException(exception,ResourceLimitError,
11673           "MemoryAllocationFailed",PackageName);
11674         goto PerlException;
11675       }
11676     if (sv_isobject(ST(0)) == 0)
11677       {
11678         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11679           PackageName);
11680         goto PerlException;
11681       }
11682     reference=SvRV(ST(0));
11683     if (SvTYPE(reference) != SVt_PVAV)
11684       {
11685         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11686           PackageName);
11687         goto PerlException;
11688       }
11689     av=(AV *) reference;
11690     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11691       exception);
11692     package_info=ClonePackageInfo(info,exception);
11693     n=1;
11694     if (items <= 1)
11695       *list=(char *) (*package_info->image_info->filename ?
11696         package_info->image_info->filename : "XC:black");
11697     else
11698       for (n=0, i=0; i < ac; i++)
11699       {
11700         list[n]=(char *) SvPV(ST(i+1),length[n]);
11701         if ((items >= 3) && strEQcase(list[n],"blob"))
11702           {
11703             void
11704               *blob;
11705
11706             i++;
11707             blob=(void *) (SvPV(ST(i+1),length[n]));
11708             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
11709           }
11710         if ((items >= 3) && strEQcase(list[n],"filename"))
11711           continue;
11712         if ((items >= 3) && strEQcase(list[n],"file"))
11713           {
11714             FILE
11715               *file;
11716
11717             PerlIO
11718               *io_info;
11719
11720             i++;
11721             io_info=IoIFP(sv_2io(ST(i+1)));
11722             if (io_info == (PerlIO *) NULL)
11723               {
11724                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11725                   PackageName);
11726                 continue;
11727               }
11728             file=PerlIO_findFILE(io_info);
11729             if (file == (FILE *) NULL)
11730               {
11731                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11732                   PackageName);
11733                 continue;
11734               }
11735             SetImageInfoFile(package_info->image_info,file);
11736           }
11737         if ((items >= 3) && strEQcase(list[n],"magick"))
11738           continue;
11739         n++;
11740       }
11741     list[n]=(char *) NULL;
11742     keep=list;
11743     status=ExpandFilenames(&n,&list);
11744     if (status == MagickFalse)
11745       {
11746         ThrowPerlException(exception,ResourceLimitError,
11747           "MemoryAllocationFailed",PackageName);
11748         goto PerlException;
11749       }
11750     count=0;
11751     for (i=0; i < n; i++)
11752     {
11753       (void) CopyMagickString(package_info->image_info->filename,list[i],
11754         MaxTextExtent);
11755       image=PingImage(package_info->image_info,exception);
11756       if (image == (Image *) NULL)
11757         break;
11758       if ((package_info->image_info->file != (FILE *) NULL) ||
11759           (package_info->image_info->blob != (void *) NULL))
11760         DisassociateImageStream(image);
11761       count+=GetImageListLength(image);
11762       EXTEND(sp,4*count);
11763       for (next=image; next; next=next->next)
11764       {
11765         PUSHs(sv_2mortal(newSViv(next->columns)));
11766         PUSHs(sv_2mortal(newSViv(next->rows)));
11767         PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
11768         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
11769       }
11770       image=DestroyImageList(image);
11771     }
11772     /*
11773       Free resources.
11774     */
11775     for (i=0; i < n; i++)
11776       if (list[i] != (char *) NULL)
11777         for (p=keep; list[i] != *p++; )
11778           if (*p == NULL)
11779             {
11780               list[i]=(char *) RelinquishMagickMemory(list[i]);
11781               break;
11782             }
11783
11784   PerlException:
11785     if (package_info != (struct PackageInfo *) NULL)
11786       DestroyPackageInfo(package_info);
11787     if (list && (list != keep))
11788       list=(char **) RelinquishMagickMemory(list);
11789     if (keep)
11790       keep=(char **) RelinquishMagickMemory(keep);
11791     if (length)
11792       length=(STRLEN *) RelinquishMagickMemory(length);
11793     InheritPerlException(exception,perl_exception);
11794     exception=DestroyExceptionInfo(exception);
11795     SvREFCNT_dec(perl_exception);  /* throw away all errors */
11796   }
11797 \f
11798 #
11799 ###############################################################################
11800 #                                                                             #
11801 #                                                                             #
11802 #                                                                             #
11803 #   P r e v i e w                                                             #
11804 #                                                                             #
11805 #                                                                             #
11806 #                                                                             #
11807 ###############################################################################
11808 #
11809 #
11810 void
11811 Preview(ref,...)
11812   Image::Magick ref=NO_INIT
11813   ALIAS:
11814     PreviewImage = 1
11815     preview      = 2
11816     previewimage = 3
11817   PPCODE:
11818   {
11819     AV
11820       *av;
11821
11822     ExceptionInfo
11823       *exception;
11824
11825     HV
11826       *hv;
11827
11828     Image
11829       *image,
11830       *preview_image;
11831
11832     PreviewType
11833       preview_type;
11834
11835     struct PackageInfo
11836       *info;
11837
11838     SV
11839       *av_reference,
11840       *perl_exception,
11841       *reference,
11842       *rv,
11843       *sv;
11844
11845     PERL_UNUSED_VAR(ref);
11846     PERL_UNUSED_VAR(ix);
11847     exception=AcquireExceptionInfo();
11848     perl_exception=newSVpv("",0);
11849     sv=NULL;
11850     av=NULL;
11851     if (sv_isobject(ST(0)) == 0)
11852       {
11853         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11854           PackageName);
11855         goto PerlException;
11856       }
11857     reference=SvRV(ST(0));
11858     hv=SvSTASH(reference);
11859     av=newAV();
11860     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11861     SvREFCNT_dec(av);
11862     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11863     if (image == (Image *) NULL)
11864       {
11865         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11866           PackageName);
11867         goto PerlException;
11868       }
11869     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11870     preview_type=GammaPreview;
11871     if (items > 1)
11872       preview_type=(PreviewType)
11873         ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
11874     for ( ; image; image=image->next)
11875     {
11876       preview_image=PreviewImage(image,preview_type,exception);
11877       if (preview_image == (Image *) NULL)
11878         goto PerlException;
11879       AddImageToRegistry(sv,preview_image);
11880       rv=newRV(sv);
11881       av_push(av,sv_bless(rv,hv));
11882       SvREFCNT_dec(sv);
11883     }
11884     exception=DestroyExceptionInfo(exception);
11885     ST(0)=av_reference;
11886     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11887     XSRETURN(1);
11888
11889   PerlException:
11890     InheritPerlException(exception,perl_exception);
11891     exception=DestroyExceptionInfo(exception);
11892     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11893     SvPOK_on(perl_exception);
11894     ST(0)=sv_2mortal(perl_exception);
11895     XSRETURN(1);
11896   }
11897 \f
11898 #
11899 ###############################################################################
11900 #                                                                             #
11901 #                                                                             #
11902 #                                                                             #
11903 #   Q u e r y C o l o r                                                       #
11904 #                                                                             #
11905 #                                                                             #
11906 #                                                                             #
11907 ###############################################################################
11908 #
11909 #
11910 void
11911 QueryColor(ref,...)
11912   Image::Magick ref=NO_INIT
11913   ALIAS:
11914     querycolor = 1
11915   PPCODE:
11916   {
11917     char
11918       *name;
11919
11920     ExceptionInfo
11921       *exception;
11922
11923     PixelInfo
11924       color;
11925
11926     register ssize_t
11927       i;
11928
11929     SV
11930       *perl_exception;
11931
11932     PERL_UNUSED_VAR(ref);
11933     PERL_UNUSED_VAR(ix);
11934     exception=AcquireExceptionInfo();
11935     perl_exception=newSVpv("",0);
11936     if (items == 1)
11937       {
11938         const ColorInfo
11939           **colorlist;
11940
11941         size_t
11942           colors;
11943
11944         colorlist=GetColorInfoList("*",&colors,exception);
11945         EXTEND(sp,colors);
11946         for (i=0; i < (ssize_t) colors; i++)
11947         {
11948           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
11949         }
11950         colorlist=(const ColorInfo **)
11951           RelinquishMagickMemory((ColorInfo **) colorlist);
11952         goto PerlException;
11953       }
11954     EXTEND(sp,5*items);
11955     for (i=1; i < items; i++)
11956     {
11957       name=(char *) SvPV(ST(i),na);
11958       if (QueryColorCompliance(name,AllCompliance,&color,exception) == MagickFalse)
11959         {
11960           PUSHs(&sv_undef);
11961           continue;
11962         }
11963       PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
11964       PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
11965       PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
11966       if (color.colorspace == CMYKColorspace)
11967         PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
11968       if (color.alpha_trait == BlendPixelTrait)
11969         PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
11970     }
11971
11972   PerlException:
11973     InheritPerlException(exception,perl_exception);
11974     exception=DestroyExceptionInfo(exception);
11975     SvREFCNT_dec(perl_exception);
11976   }
11977 \f
11978 #
11979 ###############################################################################
11980 #                                                                             #
11981 #                                                                             #
11982 #                                                                             #
11983 #   Q u e r y C o l o r N a m e                                               #
11984 #                                                                             #
11985 #                                                                             #
11986 #                                                                             #
11987 ###############################################################################
11988 #
11989 #
11990 void
11991 QueryColorname(ref,...)
11992   Image::Magick ref=NO_INIT
11993   ALIAS:
11994     querycolorname = 1
11995   PPCODE:
11996   {
11997     AV
11998       *av;
11999
12000     char
12001       message[MaxTextExtent];
12002
12003     ExceptionInfo
12004       *exception;
12005
12006     Image
12007       *image;
12008
12009     PixelInfo
12010       target_color;
12011
12012     register ssize_t
12013       i;
12014
12015     struct PackageInfo
12016       *info;
12017
12018     SV
12019       *perl_exception,
12020       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12021
12022     PERL_UNUSED_VAR(ref);
12023     PERL_UNUSED_VAR(ix);
12024     exception=AcquireExceptionInfo();
12025     perl_exception=newSVpv("",0);
12026     reference=SvRV(ST(0));
12027     av=(AV *) reference;
12028     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12029       exception);
12030     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12031     if (image == (Image *) NULL)
12032       {
12033         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12034           PackageName);
12035         goto PerlException;
12036       }
12037     EXTEND(sp,items);
12038     for (i=1; i < items; i++)
12039     {
12040       (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,&target_color,
12041         exception);
12042       (void) QueryColorname(image,&target_color,SVGCompliance,message,
12043         exception);
12044       PUSHs(sv_2mortal(newSVpv(message,0)));
12045     }
12046
12047   PerlException:
12048     InheritPerlException(exception,perl_exception);
12049     exception=DestroyExceptionInfo(exception);
12050     SvREFCNT_dec(perl_exception);
12051   }
12052 \f
12053 #
12054 ###############################################################################
12055 #                                                                             #
12056 #                                                                             #
12057 #                                                                             #
12058 #   Q u e r y F o n t                                                         #
12059 #                                                                             #
12060 #                                                                             #
12061 #                                                                             #
12062 ###############################################################################
12063 #
12064 #
12065 void
12066 QueryFont(ref,...)
12067   Image::Magick ref=NO_INIT
12068   ALIAS:
12069     queryfont = 1
12070   PPCODE:
12071   {
12072     char
12073       *name,
12074       message[MaxTextExtent];
12075
12076     ExceptionInfo
12077       *exception;
12078
12079     register ssize_t
12080       i;
12081
12082     SV
12083       *perl_exception;
12084
12085     volatile const TypeInfo
12086       *type_info;
12087
12088     PERL_UNUSED_VAR(ref);
12089     PERL_UNUSED_VAR(ix);
12090     exception=AcquireExceptionInfo();
12091     perl_exception=newSVpv("",0);
12092     if (items == 1)
12093       {
12094         const TypeInfo
12095           **typelist;
12096
12097         size_t
12098           types;
12099
12100         typelist=GetTypeInfoList("*",&types,exception);
12101         EXTEND(sp,types);
12102         for (i=0; i < (ssize_t) types; i++)
12103         {
12104           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
12105         }
12106         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
12107           typelist);
12108         goto PerlException;
12109       }
12110     EXTEND(sp,10*items);
12111     for (i=1; i < items; i++)
12112     {
12113       name=(char *) SvPV(ST(i),na);
12114       type_info=GetTypeInfo(name,exception);
12115       if (type_info == (TypeInfo *) NULL)
12116         {
12117           PUSHs(&sv_undef);
12118           continue;
12119         }
12120       if (type_info->name == (char *) NULL)
12121         PUSHs(&sv_undef);
12122       else
12123         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
12124       if (type_info->description == (char *) NULL)
12125         PUSHs(&sv_undef);
12126       else
12127         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
12128       if (type_info->family == (char *) NULL)
12129         PUSHs(&sv_undef);
12130       else
12131         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
12132       if (type_info->style == UndefinedStyle)
12133         PUSHs(&sv_undef);
12134       else
12135         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
12136           type_info->style),0)));
12137       if (type_info->stretch == UndefinedStretch)
12138         PUSHs(&sv_undef);
12139       else
12140         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
12141           type_info->stretch),0)));
12142       (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
12143         type_info->weight);
12144       PUSHs(sv_2mortal(newSVpv(message,0)));
12145       if (type_info->encoding == (char *) NULL)
12146         PUSHs(&sv_undef);
12147       else
12148         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
12149       if (type_info->foundry == (char *) NULL)
12150         PUSHs(&sv_undef);
12151       else
12152         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
12153       if (type_info->format == (char *) NULL)
12154         PUSHs(&sv_undef);
12155       else
12156         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
12157       if (type_info->metrics == (char *) NULL)
12158         PUSHs(&sv_undef);
12159       else
12160         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
12161       if (type_info->glyphs == (char *) NULL)
12162         PUSHs(&sv_undef);
12163       else
12164         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
12165     }
12166
12167   PerlException:
12168     InheritPerlException(exception,perl_exception);
12169     exception=DestroyExceptionInfo(exception);
12170     SvREFCNT_dec(perl_exception);
12171   }
12172 \f
12173 #
12174 ###############################################################################
12175 #                                                                             #
12176 #                                                                             #
12177 #                                                                             #
12178 #   Q u e r y F o n t M e t r i c s                                           #
12179 #                                                                             #
12180 #                                                                             #
12181 #                                                                             #
12182 ###############################################################################
12183 #
12184 #
12185 void
12186 QueryFontMetrics(ref,...)
12187   Image::Magick ref=NO_INIT
12188   ALIAS:
12189     queryfontmetrics = 1
12190   PPCODE:
12191   {
12192     AffineMatrix
12193       affine,
12194       current;
12195
12196     AV
12197       *av;
12198
12199     char
12200       *attribute;
12201
12202     double
12203       x,
12204       y;
12205
12206     DrawInfo
12207       *draw_info;
12208
12209     ExceptionInfo
12210       *exception;
12211
12212     GeometryInfo
12213       geometry_info;
12214
12215     Image
12216       *image;
12217
12218     MagickBooleanType
12219       status;
12220
12221     MagickStatusType
12222       flags;
12223
12224     register ssize_t
12225       i;
12226
12227     ssize_t
12228       type;
12229
12230     struct PackageInfo
12231       *info,
12232       *package_info;
12233
12234     SV
12235       *perl_exception,
12236       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12237
12238     TypeMetric
12239       metrics;
12240
12241     PERL_UNUSED_VAR(ref);
12242     PERL_UNUSED_VAR(ix);
12243     exception=AcquireExceptionInfo();
12244     package_info=(struct PackageInfo *) NULL;
12245     perl_exception=newSVpv("",0);
12246     reference=SvRV(ST(0));
12247     av=(AV *) reference;
12248     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12249       exception);
12250     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12251     if (image == (Image *) NULL)
12252       {
12253         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12254           PackageName);
12255         goto PerlException;
12256       }
12257     package_info=ClonePackageInfo(info,exception);
12258     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12259     CloneString(&draw_info->text,"");
12260     current=draw_info->affine;
12261     GetAffineMatrix(&affine);
12262     x=0.0;
12263     y=0.0;
12264     EXTEND(sp,7*items);
12265     for (i=2; i < items; i+=2)
12266     {
12267       attribute=(char *) SvPV(ST(i-1),na);
12268       switch (*attribute)
12269       {
12270         case 'A':
12271         case 'a':
12272         {
12273           if (LocaleCompare(attribute,"antialias") == 0)
12274             {
12275               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12276                 SvPV(ST(i),na));
12277               if (type < 0)
12278                 {
12279                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12280                     SvPV(ST(i),na));
12281                   break;
12282                 }
12283               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12284               break;
12285             }
12286           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12287             attribute);
12288           break;
12289         }
12290         case 'd':
12291         case 'D':
12292         {
12293           if (LocaleCompare(attribute,"density") == 0)
12294             {
12295               CloneString(&draw_info->density,SvPV(ST(i),na));
12296               break;
12297             }
12298           if (LocaleCompare(attribute,"direction") == 0)
12299             {
12300               draw_info->direction=(DirectionType) ParseCommandOption(
12301                 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12302               break;
12303             }
12304           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12305             attribute);
12306           break;
12307         }
12308         case 'e':
12309         case 'E':
12310         {
12311           if (LocaleCompare(attribute,"encoding") == 0)
12312             {
12313               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12314               break;
12315             }
12316           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12317             attribute);
12318           break;
12319         }
12320         case 'f':
12321         case 'F':
12322         {
12323           if (LocaleCompare(attribute,"family") == 0)
12324             {
12325               CloneString(&draw_info->family,SvPV(ST(i),na));
12326               break;
12327             }
12328           if (LocaleCompare(attribute,"fill") == 0)
12329             {
12330               if (info)
12331                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12332                   &draw_info->fill,exception);
12333               break;
12334             }
12335           if (LocaleCompare(attribute,"font") == 0)
12336             {
12337               CloneString(&draw_info->font,SvPV(ST(i),na));
12338               break;
12339             }
12340           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12341             attribute);
12342           break;
12343         }
12344         case 'g':
12345         case 'G':
12346         {
12347           if (LocaleCompare(attribute,"geometry") == 0)
12348             {
12349               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12350               break;
12351             }
12352           if (LocaleCompare(attribute,"gravity") == 0)
12353             {
12354               draw_info->gravity=(GravityType) ParseCommandOption(
12355                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12356               break;
12357             }
12358           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12359             attribute);
12360           break;
12361         }
12362         case 'i':
12363         case 'I':
12364         {
12365           if (LocaleCompare(attribute,"interline-spacing") == 0)
12366             {
12367               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12368               draw_info->interline_spacing=geometry_info.rho;
12369               break;
12370             }
12371           if (LocaleCompare(attribute,"interword-spacing") == 0)
12372             {
12373               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12374               draw_info->interword_spacing=geometry_info.rho;
12375               break;
12376             }
12377           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12378             attribute);
12379           break;
12380         }
12381         case 'k':
12382         case 'K':
12383         {
12384           if (LocaleCompare(attribute,"kerning") == 0)
12385             {
12386               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12387               draw_info->kerning=geometry_info.rho;
12388               break;
12389             }
12390           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12391             attribute);
12392           break;
12393         }
12394         case 'p':
12395         case 'P':
12396         {
12397           if (LocaleCompare(attribute,"pointsize") == 0)
12398             {
12399               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12400               draw_info->pointsize=geometry_info.rho;
12401               break;
12402             }
12403           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12404             attribute);
12405           break;
12406         }
12407         case 'r':
12408         case 'R':
12409         {
12410           if (LocaleCompare(attribute,"rotate") == 0)
12411             {
12412               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12413               affine.rx=geometry_info.rho;
12414               affine.ry=geometry_info.sigma;
12415               if ((flags & SigmaValue) == 0)
12416                 affine.ry=affine.rx;
12417               break;
12418             }
12419           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12420             attribute);
12421           break;
12422         }
12423         case 's':
12424         case 'S':
12425         {
12426           if (LocaleCompare(attribute,"scale") == 0)
12427             {
12428               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12429               affine.sx=geometry_info.rho;
12430               affine.sy=geometry_info.sigma;
12431               if ((flags & SigmaValue) == 0)
12432                 affine.sy=affine.sx;
12433               break;
12434             }
12435           if (LocaleCompare(attribute,"skew") == 0)
12436             {
12437               double
12438                 x_angle,
12439                 y_angle;
12440
12441               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12442               x_angle=geometry_info.rho;
12443               y_angle=geometry_info.sigma;
12444               if ((flags & SigmaValue) == 0)
12445                 y_angle=x_angle;
12446               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12447               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12448               break;
12449             }
12450           if (LocaleCompare(attribute,"stroke") == 0)
12451             {
12452               if (info)
12453                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12454                   &draw_info->stroke,exception);
12455               break;
12456             }
12457           if (LocaleCompare(attribute,"style") == 0)
12458             {
12459               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12460                 SvPV(ST(i),na));
12461               if (type < 0)
12462                 {
12463                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12464                     SvPV(ST(i),na));
12465                   break;
12466                 }
12467               draw_info->style=(StyleType) type;
12468               break;
12469             }
12470           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12471             attribute);
12472           break;
12473         }
12474         case 't':
12475         case 'T':
12476         {
12477           if (LocaleCompare(attribute,"text") == 0)
12478             {
12479               CloneString(&draw_info->text,SvPV(ST(i),na));
12480               break;
12481             }
12482           if (LocaleCompare(attribute,"translate") == 0)
12483             {
12484               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12485               affine.tx=geometry_info.rho;
12486               affine.ty=geometry_info.sigma;
12487               if ((flags & SigmaValue) == 0)
12488                 affine.ty=affine.tx;
12489               break;
12490             }
12491           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12492             attribute);
12493           break;
12494         }
12495         case 'w':
12496         case 'W':
12497         {
12498           if (LocaleCompare(attribute,"weight") == 0)
12499             {
12500               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12501               draw_info->weight=(size_t) geometry_info.rho;
12502               break;
12503             }
12504           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12505             attribute);
12506           break;
12507         }
12508         case 'x':
12509         case 'X':
12510         {
12511           if (LocaleCompare(attribute,"x") == 0)
12512             {
12513               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12514               x=geometry_info.rho;
12515               break;
12516             }
12517           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12518             attribute);
12519           break;
12520         }
12521         case 'y':
12522         case 'Y':
12523         {
12524           if (LocaleCompare(attribute,"y") == 0)
12525             {
12526               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12527               y=geometry_info.rho;
12528               break;
12529             }
12530           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12531             attribute);
12532           break;
12533         }
12534         default:
12535         {
12536           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12537             attribute);
12538           break;
12539         }
12540       }
12541     }
12542     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12543     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12544     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12545     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12546     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12547     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12548     if (draw_info->geometry == (char *) NULL)
12549       {
12550         draw_info->geometry=AcquireString((char *) NULL);
12551         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12552           "%.15g,%.15g",x,y);
12553       }
12554     status=GetTypeMetrics(image,draw_info,&metrics,exception);
12555     (void) CatchImageException(image);
12556     if (status == MagickFalse)
12557       PUSHs(&sv_undef);
12558     else
12559       {
12560         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12561         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12562         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12563         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12564         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12565         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12566         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12567         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12568         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12569         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12570         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12571         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12572         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12573       }
12574     draw_info=DestroyDrawInfo(draw_info);
12575
12576   PerlException:
12577     if (package_info != (struct PackageInfo *) NULL)
12578       DestroyPackageInfo(package_info);
12579     InheritPerlException(exception,perl_exception);
12580     exception=DestroyExceptionInfo(exception);
12581     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12582   }
12583 \f
12584 #
12585 ###############################################################################
12586 #                                                                             #
12587 #                                                                             #
12588 #                                                                             #
12589 #   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                         #
12590 #                                                                             #
12591 #                                                                             #
12592 #                                                                             #
12593 ###############################################################################
12594 #
12595 #
12596 void
12597 QueryMultilineFontMetrics(ref,...)
12598   Image::Magick ref=NO_INIT
12599   ALIAS:
12600     querymultilinefontmetrics = 1
12601   PPCODE:
12602   {
12603     AffineMatrix
12604       affine,
12605       current;
12606
12607     AV
12608       *av;
12609
12610     char
12611       *attribute;
12612
12613     double
12614       x,
12615       y;
12616
12617     DrawInfo
12618       *draw_info;
12619
12620     ExceptionInfo
12621       *exception;
12622
12623     GeometryInfo
12624       geometry_info;
12625
12626     Image
12627       *image;
12628
12629     MagickBooleanType
12630       status;
12631
12632     MagickStatusType
12633       flags;
12634
12635     register ssize_t
12636       i;
12637
12638     ssize_t
12639       type;
12640
12641     struct PackageInfo
12642       *info,
12643       *package_info;
12644
12645     SV
12646       *perl_exception,
12647       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12648
12649     TypeMetric
12650       metrics;
12651
12652     PERL_UNUSED_VAR(ref);
12653     PERL_UNUSED_VAR(ix);
12654     exception=AcquireExceptionInfo();
12655     package_info=(struct PackageInfo *) NULL;
12656     perl_exception=newSVpv("",0);
12657     reference=SvRV(ST(0));
12658     av=(AV *) reference;
12659     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12660       exception);
12661     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12662     if (image == (Image *) NULL)
12663       {
12664         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12665           PackageName);
12666         goto PerlException;
12667       }
12668     package_info=ClonePackageInfo(info,exception);
12669     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12670     CloneString(&draw_info->text,"");
12671     current=draw_info->affine;
12672     GetAffineMatrix(&affine);
12673     x=0.0;
12674     y=0.0;
12675     EXTEND(sp,7*items);
12676     for (i=2; i < items; i+=2)
12677     {
12678       attribute=(char *) SvPV(ST(i-1),na);
12679       switch (*attribute)
12680       {
12681         case 'A':
12682         case 'a':
12683         {
12684           if (LocaleCompare(attribute,"antialias") == 0)
12685             {
12686               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12687                 SvPV(ST(i),na));
12688               if (type < 0)
12689                 {
12690                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12691                     SvPV(ST(i),na));
12692                   break;
12693                 }
12694               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12695               break;
12696             }
12697           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12698             attribute);
12699           break;
12700         }
12701         case 'd':
12702         case 'D':
12703         {
12704           if (LocaleCompare(attribute,"density") == 0)
12705             {
12706               CloneString(&draw_info->density,SvPV(ST(i),na));
12707               break;
12708             }
12709           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12710             attribute);
12711           break;
12712         }
12713         case 'e':
12714         case 'E':
12715         {
12716           if (LocaleCompare(attribute,"encoding") == 0)
12717             {
12718               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12719               break;
12720             }
12721           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12722             attribute);
12723           break;
12724         }
12725         case 'f':
12726         case 'F':
12727         {
12728           if (LocaleCompare(attribute,"family") == 0)
12729             {
12730               CloneString(&draw_info->family,SvPV(ST(i),na));
12731               break;
12732             }
12733           if (LocaleCompare(attribute,"fill") == 0)
12734             {
12735               if (info)
12736                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12737                   &draw_info->fill,exception);
12738               break;
12739             }
12740           if (LocaleCompare(attribute,"font") == 0)
12741             {
12742               CloneString(&draw_info->font,SvPV(ST(i),na));
12743               break;
12744             }
12745           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12746             attribute);
12747           break;
12748         }
12749         case 'g':
12750         case 'G':
12751         {
12752           if (LocaleCompare(attribute,"geometry") == 0)
12753             {
12754               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12755               break;
12756             }
12757           if (LocaleCompare(attribute,"gravity") == 0)
12758             {
12759               draw_info->gravity=(GravityType) ParseCommandOption(
12760                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12761               break;
12762             }
12763           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12764             attribute);
12765           break;
12766         }
12767         case 'p':
12768         case 'P':
12769         {
12770           if (LocaleCompare(attribute,"pointsize") == 0)
12771             {
12772               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12773               draw_info->pointsize=geometry_info.rho;
12774               break;
12775             }
12776           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12777             attribute);
12778           break;
12779         }
12780         case 'r':
12781         case 'R':
12782         {
12783           if (LocaleCompare(attribute,"rotate") == 0)
12784             {
12785               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12786               affine.rx=geometry_info.rho;
12787               affine.ry=geometry_info.sigma;
12788               if ((flags & SigmaValue) == 0)
12789                 affine.ry=affine.rx;
12790               break;
12791             }
12792           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12793             attribute);
12794           break;
12795         }
12796         case 's':
12797         case 'S':
12798         {
12799           if (LocaleCompare(attribute,"scale") == 0)
12800             {
12801               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12802               affine.sx=geometry_info.rho;
12803               affine.sy=geometry_info.sigma;
12804               if ((flags & SigmaValue) == 0)
12805                 affine.sy=affine.sx;
12806               break;
12807             }
12808           if (LocaleCompare(attribute,"skew") == 0)
12809             {
12810               double
12811                 x_angle,
12812                 y_angle;
12813
12814               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12815               x_angle=geometry_info.rho;
12816               y_angle=geometry_info.sigma;
12817               if ((flags & SigmaValue) == 0)
12818                 y_angle=x_angle;
12819               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12820               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12821               break;
12822             }
12823           if (LocaleCompare(attribute,"stroke") == 0)
12824             {
12825               if (info)
12826                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12827                   &draw_info->stroke,exception);
12828               break;
12829             }
12830           if (LocaleCompare(attribute,"style") == 0)
12831             {
12832               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12833                 SvPV(ST(i),na));
12834               if (type < 0)
12835                 {
12836                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12837                     SvPV(ST(i),na));
12838                   break;
12839                 }
12840               draw_info->style=(StyleType) type;
12841               break;
12842             }
12843           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12844             attribute);
12845           break;
12846         }
12847         case 't':
12848         case 'T':
12849         {
12850           if (LocaleCompare(attribute,"text") == 0)
12851             {
12852               CloneString(&draw_info->text,SvPV(ST(i),na));
12853               break;
12854             }
12855           if (LocaleCompare(attribute,"translate") == 0)
12856             {
12857               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12858               affine.tx=geometry_info.rho;
12859               affine.ty=geometry_info.sigma;
12860               if ((flags & SigmaValue) == 0)
12861                 affine.ty=affine.tx;
12862               break;
12863             }
12864           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12865             attribute);
12866           break;
12867         }
12868         case 'w':
12869         case 'W':
12870         {
12871           if (LocaleCompare(attribute,"weight") == 0)
12872             {
12873               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12874               draw_info->weight=(size_t) geometry_info.rho;
12875               break;
12876             }
12877           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12878             attribute);
12879           break;
12880         }
12881         case 'x':
12882         case 'X':
12883         {
12884           if (LocaleCompare(attribute,"x") == 0)
12885             {
12886               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12887               x=geometry_info.rho;
12888               break;
12889             }
12890           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12891             attribute);
12892           break;
12893         }
12894         case 'y':
12895         case 'Y':
12896         {
12897           if (LocaleCompare(attribute,"y") == 0)
12898             {
12899               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12900               y=geometry_info.rho;
12901               break;
12902             }
12903           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12904             attribute);
12905           break;
12906         }
12907         default:
12908         {
12909           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12910             attribute);
12911           break;
12912         }
12913       }
12914     }
12915     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12916     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12917     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12918     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12919     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12920     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12921     if (draw_info->geometry == (char *) NULL)
12922       {
12923         draw_info->geometry=AcquireString((char *) NULL);
12924         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12925           "%.15g,%.15g",x,y);
12926       }
12927     status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
12928     (void) CatchException(exception);
12929     if (status == MagickFalse)
12930       PUSHs(&sv_undef);
12931     else
12932       {
12933         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12934         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12935         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12936         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12937         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12938         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12939         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12940         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12941         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12942         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12943         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12944         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12945         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12946       }
12947     draw_info=DestroyDrawInfo(draw_info);
12948
12949   PerlException:
12950     if (package_info != (struct PackageInfo *) NULL)
12951       DestroyPackageInfo(package_info);
12952     InheritPerlException(exception,perl_exception);
12953     exception=DestroyExceptionInfo(exception);
12954     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12955   }
12956 \f
12957 #
12958 ###############################################################################
12959 #                                                                             #
12960 #                                                                             #
12961 #                                                                             #
12962 #   Q u e r y F o r m a t                                                     #
12963 #                                                                             #
12964 #                                                                             #
12965 #                                                                             #
12966 ###############################################################################
12967 #
12968 #
12969 void
12970 QueryFormat(ref,...)
12971   Image::Magick ref=NO_INIT
12972   ALIAS:
12973     queryformat = 1
12974   PPCODE:
12975   {
12976     char
12977       *name;
12978
12979     ExceptionInfo
12980       *exception;
12981
12982     register ssize_t
12983       i;
12984
12985     SV
12986       *perl_exception;
12987
12988     volatile const MagickInfo
12989       *magick_info;
12990
12991     PERL_UNUSED_VAR(ref);
12992     PERL_UNUSED_VAR(ix);
12993     exception=AcquireExceptionInfo();
12994     perl_exception=newSVpv("",0);
12995     if (items == 1)
12996       {
12997         char
12998           format[MaxTextExtent];
12999
13000         const MagickInfo
13001           **format_list;
13002
13003         size_t
13004           types;
13005
13006         format_list=GetMagickInfoList("*",&types,exception);
13007         EXTEND(sp,types);
13008         for (i=0; i < (ssize_t) types; i++)
13009         {
13010           (void) CopyMagickString(format,format_list[i]->name,MaxTextExtent);
13011           LocaleLower(format);
13012           PUSHs(sv_2mortal(newSVpv(format,0)));
13013         }
13014         format_list=(const MagickInfo **)
13015           RelinquishMagickMemory((MagickInfo *) format_list);
13016         goto PerlException;
13017       }
13018     EXTEND(sp,8*items);
13019     for (i=1; i < items; i++)
13020     {
13021       name=(char *) SvPV(ST(i),na);
13022       magick_info=GetMagickInfo(name,exception);
13023       if (magick_info == (const MagickInfo *) NULL)
13024         {
13025           PUSHs(&sv_undef);
13026           continue;
13027         }
13028       PUSHs(sv_2mortal(newSViv(magick_info->adjoin)));
13029       PUSHs(sv_2mortal(newSViv(magick_info->blob_support)));
13030       PUSHs(sv_2mortal(newSViv(magick_info->raw)));
13031       PUSHs(sv_2mortal(newSViv((long) magick_info->decoder)));
13032       PUSHs(sv_2mortal(newSViv((long) magick_info->encoder)));
13033       if (magick_info->description == (char *) NULL)
13034         PUSHs(&sv_undef);
13035       else
13036         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
13037       if (magick_info->module == (char *) NULL)
13038         PUSHs(&sv_undef);
13039       else
13040         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
13041     }
13042
13043   PerlException:
13044     InheritPerlException(exception,perl_exception);
13045     exception=DestroyExceptionInfo(exception);
13046     SvREFCNT_dec(perl_exception);
13047   }
13048 \f
13049 #
13050 ###############################################################################
13051 #                                                                             #
13052 #                                                                             #
13053 #                                                                             #
13054 #   Q u e r y O p t i o n                                                     #
13055 #                                                                             #
13056 #                                                                             #
13057 #                                                                             #
13058 ###############################################################################
13059 #
13060 #
13061 void
13062 QueryOption(ref,...)
13063   Image::Magick ref=NO_INIT
13064   ALIAS:
13065     queryoption = 1
13066   PPCODE:
13067   {
13068     char
13069       **options;
13070
13071     ExceptionInfo
13072       *exception;
13073
13074     register ssize_t
13075       i;
13076
13077     ssize_t
13078       j,
13079       option;
13080
13081     SV
13082       *perl_exception;
13083
13084     PERL_UNUSED_VAR(ref);
13085     PERL_UNUSED_VAR(ix);
13086     exception=AcquireExceptionInfo();
13087     perl_exception=newSVpv("",0);
13088     EXTEND(sp,8*items);
13089     for (i=1; i < items; i++)
13090     {
13091       option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
13092         SvPV(ST(i),na));
13093       options=GetCommandOptions((CommandOption) option);
13094       if (options == (char **) NULL)
13095         PUSHs(&sv_undef);
13096       else
13097         {
13098           for (j=0; options[j] != (char *) NULL; j++)
13099             PUSHs(sv_2mortal(newSVpv(options[j],0)));
13100           options=DestroyStringList(options);
13101         }
13102     }
13103
13104     InheritPerlException(exception,perl_exception);
13105     exception=DestroyExceptionInfo(exception);
13106     SvREFCNT_dec(perl_exception);
13107   }
13108 \f
13109 #
13110 ###############################################################################
13111 #                                                                             #
13112 #                                                                             #
13113 #                                                                             #
13114 #   R e a d                                                                   #
13115 #                                                                             #
13116 #                                                                             #
13117 #                                                                             #
13118 ###############################################################################
13119 #
13120 #
13121 void
13122 Read(ref,...)
13123   Image::Magick ref=NO_INIT
13124   ALIAS:
13125     ReadImage  = 1
13126     read       = 2
13127     readimage  = 3
13128   PPCODE:
13129   {
13130     AV
13131       *av;
13132
13133     char
13134       **keep,
13135       **list;
13136
13137     ExceptionInfo
13138       *exception;
13139
13140     HV
13141       *hv;
13142
13143     Image
13144       *image;
13145
13146     int
13147       n;
13148
13149     MagickBooleanType
13150       status;
13151
13152     register char
13153       **p;
13154
13155     register ssize_t
13156       i;
13157
13158     ssize_t
13159       ac,
13160       number_images;
13161
13162     STRLEN
13163       *length;
13164
13165     struct PackageInfo
13166       *info,
13167       *package_info;
13168
13169     SV
13170       *perl_exception,  /* Perl variable for storing messages */
13171       *reference,
13172       *rv,
13173       *sv;
13174
13175     PERL_UNUSED_VAR(ref);
13176     PERL_UNUSED_VAR(ix);
13177     exception=AcquireExceptionInfo();
13178     perl_exception=newSVpv("",0);
13179     sv=NULL;
13180     package_info=(struct PackageInfo *) NULL;
13181     number_images=0;
13182     ac=(items < 2) ? 1 : items-1;
13183     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
13184     keep=list;
13185     length=(STRLEN *) NULL;
13186     if (list == (char **) NULL)
13187       {
13188         ThrowPerlException(exception,ResourceLimitError,
13189           "MemoryAllocationFailed",PackageName);
13190         goto PerlException;
13191       }
13192     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
13193     if (length == (STRLEN *) NULL)
13194       {
13195         ThrowPerlException(exception,ResourceLimitError,
13196           "MemoryAllocationFailed",PackageName);
13197         goto PerlException;
13198       }
13199     if (sv_isobject(ST(0)) == 0)
13200       {
13201         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13202           PackageName);
13203         goto PerlException;
13204       }
13205     reference=SvRV(ST(0));
13206     hv=SvSTASH(reference);
13207     if (SvTYPE(reference) != SVt_PVAV)
13208       {
13209         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13210           PackageName);
13211         goto PerlException;
13212       }
13213     av=(AV *) reference;
13214     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13215       exception);
13216     package_info=ClonePackageInfo(info,exception);
13217     n=1;
13218     if (items <= 1)
13219       *list=(char *) (*package_info->image_info->filename ?
13220         package_info->image_info->filename : "XC:black");
13221     else
13222       for (n=0, i=0; i < ac; i++)
13223       {
13224         list[n]=(char *) SvPV(ST(i+1),length[n]);
13225         if ((items >= 3) && strEQcase(list[n],"blob"))
13226           {
13227             void
13228               *blob;
13229
13230             i++;
13231             blob=(void *) (SvPV(ST(i+1),length[n]));
13232             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13233           }
13234         if ((items >= 3) && strEQcase(list[n],"filename"))
13235           continue;
13236         if ((items >= 3) && strEQcase(list[n],"file"))
13237           {
13238             FILE
13239               *file;
13240
13241             PerlIO
13242               *io_info;
13243
13244             i++;
13245             io_info=IoIFP(sv_2io(ST(i+1)));
13246             if (io_info == (PerlIO *) NULL)
13247               {
13248                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13249                   PackageName);
13250                 continue;
13251               }
13252             file=PerlIO_findFILE(io_info);
13253             if (file == (FILE *) NULL)
13254               {
13255                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13256                   PackageName);
13257                 continue;
13258               }
13259             SetImageInfoFile(package_info->image_info,file);
13260           }
13261         if ((items >= 3) && strEQcase(list[n],"magick"))
13262           continue;
13263         n++;
13264       }
13265     list[n]=(char *) NULL;
13266     keep=list;
13267     status=ExpandFilenames(&n,&list);
13268     if (status == MagickFalse)
13269       {
13270         ThrowPerlException(exception,ResourceLimitError,
13271           "MemoryAllocationFailed",PackageName);
13272         goto PerlException;
13273       }
13274     number_images=0;
13275     for (i=0; i < n; i++)
13276     {
13277       if ((package_info->image_info->file == (FILE *) NULL) &&
13278           (package_info->image_info->blob == (void *) NULL))
13279         image=ReadImages(package_info->image_info,list[i],exception);
13280       else
13281         {
13282           image=ReadImages(package_info->image_info,
13283             package_info->image_info->filename,exception);
13284           if (image != (Image *) NULL)
13285             DisassociateImageStream(image);
13286         }
13287       if (image == (Image *) NULL)
13288         break;
13289       for ( ; image; image=image->next)
13290       {
13291         AddImageToRegistry(sv,image);
13292         rv=newRV(sv);
13293         av_push(av,sv_bless(rv,hv));
13294         SvREFCNT_dec(sv);
13295         number_images++;
13296       }
13297     }
13298     /*
13299       Free resources.
13300     */
13301     for (i=0; i < n; i++)
13302       if (list[i] != (char *) NULL)
13303         for (p=keep; list[i] != *p++; )
13304           if (*p == (char *) NULL)
13305             {
13306               list[i]=(char *) RelinquishMagickMemory(list[i]);
13307               break;
13308             }
13309
13310   PerlException:
13311     if (package_info != (struct PackageInfo *) NULL)
13312       DestroyPackageInfo(package_info);
13313     if (list && (list != keep))
13314       list=(char **) RelinquishMagickMemory(list);
13315     if (keep)
13316       keep=(char **) RelinquishMagickMemory(keep);
13317     if (length)
13318       length=(STRLEN *) RelinquishMagickMemory(length);
13319     InheritPerlException(exception,perl_exception);
13320     exception=DestroyExceptionInfo(exception);
13321     sv_setiv(perl_exception,(IV) number_images);
13322     SvPOK_on(perl_exception);
13323     ST(0)=sv_2mortal(perl_exception);
13324     XSRETURN(1);
13325   }
13326 \f
13327 #
13328 ###############################################################################
13329 #                                                                             #
13330 #                                                                             #
13331 #                                                                             #
13332 #   R e m o t e                                                               #
13333 #                                                                             #
13334 #                                                                             #
13335 #                                                                             #
13336 ###############################################################################
13337 #
13338 #
13339 void
13340 Remote(ref,...)
13341   Image::Magick ref=NO_INIT
13342   ALIAS:
13343     RemoteCommand  = 1
13344     remote         = 2
13345     remoteCommand  = 3
13346   PPCODE:
13347   {
13348     AV
13349       *av;
13350
13351     ExceptionInfo
13352       *exception;
13353
13354     register ssize_t
13355       i;
13356
13357     SV
13358       *perl_exception,
13359       *reference;
13360
13361     struct PackageInfo
13362       *info;
13363
13364     PERL_UNUSED_VAR(ref);
13365     PERL_UNUSED_VAR(ix);
13366     exception=AcquireExceptionInfo();
13367     perl_exception=newSVpv("",0);
13368     reference=SvRV(ST(0));
13369     av=(AV *) reference;
13370     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13371       exception);
13372     for (i=1; i < items; i++)
13373       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13374         SvPV(ST(i),na),exception);
13375     InheritPerlException(exception,perl_exception);
13376     exception=DestroyExceptionInfo(exception);
13377     SvREFCNT_dec(perl_exception);    /* throw away all errors */
13378   }
13379 \f
13380 #
13381 ###############################################################################
13382 #                                                                             #
13383 #                                                                             #
13384 #                                                                             #
13385 #   S e t                                                                     #
13386 #                                                                             #
13387 #                                                                             #
13388 #                                                                             #
13389 ###############################################################################
13390 #
13391 #
13392 void
13393 Set(ref,...)
13394   Image::Magick ref=NO_INIT
13395   ALIAS:
13396     SetAttributes  = 1
13397     SetAttribute   = 2
13398     set            = 3
13399     setattributes  = 4
13400     setattribute   = 5
13401   PPCODE:
13402   {
13403     ExceptionInfo
13404       *exception;
13405
13406     Image
13407       *image;
13408
13409     register ssize_t
13410       i;
13411
13412     struct PackageInfo
13413       *info;
13414
13415     SV
13416       *perl_exception,
13417       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13418
13419     PERL_UNUSED_VAR(ref);
13420     PERL_UNUSED_VAR(ix);
13421     exception=AcquireExceptionInfo();
13422     perl_exception=newSVpv("",0);
13423     if (sv_isobject(ST(0)) == 0)
13424       {
13425         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13426           PackageName);
13427         goto PerlException;
13428       }
13429     reference=SvRV(ST(0));
13430     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13431     if (items == 2)
13432       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13433     else
13434       for (i=2; i < items; i+=2)
13435         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13436
13437   PerlException:
13438     InheritPerlException(exception,perl_exception);
13439     exception=DestroyExceptionInfo(exception);
13440     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13441     SvPOK_on(perl_exception);
13442     ST(0)=sv_2mortal(perl_exception);
13443     XSRETURN(1);
13444   }
13445 \f
13446 #
13447 ###############################################################################
13448 #                                                                             #
13449 #                                                                             #
13450 #                                                                             #
13451 #   S e t P i x e l                                                           #
13452 #                                                                             #
13453 #                                                                             #
13454 #                                                                             #
13455 ###############################################################################
13456 #
13457 #
13458 void
13459 SetPixel(ref,...)
13460   Image::Magick ref=NO_INIT
13461   ALIAS:
13462     setpixel = 1
13463     setPixel = 2
13464   PPCODE:
13465   {
13466     AV
13467       *av;
13468
13469     char
13470       *attribute;
13471
13472     ChannelType
13473       channel,
13474       channel_mask;
13475
13476     ExceptionInfo
13477       *exception;
13478
13479     Image
13480       *image;
13481
13482     MagickBooleanType
13483       normalize;
13484
13485     RectangleInfo
13486       region;
13487
13488     register ssize_t
13489       i;
13490
13491     register Quantum
13492       *q;
13493
13494     ssize_t
13495       option;
13496
13497     struct PackageInfo
13498       *info;
13499
13500     SV
13501       *perl_exception,
13502       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13503
13504     PERL_UNUSED_VAR(ref);
13505     PERL_UNUSED_VAR(ix);
13506     exception=AcquireExceptionInfo();
13507     perl_exception=newSVpv("",0);
13508     reference=SvRV(ST(0));
13509     av=(AV *) reference;
13510     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13511       exception);
13512     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13513     if (image == (Image *) NULL)
13514       {
13515         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13516           PackageName);
13517         goto PerlException;
13518       }
13519     av=(AV *) NULL;
13520     normalize=MagickTrue;
13521     region.x=0;
13522     region.y=0;
13523     region.width=image->columns;
13524     region.height=1;
13525     if (items == 1)
13526       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13527     channel=DefaultChannels;
13528     for (i=2; i < items; i+=2)
13529     {
13530       attribute=(char *) SvPV(ST(i-1),na);
13531       switch (*attribute)
13532       {
13533         case 'C':
13534         case 'c':
13535         {
13536           if (LocaleCompare(attribute,"channel") == 0)
13537             {
13538               ssize_t
13539                 option;
13540
13541               option=ParseChannelOption(SvPV(ST(i),na));
13542               if (option < 0)
13543                 {
13544                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13545                     SvPV(ST(i),na));
13546                   return;
13547                 }
13548               channel=(ChannelType) option;
13549               break;
13550             }
13551           if (LocaleCompare(attribute,"color") == 0)
13552             {
13553               if (SvTYPE(ST(i)) != SVt_RV)
13554                 {
13555                   char
13556                     message[MaxTextExtent];
13557
13558                   (void) FormatLocaleString(message,MaxTextExtent,
13559                     "invalid %.60s value",attribute);
13560                   ThrowPerlException(exception,OptionError,message,
13561                     SvPV(ST(i),na));
13562                 }
13563               av=(AV *) SvRV(ST(i));
13564               break;
13565             }
13566           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13567             attribute);
13568           break;
13569         }
13570         case 'g':
13571         case 'G':
13572         {
13573           if (LocaleCompare(attribute,"geometry") == 0)
13574             {
13575               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
13576               break;
13577             }
13578           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13579             attribute);
13580           break;
13581         }
13582         case 'N':
13583         case 'n':
13584         {
13585           if (LocaleCompare(attribute,"normalize") == 0)
13586             {
13587               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13588                 SvPV(ST(i),na));
13589               if (option < 0)
13590                 {
13591                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13592                     SvPV(ST(i),na));
13593                   break;
13594                 }
13595              normalize=option != 0 ? MagickTrue : MagickFalse;
13596              break;
13597             }
13598           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13599             attribute);
13600           break;
13601         }
13602         case 'x':
13603         case 'X':
13604         {
13605           if (LocaleCompare(attribute,"x") == 0)
13606             {
13607               region.x=SvIV(ST(i));
13608               break;
13609             }
13610           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13611             attribute);
13612           break;
13613         }
13614         case 'y':
13615         case 'Y':
13616         {
13617           if (LocaleCompare(attribute,"y") == 0)
13618             {
13619               region.y=SvIV(ST(i));
13620               break;
13621             }
13622           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13623             attribute);
13624           break;
13625         }
13626         default:
13627         {
13628           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13629             attribute);
13630           break;
13631         }
13632       }
13633     }
13634     (void) SetImageStorageClass(image,DirectClass,exception);
13635     channel_mask=SetImageChannelMask(image,channel);
13636     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
13637     if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
13638         (SvTYPE(av) != SVt_PVAV))
13639       PUSHs(&sv_undef);
13640     else
13641       {
13642         double
13643           scale;
13644
13645         register ssize_t
13646           i;
13647
13648         i=0;
13649         scale=1.0;
13650         if (normalize != MagickFalse)
13651           scale=QuantumRange;
13652         if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
13653             (i <= av_len(av)))
13654           {
13655             SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
13656               av_fetch(av,i,0)))),q);
13657             i++;
13658           }
13659         if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
13660             (i <= av_len(av)))
13661           {
13662             SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
13663               av_fetch(av,i,0)))),q);
13664             i++;
13665           }
13666         if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
13667             (i <= av_len(av)))
13668           {
13669             SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
13670               av_fetch(av,i,0)))),q);
13671             i++;
13672           }
13673         if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
13674             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
13675           {
13676             SetPixelBlack(image,ClampToQuantum(scale*
13677               SvNV(*(av_fetch(av,i,0)))),q);
13678             i++;
13679           }
13680         if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
13681             (i <= av_len(av)))
13682           {
13683             SetPixelAlpha(image,ClampToQuantum(scale*
13684               SvNV(*(av_fetch(av,i,0)))),q);
13685             i++;
13686           }
13687         (void) SyncAuthenticPixels(image,exception);
13688       }
13689     (void) SetImageChannelMask(image,channel_mask);
13690
13691   PerlException:
13692     InheritPerlException(exception,perl_exception);
13693     exception=DestroyExceptionInfo(exception);
13694     SvREFCNT_dec(perl_exception);
13695   }
13696 \f
13697 #
13698 ###############################################################################
13699 #                                                                             #
13700 #                                                                             #
13701 #                                                                             #
13702 #   S m u s h                                                                 #
13703 #                                                                             #
13704 #                                                                             #
13705 #                                                                             #
13706 ###############################################################################
13707 #
13708 #
13709 void
13710 Smush(ref,...)
13711   Image::Magick ref=NO_INIT
13712   ALIAS:
13713     SmushImage  = 1
13714     smush       = 2
13715     smushimage  = 3
13716   PPCODE:
13717   {
13718     AV
13719       *av;
13720
13721     char
13722       *attribute;
13723
13724     ExceptionInfo
13725       *exception;
13726
13727     HV
13728       *hv;
13729
13730     Image
13731       *image;
13732
13733     register ssize_t
13734       i;
13735
13736     ssize_t
13737       offset,
13738       stack;
13739
13740     struct PackageInfo
13741       *info;
13742
13743     SV
13744       *av_reference,
13745       *perl_exception,
13746       *reference,
13747       *rv,
13748       *sv;
13749
13750     PERL_UNUSED_VAR(ref);
13751     PERL_UNUSED_VAR(ix);
13752     exception=AcquireExceptionInfo();
13753     perl_exception=newSVpv("",0);
13754     sv=NULL;
13755     attribute=NULL;
13756     av=NULL;
13757     if (sv_isobject(ST(0)) == 0)
13758       {
13759         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13760           PackageName);
13761         goto PerlException;
13762       }
13763     reference=SvRV(ST(0));
13764     hv=SvSTASH(reference);
13765     av=newAV();
13766     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13767     SvREFCNT_dec(av);
13768     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13769     if (image == (Image *) NULL)
13770       {
13771         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13772           PackageName);
13773         goto PerlException;
13774       }
13775     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13776     /*
13777       Get options.
13778     */
13779     offset=0;
13780     stack=MagickTrue;
13781     for (i=2; i < items; i+=2)
13782     {
13783       attribute=(char *) SvPV(ST(i-1),na);
13784       switch (*attribute)
13785       {
13786         case 'O':
13787         case 'o':
13788         {
13789           if (LocaleCompare(attribute,"offset") == 0)
13790             {
13791               offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
13792               break;
13793             }
13794           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13795             attribute);
13796           break;
13797         }
13798         case 'S':
13799         case 's':
13800         {
13801           if (LocaleCompare(attribute,"stack") == 0)
13802             {
13803               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13804                 SvPV(ST(i),na));
13805               if (stack < 0)
13806                 {
13807                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13808                     SvPV(ST(i),na));
13809                   return;
13810                 }
13811               break;
13812             }
13813           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13814             attribute);
13815           break;
13816         }
13817         default:
13818         {
13819           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13820             attribute);
13821           break;
13822         }
13823       }
13824     }
13825     image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
13826       exception);
13827     if (image == (Image *) NULL)
13828       goto PerlException;
13829     for ( ; image; image=image->next)
13830     {
13831       AddImageToRegistry(sv,image);
13832       rv=newRV(sv);
13833       av_push(av,sv_bless(rv,hv));
13834       SvREFCNT_dec(sv);
13835     }
13836     exception=DestroyExceptionInfo(exception);
13837     ST(0)=av_reference;
13838     SvREFCNT_dec(perl_exception);
13839     XSRETURN(1);
13840
13841   PerlException:
13842     InheritPerlException(exception,perl_exception);
13843     exception=DestroyExceptionInfo(exception);
13844     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
13845     SvPOK_on(perl_exception);
13846     ST(0)=sv_2mortal(perl_exception);
13847     XSRETURN(1);
13848   }
13849 \f
13850 #
13851 ###############################################################################
13852 #                                                                             #
13853 #                                                                             #
13854 #                                                                             #
13855 #   S t a t i s t i c s                                                       #
13856 #                                                                             #
13857 #                                                                             #
13858 #                                                                             #
13859 ###############################################################################
13860 #
13861 #
13862 void
13863 Statistics(ref,...)
13864   Image::Magick ref=NO_INIT
13865   ALIAS:
13866     StatisticsImage = 1
13867     statistics      = 2
13868     statisticsimage = 3
13869   PPCODE:
13870   {
13871 #define ChannelStatistics(channel) \
13872 { \
13873   (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
13874     (double) channel_statistics[channel].depth); \
13875   PUSHs(sv_2mortal(newSVpv(message,0))); \
13876   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13877     channel_statistics[channel].minima/scale); \
13878   PUSHs(sv_2mortal(newSVpv(message,0))); \
13879   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13880     channel_statistics[channel].maxima/scale); \
13881   PUSHs(sv_2mortal(newSVpv(message,0))); \
13882   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13883     channel_statistics[channel].mean/scale); \
13884   PUSHs(sv_2mortal(newSVpv(message,0))); \
13885   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13886     channel_statistics[channel].standard_deviation/scale); \
13887   PUSHs(sv_2mortal(newSVpv(message,0))); \
13888   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13889     channel_statistics[channel].kurtosis); \
13890   PUSHs(sv_2mortal(newSVpv(message,0))); \
13891   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13892     channel_statistics[channel].skewness); \
13893   PUSHs(sv_2mortal(newSVpv(message,0))); \
13894 }
13895
13896     AV
13897       *av;
13898
13899     char
13900       message[MaxTextExtent];
13901
13902     ChannelStatistics
13903       *channel_statistics;
13904
13905     double
13906       scale;
13907
13908     ExceptionInfo
13909       *exception;
13910
13911     Image
13912       *image;
13913
13914     ssize_t
13915       count;
13916
13917     struct PackageInfo
13918       *info;
13919
13920     SV
13921       *perl_exception,
13922       *reference;
13923
13924     PERL_UNUSED_VAR(ref);
13925     PERL_UNUSED_VAR(ix);
13926     exception=AcquireExceptionInfo();
13927     perl_exception=newSVpv("",0);
13928     av=NULL;
13929     if (sv_isobject(ST(0)) == 0)
13930       {
13931         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13932           PackageName);
13933         goto PerlException;
13934       }
13935     reference=SvRV(ST(0));
13936     av=newAV();
13937     SvREFCNT_dec(av);
13938     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13939     if (image == (Image *) NULL)
13940       {
13941         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13942           PackageName);
13943         goto PerlException;
13944       }
13945     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13946     count=0;
13947     for ( ; image; image=image->next)
13948     {
13949       channel_statistics=GetImageStatistics(image,exception);
13950       if (channel_statistics == (ChannelStatistics *) NULL)
13951         continue;
13952       count++;
13953       EXTEND(sp,35*count);
13954       scale=(double) QuantumRange;
13955       ChannelStatistics(RedChannel);
13956       ChannelStatistics(GreenChannel);
13957       ChannelStatistics(BlueChannel);
13958       if (image->colorspace == CMYKColorspace)
13959         ChannelStatistics(BlackChannel);
13960       if (image->alpha_trait == BlendPixelTrait)
13961         ChannelStatistics(AlphaChannel);
13962       channel_statistics=(ChannelStatistics *)
13963         RelinquishMagickMemory(channel_statistics);
13964     }
13965
13966   PerlException:
13967     InheritPerlException(exception,perl_exception);
13968     exception=DestroyExceptionInfo(exception);
13969     SvREFCNT_dec(perl_exception);
13970   }
13971 \f
13972 #
13973 ###############################################################################
13974 #                                                                             #
13975 #                                                                             #
13976 #                                                                             #
13977 #   S y n c A u t h e n t i c P i x e l s                                     #
13978 #                                                                             #
13979 #                                                                             #
13980 #                                                                             #
13981 ###############################################################################
13982 #
13983 #
13984 void
13985 SyncAuthenticPixels(ref,...)
13986   Image::Magick ref = NO_INIT
13987   ALIAS:
13988     Syncauthenticpixels = 1
13989     SyncImagePixels = 2
13990     syncimagepixels = 3
13991   CODE:
13992   {
13993     ExceptionInfo
13994       *exception;
13995
13996     Image
13997       *image;
13998
13999     MagickBooleanType
14000       status;
14001
14002     struct PackageInfo
14003       *info;
14004
14005     SV
14006       *perl_exception,
14007       *reference;
14008
14009     PERL_UNUSED_VAR(ref);
14010     PERL_UNUSED_VAR(ix);
14011     exception=AcquireExceptionInfo();
14012     perl_exception=newSVpv("",0);
14013     if (sv_isobject(ST(0)) == 0)
14014       {
14015         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14016           PackageName);
14017         goto PerlException;
14018       }
14019
14020     reference=SvRV(ST(0));
14021     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14022     if (image == (Image *) NULL)
14023       {
14024         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14025           PackageName);
14026         goto PerlException;
14027       }
14028
14029     status=SyncAuthenticPixels(image,exception);
14030     if (status != MagickFalse)
14031       return;
14032
14033   PerlException:
14034     InheritPerlException(exception,perl_exception);
14035     exception=DestroyExceptionInfo(exception);
14036     SvREFCNT_dec(perl_exception);  /* throw away all errors */
14037   }
14038 \f
14039 #
14040 ###############################################################################
14041 #                                                                             #
14042 #                                                                             #
14043 #                                                                             #
14044 #   T r a n s f o r m                                                         #
14045 #                                                                             #
14046 #                                                                             #
14047 #                                                                             #
14048 ###############################################################################
14049 #
14050 #
14051 void
14052 Transform(ref,...)
14053   Image::Magick ref=NO_INIT
14054   ALIAS:
14055     TransformImage = 1
14056     transform      = 2
14057     transformimage = 3
14058   PPCODE:
14059   {
14060     AV
14061       *av;
14062
14063     char
14064       *attribute,
14065       *crop_geometry,
14066       *geometry;
14067
14068     ExceptionInfo
14069       *exception;
14070
14071     HV
14072       *hv;
14073
14074     Image
14075       *clone,
14076       *image;
14077
14078     register ssize_t
14079       i;
14080
14081     struct PackageInfo
14082       *info;
14083
14084     SV
14085       *av_reference,
14086       *perl_exception,
14087       *reference,
14088       *rv,
14089       *sv;
14090
14091     PERL_UNUSED_VAR(ref);
14092     PERL_UNUSED_VAR(ix);
14093     exception=AcquireExceptionInfo();
14094     perl_exception=newSVpv("",0);
14095     sv=NULL;
14096     av=NULL;
14097     attribute=NULL;
14098     if (sv_isobject(ST(0)) == 0)
14099       {
14100         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14101           PackageName);
14102         goto PerlException;
14103       }
14104     reference=SvRV(ST(0));
14105     hv=SvSTASH(reference);
14106     av=newAV();
14107     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14108     SvREFCNT_dec(av);
14109     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14110     if (image == (Image *) NULL)
14111       {
14112         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14113           PackageName);
14114         goto PerlException;
14115       }
14116     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14117     /*
14118       Get attribute.
14119     */
14120     crop_geometry=(char *) NULL;
14121     geometry=(char *) NULL;
14122     for (i=2; i < items; i+=2)
14123     {
14124       attribute=(char *) SvPV(ST(i-1),na);
14125       switch (*attribute)
14126       {
14127         case 'c':
14128         case 'C':
14129         {
14130           if (LocaleCompare(attribute,"crop") == 0)
14131             {
14132               crop_geometry=SvPV(ST(i),na);
14133               break;
14134             }
14135           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14136             attribute);
14137           break;
14138         }
14139         case 'g':
14140         case 'G':
14141         {
14142           if (LocaleCompare(attribute,"geometry") == 0)
14143             {
14144               geometry=SvPV(ST(i),na);
14145               break;
14146             }
14147           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14148             attribute);
14149           break;
14150         }
14151         default:
14152         {
14153           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14154             attribute);
14155           break;
14156         }
14157       }
14158     }
14159     for ( ; image; image=image->next)
14160     {
14161       clone=CloneImage(image,0,0,MagickTrue,exception);
14162       if (clone == (Image *) NULL)
14163         goto PerlException;
14164       TransformImage(&clone,crop_geometry,geometry,exception);
14165       for ( ; clone; clone=clone->next)
14166       {
14167         AddImageToRegistry(sv,clone);
14168         rv=newRV(sv);
14169         av_push(av,sv_bless(rv,hv));
14170         SvREFCNT_dec(sv);
14171       }
14172     }
14173     exception=DestroyExceptionInfo(exception);
14174     ST(0)=av_reference;
14175     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
14176     XSRETURN(1);
14177
14178   PerlException:
14179     InheritPerlException(exception,perl_exception);
14180     exception=DestroyExceptionInfo(exception);
14181     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14182     SvPOK_on(perl_exception);
14183     ST(0)=sv_2mortal(perl_exception);
14184     XSRETURN(1);
14185   }
14186 \f
14187 #
14188 ###############################################################################
14189 #                                                                             #
14190 #                                                                             #
14191 #                                                                             #
14192 #   W r i t e                                                                 #
14193 #                                                                             #
14194 #                                                                             #
14195 #                                                                             #
14196 ###############################################################################
14197 #
14198 #
14199 void
14200 Write(ref,...)
14201   Image::Magick ref=NO_INIT
14202   ALIAS:
14203     WriteImage    = 1
14204     write         = 2
14205     writeimage    = 3
14206   PPCODE:
14207   {
14208     char
14209       filename[MaxTextExtent];
14210
14211     ExceptionInfo
14212       *exception;
14213
14214     Image
14215       *image,
14216       *next;
14217
14218     register ssize_t
14219       i;
14220
14221     ssize_t
14222       number_images,
14223       scene;
14224
14225     struct PackageInfo
14226       *info,
14227       *package_info;
14228
14229     SV
14230       *perl_exception,
14231       *reference;
14232
14233     PERL_UNUSED_VAR(ref);
14234     PERL_UNUSED_VAR(ix);
14235     exception=AcquireExceptionInfo();
14236     perl_exception=newSVpv("",0);
14237     number_images=0;
14238     package_info=(struct PackageInfo *) NULL;
14239     if (sv_isobject(ST(0)) == 0)
14240       {
14241         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14242           PackageName);
14243         goto PerlException;
14244       }
14245     reference=SvRV(ST(0));
14246     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14247     if (image == (Image *) NULL)
14248       {
14249         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14250           PackageName);
14251         goto PerlException;
14252       }
14253     package_info=ClonePackageInfo(info,exception);
14254     if (items == 2)
14255       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14256     else
14257       if (items > 2)
14258         for (i=2; i < items; i+=2)
14259           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14260             exception);
14261     (void) CopyMagickString(filename,package_info->image_info->filename,
14262       MaxTextExtent);
14263     scene=0;
14264     for (next=image; next; next=next->next)
14265     {
14266       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
14267       next->scene=scene++;
14268     }
14269     SetImageInfo(package_info->image_info,(unsigned int)
14270       GetImageListLength(image),exception);
14271     for (next=image; next; next=next->next)
14272     {
14273       (void) WriteImage(package_info->image_info,next,exception);
14274       number_images++;
14275       if (package_info->image_info->adjoin)
14276         break;
14277     }
14278
14279   PerlException:
14280     if (package_info != (struct PackageInfo *) NULL)
14281       DestroyPackageInfo(package_info);
14282     InheritPerlException(exception,perl_exception);
14283     exception=DestroyExceptionInfo(exception);
14284     sv_setiv(perl_exception,(IV) number_images);
14285     SvPOK_on(perl_exception);
14286     ST(0)=sv_2mortal(perl_exception);
14287     XSRETURN(1);
14288   }