]> 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-2011 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((IV) 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   MagickRealType
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},
210       {"channel", MagickChannelOptions} } },
211     { "Colorize", { {"fill", StringReference}, {"opacity", 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}, {"fill", StringReference},
250       {"color", StringReference}, {"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     { "Swirl", { {"degrees", RealReference},
264       {"interpolate", MagickInterpolateOptions} } },
265     { "Resize", { {"geometry", StringReference}, {"width", IntegerReference},
266       {"height", IntegerReference}, {"filter", MagickFilterOptions},
267       {"support", StringReference }, {"blur", RealReference } } },
268     { "Zoom", { {"geometry", StringReference}, {"width", IntegerReference},
269       {"height", IntegerReference}, {"filter", MagickFilterOptions},
270       {"support", RealReference }, {"blur", RealReference } } },
271     { "Annotate", { {"text", StringReference}, {"font", StringReference},
272       {"pointsize", RealReference}, {"density", StringReference},
273       {"undercolor", StringReference}, {"stroke", StringReference},
274       {"fill", StringReference}, {"geometry", StringReference},
275       {"pen", StringReference}, {"x", RealReference},
276       {"y", RealReference}, {"gravity", MagickGravityOptions},
277       {"translate", StringReference}, {"scale", StringReference},
278       {"rotate", RealReference}, {"skewX", RealReference},
279       {"skewY", RealReference}, {"strokewidth", RealReference},
280       {"antialias", MagickBooleanOptions}, {"family", StringReference},
281       {"style", MagickStyleOptions}, {"stretch", MagickStretchOptions},
282       {"weight", IntegerReference}, {"align", MagickAlignOptions},
283       {"encoding", StringReference}, {"affine", ArrayReference},
284       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
285       {"tile", ImageReference}, {"kerning", RealReference},
286       {"interline-spacing", RealReference},
287       {"interword-spacing", RealReference},
288       {"direction", MagickDirectionOptions} } },
289     { "ColorFloodfill", { {"geometry", StringReference},
290       {"x", IntegerReference}, {"y", IntegerReference},
291       {"fill", StringReference}, {"bordercolor", StringReference},
292       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
293     { "Composite", { {"image", ImageReference},
294       {"compose", MagickComposeOptions}, {"geometry", StringReference},
295       {"x", IntegerReference}, {"y", IntegerReference},
296       {"gravity", MagickGravityOptions}, {"opacity", StringReference},
297       {"tile", MagickBooleanOptions}, {"rotate", RealReference},
298       {"color", StringReference}, {"mask", ImageReference},
299       {"channel", MagickChannelOptions},
300       {"interpolate", MagickInterpolateOptions}, {"args", StringReference},
301       {"blend", StringReference} } },
302     { "Contrast", { {"sharpen", MagickBooleanOptions} } },
303     { "CycleColormap", { {"display", IntegerReference} } },
304     { "Draw", { {"primitive", MagickPrimitiveOptions},
305       {"points", StringReference}, {"method", MagickMethodOptions},
306       {"stroke", StringReference}, {"fill", StringReference},
307       {"strokewidth", RealReference}, {"font", StringReference},
308       {"bordercolor", StringReference}, {"x", RealReference},
309       {"y", RealReference}, {"translate", StringReference},
310       {"scale", StringReference}, {"rotate", RealReference},
311       {"skewX", RealReference}, {"skewY", RealReference},
312       {"tile", ImageReference}, {"pointsize", RealReference},
313       {"antialias", MagickBooleanOptions}, {"density", StringReference},
314       {"linewidth", RealReference}, {"affine", ArrayReference},
315       {"stroke-dashoffset", RealReference},
316       {"stroke-dasharray", ArrayReference},
317       {"interpolate", MagickInterpolateOptions},
318       {"origin", StringReference}, {"text", StringReference},
319       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
320       {"vector-graphics", StringReference}, {"kerning", RealReference},
321       {"interline-spacing", RealReference},
322       {"interword-spacing", RealReference},
323       {"direction", MagickDirectionOptions} } },
324     { "Equalize", { {"channel", MagickChannelOptions} } },
325     { "Gamma", { {"gamma", StringReference}, {"channel", MagickChannelOptions},
326       {"red", RealReference}, {"green", RealReference},
327       {"blue", RealReference} } },
328     { "Map", { {"image", ImageReference}, {"dither", MagickBooleanOptions},
329       {"dither-method", MagickDitherOptions} } },
330     { "MatteFloodfill", { {"geometry", StringReference},
331       {"x", IntegerReference}, {"y", IntegerReference},
332       {"opacity", StringReference}, {"bordercolor", StringReference},
333       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
334     { "Modulate", { {"factor", StringReference}, {"hue", RealReference},
335       {"saturation", RealReference}, {"whiteness", RealReference},
336       {"brightness", RealReference}, {"lightness", RealReference},
337       {"blackness", RealReference} } },
338     { "Negate", { {"gray", MagickBooleanOptions},
339       {"channel", MagickChannelOptions} } },
340     { "Normalize", { {"channel", MagickChannelOptions} } },
341     { "NumberColors", },
342     { "Opaque", { {"color", StringReference}, {"fill", StringReference},
343       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
344       {"invert", MagickBooleanOptions} } },
345     { "Quantize", { {"colors", IntegerReference},
346       {"treedepth", IntegerReference}, {"colorspace", MagickColorspaceOptions},
347       {"dither", MagickBooleanOptions}, {"measure", MagickBooleanOptions},
348       {"global", MagickBooleanOptions}, {"transparent-color", StringReference},
349       {"dither-method", MagickDitherOptions} } },
350     { "Raise", { {"geometry", StringReference}, {"width", IntegerReference},
351       {"height", IntegerReference}, {"raise", MagickBooleanOptions} } },
352     { "Segment", { {"geometry", StringReference},
353       {"cluster-threshold", RealReference},
354       {"smoothing-threshold", RealReference},
355       {"colorspace", MagickColorspaceOptions},
356       {"verbose", MagickBooleanOptions} } },
357     { "Signature", },
358     { "Solarize", { {"geometry", StringReference},
359       {"threshold", StringReference} } },
360     { "Sync", },
361     { "Texture", { {"texture", ImageReference} } },
362     { "Evaluate", { {"value", RealReference},
363       {"operator", MagickEvaluateOptions},
364       {"channel", MagickChannelOptions} } },
365     { "Transparent", { {"color", StringReference}, {"opacity", StringReference},
366       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
367     { "Threshold", { {"threshold", StringReference},
368       {"channel", MagickChannelOptions} } },
369     { "Charcoal", { {"geometry", StringReference}, {"radius", RealReference},
370       {"sigma", RealReference} } },
371     { "Trim", { {"fuzz", StringReference} } },
372     { "Wave", { {"geometry", StringReference}, {"amplitude", RealReference},
373       {"wavelength", RealReference},
374       {"interpolate", MagickInterpolateOptions} } },
375     { "Separate", { {"channel", MagickChannelOptions} } },
376     { "Condense", },
377     { "Stereo", { {"image", ImageReference}, {"x", IntegerReference},
378       {"y", IntegerReference} } },
379     { "Stegano", { {"image", ImageReference}, {"offset", IntegerReference} } },
380     { "Deconstruct", },
381     { "GaussianBlur", { {"geometry", StringReference},
382       {"radius", RealReference}, {"sigma", RealReference},
383       {"channel", MagickChannelOptions} } },
384     { "Convolve", { {"coefficients", ArrayReference},
385       {"channel", MagickChannelOptions}, {"bias", StringReference},
386       {"kernel", StringReference} } },
387     { "Profile", { {"name", StringReference}, {"profile", StringReference},
388       { "rendering-intent", MagickIntentOptions},
389       { "black-point-compensation", MagickBooleanOptions} } },
390     { "UnsharpMask", { {"geometry", StringReference},
391       {"radius", RealReference}, {"sigma", RealReference},
392       {"amount", RealReference}, {"threshold", RealReference},
393       {"channel", MagickChannelOptions} } },
394     { "MotionBlur", { {"geometry", StringReference},
395       {"radius", RealReference}, {"sigma", RealReference},
396       {"angle", RealReference}, {"channel", MagickChannelOptions} } },
397     { "OrderedDither", { {"threshold", StringReference},
398       {"channel", MagickChannelOptions} } },
399     { "Shave", { {"geometry", StringReference}, {"width", IntegerReference},
400       {"height", IntegerReference} } },
401     { "Level", { {"levels", StringReference}, {"black-point", RealReference},
402       {"white-point", RealReference}, {"gamma", RealReference},
403       {"channel", MagickChannelOptions}, {"level", StringReference} } },
404     { "Clip", { {"id", StringReference}, {"inside", MagickBooleanOptions} } },
405     { "AffineTransform", { {"affine", ArrayReference},
406       {"translate", StringReference}, {"scale", StringReference},
407       {"rotate", RealReference}, {"skewX", RealReference},
408       {"skewY", RealReference}, {"interpolate", MagickInterpolateOptions},
409       {"background", StringReference} } },
410     { "Difference", { {"image", ImageReference}, {"fuzz", StringReference} } },
411     { "AdaptiveThreshold", { {"geometry", StringReference},
412       {"width", IntegerReference}, {"height", IntegerReference},
413       {"bias", RealReference} } },
414     { "Resample", { {"density", StringReference}, {"x", RealReference},
415       {"y", RealReference}, {"filter", MagickFilterOptions},
416       {"support", RealReference }, {"blur", 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}, {"opacity", 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}, {"opacity", 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       {"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     { "Recolor", { {"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     { "FloodfillPaint", { {"geometry", StringReference},
484       {"x", IntegerReference}, {"y", IntegerReference},
485       {"fill", StringReference}, {"bordercolor", StringReference},
486       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
487       {"invert", MagickBooleanOptions} } },
488     { "Distort", { {"points", ArrayReference}, {"method", MagickDistortOptions},
489       {"virtual-pixel", MagickVirtualPixelOptions},
490       {"best-fit", MagickBooleanOptions} } },
491     { "Clut", { {"image", ImageReference},
492       {"channel", MagickChannelOptions} } },
493     { "LiquidRescale", { {"geometry", StringReference},
494       {"width", IntegerReference}, {"height", IntegerReference},
495       {"delta-x", RealReference}, {"rigidity", RealReference } } },
496     { "Encipher", { {"passphrase", StringReference} } },
497     { "Decipher", { {"passphrase", StringReference} } },
498     { "Deskew", { {"geometry", StringReference},
499       {"threshold", StringReference} } },
500     { "Remap", { {"image", ImageReference}, {"dither", MagickBooleanOptions},
501       {"dither-method", MagickDitherOptions} } },
502     { "SparseColor", { {"points", ArrayReference},
503       {"method", MagickSparseColorOptions},
504       {"virtual-pixel", MagickVirtualPixelOptions},
505       {"channel", MagickChannelOptions} } },
506     { "Function", { {"parameters", ArrayReference},
507       {"function", MagickFunctionOptions},
508       {"virtual-pixel", MagickVirtualPixelOptions} } },
509     { "SelectiveBlur", { {"geometry", StringReference},
510       {"radius", RealReference}, {"sigma", RealReference},
511       {"threshold", RealReference}, {"channel", MagickChannelOptions} } },
512     { "HaldClut", { {"image", ImageReference},
513       {"channel", MagickChannelOptions} } },
514     { "BlueShift", { {"factor", StringReference} } },
515     { "ForwardFourierTransform", { {"magnitude", MagickBooleanOptions} } },
516     { "InverseFourierTransform", { {"magnitude", MagickBooleanOptions} } },
517     { "ColorDecisionList", {
518       {"color-correction-collection", StringReference} } },
519     { "AutoGamma", { {"channel", MagickChannelOptions} } },
520     { "AutoLevel", { {"channel", MagickChannelOptions} } },
521     { "LevelColors", { {"invert", MagickBooleanOptions},
522       {"black-point", StringReference}, {"white-point", StringReference},
523       {"channel", MagickChannelOptions}, {"invert", MagickBooleanOptions} } },
524     { "Clamp", { {"channel", MagickChannelOptions} } },
525     { "BrightnessContrast", { {"levels", StringReference},
526       {"brightness", RealReference},{"contrast", RealReference},
527       {"channel", MagickChannelOptions} } },
528     { "Morphology", { {"kernel", StringReference},
529       {"channel", MagickChannelOptions}, {"method", MagickMorphologyOptions},
530       {"iterations", IntegerReference} } },
531     { "ColorMatrix", { {"matrix", ArrayReference} } },
532     { "Color", { {"color", StringReference} } },
533     { "Mode", { {"geometry", StringReference},
534       {"width", IntegerReference},{"height", IntegerReference},
535       {"channel", MagickChannelOptions} } },
536     { "Statistic", { {"geometry", StringReference},
537       {"width", IntegerReference},{"height", IntegerReference},
538       {"channel", MagickChannelOptions}, {"type", MagickStatisticOptions} } }
539   };
540
541 static SplayTreeInfo
542   *magick_registry = (SplayTreeInfo *) NULL;
543 \f
544 /*
545   Forward declarations.
546 */
547 static Image
548   *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
549
550 static ssize_t
551   strEQcase(const char *,const char *);
552 \f
553 /*
554 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
555 %                                                                             %
556 %                                                                             %
557 %                                                                             %
558 %   C l o n e P a c k a g e I n f o                                           %
559 %                                                                             %
560 %                                                                             %
561 %                                                                             %
562 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
563 %
564 %  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
565 %  a new one.
566 %
567 %  The format of the ClonePackageInfo routine is:
568 %
569 %      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
570 %        exception)
571 %
572 %  A description of each parameter follows:
573 %
574 %    o info: a structure of type info.
575 %
576 %    o exception: Return any errors or warnings in this structure.
577 %
578 */
579 static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
580   ExceptionInfo *exception)
581 {
582   struct PackageInfo
583     *clone_info;
584
585   clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
586   if (clone_info == (struct PackageInfo *) NULL)
587     {
588       ThrowPerlException(exception,ResourceLimitError,
589         "UnableToClonePackageInfo",PackageName);
590       return((struct PackageInfo *) NULL);
591     }
592   if (info == (struct PackageInfo *) NULL)
593     {
594       clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
595       return(clone_info);
596     }
597   *clone_info=(*info);
598   clone_info->image_info=CloneImageInfo(info->image_info);
599   return(clone_info);
600 }
601 \f
602 /*
603 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
604 %                                                                             %
605 %                                                                             %
606 %                                                                             %
607 %   c o n s t a n t                                                           %
608 %                                                                             %
609 %                                                                             %
610 %                                                                             %
611 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
612 %
613 %  constant() returns a double value for the specified name.
614 %
615 %  The format of the constant routine is:
616 %
617 %      double constant(char *name,ssize_t sans)
618 %
619 %  A description of each parameter follows:
620 %
621 %    o value: Method constant returns a double value for the specified name.
622 %
623 %    o name: The name of the constant.
624 %
625 %    o sans: This integer value is not used.
626 %
627 */
628 static double constant(char *name,ssize_t sans)
629 {
630   (void) sans;
631   errno=0;
632   switch (*name)
633   {
634     case 'B':
635     {
636       if (strEQ(name,"BlobError"))
637         return(BlobError);
638       if (strEQ(name,"BlobWarning"))
639         return(BlobWarning);
640       break;
641     }
642     case 'C':
643     {
644       if (strEQ(name,"CacheError"))
645         return(CacheError);
646       if (strEQ(name,"CacheWarning"))
647         return(CacheWarning);
648       if (strEQ(name,"CoderError"))
649         return(CoderError);
650       if (strEQ(name,"CoderWarning"))
651         return(CoderWarning);
652       if (strEQ(name,"ConfigureError"))
653         return(ConfigureError);
654       if (strEQ(name,"ConfigureWarning"))
655         return(ConfigureWarning);
656       if (strEQ(name,"CorruptImageError"))
657         return(CorruptImageError);
658       if (strEQ(name,"CorruptImageWarning"))
659         return(CorruptImageWarning);
660       break;
661     }
662     case 'D':
663     {
664       if (strEQ(name,"DelegateError"))
665         return(DelegateError);
666       if (strEQ(name,"DelegateWarning"))
667         return(DelegateWarning);
668       if (strEQ(name,"DrawError"))
669         return(DrawError);
670       if (strEQ(name,"DrawWarning"))
671         return(DrawWarning);
672       break;
673     }
674     case 'E':
675     {
676       if (strEQ(name,"ErrorException"))
677         return(ErrorException);
678       if (strEQ(name,"ExceptionError"))
679         return(CoderError);
680       if (strEQ(name,"ExceptionWarning"))
681         return(CoderWarning);
682       break;
683     }
684     case 'F':
685     {
686       if (strEQ(name,"FatalErrorException"))
687         return(FatalErrorException);
688       if (strEQ(name,"FileOpenError"))
689         return(FileOpenError);
690       if (strEQ(name,"FileOpenWarning"))
691         return(FileOpenWarning);
692       break;
693     }
694     case 'I':
695     {
696       if (strEQ(name,"ImageError"))
697         return(ImageError);
698       if (strEQ(name,"ImageWarning"))
699         return(ImageWarning);
700       break;
701     }
702     case 'M':
703     {
704       if (strEQ(name,"MaxRGB"))
705         return(QuantumRange);
706       if (strEQ(name,"MissingDelegateError"))
707         return(MissingDelegateError);
708       if (strEQ(name,"MissingDelegateWarning"))
709         return(MissingDelegateWarning);
710       if (strEQ(name,"ModuleError"))
711         return(ModuleError);
712       if (strEQ(name,"ModuleWarning"))
713         return(ModuleWarning);
714       break;
715     }
716     case 'O':
717     {
718       if (strEQ(name,"Opaque"))
719         return(OpaqueAlpha);
720       if (strEQ(name,"OptionError"))
721         return(OptionError);
722       if (strEQ(name,"OptionWarning"))
723         return(OptionWarning);
724       break;
725     }
726     case 'Q':
727     {
728       if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
729         return(MAGICKCORE_QUANTUM_DEPTH);
730       if (strEQ(name,"QuantumDepth"))
731         return(MAGICKCORE_QUANTUM_DEPTH);
732       if (strEQ(name,"QuantumRange"))
733         return(QuantumRange);
734       break;
735     }
736     case 'R':
737     {
738       if (strEQ(name,"ResourceLimitError"))
739         return(ResourceLimitError);
740       if (strEQ(name,"ResourceLimitWarning"))
741         return(ResourceLimitWarning);
742       if (strEQ(name,"RegistryError"))
743         return(RegistryError);
744       if (strEQ(name,"RegistryWarning"))
745         return(RegistryWarning);
746       break;
747     }
748     case 'S':
749     {
750       if (strEQ(name,"StreamError"))
751         return(StreamError);
752       if (strEQ(name,"StreamWarning"))
753         return(StreamWarning);
754       if (strEQ(name,"Success"))
755         return(0);
756       break;
757     }
758     case 'T':
759     {
760       if (strEQ(name,"Transparent"))
761         return(TransparentAlpha);
762       if (strEQ(name,"TypeError"))
763         return(TypeError);
764       if (strEQ(name,"TypeWarning"))
765         return(TypeWarning);
766       break;
767     }
768     case 'W':
769     {
770       if (strEQ(name,"WarningException"))
771         return(WarningException);
772       break;
773     }
774     case 'X':
775     {
776       if (strEQ(name,"XServerError"))
777         return(XServerError);
778       if (strEQ(name,"XServerWarning"))
779         return(XServerWarning);
780       break;
781     }
782   }
783   errno=EINVAL;
784   return(0);
785 }
786 \f
787 /*
788 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
789 %                                                                             %
790 %                                                                             %
791 %                                                                             %
792 %   D e s t r o y P a c k a g e I n f o                                       %
793 %                                                                             %
794 %                                                                             %
795 %                                                                             %
796 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
797 %
798 %  Method DestroyPackageInfo frees a previously created info structure.
799 %
800 %  The format of the DestroyPackageInfo routine is:
801 %
802 %      DestroyPackageInfo(struct PackageInfo *info)
803 %
804 %  A description of each parameter follows:
805 %
806 %    o info: a structure of type info.
807 %
808 */
809 static void DestroyPackageInfo(struct PackageInfo *info)
810 {
811   info->image_info=DestroyImageInfo(info->image_info);
812   info=(struct PackageInfo *) RelinquishMagickMemory(info);
813 }
814 \f
815 /*
816 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
817 %                                                                             %
818 %                                                                             %
819 %                                                                             %
820 %   G e t L i s t                                                             %
821 %                                                                             %
822 %                                                                             %
823 %                                                                             %
824 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
825 %
826 %  Method GetList is recursively called by SetupList to traverse the
827 %  Image__Magick reference.  If building an reference_vector (see SetupList),
828 %  *current is the current position in *reference_vector and *last is the final
829 %  entry in *reference_vector.
830 %
831 %  The format of the GetList routine is:
832 %
833 %      GetList(info)
834 %
835 %  A description of each parameter follows:
836 %
837 %    o info: a structure of type info.
838 %
839 */
840 static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
841   ssize_t *current,ssize_t *last,ExceptionInfo *exception)
842 {
843   Image
844     *image;
845
846   if (reference == (SV *) NULL)
847     return(NULL);
848   switch (SvTYPE(reference))
849   {
850     case SVt_PVAV:
851     {
852       AV
853         *av;
854
855       Image
856         *head,
857         *previous;
858
859       register ssize_t
860         i;
861
862       ssize_t
863         n;
864
865       /*
866         Array of images.
867       */
868       previous=(Image *) NULL;
869       head=(Image *) NULL;
870       av=(AV *) reference;
871       n=av_len(av);
872       for (i=0; i <= n; i++)
873       {
874         SV
875           **rv;
876
877         rv=av_fetch(av,i,0);
878         if (rv && *rv && sv_isobject(*rv))
879           {
880             image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
881               exception);
882             if (image == (Image *) NULL)
883               continue;
884             if (image == previous)
885               {
886                 image=CloneImage(image,0,0,MagickTrue,exception);
887                 if (image == (Image *) NULL)
888                   return(NULL);
889               }
890             image->previous=previous;
891             *(previous ? &previous->next : &head)=image;
892             for (previous=image; previous->next; previous=previous->next) ;
893           }
894       }
895       return(head);
896     }
897     case SVt_PVMG:
898     {
899       /*
900         Blessed scalar, one image.
901       */
902       image=(Image *) SvIV(reference);
903       if (image == (Image *) NULL)
904         return(NULL);
905       image->previous=(Image *) NULL;
906       image->next=(Image *) NULL;
907       if (reference_vector)
908         {
909           if (*current == *last)
910             {
911               *last+=256;
912               if (*reference_vector == (SV **) NULL)
913                 *reference_vector=(SV **) AcquireQuantumMemory(*last,
914                   sizeof(*reference_vector));
915               else
916                 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
917                   *last,sizeof(*reference_vector));
918             }
919           if (*reference_vector == (SV **) NULL)
920             {
921               ThrowPerlException(exception,ResourceLimitError,
922                 "MemoryAllocationFailed",PackageName);
923               return((Image *) NULL);
924             }
925           (*reference_vector)[*current]=reference;
926           (*reference_vector)[++(*current)]=NULL;
927         }
928       return(image);
929     }
930     default:
931       break;
932   }
933   (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
934     (double) SvTYPE(reference));
935   return((Image *) NULL);
936 }
937 \f
938 /*
939 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
940 %                                                                             %
941 %                                                                             %
942 %                                                                             %
943 %   G e t P a c k a g e I n f o                                               %
944 %                                                                             %
945 %                                                                             %
946 %                                                                             %
947 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
948 %
949 %  Method GetPackageInfo looks up or creates an info structure for the given
950 %  Image__Magick reference.  If it does create a new one, the information in
951 %  package_info is used to initialize it.
952 %
953 %  The format of the GetPackageInfo routine is:
954 %
955 %      struct PackageInfo *GetPackageInfo(void *reference,
956 %        struct PackageInfo *package_info,ExceptionInfo *exception)
957 %
958 %  A description of each parameter follows:
959 %
960 %    o info: a structure of type info.
961 %
962 %    o exception: Return any errors or warnings in this structure.
963 %
964 */
965 static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
966   struct PackageInfo *package_info,ExceptionInfo *exception)
967 {
968   char
969     message[MaxTextExtent];
970
971   struct PackageInfo
972     *clone_info;
973
974   SV
975     *sv;
976
977   (void) FormatLocaleString(message,MaxTextExtent,"%s::package%s%p",
978     PackageName,XS_VERSION,reference);
979   sv=perl_get_sv(message,(TRUE | 0x02));
980   if (sv == (SV *) NULL)
981     {
982       ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
983         message);
984       return(package_info);
985     }
986   if (SvREFCNT(sv) == 0)
987     (void) SvREFCNT_inc(sv);
988   if (SvIOKp(sv) && (clone_info=(struct PackageInfo *) SvIV(sv)))
989     return(clone_info);
990   clone_info=ClonePackageInfo(package_info,exception);
991   sv_setiv(sv,(IV) clone_info);
992   return(clone_info);
993 }
994 \f
995 /*
996 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
997 %                                                                             %
998 %                                                                             %
999 %                                                                             %
1000 %   S e t A t t r i b u t e                                                   %
1001 %                                                                             %
1002 %                                                                             %
1003 %                                                                             %
1004 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1005 %
1006 %  SetAttribute() sets the attribute to the value in sval.  This can change
1007 %  either or both of image or info.
1008 %
1009 %  The format of the SetAttribute routine is:
1010 %
1011 %      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1012 %        SV *sval,ExceptionInfo *exception)
1013 %
1014 %  A description of each parameter follows:
1015 %
1016 %    o list: a list of strings.
1017 %
1018 %    o string: a character string.
1019 %
1020 */
1021
1022 static double SiPrefixToDouble(const char *string,const double interval)
1023 {
1024   char
1025     *q;
1026
1027   double
1028     scale,
1029     value;
1030
1031   value=InterpretLocaleValue(string,&q);
1032   scale=1000.0;
1033   if ((*q != '\0') && (tolower((int) ((unsigned char) *(q+1))) == 'i'))
1034     scale=1024.0;
1035   switch (tolower((int) ((unsigned char) *q)))
1036   {
1037     case '%': value*=pow(scale,0)*interval/100.0; break;
1038     case 'k': value*=pow(scale,1); break;
1039     case 'm': value*=pow(scale,2); break;
1040     case 'g': value*=pow(scale,3); break;
1041     case 't': value*=pow(scale,4); break;
1042     case 'p': value*=pow(scale,5); break;
1043     case 'e': value*=pow(scale,6); break;
1044     case 'z': value*=pow(scale,7); break;
1045     case 'y': value*=pow(scale,8); break;
1046     default:  break;
1047   }
1048   return(value);
1049 }
1050
1051 static inline ssize_t StringToLong(const char *value)
1052 {
1053   return(strtol(value,(char **) NULL,10));
1054 }
1055
1056 static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1057   const char *attribute,SV *sval,ExceptionInfo *exception)
1058 {
1059   GeometryInfo
1060     geometry_info;
1061
1062   long
1063     x,
1064     y;
1065
1066   PixelInfo
1067     pixel;
1068
1069   MagickStatusType
1070     flags;
1071
1072   PixelPacket
1073     *color,
1074     target_color;
1075
1076   ssize_t
1077     sp;
1078
1079   switch (*attribute)
1080   {
1081     case 'A':
1082     case 'a':
1083     {
1084       if (LocaleCompare(attribute,"adjoin") == 0)
1085         {
1086           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1087             SvPV(sval,na)) : SvIV(sval);
1088           if (sp < 0)
1089             {
1090               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1091                 SvPV(sval,na));
1092               break;
1093             }
1094           if (info)
1095             info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1096           break;
1097         }
1098       if (LocaleCompare(attribute,"alpha") == 0)
1099         {
1100           sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaOptions,MagickFalse,
1101             SvPV(sval,na)) : SvIV(sval);
1102           if (sp < 0)
1103             {
1104               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1105                 SvPV(sval,na));
1106               break;
1107             }
1108           for ( ; image; image=image->next)
1109             (void) SetImageAlphaChannel(image,(AlphaChannelType) sp,exception);
1110           break;
1111         }
1112       if (LocaleCompare(attribute,"antialias") == 0)
1113         {
1114           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1115             SvPV(sval,na)) : SvIV(sval);
1116           if (sp < 0)
1117             {
1118               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1119                 SvPV(sval,na));
1120               break;
1121             }
1122           if (info)
1123             info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1124           break;
1125         }
1126       if (LocaleCompare(attribute,"area-limit") == 0)
1127         {
1128           MagickSizeType
1129             limit;
1130
1131           limit=MagickResourceInfinity;
1132           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1133             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1134           (void) SetMagickResourceLimit(AreaResource,limit);
1135           break;
1136         }
1137       if (LocaleCompare(attribute,"attenuate") == 0)
1138         {
1139           if (info)
1140             (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1141           break;
1142         }
1143       if (LocaleCompare(attribute,"authenticate") == 0)
1144         {
1145           if (info)
1146             (void) CloneString(&info->image_info->authenticate,SvPV(sval,na));
1147           break;
1148         }
1149       if (info)
1150         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1151       for ( ; image; image=image->next)
1152         SetImageProperty(image,attribute,SvPV(sval,na));
1153       break;
1154     }
1155     case 'B':
1156     case 'b':
1157     {
1158       if (LocaleCompare(attribute,"background") == 0)
1159         {
1160           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1161           if (info)
1162             info->image_info->background_color=target_color;
1163           for ( ; image; image=image->next)
1164             image->background_color=target_color;
1165           break;
1166         }
1167       if (LocaleCompare(attribute,"bias") == 0)
1168         {
1169           for ( ; image; image=image->next)
1170             image->bias=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1171           break;
1172         }
1173       if (LocaleCompare(attribute,"blue-primary") == 0)
1174         {
1175           for ( ; image; image=image->next)
1176           {
1177             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1178             image->chromaticity.blue_primary.x=geometry_info.rho;
1179             image->chromaticity.blue_primary.y=geometry_info.sigma;
1180             if ((flags & SigmaValue) == 0)
1181               image->chromaticity.blue_primary.y=
1182                 image->chromaticity.blue_primary.x;
1183           }
1184           break;
1185         }
1186       if (LocaleCompare(attribute,"bordercolor") == 0)
1187         {
1188           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1189           if (info)
1190             info->image_info->border_color=target_color;
1191           for ( ; image; image=image->next)
1192             image->border_color=target_color;
1193           break;
1194         }
1195       if (info)
1196         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1197       for ( ; image; image=image->next)
1198         SetImageProperty(image,attribute,SvPV(sval,na));
1199       break;
1200     }
1201     case 'C':
1202     case 'c':
1203     {
1204       if (LocaleCompare(attribute,"cache-threshold") == 0)
1205         {
1206           (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1207             SiPrefixToDouble(SvPV(sval,na),100.0));
1208           (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1209             (2*SiPrefixToDouble(SvPV(sval,na),100.0)));
1210           break;
1211         }
1212       if (LocaleCompare(attribute,"clip-mask") == 0)
1213         {
1214           Image
1215             *clip_mask;
1216
1217           clip_mask=(Image *) NULL;
1218           if (SvPOK(sval))
1219             clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1220           for ( ; image; image=image->next)
1221             SetImageClipMask(image,clip_mask,exception);
1222           break;
1223         }
1224       if (LocaleNCompare(attribute,"colormap",8) == 0)
1225         {
1226           for ( ; image; image=image->next)
1227           {
1228             int
1229               items;
1230
1231             long
1232               i;
1233
1234             if (image->storage_class == DirectClass)
1235               continue;
1236             i=0;
1237             items=sscanf(attribute,"%*[^[][%ld",&i);
1238             (void) items;
1239             if (i > (ssize_t) image->colors)
1240               i%=image->colors;
1241             if ((strchr(SvPV(sval,na),',') == 0) ||
1242                 (strchr(SvPV(sval,na),')') != 0))
1243               QueryColorDatabase(SvPV(sval,na),image->colormap+i,exception);
1244             else
1245               {
1246                 color=image->colormap+i;
1247                 pixel.red=color->red;
1248                 pixel.green=color->green;
1249                 pixel.blue=color->blue;
1250                 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1251                 pixel.red=geometry_info.rho;
1252                 pixel.green=geometry_info.sigma;
1253                 pixel.blue=geometry_info.xi;
1254                 color->red=ClampToQuantum(pixel.red);
1255                 color->green=ClampToQuantum(pixel.green);
1256                 color->blue=ClampToQuantum(pixel.blue);
1257               }
1258           }
1259           break;
1260         }
1261       if (LocaleCompare(attribute,"colorspace") == 0)
1262         {
1263           sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1264             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1265           if (sp < 0)
1266             {
1267               ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1268                 SvPV(sval,na));
1269               break;
1270             }
1271           for ( ; image; image=image->next)
1272             (void) TransformImageColorspace(image,(ColorspaceType) sp);
1273           break;
1274         }
1275       if (LocaleCompare(attribute,"comment") == 0)
1276         {
1277           for ( ; image; image=image->next)
1278             (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1279               info ? info->image_info : (ImageInfo *) NULL,image,
1280               SvPV(sval,na),exception));
1281           break;
1282         }
1283       if (LocaleCompare(attribute,"compression") == 0)
1284         {
1285           sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1286             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1287           if (sp < 0)
1288             {
1289               ThrowPerlException(exception,OptionError,
1290                 "UnrecognizedImageCompression",SvPV(sval,na));
1291               break;
1292             }
1293           if (info)
1294             info->image_info->compression=(CompressionType) sp;
1295           for ( ; image; image=image->next)
1296             image->compression=(CompressionType) sp;
1297           break;
1298         }
1299       if (info)
1300         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1301       for ( ; image; image=image->next)
1302         SetImageProperty(image,attribute,SvPV(sval,na));
1303       break;
1304     }
1305     case 'D':
1306     case 'd':
1307     {
1308       if (LocaleCompare(attribute,"debug") == 0)
1309         {
1310           SetLogEventMask(SvPV(sval,na));
1311           break;
1312         }
1313       if (LocaleCompare(attribute,"delay") == 0)
1314         {
1315           flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1316           for ( ; image; image=image->next)
1317           {
1318             image->delay=(size_t) floor(geometry_info.rho+0.5);
1319             if ((flags & SigmaValue) != 0)
1320               image->ticks_per_second=(ssize_t)
1321                 floor(geometry_info.sigma+0.5);
1322           }
1323           break;
1324         }
1325       if (LocaleCompare(attribute,"disk-limit") == 0)
1326         {
1327           MagickSizeType
1328             limit;
1329
1330           limit=MagickResourceInfinity;
1331           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1332             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1333           (void) SetMagickResourceLimit(DiskResource,limit);
1334           break;
1335         }
1336       if (LocaleCompare(attribute,"density") == 0)
1337         {
1338           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1339             {
1340               ThrowPerlException(exception,OptionError,"MissingGeometry",
1341                 SvPV(sval,na));
1342               break;
1343             }
1344           if (info)
1345             (void) CloneString(&info->image_info->density,SvPV(sval,na));
1346           for ( ; image; image=image->next)
1347           {
1348             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1349             image->x_resolution=geometry_info.rho;
1350             image->y_resolution=geometry_info.sigma;
1351             if ((flags & SigmaValue) == 0)
1352               image->y_resolution=image->x_resolution;
1353           }
1354           break;
1355         }
1356       if (LocaleCompare(attribute,"depth") == 0)
1357         {
1358           if (info)
1359             info->image_info->depth=SvIV(sval);
1360           for ( ; image; image=image->next)
1361             (void) SetImageDepth(image,SvIV(sval));
1362           break;
1363         }
1364       if (LocaleCompare(attribute,"dispose") == 0)
1365         {
1366           sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1367             SvPV(sval,na)) : SvIV(sval);
1368           if (sp < 0)
1369             {
1370               ThrowPerlException(exception,OptionError,
1371                 "UnrecognizedDisposeMethod",SvPV(sval,na));
1372               break;
1373             }
1374           for ( ; image; image=image->next)
1375             image->dispose=(DisposeType) sp;
1376           break;
1377         }
1378       if (LocaleCompare(attribute,"dither") == 0)
1379         {
1380           if (info)
1381             {
1382               sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1383                 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1384               if (sp < 0)
1385                 {
1386                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
1387                     SvPV(sval,na));
1388                   break;
1389                 }
1390               info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1391             }
1392           break;
1393         }
1394       if (LocaleCompare(attribute,"display") == 0)
1395         {
1396           display:
1397           if (info)
1398             (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1399           break;
1400         }
1401       if (info)
1402         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1403       for ( ; image; image=image->next)
1404         SetImageProperty(image,attribute,SvPV(sval,na));
1405       break;
1406     }
1407     case 'E':
1408     case 'e':
1409     {
1410       if (LocaleCompare(attribute,"endian") == 0)
1411         {
1412           sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1413             SvPV(sval,na)) : SvIV(sval);
1414           if (sp < 0)
1415             {
1416               ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1417                 SvPV(sval,na));
1418               break;
1419             }
1420           if (info)
1421             info->image_info->endian=(EndianType) sp;
1422           for ( ; image; image=image->next)
1423             image->endian=(EndianType) sp;
1424           break;
1425         }
1426       if (LocaleCompare(attribute,"extract") == 0)
1427         {
1428           /*
1429             Set image extract geometry.
1430           */
1431           (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1432           break;
1433         }
1434       if (info)
1435         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1436       for ( ; image; image=image->next)
1437         SetImageProperty(image,attribute,SvPV(sval,na));
1438       break;
1439     }
1440     case 'F':
1441     case 'f':
1442     {
1443       if (LocaleCompare(attribute,"filename") == 0)
1444         {
1445           if (info)
1446             (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1447               MaxTextExtent);
1448           for ( ; image; image=image->next)
1449             (void) CopyMagickString(image->filename,SvPV(sval,na),
1450               MaxTextExtent);
1451           break;
1452         }
1453       if (LocaleCompare(attribute,"file") == 0)
1454         {
1455           FILE
1456             *file;
1457
1458           PerlIO
1459             *io_info;
1460
1461           if (info == (struct PackageInfo *) NULL)
1462             break;
1463           io_info=IoIFP(sv_2io(sval));
1464           if (io_info == (PerlIO *) NULL)
1465             {
1466               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1467                 PackageName);
1468               break;
1469             }
1470           file=PerlIO_findFILE(io_info);
1471           if (file == (FILE *) NULL)
1472             {
1473               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1474                 PackageName);
1475               break;
1476             }
1477           SetImageInfoFile(info->image_info,file);
1478           break;
1479         }
1480       if (LocaleCompare(attribute,"fill") == 0)
1481         {
1482           if (info)
1483             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1484           break;
1485         }
1486       if (LocaleCompare(attribute,"font") == 0)
1487         {
1488           if (info)
1489             (void) CloneString(&info->image_info->font,SvPV(sval,na));
1490           break;
1491         }
1492       if (LocaleCompare(attribute,"foreground") == 0)
1493         break;
1494       if (LocaleCompare(attribute,"fuzz") == 0)
1495         {
1496           if (info)
1497             info->image_info->fuzz=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1498           for ( ; image; image=image->next)
1499             image->fuzz=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1500           break;
1501         }
1502       if (info)
1503         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1504       for ( ; image; image=image->next)
1505         SetImageProperty(image,attribute,SvPV(sval,na));
1506       break;
1507     }
1508     case 'G':
1509     case 'g':
1510     {
1511       if (LocaleCompare(attribute,"gamma") == 0)
1512         {
1513           for ( ; image; image=image->next)
1514             image->gamma=SvNV(sval);
1515           break;
1516         }
1517       if (LocaleCompare(attribute,"gravity") == 0)
1518         {
1519           sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1520             SvPV(sval,na)) : SvIV(sval);
1521           if (sp < 0)
1522             {
1523               ThrowPerlException(exception,OptionError,
1524                 "UnrecognizedGravityType",SvPV(sval,na));
1525               break;
1526             }
1527           if (info)
1528             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1529           for ( ; image; image=image->next)
1530             image->gravity=(GravityType) sp;
1531           break;
1532         }
1533       if (LocaleCompare(attribute,"green-primary") == 0)
1534         {
1535           for ( ; image; image=image->next)
1536           {
1537             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1538             image->chromaticity.green_primary.x=geometry_info.rho;
1539             image->chromaticity.green_primary.y=geometry_info.sigma;
1540             if ((flags & SigmaValue) == 0)
1541               image->chromaticity.green_primary.y=
1542                 image->chromaticity.green_primary.x;
1543           }
1544           break;
1545         }
1546       if (info)
1547         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1548       for ( ; image; image=image->next)
1549         SetImageProperty(image,attribute,SvPV(sval,na));
1550       break;
1551     }
1552     case 'I':
1553     case 'i':
1554     {
1555       if (LocaleNCompare(attribute,"index",5) == 0)
1556         {
1557           int
1558             items;
1559
1560           long
1561             index;
1562
1563           register Quantum
1564             *q;
1565
1566           CacheView
1567             *image_view;
1568
1569           for ( ; image; image=image->next)
1570           {
1571             if (image->storage_class != PseudoClass)
1572               continue;
1573             x=0;
1574             y=0;
1575             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1576             (void) items;
1577             image_view=AcquireCacheView(image);
1578             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1579             if (q != (Quantum *) NULL)
1580               {
1581                 items=sscanf(SvPV(sval,na),"%ld",&index);
1582                 if ((index >= 0) && (index < (ssize_t) image->colors))
1583                   SetPixelIndex(image,index,q);
1584                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1585               }
1586             image_view=DestroyCacheView(image_view);
1587           }
1588           break;
1589         }
1590       if (LocaleCompare(attribute,"iterations") == 0)
1591         {
1592   iterations:
1593           for ( ; image; image=image->next)
1594             image->iterations=SvIV(sval);
1595           break;
1596         }
1597       if (LocaleCompare(attribute,"interlace") == 0)
1598         {
1599           sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1600             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1601           if (sp < 0)
1602             {
1603               ThrowPerlException(exception,OptionError,
1604                 "UnrecognizedInterlaceType",SvPV(sval,na));
1605               break;
1606             }
1607           if (info)
1608             info->image_info->interlace=(InterlaceType) sp;
1609           for ( ; image; image=image->next)
1610             image->interlace=(InterlaceType) sp;
1611           break;
1612         }
1613       if (info)
1614         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1615       for ( ; image; image=image->next)
1616         SetImageProperty(image,attribute,SvPV(sval,na));
1617       break;
1618     }
1619     case 'L':
1620     case 'l':
1621     {
1622       if (LocaleCompare(attribute,"label") == 0)
1623         {
1624           for ( ; image; image=image->next)
1625             (void) SetImageProperty(image,"label",InterpretImageProperties(
1626               info ? info->image_info : (ImageInfo *) NULL,image,
1627               SvPV(sval,na),exception));
1628           break;
1629         }
1630       if (LocaleCompare(attribute,"loop") == 0)
1631         goto iterations;
1632       if (info)
1633         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1634       for ( ; image; image=image->next)
1635         SetImageProperty(image,attribute,SvPV(sval,na));
1636       break;
1637     }
1638     case 'M':
1639     case 'm':
1640     {
1641       if (LocaleCompare(attribute,"magick") == 0)
1642         {
1643           if (info)
1644             (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
1645               "%s:",SvPV(sval,na));
1646           for ( ; image; image=image->next)
1647             (void) CopyMagickString(image->magick,SvPV(sval,na),MaxTextExtent);
1648           break;
1649         }
1650       if (LocaleCompare(attribute,"map-limit") == 0)
1651         {
1652           MagickSizeType
1653             limit;
1654
1655           limit=MagickResourceInfinity;
1656           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1657             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1658           (void) SetMagickResourceLimit(MapResource,limit);
1659           break;
1660         }
1661       if (LocaleCompare(attribute,"mask") == 0)
1662         {
1663           Image
1664             *mask;
1665
1666           mask=(Image *) NULL;
1667           if (SvPOK(sval))
1668             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1669           for ( ; image; image=image->next)
1670             SetImageMask(image,mask,exception);
1671           break;
1672         }
1673       if (LocaleCompare(attribute,"mattecolor") == 0)
1674         {
1675           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1676           if (info)
1677             info->image_info->matte_color=target_color;
1678           for ( ; image; image=image->next)
1679             image->matte_color=target_color;
1680           break;
1681         }
1682       if (LocaleCompare(attribute,"matte") == 0)
1683         {
1684           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1685             SvPV(sval,na)) : SvIV(sval);
1686           if (sp < 0)
1687             {
1688               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1689                 SvPV(sval,na));
1690               break;
1691             }
1692           for ( ; image; image=image->next)
1693             image->matte=sp != 0 ? MagickTrue : MagickFalse;
1694           break;
1695         }
1696       if (LocaleCompare(attribute,"memory-limit") == 0)
1697         {
1698           MagickSizeType
1699             limit;
1700
1701           limit=MagickResourceInfinity;
1702           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1703             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1704           (void) SetMagickResourceLimit(MemoryResource,limit);
1705           break;
1706         }
1707       if (LocaleCompare(attribute,"monochrome") == 0)
1708         {
1709           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1710             SvPV(sval,na)) : SvIV(sval);
1711           if (sp < 0)
1712             {
1713               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1714                 SvPV(sval,na));
1715               break;
1716             }
1717           if (info)
1718             info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1719           for ( ; image; image=image->next)
1720             (void) SetImageType(image,BilevelType,exception);
1721           break;
1722         }
1723       if (info)
1724         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1725       for ( ; image; image=image->next)
1726         SetImageProperty(image,attribute,SvPV(sval,na));
1727       break;
1728     }
1729     case 'O':
1730     case 'o':
1731     {
1732       if (LocaleCompare(attribute,"option") == 0)
1733         {
1734           if (info)
1735             DefineImageOption(info->image_info,SvPV(sval,na));
1736           break;
1737         }
1738       if (LocaleCompare(attribute,"orientation") == 0)
1739         {
1740           sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1741             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1742           if (sp < 0)
1743             {
1744               ThrowPerlException(exception,OptionError,
1745                 "UnrecognizedOrientationType",SvPV(sval,na));
1746               break;
1747             }
1748           if (info)
1749             info->image_info->orientation=(OrientationType) sp;
1750           for ( ; image; image=image->next)
1751             image->orientation=(OrientationType) sp;
1752           break;
1753         }
1754       if (info)
1755         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1756       for ( ; image; image=image->next)
1757         SetImageProperty(image,attribute,SvPV(sval,na));
1758       break;
1759     }
1760     case 'P':
1761     case 'p':
1762     {
1763       if (LocaleCompare(attribute,"page") == 0)
1764         {
1765           char
1766             *geometry;
1767
1768           geometry=GetPageGeometry(SvPV(sval,na));
1769           if (info)
1770             (void) CloneString(&info->image_info->page,geometry);
1771           for ( ; image; image=image->next)
1772             (void) ParsePageGeometry(image,geometry,&image->page,exception);
1773           geometry=(char *) RelinquishMagickMemory(geometry);
1774           break;
1775         }
1776       if (LocaleCompare(attribute,"pen") == 0)
1777         {
1778           if (info)
1779             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1780           break;
1781         }
1782       if (LocaleNCompare(attribute,"pixel",5) == 0)
1783         {
1784           int
1785             items;
1786
1787           PixelInfo
1788             pixel;
1789
1790           register Quantum
1791             *q;
1792
1793           CacheView
1794             *image_view;
1795
1796           for ( ; image; image=image->next)
1797           {
1798             if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1799               break;
1800             x=0;
1801             y=0;
1802             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1803             (void) items;
1804             image_view=AcquireCacheView(image);
1805             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1806             if (q != (Quantum *) NULL)
1807               {
1808                 if ((strchr(SvPV(sval,na),',') == 0) ||
1809                     (strchr(SvPV(sval,na),')') != 0))
1810                   QueryMagickColor(SvPV(sval,na),&pixel,exception);
1811                 else
1812                   {
1813                     GetPixelInfo(image,&pixel);
1814                     flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1815                     pixel.red=geometry_info.rho;
1816                     if ((flags & SigmaValue) != 0)
1817                       pixel.green=geometry_info.sigma;
1818                     if ((flags & XiValue) != 0)
1819                       pixel.blue=geometry_info.xi;
1820                     if ((flags & PsiValue) != 0)
1821                       pixel.alpha=geometry_info.psi;
1822                     if ((flags & ChiValue) != 0)
1823                       pixel.black=geometry_info.chi;
1824                   }
1825                 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1826                 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1827                 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1828                 if (image->colorspace == CMYKColorspace)
1829                   SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1830                 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1831                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1832               }
1833             image_view=DestroyCacheView(image_view);
1834           }
1835           break;
1836         }
1837       if (LocaleCompare(attribute,"pointsize") == 0)
1838         {
1839           if (info)
1840             {
1841               (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1842               info->image_info->pointsize=geometry_info.rho;
1843             }
1844           break;
1845         }
1846       if (LocaleCompare(attribute,"preview") == 0)
1847         {
1848           sp=SvPOK(sval) ? ParseCommandOption(MagickPreviewOptions,MagickFalse,
1849             SvPV(sval,na)) : SvIV(sval);
1850           if (sp < 0)
1851             {
1852               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1853                 SvPV(sval,na));
1854               break;
1855             }
1856           if (info)
1857             info->image_info->preview_type=(PreviewType) sp;
1858           break;
1859         }
1860       if (info)
1861         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1862       for ( ; image; image=image->next)
1863         SetImageProperty(image,attribute,SvPV(sval,na));
1864       break;
1865     }
1866     case 'Q':
1867     case 'q':
1868     {
1869       if (LocaleCompare(attribute,"quality") == 0)
1870         {
1871           if (info)
1872             info->image_info->quality=SvIV(sval);
1873           for ( ; image; image=image->next)
1874             image->quality=SvIV(sval);
1875           break;
1876         }
1877       if (info)
1878         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1879       for ( ; image; image=image->next)
1880         SetImageProperty(image,attribute,SvPV(sval,na));
1881       break;
1882     }
1883     case 'R':
1884     case 'r':
1885     {
1886       if (LocaleCompare(attribute,"red-primary") == 0)
1887         {
1888           for ( ; image; image=image->next)
1889           {
1890             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1891             image->chromaticity.red_primary.x=geometry_info.rho;
1892             image->chromaticity.red_primary.y=geometry_info.sigma;
1893             if ((flags & SigmaValue) == 0)
1894               image->chromaticity.red_primary.y=
1895                 image->chromaticity.red_primary.x;
1896           }
1897           break;
1898         }
1899       if (LocaleCompare(attribute,"render") == 0)
1900         {
1901           sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1902             SvPV(sval,na)) : SvIV(sval);
1903           if (sp < 0)
1904             {
1905               ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1906                 SvPV(sval,na));
1907               break;
1908             }
1909          for ( ; image; image=image->next)
1910            image->rendering_intent=(RenderingIntent) sp;
1911          break;
1912        }
1913       if (LocaleCompare(attribute,"repage") == 0)
1914         {
1915           RectangleInfo
1916             geometry;
1917
1918           for ( ; image; image=image->next)
1919           {
1920             flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
1921             if ((flags & WidthValue) != 0)
1922               {
1923                 if ((flags & HeightValue) == 0)
1924                   geometry.height=geometry.width;
1925                 image->page.width=geometry.width;
1926                 image->page.height=geometry.height;
1927               }
1928             if ((flags & AspectValue) != 0)
1929               {
1930                 if ((flags & XValue) != 0)
1931                   image->page.x+=geometry.x;
1932                 if ((flags & YValue) != 0)
1933                   image->page.y+=geometry.y;
1934               }
1935             else
1936               {
1937                 if ((flags & XValue) != 0)
1938                   {
1939                     image->page.x=geometry.x;
1940                     if (((flags & WidthValue) != 0) && (geometry.x > 0))
1941                       image->page.width=image->columns+geometry.x;
1942                   }
1943                 if ((flags & YValue) != 0)
1944                   {
1945                     image->page.y=geometry.y;
1946                     if (((flags & HeightValue) != 0) && (geometry.y > 0))
1947                       image->page.height=image->rows+geometry.y;
1948                   }
1949               }
1950           }
1951           break;
1952         }
1953       if (info)
1954         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1955       for ( ; image; image=image->next)
1956         SetImageProperty(image,attribute,SvPV(sval,na));
1957       break;
1958     }
1959     case 'S':
1960     case 's':
1961     {
1962       if (LocaleCompare(attribute,"sampling-factor") == 0)
1963         {
1964           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1965             {
1966               ThrowPerlException(exception,OptionError,"MissingGeometry",
1967                 SvPV(sval,na));
1968               break;
1969             }
1970           if (info)
1971             (void) CloneString(&info->image_info->sampling_factor,
1972               SvPV(sval,na));
1973           break;
1974         }
1975       if (LocaleCompare(attribute,"scene") == 0)
1976         {
1977           for ( ; image; image=image->next)
1978             image->scene=SvIV(sval);
1979           break;
1980         }
1981       if (LocaleCompare(attribute,"server") == 0)
1982         goto display;
1983       if (LocaleCompare(attribute,"size") == 0)
1984         {
1985           if (info)
1986             {
1987               if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1988                 {
1989                   ThrowPerlException(exception,OptionError,"MissingGeometry",
1990                     SvPV(sval,na));
1991                   break;
1992                 }
1993               (void) CloneString(&info->image_info->size,SvPV(sval,na));
1994             }
1995           break;
1996         }
1997       if (LocaleCompare(attribute,"stroke") == 0)
1998         {
1999           if (info)
2000             (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2001           break;
2002         }
2003       if (info)
2004         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2005       for ( ; image; image=image->next)
2006         SetImageProperty(image,attribute,SvPV(sval,na));
2007       break;
2008     }
2009     case 'T':
2010     case 't':
2011     {
2012       if (LocaleCompare(attribute,"texture") == 0)
2013         {
2014           if (info)
2015             (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2016           break;
2017         }
2018       if (LocaleCompare(attribute,"thread-limit") == 0)
2019         {
2020           MagickSizeType
2021             limit;
2022
2023           limit=MagickResourceInfinity;
2024           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2025             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
2026           (void) SetMagickResourceLimit(ThreadResource,limit);
2027           break;
2028         }
2029       if (LocaleCompare(attribute,"tile-offset") == 0)
2030         {
2031           char
2032             *geometry;
2033
2034           geometry=GetPageGeometry(SvPV(sval,na));
2035           if (info)
2036             (void) CloneString(&info->image_info->page,geometry);
2037           for ( ; image; image=image->next)
2038             (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2039               exception);
2040           geometry=(char *) RelinquishMagickMemory(geometry);
2041           break;
2042         }
2043       if (LocaleCompare(attribute,"time-limit") == 0)
2044         {
2045           MagickSizeType
2046             limit;
2047
2048           limit=MagickResourceInfinity;
2049           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2050             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
2051           (void) SetMagickResourceLimit(TimeResource,limit);
2052           break;
2053         }
2054       if (LocaleCompare(attribute,"transparent-color") == 0)
2055         {
2056           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
2057           if (info)
2058             info->image_info->transparent_color=target_color;
2059           for ( ; image; image=image->next)
2060             image->transparent_color=target_color;
2061           break;
2062         }
2063       if (LocaleCompare(attribute,"type") == 0)
2064         {
2065           sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2066             SvPV(sval,na)) : SvIV(sval);
2067           if (sp < 0)
2068             {
2069               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2070                 SvPV(sval,na));
2071               break;
2072             }
2073           if (info)
2074             info->image_info->type=(ImageType) sp;
2075           for ( ; image; image=image->next)
2076             SetImageType(image,(ImageType) sp,exception);
2077           break;
2078         }
2079       if (info)
2080         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2081       for ( ; image; image=image->next)
2082         SetImageProperty(image,attribute,SvPV(sval,na));
2083       break;
2084     }
2085     case 'U':
2086     case 'u':
2087     {
2088       if (LocaleCompare(attribute,"units") == 0)
2089         {
2090           sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2091             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2092           if (sp < 0)
2093             {
2094               ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2095                 SvPV(sval,na));
2096               break;
2097             }
2098           if (info)
2099             info->image_info->units=(ResolutionType) sp;
2100           for ( ; image; image=image->next)
2101           {
2102             ResolutionType
2103               units;
2104
2105             units=(ResolutionType) sp;
2106             if (image->units != units)
2107               switch (image->units)
2108               {
2109                 case UndefinedResolution:
2110                 case PixelsPerInchResolution:
2111                 {
2112                   if (units == PixelsPerCentimeterResolution)
2113                     {
2114                       image->x_resolution*=2.54;
2115                       image->y_resolution*=2.54;
2116                     }
2117                   break;
2118                 }
2119                 case PixelsPerCentimeterResolution:
2120                 {
2121                   if (units == PixelsPerInchResolution)
2122                     {
2123                       image->x_resolution/=2.54;
2124                       image->y_resolution/=2.54;
2125                     }
2126                   break;
2127                 }
2128               }
2129             image->units=units;
2130           }
2131           break;
2132         }
2133       if (info)
2134         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2135       for ( ; image; image=image->next)
2136         SetImageProperty(image,attribute,SvPV(sval,na));
2137       break;
2138     }
2139     case 'V':
2140     case 'v':
2141     {
2142       if (LocaleCompare(attribute,"verbose") == 0)
2143         {
2144           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2145             SvPV(sval,na)) : SvIV(sval);
2146           if (sp < 0)
2147             {
2148               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2149                 SvPV(sval,na));
2150               break;
2151             }
2152           if (info)
2153             info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2154           break;
2155         }
2156       if (LocaleCompare(attribute,"view") == 0)
2157         {
2158           if (info)
2159             (void) CloneString(&info->image_info->view,SvPV(sval,na));
2160           break;
2161         }
2162       if (LocaleCompare(attribute,"virtual-pixel") == 0)
2163         {
2164           sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2165             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2166           if (sp < 0)
2167             {
2168               ThrowPerlException(exception,OptionError,
2169                 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2170               break;
2171             }
2172           if (info)
2173             info->image_info->virtual_pixel_method=(VirtualPixelMethod) sp;
2174           for ( ; image; image=image->next)
2175             SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp);
2176           break;
2177         }
2178       if (info)
2179         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2180       for ( ; image; image=image->next)
2181         SetImageProperty(image,attribute,SvPV(sval,na));
2182       break;
2183     }
2184     case 'W':
2185     case 'w':
2186     {
2187       if (LocaleCompare(attribute,"white-point") == 0)
2188         {
2189           for ( ; image; image=image->next)
2190           {
2191             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2192             image->chromaticity.white_point.x=geometry_info.rho;
2193             image->chromaticity.white_point.y=geometry_info.sigma;
2194             if ((flags & SigmaValue) == 0)
2195               image->chromaticity.white_point.y=
2196                 image->chromaticity.white_point.x;
2197           }
2198           break;
2199         }
2200       if (info)
2201         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2202       for ( ; image; image=image->next)
2203         SetImageProperty(image,attribute,SvPV(sval,na));
2204       break;
2205     }
2206     default:
2207     {
2208       if (info)
2209         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2210       for ( ; image; image=image->next)
2211         SetImageProperty(image,attribute,SvPV(sval,na));
2212       break;
2213     }
2214   }
2215 }
2216 \f
2217 /*
2218 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2219 %                                                                             %
2220 %                                                                             %
2221 %                                                                             %
2222 %   S e t u p L i s t                                                         %
2223 %                                                                             %
2224 %                                                                             %
2225 %                                                                             %
2226 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2227 %
2228 %  Method SetupList returns the list of all the images linked by their
2229 %  image->next and image->previous link lists for use with ImageMagick.  If
2230 %  info is non-NULL, an info structure is returned in *info.  If
2231 %  reference_vector is non-NULL,an array of SV* are returned in
2232 %  *reference_vector.  Reference_vector is used when the images are going to be
2233 %  replaced with new Image*'s.
2234 %
2235 %  The format of the SetupList routine is:
2236 %
2237 %      Image *SetupList(SV *reference,struct PackageInfo **info,
2238 %        SV ***reference_vector,ExceptionInfo *exception)
2239 %
2240 %  A description of each parameter follows:
2241 %
2242 %    o list: a list of strings.
2243 %
2244 %    o string: a character string.
2245 %
2246 %    o exception: Return any errors or warnings in this structure.
2247 %
2248 */
2249 static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2250   SV ***reference_vector,ExceptionInfo *exception)
2251 {
2252   Image
2253     *image;
2254
2255   ssize_t
2256     current,
2257     last;
2258
2259   if (reference_vector)
2260     *reference_vector=NULL;
2261   if (info)
2262     *info=NULL;
2263   current=0;
2264   last=0;
2265   image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2266   if (info && (SvTYPE(reference) == SVt_PVAV))
2267     *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2268       exception);
2269   return(image);
2270 }
2271 \f
2272 /*
2273 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2274 %                                                                             %
2275 %                                                                             %
2276 %                                                                             %
2277 %   s t r E Q c a s e                                                         %
2278 %                                                                             %
2279 %                                                                             %
2280 %                                                                             %
2281 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2282 %
2283 %  strEQcase() compares two strings and returns 0 if they are the
2284 %  same or if the second string runs out first.  The comparison is case
2285 %  insensitive.
2286 %
2287 %  The format of the strEQcase routine is:
2288 %
2289 %      ssize_t strEQcase(const char *p,const char *q)
2290 %
2291 %  A description of each parameter follows:
2292 %
2293 %    o p: a character string.
2294 %
2295 %    o q: a character string.
2296 %
2297 %
2298 */
2299 static ssize_t strEQcase(const char *p,const char *q)
2300 {
2301   char
2302     c;
2303
2304   register ssize_t
2305     i;
2306
2307   for (i=0 ; (c=(*q)) != 0; i++)
2308   {
2309     if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2310         (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2311       return(0);
2312     p++;
2313     q++;
2314   }
2315   return(((*q == 0) && (*p == 0)) ? i : 0);
2316 }
2317 \f
2318 /*
2319 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2320 %                                                                             %
2321 %                                                                             %
2322 %                                                                             %
2323 %   I m a g e : : M a g i c k                                                 %
2324 %                                                                             %
2325 %                                                                             %
2326 %                                                                             %
2327 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2328 %
2329 %
2330 */
2331 MODULE = Image::Magick PACKAGE = Image::Magick
2332
2333 PROTOTYPES: ENABLE
2334
2335 BOOT:
2336   MagickCoreGenesis("PerlMagick",MagickFalse);
2337   SetWarningHandler(NULL);
2338   SetErrorHandler(NULL);
2339   magick_registry=NewSplayTree((int (*)(const void *,const void *))
2340     NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2341
2342 void
2343 UNLOAD()
2344   PPCODE:
2345   {
2346     if (magick_registry != (SplayTreeInfo *) NULL)
2347       magick_registry=DestroySplayTree(magick_registry);
2348     MagickCoreTerminus();
2349   }
2350
2351 double
2352 constant(name,argument)
2353   char *name
2354   ssize_t argument
2355 \f
2356 #
2357 ###############################################################################
2358 #                                                                             #
2359 #                                                                             #
2360 #                                                                             #
2361 #   A n i m a t e                                                             #
2362 #                                                                             #
2363 #                                                                             #
2364 #                                                                             #
2365 ###############################################################################
2366 #
2367 #
2368 void
2369 Animate(ref,...)
2370   Image::Magick ref=NO_INIT
2371   ALIAS:
2372     AnimateImage  = 1
2373     animate       = 2
2374     animateimage  = 3
2375   PPCODE:
2376   {
2377     ExceptionInfo
2378       *exception;
2379
2380     Image
2381       *image;
2382
2383     register ssize_t
2384       i;
2385
2386     struct PackageInfo
2387       *info,
2388       *package_info;
2389
2390     SV
2391       *perl_exception,
2392       *reference;
2393
2394     PERL_UNUSED_VAR(ref);
2395     PERL_UNUSED_VAR(ix);
2396     exception=AcquireExceptionInfo();
2397     perl_exception=newSVpv("",0);
2398     package_info=(struct PackageInfo *) NULL;
2399     if (sv_isobject(ST(0)) == 0)
2400       {
2401         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2402           PackageName);
2403         goto PerlException;
2404       }
2405     reference=SvRV(ST(0));
2406     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2407     if (image == (Image *) NULL)
2408       {
2409         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2410           PackageName);
2411         goto PerlException;
2412       }
2413     package_info=ClonePackageInfo(info,exception);
2414     if (items == 2)
2415       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2416     else
2417       if (items > 2)
2418         for (i=2; i < items; i+=2)
2419           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2420             exception);
2421     (void) AnimateImages(package_info->image_info,image,exception);
2422     (void) CatchImageException(image);
2423
2424   PerlException:
2425     if (package_info != (struct PackageInfo *) NULL)
2426       DestroyPackageInfo(package_info);
2427     InheritPerlException(exception,perl_exception);
2428     exception=DestroyExceptionInfo(exception);
2429     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2430     SvPOK_on(perl_exception);
2431     ST(0)=sv_2mortal(perl_exception);
2432     XSRETURN(1);
2433   }
2434 \f
2435 #
2436 ###############################################################################
2437 #                                                                             #
2438 #                                                                             #
2439 #                                                                             #
2440 #   A p p e n d                                                               #
2441 #                                                                             #
2442 #                                                                             #
2443 #                                                                             #
2444 ###############################################################################
2445 #
2446 #
2447 void
2448 Append(ref,...)
2449   Image::Magick ref=NO_INIT
2450   ALIAS:
2451     AppendImage  = 1
2452     append       = 2
2453     appendimage  = 3
2454   PPCODE:
2455   {
2456     AV
2457       *av;
2458
2459     char
2460       *attribute;
2461
2462     ExceptionInfo
2463       *exception;
2464
2465     HV
2466       *hv;
2467
2468     Image
2469       *image;
2470
2471     register ssize_t
2472       i;
2473
2474     ssize_t
2475       stack;
2476
2477     struct PackageInfo
2478       *info;
2479
2480     SV
2481       *av_reference,
2482       *perl_exception,
2483       *reference,
2484       *rv,
2485       *sv;
2486
2487     PERL_UNUSED_VAR(ref);
2488     PERL_UNUSED_VAR(ix);
2489     exception=AcquireExceptionInfo();
2490     perl_exception=newSVpv("",0);
2491     sv=NULL;
2492     attribute=NULL;
2493     av=NULL;
2494     if (sv_isobject(ST(0)) == 0)
2495       {
2496         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2497           PackageName);
2498         goto PerlException;
2499       }
2500     reference=SvRV(ST(0));
2501     hv=SvSTASH(reference);
2502     av=newAV();
2503     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2504     SvREFCNT_dec(av);
2505     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2506     if (image == (Image *) NULL)
2507       {
2508         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2509           PackageName);
2510         goto PerlException;
2511       }
2512     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2513     /*
2514       Get options.
2515     */
2516     stack=MagickTrue;
2517     for (i=2; i < items; i+=2)
2518     {
2519       attribute=(char *) SvPV(ST(i-1),na);
2520       switch (*attribute)
2521       {
2522         case 'S':
2523         case 's':
2524         {
2525           if (LocaleCompare(attribute,"stack") == 0)
2526             {
2527               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2528                 SvPV(ST(i),na));
2529               if (stack < 0)
2530                 {
2531                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
2532                     SvPV(ST(i),na));
2533                   return;
2534                 }
2535               break;
2536             }
2537           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2538             attribute);
2539           break;
2540         }
2541         default:
2542         {
2543           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2544             attribute);
2545           break;
2546         }
2547       }
2548     }
2549     image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2550     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2551       goto PerlException;
2552     for ( ; image; image=image->next)
2553     {
2554       AddImageToRegistry(sv,image);
2555       rv=newRV(sv);
2556       av_push(av,sv_bless(rv,hv));
2557       SvREFCNT_dec(sv);
2558     }
2559     exception=DestroyExceptionInfo(exception);
2560     ST(0)=av_reference;
2561     SvREFCNT_dec(perl_exception);
2562     XSRETURN(1);
2563
2564   PerlException:
2565     InheritPerlException(exception,perl_exception);
2566     exception=DestroyExceptionInfo(exception);
2567     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2568     SvPOK_on(perl_exception);
2569     ST(0)=sv_2mortal(perl_exception);
2570     XSRETURN(1);
2571   }
2572 \f
2573 #
2574 ###############################################################################
2575 #                                                                             #
2576 #                                                                             #
2577 #                                                                             #
2578 #   A v e r a g e                                                             #
2579 #                                                                             #
2580 #                                                                             #
2581 #                                                                             #
2582 ###############################################################################
2583 #
2584 #
2585 void
2586 Average(ref)
2587   Image::Magick ref=NO_INIT
2588   ALIAS:
2589     AverageImage   = 1
2590     average        = 2
2591     averageimage   = 3
2592   PPCODE:
2593   {
2594     AV
2595       *av;
2596
2597     char
2598       *p;
2599
2600     ExceptionInfo
2601       *exception;
2602
2603     HV
2604       *hv;
2605
2606     Image
2607       *image;
2608
2609     struct PackageInfo
2610       *info;
2611
2612     SV
2613       *perl_exception,
2614       *reference,
2615       *rv,
2616       *sv;
2617
2618     PERL_UNUSED_VAR(ref);
2619     PERL_UNUSED_VAR(ix);
2620     exception=AcquireExceptionInfo();
2621     perl_exception=newSVpv("",0);
2622     sv=NULL;
2623     if (sv_isobject(ST(0)) == 0)
2624       {
2625         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2626           PackageName);
2627         goto PerlException;
2628       }
2629     reference=SvRV(ST(0));
2630     hv=SvSTASH(reference);
2631     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2632     if (image == (Image *) NULL)
2633       {
2634         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2635           PackageName);
2636         goto PerlException;
2637       }
2638     image=EvaluateImages(image,MeanEvaluateOperator,exception);
2639     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2640       goto PerlException;
2641     /*
2642       Create blessed Perl array for the returned image.
2643     */
2644     av=newAV();
2645     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2646     SvREFCNT_dec(av);
2647     AddImageToRegistry(sv,image);
2648     rv=newRV(sv);
2649     av_push(av,sv_bless(rv,hv));
2650     SvREFCNT_dec(sv);
2651     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2652     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
2653       "average-%.*s",(int) (MaxTextExtent-9),
2654       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2655     (void) CopyMagickString(image->filename,info->image_info->filename,
2656       MaxTextExtent);
2657     SetImageInfo(info->image_info,0,exception);
2658     exception=DestroyExceptionInfo(exception);
2659     SvREFCNT_dec(perl_exception);
2660     XSRETURN(1);
2661
2662   PerlException:
2663     InheritPerlException(exception,perl_exception);
2664     exception=DestroyExceptionInfo(exception);
2665     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2666     SvPOK_on(perl_exception);
2667     ST(0)=sv_2mortal(perl_exception);
2668     XSRETURN(1);
2669   }
2670 \f
2671 #
2672 ###############################################################################
2673 #                                                                             #
2674 #                                                                             #
2675 #                                                                             #
2676 #   B l o b T o I m a g e                                                     #
2677 #                                                                             #
2678 #                                                                             #
2679 #                                                                             #
2680 ###############################################################################
2681 #
2682 #
2683 void
2684 BlobToImage(ref,...)
2685   Image::Magick ref=NO_INIT
2686   ALIAS:
2687     BlobToImage  = 1
2688     blobtoimage  = 2
2689     blobto       = 3
2690   PPCODE:
2691   {
2692     AV
2693       *av;
2694
2695     char
2696       **keep,
2697       **list;
2698
2699     ExceptionInfo
2700       *exception;
2701
2702     HV
2703       *hv;
2704
2705     Image
2706       *image;
2707
2708     register char
2709       **p;
2710
2711     register ssize_t
2712       i;
2713
2714     ssize_t
2715       ac,
2716       n,
2717       number_images;
2718
2719     STRLEN
2720       *length;
2721
2722     struct PackageInfo
2723       *info;
2724
2725     SV
2726       *perl_exception,
2727       *reference,
2728       *rv,
2729       *sv;
2730
2731     PERL_UNUSED_VAR(ref);
2732     PERL_UNUSED_VAR(ix);
2733     exception=AcquireExceptionInfo();
2734     perl_exception=newSVpv("",0);
2735     sv=NULL;
2736     number_images=0;
2737     ac=(items < 2) ? 1 : items-1;
2738     length=(STRLEN *) NULL;
2739     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2740     if (list == (char **) NULL)
2741       {
2742         ThrowPerlException(exception,ResourceLimitError,
2743           "MemoryAllocationFailed",PackageName);
2744         goto PerlException;
2745       }
2746     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2747     if (length == (STRLEN *) NULL)
2748       {
2749         ThrowPerlException(exception,ResourceLimitError,
2750           "MemoryAllocationFailed",PackageName);
2751         goto PerlException;
2752       }
2753     if (sv_isobject(ST(0)) == 0)
2754       {
2755         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2756           PackageName);
2757         goto PerlException;
2758       }
2759     reference=SvRV(ST(0));
2760     hv=SvSTASH(reference);
2761     if (SvTYPE(reference) != SVt_PVAV)
2762       {
2763         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2764           PackageName);
2765         goto PerlException;
2766       }
2767     av=(AV *) reference;
2768     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2769       exception);
2770     n=1;
2771     if (items <= 1)
2772       {
2773         ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2774         goto PerlException;
2775       }
2776     for (n=0, i=0; i < ac; i++)
2777     {
2778       list[n]=(char *) (SvPV(ST(i+1),length[n]));
2779       if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2780         {
2781           list[n]=(char *) (SvPV(ST(i+2),length[n]));
2782           continue;
2783         }
2784       n++;
2785     }
2786     list[n]=(char *) NULL;
2787     keep=list;
2788     for (i=number_images=0; i < n; i++)
2789     {
2790       image=BlobToImage(info->image_info,list[i],length[i],exception);
2791       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2792         break;
2793       for ( ; image; image=image->next)
2794       {
2795         AddImageToRegistry(sv,image);
2796         rv=newRV(sv);
2797         av_push(av,sv_bless(rv,hv));
2798         SvREFCNT_dec(sv);
2799         number_images++;
2800       }
2801     }
2802     /*
2803       Free resources.
2804     */
2805     for (i=0; i < n; i++)
2806       if (list[i] != (char *) NULL)
2807         for (p=keep; list[i] != *p++; )
2808           if (*p == (char *) NULL)
2809             {
2810               list[i]=(char *) RelinquishMagickMemory(list[i]);
2811               break;
2812             }
2813
2814   PerlException:
2815     if (list)
2816       list=(char **) RelinquishMagickMemory(list);
2817     if (length)
2818       length=(STRLEN *) RelinquishMagickMemory(length);
2819     InheritPerlException(exception,perl_exception);
2820     exception=DestroyExceptionInfo(exception);
2821     sv_setiv(perl_exception,(IV) number_images);
2822     SvPOK_on(perl_exception);
2823     ST(0)=sv_2mortal(perl_exception);
2824     XSRETURN(1);
2825   }
2826 \f
2827 #
2828 ###############################################################################
2829 #                                                                             #
2830 #                                                                             #
2831 #                                                                             #
2832 #   C l o n e                                                                 #
2833 #                                                                             #
2834 #                                                                             #
2835 #                                                                             #
2836 ###############################################################################
2837 #
2838 #
2839 void
2840 Clone(ref)
2841   Image::Magick ref=NO_INIT
2842   ALIAS:
2843     CopyImage   = 1
2844     copy        = 2
2845     copyimage   = 3
2846     CloneImage  = 4
2847     clone       = 5
2848     cloneimage  = 6
2849     Clone       = 7
2850   PPCODE:
2851   {
2852     AV
2853       *av;
2854
2855     ExceptionInfo
2856       *exception;
2857
2858     HV
2859       *hv;
2860
2861     Image
2862       *clone,
2863       *image;
2864
2865     struct PackageInfo
2866       *info;
2867
2868     SV
2869       *perl_exception,
2870       *reference,
2871       *rv,
2872       *sv;
2873
2874     PERL_UNUSED_VAR(ref);
2875     PERL_UNUSED_VAR(ix);
2876     exception=AcquireExceptionInfo();
2877     perl_exception=newSVpv("",0);
2878     sv=NULL;
2879     if (sv_isobject(ST(0)) == 0)
2880       {
2881         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2882           PackageName);
2883         goto PerlException;
2884       }
2885     reference=SvRV(ST(0));
2886     hv=SvSTASH(reference);
2887     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2888     if (image == (Image *) NULL)
2889       {
2890         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2891           PackageName);
2892         goto PerlException;
2893       }
2894     /*
2895       Create blessed Perl array for the returned image.
2896     */
2897     av=newAV();
2898     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2899     SvREFCNT_dec(av);
2900     for ( ; image; image=image->next)
2901     {
2902       clone=CloneImage(image,0,0,MagickTrue,exception);
2903       if ((clone == (Image *) NULL) || (exception->severity >= ErrorException))
2904         break;
2905       AddImageToRegistry(sv,clone);
2906       rv=newRV(sv);
2907       av_push(av,sv_bless(rv,hv));
2908       SvREFCNT_dec(sv);
2909     }
2910     exception=DestroyExceptionInfo(exception);
2911     SvREFCNT_dec(perl_exception);
2912     XSRETURN(1);
2913
2914   PerlException:
2915     InheritPerlException(exception,perl_exception);
2916     exception=DestroyExceptionInfo(exception);
2917     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2918     SvPOK_on(perl_exception);
2919     ST(0)=sv_2mortal(perl_exception);
2920     XSRETURN(1);
2921   }
2922 \f
2923 #
2924 ###############################################################################
2925 #                                                                             #
2926 #                                                                             #
2927 #                                                                             #
2928 #   C L O N E                                                                 #
2929 #                                                                             #
2930 #                                                                             #
2931 #                                                                             #
2932 ###############################################################################
2933 #
2934 #
2935 void
2936 CLONE(ref,...)
2937   SV *ref;
2938   CODE:
2939   {
2940     PERL_UNUSED_VAR(ref);
2941     if (magick_registry != (SplayTreeInfo *) NULL)
2942       {
2943         register Image
2944           *p;
2945
2946         ResetSplayTreeIterator(magick_registry);
2947         p=(Image *) GetNextKeyInSplayTree(magick_registry);
2948         while (p != (Image *) NULL)
2949         {
2950           ReferenceImage(p);
2951           p=(Image *) GetNextKeyInSplayTree(magick_registry);
2952         }
2953       }
2954   }
2955 \f
2956 #
2957 ###############################################################################
2958 #                                                                             #
2959 #                                                                             #
2960 #                                                                             #
2961 #   C o a l e s c e                                                           #
2962 #                                                                             #
2963 #                                                                             #
2964 #                                                                             #
2965 ###############################################################################
2966 #
2967 #
2968 void
2969 Coalesce(ref)
2970   Image::Magick ref=NO_INIT
2971   ALIAS:
2972     CoalesceImage   = 1
2973     coalesce        = 2
2974     coalesceimage   = 3
2975   PPCODE:
2976   {
2977     AV
2978       *av;
2979
2980     ExceptionInfo
2981       *exception;
2982
2983     HV
2984       *hv;
2985
2986     Image
2987       *image;
2988
2989     struct PackageInfo
2990       *info;
2991
2992     SV
2993       *av_reference,
2994       *perl_exception,
2995       *reference,
2996       *rv,
2997       *sv;
2998
2999     PERL_UNUSED_VAR(ref);
3000     PERL_UNUSED_VAR(ix);
3001     exception=AcquireExceptionInfo();
3002     perl_exception=newSVpv("",0);
3003     sv=NULL;
3004     if (sv_isobject(ST(0)) == 0)
3005       {
3006         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3007           PackageName);
3008         goto PerlException;
3009       }
3010     reference=SvRV(ST(0));
3011     hv=SvSTASH(reference);
3012     av=newAV();
3013     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3014     SvREFCNT_dec(av);
3015     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3016     if (image == (Image *) NULL)
3017       {
3018         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3019           PackageName);
3020         goto PerlException;
3021       }
3022     image=CoalesceImages(image,exception);
3023     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3024       goto PerlException;
3025     for ( ; image; image=image->next)
3026     {
3027       AddImageToRegistry(sv,image);
3028       rv=newRV(sv);
3029       av_push(av,sv_bless(rv,hv));
3030       SvREFCNT_dec(sv);
3031     }
3032     exception=DestroyExceptionInfo(exception);
3033     ST(0)=av_reference;
3034     SvREFCNT_dec(perl_exception);
3035     XSRETURN(1);
3036
3037   PerlException:
3038     InheritPerlException(exception,perl_exception);
3039     exception=DestroyExceptionInfo(exception);
3040     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3041     SvPOK_on(perl_exception);
3042     ST(0)=sv_2mortal(perl_exception);
3043     XSRETURN(1);
3044   }
3045 \f
3046 #
3047 ###############################################################################
3048 #                                                                             #
3049 #                                                                             #
3050 #                                                                             #
3051 #   C o m p a r e                                                             #
3052 #                                                                             #
3053 #                                                                             #
3054 #                                                                             #
3055 ###############################################################################
3056 #
3057 #
3058 void
3059 Compare(ref,...)
3060   Image::Magick ref=NO_INIT
3061   ALIAS:
3062     CompareImages = 1
3063     compare      = 2
3064     compareimage = 3
3065   PPCODE:
3066   {
3067     AV
3068       *av;
3069
3070     char
3071       *attribute;
3072
3073     double
3074       distortion;
3075
3076     ExceptionInfo
3077       *exception;
3078
3079     HV
3080       *hv;
3081
3082     Image
3083       *difference_image,
3084       *image,
3085       *reconstruct_image;
3086
3087     MetricType
3088       metric;
3089
3090     register ssize_t
3091       i;
3092
3093     ssize_t
3094       option;
3095
3096     struct PackageInfo
3097       *info;
3098
3099     SV
3100       *av_reference,
3101       *perl_exception,
3102       *reference,
3103       *rv,
3104       *sv;
3105
3106     PERL_UNUSED_VAR(ref);
3107     PERL_UNUSED_VAR(ix);
3108     exception=AcquireExceptionInfo();
3109     perl_exception=newSVpv("",0);
3110     sv=NULL;
3111     av=NULL;
3112     attribute=NULL;
3113     if (sv_isobject(ST(0)) == 0)
3114       {
3115         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3116           PackageName);
3117         goto PerlException;
3118       }
3119     reference=SvRV(ST(0));
3120     hv=SvSTASH(reference);
3121     av=newAV();
3122     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3123     SvREFCNT_dec(av);
3124     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3125     if (image == (Image *) NULL)
3126       {
3127         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3128           PackageName);
3129         goto PerlException;
3130       }
3131     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3132     /*
3133       Get attribute.
3134     */
3135     reconstruct_image=image;
3136     metric=RootMeanSquaredErrorMetric;
3137     for (i=2; i < items; i+=2)
3138     {
3139       attribute=(char *) SvPV(ST(i-1),na);
3140       switch (*attribute)
3141       {
3142         case 'C':
3143         case 'c':
3144         {
3145           if (LocaleCompare(attribute,"channel") == 0)
3146             {
3147               ssize_t
3148                 option;
3149
3150               option=ParseChannelOption(SvPV(ST(i),na));
3151               if (option < 0)
3152                 {
3153                   ThrowPerlException(exception,OptionError,
3154                     "UnrecognizedType",SvPV(ST(i),na));
3155                   return;
3156                 }
3157               SetPixelChannelMap(image,(ChannelType) option);
3158               break;
3159             }
3160           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3161             attribute);
3162           break;
3163         }
3164         case 'F':
3165         case 'f':
3166         {
3167           if (LocaleCompare(attribute,"fuzz") == 0)
3168             {
3169               image->fuzz=SiPrefixToDouble(SvPV(ST(i),na),100.0);
3170               break;
3171             }
3172           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3173             attribute);
3174           break;
3175         }
3176         case 'I':
3177         case 'i':
3178         {
3179           if (LocaleCompare(attribute,"image") == 0)
3180             {
3181               reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3182                 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3183               break;
3184             }
3185           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3186             attribute);
3187           break;
3188         }
3189         case 'M':
3190         case 'm':
3191         {
3192           if (LocaleCompare(attribute,"metric") == 0)
3193             {
3194               option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3195                 SvPV(ST(i),na));
3196               if (option < 0)
3197                 {
3198                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3199                     SvPV(ST(i),na));
3200                   break;
3201                 }
3202               metric=(MetricType) option;
3203               break;
3204             }
3205           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3206             attribute);
3207           break;
3208         }
3209         default:
3210         {
3211           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3212             attribute);
3213           break;
3214         }
3215       }
3216     }
3217     difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3218       exception);
3219     if (difference_image != (Image *) NULL)
3220       {
3221         difference_image->error.mean_error_per_pixel=distortion;
3222         AddImageToRegistry(sv,difference_image);
3223         rv=newRV(sv);
3224         av_push(av,sv_bless(rv,hv));
3225         SvREFCNT_dec(sv);
3226       }
3227     exception=DestroyExceptionInfo(exception);
3228     ST(0)=av_reference;
3229     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3230     XSRETURN(1);
3231
3232   PerlException:
3233     InheritPerlException(exception,perl_exception);
3234     exception=DestroyExceptionInfo(exception);
3235     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3236     SvPOK_on(perl_exception);
3237     ST(0)=sv_2mortal(perl_exception);
3238     XSRETURN(1);
3239   }
3240 \f
3241 #
3242 ###############################################################################
3243 #                                                                             #
3244 #                                                                             #
3245 #                                                                             #
3246 #   C o m p a r e L a y e r s                                                 #
3247 #                                                                             #
3248 #                                                                             #
3249 #                                                                             #
3250 ###############################################################################
3251 #
3252 #
3253 void
3254 CompareLayers(ref)
3255   Image::Magick ref=NO_INIT
3256   ALIAS:
3257     CompareImagesLayers   = 1
3258     comparelayers        = 2
3259     compareimagelayers   = 3
3260   PPCODE:
3261   {
3262     AV
3263       *av;
3264
3265     char
3266       *attribute;
3267
3268     ExceptionInfo
3269       *exception;
3270
3271     HV
3272       *hv;
3273
3274     Image
3275       *image;
3276
3277     ImageLayerMethod
3278       method;
3279
3280     register ssize_t
3281       i;
3282
3283     ssize_t
3284       option;
3285
3286     struct PackageInfo
3287       *info;
3288
3289     SV
3290       *av_reference,
3291       *perl_exception,
3292       *reference,
3293       *rv,
3294       *sv;
3295
3296     PERL_UNUSED_VAR(ref);
3297     PERL_UNUSED_VAR(ix);
3298     exception=AcquireExceptionInfo();
3299     perl_exception=newSVpv("",0);
3300     sv=NULL;
3301     if (sv_isobject(ST(0)) == 0)
3302       {
3303         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3304           PackageName);
3305         goto PerlException;
3306       }
3307     reference=SvRV(ST(0));
3308     hv=SvSTASH(reference);
3309     av=newAV();
3310     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3311     SvREFCNT_dec(av);
3312     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3313     if (image == (Image *) NULL)
3314       {
3315         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3316           PackageName);
3317         goto PerlException;
3318       }
3319     method=CompareAnyLayer;
3320     for (i=2; i < items; i+=2)
3321     {
3322       attribute=(char *) SvPV(ST(i-1),na);
3323       switch (*attribute)
3324       {
3325         case 'M':
3326         case 'm':
3327         {
3328           if (LocaleCompare(attribute,"method") == 0)
3329             {
3330               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3331                 SvPV(ST(i),na));
3332               if (option < 0)
3333                 {
3334                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3335                     SvPV(ST(i),na));
3336                   break;
3337                 }
3338                method=(ImageLayerMethod) option;
3339               break;
3340             }
3341           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3342             attribute);
3343           break;
3344         }
3345         default:
3346         {
3347           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3348             attribute);
3349           break;
3350         }
3351       }
3352     }
3353     image=CompareImagesLayers(image,method,exception);
3354     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3355       goto PerlException;
3356     for ( ; image; image=image->next)
3357     {
3358       AddImageToRegistry(sv,image);
3359       rv=newRV(sv);
3360       av_push(av,sv_bless(rv,hv));
3361       SvREFCNT_dec(sv);
3362     }
3363     exception=DestroyExceptionInfo(exception);
3364     ST(0)=av_reference;
3365     SvREFCNT_dec(perl_exception);
3366     XSRETURN(1);
3367
3368   PerlException:
3369     InheritPerlException(exception,perl_exception);
3370     exception=DestroyExceptionInfo(exception);
3371     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3372     SvPOK_on(perl_exception);
3373     ST(0)=sv_2mortal(perl_exception);
3374     XSRETURN(1);
3375   }
3376 \f
3377 #
3378 ###############################################################################
3379 #                                                                             #
3380 #                                                                             #
3381 #                                                                             #
3382 #   D e s t r o y                                                             #
3383 #                                                                             #
3384 #                                                                             #
3385 #                                                                             #
3386 ###############################################################################
3387 #
3388 #
3389 void
3390 DESTROY(ref)
3391   Image::Magick ref=NO_INIT
3392   PPCODE:
3393   {
3394     SV
3395       *reference;
3396
3397     PERL_UNUSED_VAR(ref);
3398     if (sv_isobject(ST(0)) == 0)
3399       croak("ReferenceIsNotMyType");
3400     reference=SvRV(ST(0));
3401     switch (SvTYPE(reference))
3402     {
3403       case SVt_PVAV:
3404       {
3405         char
3406           message[MaxTextExtent];
3407
3408         const SV
3409           *key;
3410
3411         HV
3412           *hv;
3413
3414         GV
3415           **gvp;
3416
3417         struct PackageInfo
3418           *info;
3419
3420         SV
3421           *sv;
3422
3423         /*
3424           Array (AV *) reference
3425         */
3426         (void) FormatLocaleString(message,MaxTextExtent,"package%s%p",
3427           XS_VERSION,reference);
3428         hv=gv_stashpv(PackageName, FALSE);
3429         if (!hv)
3430           break;
3431         gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3432         if (!gvp)
3433           break;
3434         sv=GvSV(*gvp);
3435         if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3436           {
3437             info=(struct PackageInfo *) SvIV(sv);
3438             DestroyPackageInfo(info);
3439           }
3440         key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3441         (void) key;
3442         break;
3443       }
3444       case SVt_PVMG:
3445       {
3446         Image
3447           *image;
3448
3449         /*
3450           Blessed scalar = (Image *) SvIV(reference)
3451         */
3452         image=(Image *) SvIV(reference);
3453         if (image != (Image *) NULL)
3454           DeleteImageFromRegistry(reference,image);
3455         break;
3456       }
3457       default:
3458         break;
3459     }
3460   }
3461 \f
3462 #
3463 ###############################################################################
3464 #                                                                             #
3465 #                                                                             #
3466 #                                                                             #
3467 #   D i s p l a y                                                             #
3468 #                                                                             #
3469 #                                                                             #
3470 #                                                                             #
3471 ###############################################################################
3472 #
3473 #
3474 void
3475 Display(ref,...)
3476   Image::Magick ref=NO_INIT
3477   ALIAS:
3478     DisplayImage  = 1
3479     display       = 2
3480     displayimage  = 3
3481   PPCODE:
3482   {
3483     ExceptionInfo
3484       *exception;
3485
3486     Image
3487       *image;
3488
3489     register ssize_t
3490       i;
3491
3492     struct PackageInfo
3493       *info,
3494       *package_info;
3495
3496     SV
3497       *perl_exception,
3498       *reference;
3499
3500     PERL_UNUSED_VAR(ref);
3501     PERL_UNUSED_VAR(ix);
3502     exception=AcquireExceptionInfo();
3503     perl_exception=newSVpv("",0);
3504     package_info=(struct PackageInfo *) NULL;
3505     if (sv_isobject(ST(0)) == 0)
3506       {
3507         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3508           PackageName);
3509         goto PerlException;
3510       }
3511     reference=SvRV(ST(0));
3512     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3513     if (image == (Image *) NULL)
3514       {
3515         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3516           PackageName);
3517         goto PerlException;
3518       }
3519     package_info=ClonePackageInfo(info,exception);
3520     if (items == 2)
3521       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3522     else
3523       if (items > 2)
3524         for (i=2; i < items; i+=2)
3525           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3526             exception);
3527     (void) DisplayImages(package_info->image_info,image,exception);
3528     (void) CatchImageException(image);
3529
3530   PerlException:
3531     if (package_info != (struct PackageInfo *) NULL)
3532       DestroyPackageInfo(package_info);
3533     InheritPerlException(exception,perl_exception);
3534     exception=DestroyExceptionInfo(exception);
3535     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3536     SvPOK_on(perl_exception);
3537     ST(0)=sv_2mortal(perl_exception);
3538     XSRETURN(1);
3539   }
3540 \f
3541 #
3542 ###############################################################################
3543 #                                                                             #
3544 #                                                                             #
3545 #                                                                             #
3546 #   E v a l u a t e I m a g e s                                               #
3547 #                                                                             #
3548 #                                                                             #
3549 #                                                                             #
3550 ###############################################################################
3551 #
3552 #
3553 void
3554 EvaluateImages(ref)
3555   Image::Magick ref=NO_INIT
3556   ALIAS:
3557     EvaluateImages   = 1
3558     evaluateimages   = 2
3559   PPCODE:
3560   {
3561     AV
3562       *av;
3563
3564     char
3565       *attribute,
3566       *p;
3567
3568     ExceptionInfo
3569       *exception;
3570
3571     HV
3572       *hv;
3573
3574     Image
3575       *image;
3576
3577     MagickEvaluateOperator
3578       op;
3579
3580     register ssize_t
3581       i;
3582
3583     struct PackageInfo
3584       *info;
3585
3586     SV
3587       *perl_exception,
3588       *reference,
3589       *rv,
3590       *sv;
3591
3592     PERL_UNUSED_VAR(ref);
3593     PERL_UNUSED_VAR(ix);
3594     exception=AcquireExceptionInfo();
3595     perl_exception=newSVpv("",0);
3596     sv=NULL;
3597     if (sv_isobject(ST(0)) == 0)
3598       {
3599         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3600           PackageName);
3601         goto PerlException;
3602       }
3603     reference=SvRV(ST(0));
3604     hv=SvSTASH(reference);
3605     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3606     if (image == (Image *) NULL)
3607       {
3608         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3609           PackageName);
3610         goto PerlException;
3611       }
3612     op=MeanEvaluateOperator;
3613     if (items == 2)
3614       {
3615         ssize_t
3616           in;
3617
3618         in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
3619           SvPV(ST(1),na));
3620         if (in < 0)
3621           {
3622             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3623               SvPV(ST(1),na));
3624             return;
3625           }
3626         op=(MagickEvaluateOperator) in;
3627       }
3628     else
3629       for (i=2; i < items; i+=2)
3630       {
3631         attribute=(char *) SvPV(ST(i-1),na);
3632         switch (*attribute)
3633         {
3634           case 'O':
3635           case 'o':
3636           {
3637             if (LocaleCompare(attribute,"operator") == 0)
3638               {
3639                 ssize_t
3640                   in;
3641
3642                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3643                   MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
3644                 if (in < 0)
3645                   {
3646                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3647                       SvPV(ST(i),na));
3648                     return;
3649                   }
3650                 op=(MagickEvaluateOperator) in;
3651                 break;
3652               }
3653             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3654               attribute);
3655             break;
3656           }
3657           default:
3658           {
3659             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3660               attribute);
3661             break;
3662           }
3663         }
3664       }
3665     image=EvaluateImages(image,op,exception);
3666     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3667       goto PerlException;
3668     /*
3669       Create blessed Perl array for the returned image.
3670     */
3671     av=newAV();
3672     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3673     SvREFCNT_dec(av);
3674     AddImageToRegistry(sv,image);
3675     rv=newRV(sv);
3676     av_push(av,sv_bless(rv,hv));
3677     SvREFCNT_dec(sv);
3678     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3679     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
3680       "evaluate-%.*s",(int) (MaxTextExtent-9),
3681       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3682     (void) CopyMagickString(image->filename,info->image_info->filename,
3683       MaxTextExtent);
3684     SetImageInfo(info->image_info,0,exception);
3685     exception=DestroyExceptionInfo(exception);
3686     SvREFCNT_dec(perl_exception);
3687     XSRETURN(1);
3688
3689   PerlException:
3690     InheritPerlException(exception,perl_exception);
3691     exception=DestroyExceptionInfo(exception);
3692     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3693     SvPOK_on(perl_exception);
3694     ST(0)=sv_2mortal(perl_exception);
3695     XSRETURN(1);
3696   }
3697 \f
3698 #
3699 ###############################################################################
3700 #                                                                             #
3701 #                                                                             #
3702 #                                                                             #
3703 #   F e a t u r e s                                                           #
3704 #                                                                             #
3705 #                                                                             #
3706 #                                                                             #
3707 ###############################################################################
3708 #
3709 #
3710 void
3711 Features(ref,...)
3712   Image::Magick ref=NO_INIT
3713   ALIAS:
3714     FeaturesImage = 1
3715     features      = 2
3716     featuresimage = 3
3717   PPCODE:
3718   {
3719 #define ChannelFeatures(channel,direction) \
3720 { \
3721   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3722     channel_features[channel].angular_second_moment[direction]); \
3723   PUSHs(sv_2mortal(newSVpv(message,0))); \
3724   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3725     channel_features[channel].contrast[direction]); \
3726   PUSHs(sv_2mortal(newSVpv(message,0))); \
3727   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3728     channel_features[channel].contrast[direction]); \
3729   PUSHs(sv_2mortal(newSVpv(message,0))); \
3730   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3731     channel_features[channel].variance_sum_of_squares[direction]); \
3732   PUSHs(sv_2mortal(newSVpv(message,0))); \
3733   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3734     channel_features[channel].inverse_difference_moment[direction]); \
3735   PUSHs(sv_2mortal(newSVpv(message,0))); \
3736   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3737     channel_features[channel].sum_average[direction]); \
3738   PUSHs(sv_2mortal(newSVpv(message,0))); \
3739   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3740     channel_features[channel].sum_variance[direction]); \
3741   PUSHs(sv_2mortal(newSVpv(message,0))); \
3742   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3743     channel_features[channel].sum_entropy[direction]); \
3744   PUSHs(sv_2mortal(newSVpv(message,0))); \
3745   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3746     channel_features[channel].entropy[direction]); \
3747   PUSHs(sv_2mortal(newSVpv(message,0))); \
3748   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3749     channel_features[channel].difference_variance[direction]); \
3750   PUSHs(sv_2mortal(newSVpv(message,0))); \
3751   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3752     channel_features[channel].difference_entropy[direction]); \
3753   PUSHs(sv_2mortal(newSVpv(message,0))); \
3754   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3755     channel_features[channel].measure_of_correlation_1[direction]); \
3756   PUSHs(sv_2mortal(newSVpv(message,0))); \
3757   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3758     channel_features[channel].measure_of_correlation_2[direction]); \
3759   PUSHs(sv_2mortal(newSVpv(message,0))); \
3760   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3761     channel_features[channel].maximum_correlation_coefficient[direction]); \
3762   PUSHs(sv_2mortal(newSVpv(message,0))); \
3763 }
3764
3765     AV
3766       *av;
3767
3768     char
3769       *attribute,
3770       message[MaxTextExtent];
3771
3772     ChannelFeatures
3773       *channel_features;
3774
3775     double
3776       distance;
3777
3778     ExceptionInfo
3779       *exception;
3780
3781     Image
3782       *image;
3783
3784     register ssize_t
3785       i;
3786
3787     ssize_t
3788       count;
3789
3790     struct PackageInfo
3791       *info;
3792
3793     SV
3794       *perl_exception,
3795       *reference;
3796
3797     PERL_UNUSED_VAR(ref);
3798     PERL_UNUSED_VAR(ix);
3799     exception=AcquireExceptionInfo();
3800     perl_exception=newSVpv("",0);
3801     av=NULL;
3802     if (sv_isobject(ST(0)) == 0)
3803       {
3804         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3805           PackageName);
3806         goto PerlException;
3807       }
3808     reference=SvRV(ST(0));
3809     av=newAV();
3810     SvREFCNT_dec(av);
3811     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3812     if (image == (Image *) NULL)
3813       {
3814         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3815           PackageName);
3816         goto PerlException;
3817       }
3818     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3819     distance=1;
3820     for (i=2; i < items; i+=2)
3821     {
3822       attribute=(char *) SvPV(ST(i-1),na);
3823       switch (*attribute)
3824       {
3825         case 'D':
3826         case 'd':
3827         {
3828           if (LocaleCompare(attribute,"distance") == 0)
3829             {
3830               distance=StringToLong((char *) SvPV(ST(1),na));
3831               break;
3832             }
3833           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3834             attribute);
3835           break;
3836         }
3837         default:
3838         {
3839           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3840             attribute);
3841           break;
3842         }
3843       }
3844     }
3845     count=0;
3846     for ( ; image; image=image->next)
3847     {
3848       channel_features=GetImageFeatures(image,distance,
3849         &image->exception);
3850       if (channel_features == (ChannelFeatures *) NULL)
3851         continue;
3852       count++;
3853       EXTEND(sp,75*count);
3854       for (i=0; i < 4; i++)
3855       {
3856         ChannelFeatures(RedChannel,i);
3857         ChannelFeatures(GreenChannel,i);
3858         ChannelFeatures(BlueChannel,i);
3859         if (image->colorspace == CMYKColorspace)
3860           ChannelFeatures(BlackChannel,i);
3861         if (image->matte != MagickFalse)
3862           ChannelFeatures(AlphaChannel,i);
3863       }
3864       channel_features=(ChannelFeatures *)
3865         RelinquishMagickMemory(channel_features);
3866     }
3867
3868   PerlException:
3869     InheritPerlException(exception,perl_exception);
3870     exception=DestroyExceptionInfo(exception);
3871     SvREFCNT_dec(perl_exception);
3872   }
3873 \f
3874 #
3875 ###############################################################################
3876 #                                                                             #
3877 #                                                                             #
3878 #                                                                             #
3879 #   F l a t t e n                                                             #
3880 #                                                                             #
3881 #                                                                             #
3882 #                                                                             #
3883 ###############################################################################
3884 #
3885 #
3886 void
3887 Flatten(ref)
3888   Image::Magick ref=NO_INIT
3889   ALIAS:
3890     FlattenImage   = 1
3891     flatten        = 2
3892     flattenimage   = 3
3893   PPCODE:
3894   {
3895     AV
3896       *av;
3897
3898     char
3899       *attribute,
3900       *p;
3901
3902     ExceptionInfo
3903       *exception;
3904
3905     HV
3906       *hv;
3907
3908     Image
3909       *image;
3910
3911     PixelPacket
3912       background_color;
3913
3914     register ssize_t
3915       i;
3916
3917     struct PackageInfo
3918       *info;
3919
3920     SV
3921       *perl_exception,
3922       *reference,
3923       *rv,
3924       *sv;
3925
3926     PERL_UNUSED_VAR(ref);
3927     PERL_UNUSED_VAR(ix);
3928     exception=AcquireExceptionInfo();
3929     perl_exception=newSVpv("",0);
3930     sv=NULL;
3931     if (sv_isobject(ST(0)) == 0)
3932       {
3933         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3934           PackageName);
3935         goto PerlException;
3936       }
3937     reference=SvRV(ST(0));
3938     hv=SvSTASH(reference);
3939     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3940     if (image == (Image *) NULL)
3941       {
3942         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3943           PackageName);
3944         goto PerlException;
3945       }
3946     background_color=image->background_color;
3947     if (items == 2)
3948       (void) QueryColorDatabase((char *) SvPV(ST(1),na),&background_color,
3949         exception);
3950     else
3951       for (i=2; i < items; i+=2)
3952       {
3953         attribute=(char *) SvPV(ST(i-1),na);
3954         switch (*attribute)
3955         {
3956           case 'B':
3957           case 'b':
3958           {
3959             if (LocaleCompare(attribute,"background") == 0)
3960               {
3961                 (void) QueryColorDatabase((char *) SvPV(ST(1),na),
3962                   &background_color,exception);
3963                 break;
3964               }
3965             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3966               attribute);
3967             break;
3968           }
3969           default:
3970           {
3971             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3972               attribute);
3973             break;
3974           }
3975         }
3976       }
3977     image->background_color=background_color;
3978     image=MergeImageLayers(image,FlattenLayer,exception);
3979     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3980       goto PerlException;
3981     /*
3982       Create blessed Perl array for the returned image.
3983     */
3984     av=newAV();
3985     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3986     SvREFCNT_dec(av);
3987     AddImageToRegistry(sv,image);
3988     rv=newRV(sv);
3989     av_push(av,sv_bless(rv,hv));
3990     SvREFCNT_dec(sv);
3991     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3992     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
3993       "flatten-%.*s",(int) (MaxTextExtent-9),
3994       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3995     (void) CopyMagickString(image->filename,info->image_info->filename,
3996       MaxTextExtent);
3997     SetImageInfo(info->image_info,0,exception);
3998     exception=DestroyExceptionInfo(exception);
3999     SvREFCNT_dec(perl_exception);
4000     XSRETURN(1);
4001
4002   PerlException:
4003     InheritPerlException(exception,perl_exception);
4004     exception=DestroyExceptionInfo(exception);
4005     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4006     SvPOK_on(perl_exception);  /* return messages in string context */
4007     ST(0)=sv_2mortal(perl_exception);
4008     XSRETURN(1);
4009   }
4010 \f
4011 #
4012 ###############################################################################
4013 #                                                                             #
4014 #                                                                             #
4015 #                                                                             #
4016 #   F x                                                                       #
4017 #                                                                             #
4018 #                                                                             #
4019 #                                                                             #
4020 ###############################################################################
4021 #
4022 #
4023 void
4024 Fx(ref,...)
4025   Image::Magick ref=NO_INIT
4026   ALIAS:
4027     FxImage  = 1
4028     fx       = 2
4029     fximage  = 3
4030   PPCODE:
4031   {
4032     AV
4033       *av;
4034
4035     char
4036       *attribute,
4037       expression[MaxTextExtent];
4038
4039     ChannelType
4040       channel,
4041       channel_mask;
4042
4043     ExceptionInfo
4044       *exception;
4045
4046     HV
4047       *hv;
4048
4049     Image
4050       *image;
4051
4052     register ssize_t
4053       i;
4054
4055     struct PackageInfo
4056       *info;
4057
4058     SV
4059       *av_reference,
4060       *perl_exception,
4061       *reference,
4062       *rv,
4063       *sv;
4064
4065     PERL_UNUSED_VAR(ref);
4066     PERL_UNUSED_VAR(ix);
4067     exception=AcquireExceptionInfo();
4068     perl_exception=newSVpv("",0);
4069     sv=NULL;
4070     attribute=NULL;
4071     av=NULL;
4072     if (sv_isobject(ST(0)) == 0)
4073       {
4074         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4075           PackageName);
4076         goto PerlException;
4077       }
4078     reference=SvRV(ST(0));
4079     hv=SvSTASH(reference);
4080     av=newAV();
4081     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4082     SvREFCNT_dec(av);
4083     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4084     if (image == (Image *) NULL)
4085       {
4086         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4087           PackageName);
4088         goto PerlException;
4089       }
4090     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4091     /*
4092       Get options.
4093     */
4094     channel=DefaultChannels;
4095     (void) CopyMagickString(expression,"u",MaxTextExtent);
4096     if (items == 2)
4097       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MaxTextExtent);
4098     else
4099       for (i=2; i < items; i+=2)
4100       {
4101         attribute=(char *) SvPV(ST(i-1),na);
4102         switch (*attribute)
4103         {
4104           case 'C':
4105           case 'c':
4106           {
4107             if (LocaleCompare(attribute,"channel") == 0)
4108               {
4109                 ssize_t
4110                   option;
4111
4112                 option=ParseChannelOption(SvPV(ST(i),na));
4113                 if (option < 0)
4114                   {
4115                     ThrowPerlException(exception,OptionError,
4116                       "UnrecognizedType",SvPV(ST(i),na));
4117                     return;
4118                   }
4119                 channel=(ChannelType) option;
4120                 break;
4121               }
4122             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4123               attribute);
4124             break;
4125           }
4126           case 'E':
4127           case 'e':
4128           {
4129             if (LocaleCompare(attribute,"expression") == 0)
4130               {
4131                 (void) CopyMagickString(expression,SvPV(ST(i),na),
4132                   MaxTextExtent);
4133                 break;
4134               }
4135             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4136               attribute);
4137             break;
4138           }
4139           default:
4140           {
4141             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4142               attribute);
4143             break;
4144           }
4145         }
4146       }
4147     channel_mask=SetPixelChannelMask(image,channel);
4148     image=FxImage(image,expression,exception);
4149     if (image != (Image *) NULL)
4150       (void) SetPixelChannelMask(image,channel_mask);
4151     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
4152       goto PerlException;
4153     for ( ; image; image=image->next)
4154     {
4155       AddImageToRegistry(sv,image);
4156       rv=newRV(sv);
4157       av_push(av,sv_bless(rv,hv));
4158       SvREFCNT_dec(sv);
4159     }
4160     exception=DestroyExceptionInfo(exception);
4161     ST(0)=av_reference;
4162     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4163     XSRETURN(1);
4164
4165   PerlException:
4166     InheritPerlException(exception,perl_exception);
4167     exception=DestroyExceptionInfo(exception);
4168     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4169     SvPOK_on(perl_exception);
4170     ST(0)=sv_2mortal(perl_exception);
4171     XSRETURN(1);
4172   }
4173 \f
4174 #
4175 ###############################################################################
4176 #                                                                             #
4177 #                                                                             #
4178 #                                                                             #
4179 #   G e t                                                                     #
4180 #                                                                             #
4181 #                                                                             #
4182 #                                                                             #
4183 ###############################################################################
4184 #
4185 #
4186 void
4187 Get(ref,...)
4188   Image::Magick ref=NO_INIT
4189   ALIAS:
4190     GetAttributes = 1
4191     GetAttribute  = 2
4192     get           = 3
4193     getattributes = 4
4194     getattribute  = 5
4195   PPCODE:
4196   {
4197     char
4198       *attribute,
4199       color[MaxTextExtent];
4200
4201     const char
4202       *value;
4203
4204     ExceptionInfo
4205       *exception;
4206
4207     Image
4208       *image;
4209
4210     long
4211       j;
4212
4213     register ssize_t
4214       i;
4215
4216     struct PackageInfo
4217       *info;
4218
4219     SV
4220       *perl_exception,
4221       *reference,
4222       *s;
4223
4224     PERL_UNUSED_VAR(ref);
4225     PERL_UNUSED_VAR(ix);
4226     exception=AcquireExceptionInfo();
4227     perl_exception=newSVpv("",0);
4228     if (sv_isobject(ST(0)) == 0)
4229       {
4230         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4231           PackageName);
4232         XSRETURN_EMPTY;
4233       }
4234     reference=SvRV(ST(0));
4235     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4236     if (image == (Image *) NULL && !info)
4237       XSRETURN_EMPTY;
4238     EXTEND(sp,items);
4239     for (i=1; i < items; i++)
4240     {
4241       attribute=(char *) SvPV(ST(i),na);
4242       s=NULL;
4243       switch (*attribute)
4244       {
4245         case 'A':
4246         case 'a':
4247         {
4248           if (LocaleCompare(attribute,"adjoin") == 0)
4249             {
4250               if (info)
4251                 s=newSViv((ssize_t) info->image_info->adjoin);
4252               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4253               continue;
4254             }
4255           if (LocaleCompare(attribute,"antialias") == 0)
4256             {
4257               if (info)
4258                 s=newSViv((ssize_t) info->image_info->antialias);
4259               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4260               continue;
4261             }
4262           if (LocaleCompare(attribute,"area") == 0)
4263             {
4264               s=newSViv(GetMagickResource(AreaResource));
4265               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4266               continue;
4267             }
4268           if (LocaleCompare(attribute,"attenuate") == 0)
4269             {
4270               const char
4271                 *value;
4272
4273               value=GetImageProperty(image,attribute);
4274               if (value != (const char *) NULL)
4275                 s=newSVpv(value,0);
4276               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4277               continue;
4278             }
4279           if (LocaleCompare(attribute,"authenticate") == 0)
4280             {
4281               if (info)
4282                 s=newSVpv(info->image_info->authenticate,0);
4283               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4284               continue;
4285             }
4286           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4287             attribute);
4288           break;
4289         }
4290         case 'B':
4291         case 'b':
4292         {
4293           if (LocaleCompare(attribute,"background") == 0)
4294             {
4295               if (image == (Image *) NULL)
4296                 break;
4297               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4298                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4299                 image->background_color.red,image->background_color.green,
4300                 image->background_color.blue,image->background_color.alpha);
4301               s=newSVpv(color,0);
4302               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4303               continue;
4304             }
4305           if (LocaleCompare(attribute,"base-columns") == 0)
4306             {
4307               if (image != (Image *) NULL)
4308                 s=newSViv((ssize_t) image->magick_columns);
4309               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4310               continue;
4311             }
4312           if (LocaleCompare(attribute,"base-filename") == 0)
4313             {
4314               if (image != (Image *) NULL)
4315                 s=newSVpv(image->magick_filename,0);
4316               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4317               continue;
4318             }
4319           if (LocaleCompare(attribute,"base-height") == 0)
4320             {
4321               if (image != (Image *) NULL)
4322                 s=newSViv((ssize_t) image->magick_rows);
4323               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4324               continue;
4325             }
4326           if (LocaleCompare(attribute,"base-rows") == 0)
4327             {
4328               if (image != (Image *) NULL)
4329                 s=newSViv((ssize_t) image->magick_rows);
4330               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4331               continue;
4332             }
4333           if (LocaleCompare(attribute,"base-width") == 0)
4334             {
4335               if (image != (Image *) NULL)
4336                 s=newSViv((ssize_t) image->magick_columns);
4337               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4338               continue;
4339             }
4340           if (LocaleCompare(attribute,"bias") == 0)
4341             {
4342               if (image != (Image *) NULL)
4343                 s=newSVnv(image->bias);
4344               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4345               continue;
4346             }
4347           if (LocaleCompare(attribute,"blue-primary") == 0)
4348             {
4349               if (image == (Image *) NULL)
4350                 break;
4351               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4352                 image->chromaticity.blue_primary.x,
4353                 image->chromaticity.blue_primary.y);
4354               s=newSVpv(color,0);
4355               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4356               continue;
4357             }
4358           if (LocaleCompare(attribute,"bordercolor") == 0)
4359             {
4360               if (image == (Image *) NULL)
4361                 break;
4362               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4363                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4364                 image->border_color.red,image->border_color.green,
4365                 image->border_color.blue,image->border_color.alpha);
4366               s=newSVpv(color,0);
4367               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4368               continue;
4369             }
4370           if (LocaleCompare(attribute,"bounding-box") == 0)
4371             {
4372               char
4373                 geometry[MaxTextExtent];
4374
4375               RectangleInfo
4376                 page;
4377
4378               if (image == (Image *) NULL)
4379                 break;
4380               page=GetImageBoundingBox(image,&image->exception);
4381               (void) FormatLocaleString(geometry,MaxTextExtent,
4382                 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4383                 page.height,(double) page.x,(double) page.y);
4384               s=newSVpv(geometry,0);
4385               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4386               continue;
4387             }
4388           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4389             attribute);
4390           break;
4391         }
4392         case 'C':
4393         case 'c':
4394         {
4395           if (LocaleCompare(attribute,"class") == 0)
4396             {
4397               if (image == (Image *) NULL)
4398                 break;
4399               s=newSViv(image->storage_class);
4400               (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4401                 image->storage_class));
4402               SvIOK_on(s);
4403               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4404               continue;
4405             }
4406           if (LocaleCompare(attribute,"clip-mask") == 0)
4407             {
4408               if (image != (Image *) NULL)
4409                 {
4410                   SV
4411                     *sv;
4412
4413                   sv=NULL;
4414                   if (image->mask == (Image *) NULL)
4415                     ClipImage(image,exception);
4416                   if (image->mask != (Image *) NULL)
4417                     {
4418                       AddImageToRegistry(sv,image->mask);
4419                       s=sv_bless(newRV(sv),SvSTASH(reference));
4420                     }
4421                 }
4422               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4423               continue;
4424             }
4425           if (LocaleCompare(attribute,"clip-path") == 0)
4426             {
4427               if (image != (Image *) NULL)
4428                 {
4429                   SV
4430                     *sv;
4431
4432                   sv=NULL;
4433                   if (image->clip_mask == (Image *) NULL)
4434                     ClipImage(image,exception);
4435                   if (image->clip_mask != (Image *) NULL)
4436                     {
4437                       AddImageToRegistry(sv,image->clip_mask);
4438                       s=sv_bless(newRV(sv),SvSTASH(reference));
4439                     }
4440                 }
4441               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4442               continue;
4443             }
4444           if (LocaleCompare(attribute,"compression") == 0)
4445             {
4446               j=info ? info->image_info->compression : image ?
4447                 image->compression : UndefinedCompression;
4448               if (info)
4449                 if (info->image_info->compression == UndefinedCompression)
4450                   j=image->compression;
4451               s=newSViv(j);
4452               (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4453                 j));
4454               SvIOK_on(s);
4455               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4456               continue;
4457             }
4458           if (LocaleCompare(attribute,"colorspace") == 0)
4459             {
4460               j=image ? image->colorspace : RGBColorspace;
4461               s=newSViv(j);
4462               (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4463                 j));
4464               SvIOK_on(s);
4465               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4466               continue;
4467             }
4468           if (LocaleCompare(attribute,"colors") == 0)
4469             {
4470               if (image != (Image *) NULL)
4471                 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4472                   &image->exception));
4473               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4474               continue;
4475             }
4476           if (LocaleNCompare(attribute,"colormap",8) == 0)
4477             {
4478               int
4479                 items;
4480
4481               if (image == (Image *) NULL || !image->colormap)
4482                 break;
4483               j=0;
4484               items=sscanf(attribute,"%*[^[][%ld",&j);
4485               (void) items;
4486               if (j > (ssize_t) image->colors)
4487                 j%=image->colors;
4488               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4489                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4490                 image->colormap[j].red,image->colormap[j].green,
4491                 image->colormap[j].blue,image->colormap[j].alpha);
4492               s=newSVpv(color,0);
4493               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4494               continue;
4495             }
4496           if (LocaleCompare(attribute,"columns") == 0)
4497             {
4498               if (image != (Image *) NULL)
4499                 s=newSViv((ssize_t) image->columns);
4500               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4501               continue;
4502             }
4503           if (LocaleCompare(attribute,"comment") == 0)
4504             {
4505               const char
4506                 *value;
4507
4508               value=GetImageProperty(image,attribute);
4509               if (value != (const char *) NULL)
4510                 s=newSVpv(value,0);
4511               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4512               continue;
4513             }
4514           if (LocaleCompare(attribute,"copyright") == 0)
4515             {
4516               s=newSVpv(GetMagickCopyright(),0);
4517               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4518               continue;
4519             }
4520           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4521             attribute);
4522           break;
4523         }
4524         case 'D':
4525         case 'd':
4526         {
4527           if (LocaleCompare(attribute,"density") == 0)
4528             {
4529               char
4530                 geometry[MaxTextExtent];
4531
4532               if (image == (Image *) NULL)
4533                 break;
4534               (void) FormatLocaleString(geometry,MaxTextExtent,"%.15gx%.15g",
4535                 image->x_resolution,image->y_resolution);
4536               s=newSVpv(geometry,0);
4537               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4538               continue;
4539             }
4540           if (LocaleCompare(attribute,"delay") == 0)
4541             {
4542               if (image != (Image *) NULL)
4543                 s=newSViv((ssize_t) image->delay);
4544               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4545               continue;
4546             }
4547           if (LocaleCompare(attribute,"depth") == 0)
4548             {
4549               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4550               if (image != (Image *) NULL)
4551                 s=newSViv((ssize_t) GetImageDepth(image,&image->exception));
4552               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4553               continue;
4554             }
4555           if (LocaleCompare(attribute,"directory") == 0)
4556             {
4557               if (image && image->directory)
4558                 s=newSVpv(image->directory,0);
4559               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4560               continue;
4561             }
4562           if (LocaleCompare(attribute,"dispose") == 0)
4563             {
4564               if (image == (Image *) NULL)
4565                 break;
4566
4567               s=newSViv(image->dispose);
4568               (void) sv_setpv(s,
4569                 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
4570               SvIOK_on(s);
4571               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4572               continue;
4573             }
4574           if (LocaleCompare(attribute,"disk") == 0)
4575             {
4576               s=newSViv(GetMagickResource(DiskResource));
4577               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4578               continue;
4579             }
4580           if (LocaleCompare(attribute,"dither") == 0)
4581             {
4582               if (info)
4583                 s=newSViv((ssize_t) info->image_info->dither);
4584               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4585               continue;
4586             }
4587           if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4588             {
4589               if (info && info->image_info->server_name)
4590                 s=newSVpv(info->image_info->server_name,0);
4591               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4592               continue;
4593             }
4594           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4595             attribute);
4596           break;
4597         }
4598         case 'E':
4599         case 'e':
4600         {
4601           if (LocaleCompare(attribute,"elapsed-time") == 0)
4602             {
4603               if (image != (Image *) NULL)
4604                 s=newSVnv(GetElapsedTime(&image->timer));
4605               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4606               continue;
4607             }
4608           if (LocaleCompare(attribute,"endian") == 0)
4609             {
4610               j=info ? info->image_info->endian : image ? image->endian :
4611                 UndefinedEndian;
4612               s=newSViv(j);
4613               (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
4614               SvIOK_on(s);
4615               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4616               continue;
4617             }
4618           if (LocaleCompare(attribute,"error") == 0)
4619             {
4620               if (image != (Image *) NULL)
4621                 s=newSVnv(image->error.mean_error_per_pixel);
4622               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4623               continue;
4624             }
4625           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4626             attribute);
4627           break;
4628         }
4629         case 'F':
4630         case 'f':
4631         {
4632           if (LocaleCompare(attribute,"filesize") == 0)
4633             {
4634               if (image != (Image *) NULL)
4635                 s=newSViv((ssize_t) GetBlobSize(image));
4636               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4637               continue;
4638             }
4639           if (LocaleCompare(attribute,"filename") == 0)
4640             {
4641               if (info && info->image_info->filename &&
4642                   *info->image_info->filename)
4643                 s=newSVpv(info->image_info->filename,0);
4644               if (image != (Image *) NULL)
4645                 s=newSVpv(image->filename,0);
4646               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4647               continue;
4648             }
4649           if (LocaleCompare(attribute,"filter") == 0)
4650             {
4651               s=image ? newSViv(image->filter) : newSViv(0);
4652               (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
4653                 image->filter));
4654               SvIOK_on(s);
4655               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4656               continue;
4657             }
4658           if (LocaleCompare(attribute,"font") == 0)
4659             {
4660               if (info && info->image_info->font)
4661                 s=newSVpv(info->image_info->font,0);
4662               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4663               continue;
4664             }
4665           if (LocaleCompare(attribute,"foreground") == 0)
4666             continue;
4667           if (LocaleCompare(attribute,"format") == 0)
4668             {
4669               const MagickInfo
4670                 *magick_info;
4671
4672               magick_info=(const MagickInfo *) NULL;
4673               if (info && (*info->image_info->magick != '\0'))
4674                 magick_info=GetMagickInfo(info->image_info->magick,exception);
4675               if (image != (Image *) NULL)
4676                 magick_info=GetMagickInfo(image->magick,&image->exception);
4677               if ((magick_info != (const MagickInfo *) NULL) &&
4678                   (*magick_info->description != '\0'))
4679                 s=newSVpv((char *) magick_info->description,0);
4680               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4681               continue;
4682             }
4683           if (LocaleCompare(attribute,"fuzz") == 0)
4684             {
4685               if (info)
4686                 s=newSVnv(info->image_info->fuzz);
4687               if (image != (Image *) NULL)
4688                 s=newSVnv(image->fuzz);
4689               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4690               continue;
4691             }
4692           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4693             attribute);
4694           break;
4695         }
4696         case 'G':
4697         case 'g':
4698         {
4699           if (LocaleCompare(attribute,"gamma") == 0)
4700             {
4701               if (image != (Image *) NULL)
4702                 s=newSVnv(image->gamma);
4703               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4704               continue;
4705             }
4706           if (LocaleCompare(attribute,"geometry") == 0)
4707             {
4708               if (image && image->geometry)
4709                 s=newSVpv(image->geometry,0);
4710               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4711               continue;
4712             }
4713           if (LocaleCompare(attribute,"gravity") == 0)
4714             {
4715               s=image ? newSViv(image->gravity) : newSViv(0);
4716               (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
4717                 image->gravity));
4718               SvIOK_on(s);
4719               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4720               continue;
4721             }
4722           if (LocaleCompare(attribute,"green-primary") == 0)
4723             {
4724               if (image == (Image *) NULL)
4725                 break;
4726               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4727                 image->chromaticity.green_primary.x,
4728                 image->chromaticity.green_primary.y);
4729               s=newSVpv(color,0);
4730               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4731               continue;
4732             }
4733           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4734             attribute);
4735           break;
4736         }
4737         case 'H':
4738         case 'h':
4739         {
4740           if (LocaleCompare(attribute,"height") == 0)
4741             {
4742               if (image != (Image *) NULL)
4743                 s=newSViv((ssize_t) image->rows);
4744               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4745               continue;
4746             }
4747           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4748             attribute);
4749           break;
4750         }
4751         case 'I':
4752         case 'i':
4753         {
4754           if (LocaleCompare(attribute,"icc") == 0)
4755             {
4756               if (image != (Image *) NULL)
4757                 {
4758                   const StringInfo
4759                     *profile;
4760
4761                   profile=GetImageProfile(image,"icc");
4762                   if (profile != (StringInfo *) NULL)
4763                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4764                       GetStringInfoLength(profile));
4765                 }
4766               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4767               continue;
4768             }
4769           if (LocaleCompare(attribute,"icm") == 0)
4770             {
4771               if (image != (Image *) NULL)
4772                 {
4773                   const StringInfo
4774                     *profile;
4775
4776                   profile=GetImageProfile(image,"icm");
4777                   if (profile != (const StringInfo *) NULL)
4778                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4779                       GetStringInfoLength(profile));
4780                 }
4781               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4782               continue;
4783             }
4784           if (LocaleCompare(attribute,"id") == 0)
4785             {
4786               if (image != (Image *) NULL)
4787                 {
4788                   char
4789                     key[MaxTextExtent];
4790
4791                   MagickBooleanType
4792                     status;
4793
4794                   static ssize_t
4795                     id = 0;
4796
4797                   (void) FormatLocaleString(key,MaxTextExtent,"%.20g\n",(double)
4798                     id);
4799                   status=SetImageRegistry(ImageRegistryType,key,image,
4800                     &image->exception);
4801                   (void) status;
4802                   s=newSViv(id++);
4803                 }
4804               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4805               continue;
4806             }
4807           if (LocaleNCompare(attribute,"index",5) == 0)
4808             {
4809               char
4810                 name[MaxTextExtent];
4811
4812               int
4813                 items;
4814
4815               long
4816                 x,
4817                 y;
4818
4819               register const Quantum
4820                 *p;
4821
4822               CacheView
4823                 *image_view;
4824
4825               if (image == (Image *) NULL)
4826                 break;
4827               if (image->storage_class != PseudoClass)
4828                 break;
4829               x=0;
4830               y=0;
4831               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
4832               (void) items;
4833               image_view=AcquireCacheView(image);
4834               p=GetCacheViewVirtualPixels(image_view,x,y,1,1,&image->exception);
4835               if (p != (const Quantum *) NULL)
4836                 {
4837                   (void) FormatLocaleString(name,MaxTextExtent,QuantumFormat,
4838                     GetPixelIndex(image,p));
4839                   s=newSVpv(name,0);
4840                   PUSHs(s ? sv_2mortal(s) : &sv_undef);
4841                 }
4842               image_view=DestroyCacheView(image_view);
4843               continue;
4844             }
4845           if (LocaleCompare(attribute,"iptc") == 0)
4846             {
4847               if (image != (Image *) NULL)
4848                 {
4849                   const StringInfo
4850                     *profile;
4851
4852                   profile=GetImageProfile(image,"iptc");
4853                   if (profile != (const StringInfo *) NULL)
4854                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4855                       GetStringInfoLength(profile));
4856                 }
4857               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4858               continue;
4859             }
4860           if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
4861             {
4862               if (image != (Image *) NULL)
4863                 s=newSViv((ssize_t) image->iterations);
4864               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4865               continue;
4866             }
4867           if (LocaleCompare(attribute,"interlace") == 0)
4868             {
4869               j=info ? info->image_info->interlace : image ? image->interlace :
4870                 UndefinedInterlace;
4871               s=newSViv(j);
4872               (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
4873                 j));
4874               SvIOK_on(s);
4875               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4876               continue;
4877             }
4878           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4879             attribute);
4880           break;
4881         }
4882         case 'L':
4883         case 'l':
4884         {
4885           if (LocaleCompare(attribute,"label") == 0)
4886             {
4887               const char
4888                 *value;
4889
4890               if (image == (Image *) NULL)
4891                 break;
4892               value=GetImageProperty(image,"Label");
4893               if (value != (const char *) NULL)
4894                 s=newSVpv(value,0);
4895               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4896               continue;
4897             }
4898           if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
4899             {
4900               if (image != (Image *) NULL)
4901                 s=newSViv((ssize_t) image->iterations);
4902               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4903               continue;
4904             }
4905           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4906             attribute);
4907           break;
4908         }
4909         case 'M':
4910         case 'm':
4911         {
4912           if (LocaleCompare(attribute,"magick") == 0)
4913             {
4914               if (info && *info->image_info->magick)
4915                 s=newSVpv(info->image_info->magick,0);
4916               if (image != (Image *) NULL)
4917                 s=newSVpv(image->magick,0);
4918               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4919               continue;
4920             }
4921           if (LocaleCompare(attribute,"map") == 0)
4922             {
4923               s=newSViv(GetMagickResource(MapResource));
4924               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4925               continue;
4926             }
4927           if (LocaleCompare(attribute,"maximum-error") == 0)
4928             {
4929               if (image != (Image *) NULL)
4930                 s=newSVnv(image->error.normalized_maximum_error);
4931               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4932               continue;
4933             }
4934           if (LocaleCompare(attribute,"memory") == 0)
4935             {
4936               s=newSViv(GetMagickResource(MemoryResource));
4937               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4938               continue;
4939             }
4940           if (LocaleCompare(attribute,"mean-error") == 0)
4941             {
4942               if (image != (Image *) NULL)
4943                 s=newSVnv(image->error.normalized_mean_error);
4944               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4945               continue;
4946             }
4947           if (LocaleCompare(attribute,"mime") == 0)
4948             {
4949               if (info && *info->image_info->magick)
4950                 s=newSVpv(MagickToMime(info->image_info->magick),0);
4951               if (image != (Image *) NULL)
4952                 s=newSVpv(MagickToMime(image->magick),0);
4953               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4954               continue;
4955             }
4956           if (LocaleCompare(attribute,"mattecolor") == 0)
4957             {
4958               if (image == (Image *) NULL)
4959                 break;
4960               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4961                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4962                 image->matte_color.red,image->matte_color.green,
4963                 image->matte_color.blue,image->matte_color.alpha);
4964               s=newSVpv(color,0);
4965               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4966               continue;
4967             }
4968           if (LocaleCompare(attribute,"matte") == 0)
4969             {
4970               if (image != (Image *) NULL)
4971                 s=newSViv((ssize_t) image->matte);
4972               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4973               continue;
4974             }
4975           if (LocaleCompare(attribute,"mime") == 0)
4976             {
4977               const char
4978                 *magick;
4979
4980               magick=NULL;
4981               if (info && *info->image_info->magick)
4982                 magick=info->image_info->magick;
4983               if (image != (Image *) NULL)
4984                 magick=image->magick;
4985               if (magick)
4986                 {
4987                   char
4988                     *mime;
4989
4990                   mime=MagickToMime(magick);
4991                   s=newSVpv(mime,0);
4992                   mime=(char *) RelinquishMagickMemory(mime);
4993                 }
4994               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4995               continue;
4996             }
4997           if (LocaleCompare(attribute,"monochrome") == 0)
4998             {
4999               if (image == (Image *) NULL)
5000                 continue;
5001               j=info ? info->image_info->monochrome :
5002                 IsImageMonochrome(image,&image->exception);
5003               s=newSViv(j);
5004               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5005               continue;
5006             }
5007           if (LocaleCompare(attribute,"montage") == 0)
5008             {
5009               if (image && image->montage)
5010                 s=newSVpv(image->montage,0);
5011               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5012               continue;
5013             }
5014           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5015             attribute);
5016           break;
5017         }
5018         case 'O':
5019         case 'o':
5020         {
5021           if (LocaleCompare(attribute,"orientation") == 0)
5022             {
5023               j=info ? info->image_info->orientation : image ?
5024                 image->orientation : UndefinedOrientation;
5025               s=newSViv(j);
5026               (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5027                 j));
5028               SvIOK_on(s);
5029               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5030               continue;
5031             }
5032           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5033             attribute);
5034           break;
5035         }
5036         case 'P':
5037         case 'p':
5038         {
5039           if (LocaleCompare(attribute,"page") == 0)
5040             {
5041               if (info && info->image_info->page)
5042                 s=newSVpv(info->image_info->page,0);
5043               if (image != (Image *) NULL)
5044                 {
5045                   char
5046                     geometry[MaxTextExtent];
5047
5048                   (void) FormatLocaleString(geometry,MaxTextExtent,
5049                     "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5050                     (double) image->page.height,(double) image->page.x,(double)
5051                     image->page.y);
5052                   s=newSVpv(geometry,0);
5053                 }
5054               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5055               continue;
5056             }
5057           if (LocaleCompare(attribute,"page.x") == 0)
5058             {
5059               if (image != (Image *) NULL)
5060                 s=newSViv((ssize_t) image->page.x);
5061               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5062               continue;
5063             }
5064           if (LocaleCompare(attribute,"page.y") == 0)
5065             {
5066               if (image != (Image *) NULL)
5067                 s=newSViv((ssize_t) image->page.y);
5068               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5069               continue;
5070             }
5071           if (LocaleNCompare(attribute,"pixel",5) == 0)
5072             {
5073               char
5074                 tuple[MaxTextExtent];
5075
5076               int
5077                 items;
5078
5079               long
5080                 x,
5081                 y;
5082
5083               register const Quantum
5084                 *p;
5085
5086               if (image == (Image *) NULL)
5087                 break;
5088               x=0;
5089               y=0;
5090               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5091               (void) items;
5092               p=GetVirtualPixels(image,x,y,1,1,exception);
5093               if (image->colorspace != CMYKColorspace)
5094                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5095                   QuantumFormat "," QuantumFormat "," QuantumFormat,
5096                   GetPixelRed(image,p),GetPixelGreen(image,p),
5097                   GetPixelBlue(image,p),GetPixelAlpha(image,p));
5098               else
5099                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5100                   QuantumFormat "," QuantumFormat "," QuantumFormat ","
5101                   QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5102                   GetPixelBlue(image,p),GetPixelBlack(image,p),
5103                   GetPixelAlpha(image,p));
5104               s=newSVpv(tuple,0);
5105               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5106               continue;
5107             }
5108           if (LocaleCompare(attribute,"pointsize") == 0)
5109             {
5110               if (info)
5111                 s=newSViv((ssize_t) info->image_info->pointsize);
5112               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5113               continue;
5114             }
5115           if (LocaleCompare(attribute,"preview") == 0)
5116             {
5117               s=newSViv(info->image_info->preview_type);
5118               (void) sv_setpv(s,CommandOptionToMnemonic(MagickPreviewOptions,
5119                 info->image_info->preview_type));
5120               SvIOK_on(s);
5121               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5122               continue;
5123             }
5124           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5125             attribute);
5126           break;
5127         }
5128         case 'Q':
5129         case 'q':
5130         {
5131           if (LocaleCompare(attribute,"quality") == 0)
5132             {
5133               if (info)
5134                 s=newSViv((ssize_t) info->image_info->quality);
5135               if (image != (Image *) NULL)
5136                 s=newSViv((ssize_t) image->quality);
5137               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5138               continue;
5139             }
5140           if (LocaleCompare(attribute,"quantum") == 0)
5141             {
5142               if (info)
5143                 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5144               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5145               continue;
5146             }
5147           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5148             attribute);
5149           break;
5150         }
5151         case 'R':
5152         case 'r':
5153         {
5154           if (LocaleCompare(attribute,"rendering-intent") == 0)
5155             {
5156               s=newSViv(image->rendering_intent);
5157               (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5158                 image->rendering_intent));
5159               SvIOK_on(s);
5160               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5161               continue;
5162             }
5163           if (LocaleCompare(attribute,"red-primary") == 0)
5164             {
5165               if (image == (Image *) NULL)
5166                 break;
5167               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5168                 image->chromaticity.red_primary.x,
5169                 image->chromaticity.red_primary.y);
5170               s=newSVpv(color,0);
5171               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5172               continue;
5173             }
5174           if (LocaleCompare(attribute,"rows") == 0)
5175             {
5176               if (image != (Image *) NULL)
5177                 s=newSViv((ssize_t) image->rows);
5178               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5179               continue;
5180             }
5181           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5182             attribute);
5183           break;
5184         }
5185         case 'S':
5186         case 's':
5187         {
5188           if (LocaleCompare(attribute,"sampling-factor") == 0)
5189             {
5190               if (info && info->image_info->sampling_factor)
5191                 s=newSVpv(info->image_info->sampling_factor,0);
5192               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5193               continue;
5194             }
5195           if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5196             {
5197               if (info && info->image_info->server_name)
5198                 s=newSVpv(info->image_info->server_name,0);
5199               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5200               continue;
5201             }
5202           if (LocaleCompare(attribute,"size") == 0)
5203             {
5204               if (info && info->image_info->size)
5205                 s=newSVpv(info->image_info->size,0);
5206               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5207               continue;
5208             }
5209           if (LocaleCompare(attribute,"scene") == 0)
5210             {
5211               if (image != (Image *) NULL)
5212                 s=newSViv((ssize_t) image->scene);
5213               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5214               continue;
5215             }
5216           if (LocaleCompare(attribute,"scenes") == 0)
5217             {
5218               if (image != (Image *) NULL)
5219                 s=newSViv((ssize_t) info->image_info->number_scenes);
5220               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5221               continue;
5222             }
5223           if (LocaleCompare(attribute,"signature") == 0)
5224             {
5225               const char
5226                 *value;
5227
5228               if (image == (Image *) NULL)
5229                 break;
5230               (void) SignatureImage(image,exception);
5231               value=GetImageProperty(image,"Signature");
5232               if (value != (const char *) NULL)
5233                 s=newSVpv(value,0);
5234               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5235               continue;
5236             }
5237           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5238             attribute);
5239           break;
5240         }
5241         case 'T':
5242         case 't':
5243         {
5244           if (LocaleCompare(attribute,"taint") == 0)
5245             {
5246               if (image != (Image *) NULL)
5247                 s=newSViv((ssize_t) IsTaintImage(image));
5248               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5249               continue;
5250             }
5251           if (LocaleCompare(attribute,"texture") == 0)
5252             {
5253               if (info && info->image_info->texture)
5254                 s=newSVpv(info->image_info->texture,0);
5255               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5256               continue;
5257             }
5258           if (LocaleCompare(attribute,"total-ink-density") == 0)
5259             {
5260               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5261               if (image != (Image *) NULL)
5262                 s=newSVnv(GetImageTotalInkDensity(image));
5263               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5264               continue;
5265             }
5266           if (LocaleCompare(attribute,"transparent-color") == 0)
5267             {
5268               if (image == (Image *) NULL)
5269                 break;
5270               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
5271                 QuantumFormat "," QuantumFormat "," QuantumFormat,
5272                 image->transparent_color.red,image->transparent_color.green,
5273                 image->transparent_color.blue,image->transparent_color.alpha);
5274               s=newSVpv(color,0);
5275               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5276               continue;
5277             }
5278           if (LocaleCompare(attribute,"type") == 0)
5279             {
5280               if (image == (Image *) NULL)
5281                 break;
5282               j=(ssize_t) GetImageType(image,&image->exception);
5283               s=newSViv(j);
5284               (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5285               SvIOK_on(s);
5286               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5287               continue;
5288             }
5289           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5290             attribute);
5291           break;
5292         }
5293         case 'U':
5294         case 'u':
5295         {
5296           if (LocaleCompare(attribute,"units") == 0)
5297             {
5298               j=info ? info->image_info->units : image ? image->units :
5299                 UndefinedResolution;
5300               if (info && (info->image_info->units == UndefinedResolution))
5301                 if (image)
5302                   j=image->units;
5303               if (j == UndefinedResolution)
5304                 s=newSVpv("undefined units",0);
5305               else
5306                 if (j == PixelsPerInchResolution)
5307                   s=newSVpv("pixels / inch",0);
5308                 else
5309                   s=newSVpv("pixels / centimeter",0);
5310               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5311               continue;
5312             }
5313           if (LocaleCompare(attribute,"user-time") == 0)
5314             {
5315               if (image != (Image *) NULL)
5316                 s=newSVnv(GetUserTime(&image->timer));
5317               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5318               continue;
5319             }
5320           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5321             attribute);
5322           break;
5323         }
5324         case 'V':
5325         case 'v':
5326         {
5327           if (LocaleCompare(attribute,"verbose") == 0)
5328             {
5329               if (info)
5330                 s=newSViv((ssize_t) info->image_info->verbose);
5331               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5332               continue;
5333             }
5334           if (LocaleCompare(attribute,"version") == 0)
5335             {
5336               s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5337               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5338               continue;
5339             }
5340           if (LocaleCompare(attribute,"view") == 0)
5341             {
5342               if (info && info->image_info->view)
5343                 s=newSVpv(info->image_info->view,0);
5344               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5345               continue;
5346             }
5347           if (LocaleCompare(attribute,"virtual-pixel") == 0)
5348             {
5349               if (image == (Image *) NULL)
5350                 break;
5351               j=(ssize_t) GetImageVirtualPixelMethod(image);
5352               s=newSViv(j);
5353               (void) sv_setpv(s,CommandOptionToMnemonic(
5354                 MagickVirtualPixelOptions,j));
5355               SvIOK_on(s);
5356               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5357               continue;
5358             }
5359           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5360             attribute);
5361           break;
5362         }
5363         case 'W':
5364         case 'w':
5365         {
5366           if (LocaleCompare(attribute,"white-point") == 0)
5367             {
5368               if (image == (Image *) NULL)
5369                 break;
5370               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5371                 image->chromaticity.white_point.x,
5372                 image->chromaticity.white_point.y);
5373               s=newSVpv(color,0);
5374               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5375               continue;
5376             }
5377           if (LocaleCompare(attribute,"width") == 0)
5378             {
5379               if (image != (Image *) NULL)
5380                 s=newSViv((ssize_t) image->columns);
5381               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5382               continue;
5383             }
5384           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5385              attribute);
5386           break;
5387         }
5388         case 'X':
5389         case 'x':
5390         {
5391           if (LocaleCompare(attribute,"x-resolution") == 0)
5392             {
5393               if (image != (Image *) NULL)
5394                 s=newSVnv(image->x_resolution);
5395               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5396               continue;
5397             }
5398           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5399             attribute);
5400           break;
5401         }
5402         case 'Y':
5403         case 'y':
5404         {
5405           if (LocaleCompare(attribute,"y-resolution") == 0)
5406             {
5407               if (image != (Image *) NULL)
5408                 s=newSVnv(image->y_resolution);
5409               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5410               continue;
5411             }
5412           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5413             attribute);
5414           break;
5415         }
5416         default:
5417           break;
5418       }
5419       if (image == (Image *) NULL)
5420         ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5421           attribute)
5422       else
5423         {
5424           value=GetImageProperty(image,attribute);
5425           if (value != (const char *) NULL)
5426             {
5427               s=newSVpv(value,0);
5428               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5429             }
5430           else
5431             if (*attribute != '%')
5432               ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5433                 attribute)
5434             else
5435               {
5436                  char
5437                    *meta;
5438
5439                  meta=InterpretImageProperties(info ? info->image_info :
5440                    (ImageInfo *) NULL,image,attribute,exception);
5441                  s=newSVpv(meta,0);
5442                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5443                  meta=(char *) RelinquishMagickMemory(meta);
5444               }
5445         }
5446     }
5447     exception=DestroyExceptionInfo(exception);
5448     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5449   }
5450 \f
5451 #
5452 ###############################################################################
5453 #                                                                             #
5454 #                                                                             #
5455 #                                                                             #
5456 #   G e t A u t h e n t i c P i x e l s                                       #
5457 #                                                                             #
5458 #                                                                             #
5459 #                                                                             #
5460 ###############################################################################
5461 #
5462 #
5463 void *
5464 GetAuthenticPixels(ref,...)
5465   Image::Magick ref = NO_INIT
5466   ALIAS:
5467     getauthenticpixels = 1
5468     GetImagePixels = 2
5469     getimagepixels = 3
5470   CODE:
5471   {
5472     char
5473       *attribute;
5474
5475     ExceptionInfo
5476       *exception;
5477
5478     Image
5479       *image;
5480
5481     RectangleInfo
5482       region;
5483
5484     ssize_t
5485       i;
5486
5487     struct PackageInfo
5488       *info;
5489
5490     SV
5491       *perl_exception,
5492       *reference;
5493
5494     void
5495       *blob = NULL;
5496
5497     PERL_UNUSED_VAR(ref);
5498     PERL_UNUSED_VAR(ix);
5499     exception=AcquireExceptionInfo();
5500     perl_exception=newSVpv("",0);
5501     if (sv_isobject(ST(0)) == 0)
5502       {
5503         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5504           PackageName);
5505         goto PerlException;
5506       }
5507     reference=SvRV(ST(0));
5508
5509     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5510     if (image == (Image *) NULL)
5511       {
5512         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5513           PackageName);
5514         goto PerlException;
5515       }
5516
5517     region.x=0;
5518     region.y=0;
5519     region.width=image->columns;
5520     region.height=1;
5521     if (items == 1)
5522       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5523     for (i=2; i < items; i+=2)
5524     {
5525       attribute=(char *) SvPV(ST(i-1),na);
5526       switch (*attribute)
5527       {
5528         case 'g':
5529         case 'G':
5530         {
5531           if (LocaleCompare(attribute,"geometry") == 0)
5532             {
5533               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5534               break;
5535             }
5536           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5537             attribute);
5538           break;
5539         }
5540         case 'H':
5541         case 'h':
5542         {
5543           if (LocaleCompare(attribute,"height") == 0)
5544             {
5545               region.height=SvIV(ST(i));
5546               continue;
5547             }
5548           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5549             attribute);
5550           break;
5551         }
5552         case 'X':
5553         case 'x':
5554         {
5555           if (LocaleCompare(attribute,"x") == 0)
5556             {
5557               region.x=SvIV(ST(i));
5558               continue;
5559             }
5560           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5561             attribute);
5562           break;
5563         }
5564         case 'Y':
5565         case 'y':
5566         {
5567           if (LocaleCompare(attribute,"y") == 0)
5568             {
5569               region.y=SvIV(ST(i));
5570               continue;
5571             }
5572           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5573             attribute);
5574           break;
5575         }
5576         case 'W':
5577         case 'w':
5578         {
5579           if (LocaleCompare(attribute,"width") == 0)
5580             {
5581               region.width=SvIV(ST(i));
5582               continue;
5583             }
5584           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5585             attribute);
5586           break;
5587         }
5588       }
5589     }
5590     blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5591       region.height,exception);
5592     if (blob != (void *) NULL)
5593       goto PerlEnd;
5594
5595   PerlException:
5596     InheritPerlException(exception,perl_exception);
5597     exception=DestroyExceptionInfo(exception);
5598     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5599
5600   PerlEnd:
5601     RETVAL = blob;
5602   }
5603   OUTPUT:
5604     RETVAL
5605 \f
5606 #
5607 ###############################################################################
5608 #                                                                             #
5609 #                                                                             #
5610 #                                                                             #
5611 #   G e t V i r t u a l P i x e l s                                           #
5612 #                                                                             #
5613 #                                                                             #
5614 #                                                                             #
5615 ###############################################################################
5616 #
5617 #
5618 void *
5619 GetVirtualPixels(ref,...)
5620   Image::Magick ref = NO_INIT
5621   ALIAS:
5622     getvirtualpixels = 1
5623     AcquireImagePixels = 2
5624     acquireimagepixels = 3
5625   CODE:
5626   {
5627     char
5628       *attribute;
5629
5630     const void
5631       *blob = NULL;
5632
5633     ExceptionInfo
5634       *exception;
5635
5636     Image
5637       *image;
5638
5639     RectangleInfo
5640       region;
5641
5642     ssize_t
5643       i;
5644
5645     struct PackageInfo
5646       *info;
5647
5648     SV
5649       *perl_exception,
5650       *reference;
5651
5652     PERL_UNUSED_VAR(ref);
5653     PERL_UNUSED_VAR(ix);
5654     exception=AcquireExceptionInfo();
5655     perl_exception=newSVpv("",0);
5656     if (sv_isobject(ST(0)) == 0)
5657       {
5658         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5659           PackageName);
5660         goto PerlException;
5661       }
5662     reference=SvRV(ST(0));
5663
5664     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5665     if (image == (Image *) NULL)
5666       {
5667         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5668           PackageName);
5669         goto PerlException;
5670       }
5671
5672     region.x=0;
5673     region.y=0;
5674     region.width=image->columns;
5675     region.height=1;
5676     if (items == 1)
5677       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5678     for (i=2; i < items; i+=2)
5679     {
5680       attribute=(char *) SvPV(ST(i-1),na);
5681       switch (*attribute)
5682       {
5683         case 'g':
5684         case 'G':
5685         {
5686           if (LocaleCompare(attribute,"geometry") == 0)
5687             {
5688               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5689               break;
5690             }
5691           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5692             attribute);
5693           break;
5694         }
5695         case 'H':
5696         case 'h':
5697         {
5698           if (LocaleCompare(attribute,"height") == 0)
5699             {
5700               region.height=SvIV(ST(i));
5701               continue;
5702             }
5703           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5704             attribute);
5705           break;
5706         }
5707         case 'X':
5708         case 'x':
5709         {
5710           if (LocaleCompare(attribute,"x") == 0)
5711             {
5712               region.x=SvIV(ST(i));
5713               continue;
5714             }
5715           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5716             attribute);
5717           break;
5718         }
5719         case 'Y':
5720         case 'y':
5721         {
5722           if (LocaleCompare(attribute,"y") == 0)
5723             {
5724               region.y=SvIV(ST(i));
5725               continue;
5726             }
5727           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5728             attribute);
5729           break;
5730         }
5731         case 'W':
5732         case 'w':
5733         {
5734           if (LocaleCompare(attribute,"width") == 0)
5735             {
5736               region.width=SvIV(ST(i));
5737               continue;
5738             }
5739           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5740             attribute);
5741           break;
5742         }
5743       }
5744     }
5745     blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
5746       region.height,exception);
5747     if (blob != (void *) NULL)
5748       goto PerlEnd;
5749
5750   PerlException:
5751     InheritPerlException(exception,perl_exception);
5752     exception=DestroyExceptionInfo(exception);
5753     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5754
5755   PerlEnd:
5756     RETVAL = (void *) blob;
5757   }
5758   OUTPUT:
5759     RETVAL
5760 \f
5761 #
5762 ###############################################################################
5763 #                                                                             #
5764 #                                                                             #
5765 #                                                                             #
5766 #   G e t A u t h e n t i c M e t a c o n t e n t                             #
5767 #                                                                             #
5768 #                                                                             #
5769 #                                                                             #
5770 ###############################################################################
5771 #
5772 #
5773 void *
5774 GetAuthenticMetacontent(ref,...)
5775   Image::Magick ref = NO_INIT
5776   ALIAS:
5777     getauthenticmetacontent = 1
5778     GetMetacontent = 2
5779     getmetacontent = 3
5780   CODE:
5781   {
5782     ExceptionInfo
5783       *exception;
5784
5785     Image
5786       *image;
5787
5788     struct PackageInfo
5789       *info;
5790
5791     SV
5792       *perl_exception,
5793       *reference;
5794
5795     void
5796       *blob = NULL;
5797
5798     PERL_UNUSED_VAR(ref);
5799     PERL_UNUSED_VAR(ix);
5800     exception=AcquireExceptionInfo();
5801     perl_exception=newSVpv("",0);
5802     if (sv_isobject(ST(0)) == 0)
5803       {
5804         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5805           PackageName);
5806         goto PerlException;
5807       }
5808     reference=SvRV(ST(0));
5809
5810     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5811     if (image == (Image *) NULL)
5812       {
5813         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5814           PackageName);
5815         goto PerlException;
5816       }
5817
5818     blob=(void *) GetAuthenticMetacontent(image);
5819     if (blob != (void *) NULL)
5820       goto PerlEnd;
5821
5822   PerlException:
5823     InheritPerlException(exception,perl_exception);
5824     exception=DestroyExceptionInfo(exception);
5825     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5826
5827   PerlEnd:
5828     RETVAL = blob;
5829   }
5830   OUTPUT:
5831     RETVAL
5832 \f
5833 #
5834 ###############################################################################
5835 #                                                                             #
5836 #                                                                             #
5837 #                                                                             #
5838 #   G e t V i r t u a l M e t a c o n t e n t                                 #
5839 #                                                                             #
5840 #                                                                             #
5841 #                                                                             #
5842 ###############################################################################
5843 #
5844 #
5845 void *
5846 GetVirtualMetacontent(ref,...)
5847   Image::Magick ref = NO_INIT
5848   ALIAS:
5849     getvirtualmetacontent = 1
5850   CODE:
5851   {
5852     ExceptionInfo
5853       *exception;
5854
5855     Image
5856       *image;
5857
5858     struct PackageInfo
5859       *info;
5860
5861     SV
5862       *perl_exception,
5863       *reference;
5864
5865     void
5866       *blob = NULL;
5867
5868     PERL_UNUSED_VAR(ref);
5869     PERL_UNUSED_VAR(ix);
5870     exception=AcquireExceptionInfo();
5871     perl_exception=newSVpv("",0);
5872     if (sv_isobject(ST(0)) == 0)
5873       {
5874         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5875           PackageName);
5876         goto PerlException;
5877       }
5878     reference=SvRV(ST(0));
5879
5880     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5881     if (image == (Image *) NULL)
5882       {
5883         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5884           PackageName);
5885         goto PerlException;
5886       }
5887
5888     blob=(void *) GetVirtualMetacontent(image);
5889     if (blob != (void *) NULL)
5890       goto PerlEnd;
5891
5892   PerlException:
5893     InheritPerlException(exception,perl_exception);
5894     exception=DestroyExceptionInfo(exception);
5895     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5896
5897   PerlEnd:
5898     RETVAL = blob;
5899   }
5900   OUTPUT:
5901     RETVAL
5902 \f
5903 #
5904 ###############################################################################
5905 #                                                                             #
5906 #                                                                             #
5907 #                                                                             #
5908 #   H i s t o g r a m                                                         #
5909 #                                                                             #
5910 #                                                                             #
5911 #                                                                             #
5912 ###############################################################################
5913 #
5914 #
5915 void
5916 Histogram(ref,...)
5917   Image::Magick ref=NO_INIT
5918   ALIAS:
5919     HistogramImage = 1
5920     histogram      = 2
5921     histogramimage = 3
5922   PPCODE:
5923   {
5924     AV
5925       *av;
5926
5927     char
5928       message[MaxTextExtent];
5929
5930     PixelPacket
5931       *histogram;
5932
5933     ExceptionInfo
5934       *exception;
5935
5936     Image
5937       *image;
5938
5939     register ssize_t
5940       i;
5941
5942     ssize_t
5943       count;
5944
5945     struct PackageInfo
5946       *info;
5947
5948     SV
5949       *perl_exception,
5950       *reference;
5951
5952     size_t
5953       number_colors;
5954
5955     PERL_UNUSED_VAR(ref);
5956     PERL_UNUSED_VAR(ix);
5957     exception=AcquireExceptionInfo();
5958     perl_exception=newSVpv("",0);
5959     av=NULL;
5960     if (sv_isobject(ST(0)) == 0)
5961       {
5962         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5963           PackageName);
5964         goto PerlException;
5965       }
5966     reference=SvRV(ST(0));
5967     av=newAV();
5968     SvREFCNT_dec(av);
5969     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5970     if (image == (Image *) NULL)
5971       {
5972         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5973           PackageName);
5974         goto PerlException;
5975       }
5976     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
5977     count=0;
5978     for ( ; image; image=image->next)
5979     {
5980       histogram=GetImageHistogram(image,&number_colors,&image->exception);
5981       if (histogram == (PixelPacket *) NULL)
5982         continue;
5983       count+=(ssize_t) number_colors;
5984       EXTEND(sp,6*count);
5985       for (i=0; i < (ssize_t) number_colors; i++)
5986       {
5987         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
5988           histogram[i].red);
5989         PUSHs(sv_2mortal(newSVpv(message,0)));
5990         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
5991           histogram[i].green);
5992         PUSHs(sv_2mortal(newSVpv(message,0)));
5993         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
5994           histogram[i].blue);
5995         PUSHs(sv_2mortal(newSVpv(message,0)));
5996         if (image->colorspace == CMYKColorspace)
5997           {
5998             (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
5999               histogram[i].black);
6000             PUSHs(sv_2mortal(newSVpv(message,0)));
6001           }
6002         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
6003           histogram[i].alpha);
6004         PUSHs(sv_2mortal(newSVpv(message,0)));
6005         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
6006           histogram[i].count);
6007         PUSHs(sv_2mortal(newSVpv(message,0)));
6008       }
6009       histogram=(PixelPacket *) RelinquishMagickMemory(histogram);
6010     }
6011
6012   PerlException:
6013     InheritPerlException(exception,perl_exception);
6014     exception=DestroyExceptionInfo(exception);
6015     SvREFCNT_dec(perl_exception);
6016   }
6017 \f
6018 #
6019 ###############################################################################
6020 #                                                                             #
6021 #                                                                             #
6022 #                                                                             #
6023 #   G e t P i x e l                                                           #
6024 #                                                                             #
6025 #                                                                             #
6026 #                                                                             #
6027 ###############################################################################
6028 #
6029 #
6030 void
6031 GetPixel(ref,...)
6032   Image::Magick ref=NO_INIT
6033   ALIAS:
6034     getpixel = 1
6035     getPixel = 2
6036   PPCODE:
6037   {
6038     AV
6039       *av;
6040
6041     char
6042       *attribute;
6043
6044     ExceptionInfo
6045       *exception;
6046
6047     Image
6048       *image;
6049
6050     MagickBooleanType
6051       normalize;
6052
6053     RectangleInfo
6054       region;
6055
6056     register const Quantum
6057       *p;
6058
6059     register ssize_t
6060       i;
6061
6062     ssize_t
6063       option;
6064
6065     struct PackageInfo
6066       *info;
6067
6068     SV
6069       *perl_exception,
6070       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6071
6072     PERL_UNUSED_VAR(ref);
6073     PERL_UNUSED_VAR(ix);
6074     exception=AcquireExceptionInfo();
6075     perl_exception=newSVpv("",0);
6076     reference=SvRV(ST(0));
6077     av=(AV *) reference;
6078     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6079       exception);
6080     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6081     if (image == (Image *) NULL)
6082       {
6083         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6084           PackageName);
6085         goto PerlException;
6086       }
6087     normalize=MagickTrue;
6088     region.x=0;
6089     region.y=0;
6090     region.width=image->columns;
6091     region.height=1;
6092     if (items == 1)
6093       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6094     for (i=2; i < items; i+=2)
6095     {
6096       attribute=(char *) SvPV(ST(i-1),na);
6097       switch (*attribute)
6098       {
6099         case 'C':
6100         case 'c':
6101         {
6102           if (LocaleCompare(attribute,"channel") == 0)
6103             {
6104               ssize_t
6105                 option;
6106
6107               option=ParseChannelOption(SvPV(ST(i),na));
6108               if (option < 0)
6109                 {
6110                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6111                     SvPV(ST(i),na));
6112                   return;
6113                 }
6114               SetPixelChannelMap(image,(ChannelType) option);
6115               break;
6116             }
6117           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6118             attribute);
6119           break;
6120         }
6121         case 'g':
6122         case 'G':
6123         {
6124           if (LocaleCompare(attribute,"geometry") == 0)
6125             {
6126               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6127               break;
6128             }
6129           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6130             attribute);
6131           break;
6132         }
6133         case 'N':
6134         case 'n':
6135         {
6136           if (LocaleCompare(attribute,"normalize") == 0)
6137             {
6138               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6139                 SvPV(ST(i),na));
6140               if (option < 0)
6141                 {
6142                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6143                     SvPV(ST(i),na));
6144                   break;
6145                 }
6146              normalize=option != 0 ? MagickTrue : MagickFalse;
6147              break;
6148             }
6149           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6150             attribute);
6151           break;
6152         }
6153         case 'x':
6154         case 'X':
6155         {
6156           if (LocaleCompare(attribute,"x") == 0)
6157             {
6158               region.x=SvIV(ST(i));
6159               break;
6160             }
6161           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6162             attribute);
6163           break;
6164         }
6165         case 'y':
6166         case 'Y':
6167         {
6168           if (LocaleCompare(attribute,"y") == 0)
6169             {
6170               region.y=SvIV(ST(i));
6171               break;
6172             }
6173           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6174             attribute);
6175           break;
6176         }
6177         default:
6178         {
6179           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6180             attribute);
6181           break;
6182         }
6183       }
6184     }
6185     p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6186     if (p == (const Quantum *) NULL)
6187       PUSHs(&sv_undef);
6188     else
6189       {
6190         double
6191           scale;
6192
6193         scale=1.0;
6194         if (normalize != MagickFalse)
6195           scale=1.0/QuantumRange;
6196         if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
6197           PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6198         if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6199           PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6200         if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6201           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6202         if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6203             (image->colorspace == CMYKColorspace))
6204           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6205         if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
6206           PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6207       }
6208
6209   PerlException:
6210     InheritPerlException(exception,perl_exception);
6211     exception=DestroyExceptionInfo(exception);
6212     SvREFCNT_dec(perl_exception);
6213   }
6214 \f
6215 #
6216 ###############################################################################
6217 #                                                                             #
6218 #                                                                             #
6219 #                                                                             #
6220 #   G e t P i x e l s                                                         #
6221 #                                                                             #
6222 #                                                                             #
6223 #                                                                             #
6224 ###############################################################################
6225 #
6226 #
6227 void
6228 GetPixels(ref,...)
6229   Image::Magick ref=NO_INIT
6230   ALIAS:
6231     getpixels = 1
6232     getPixels = 2
6233   PPCODE:
6234   {
6235     AV
6236       *av;
6237
6238     char
6239       *attribute;
6240
6241     const char
6242       *map;
6243
6244     ExceptionInfo
6245       *exception;
6246
6247     Image
6248       *image;
6249
6250     MagickBooleanType
6251       normalize,
6252       status;
6253
6254     RectangleInfo
6255       region;
6256
6257     register ssize_t
6258       i;
6259
6260     ssize_t
6261       option;
6262
6263     struct PackageInfo
6264       *info;
6265
6266     SV
6267       *perl_exception,
6268       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6269
6270     PERL_UNUSED_VAR(ref);
6271     PERL_UNUSED_VAR(ix);
6272     exception=AcquireExceptionInfo();
6273     perl_exception=newSVpv("",0);
6274     reference=SvRV(ST(0));
6275     av=(AV *) reference;
6276     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6277       exception);
6278     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6279     if (image == (Image *) NULL)
6280       {
6281         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6282           PackageName);
6283         goto PerlException;
6284       }
6285     map="RGB";
6286     if (image->matte != MagickFalse)
6287       map="RGBA";
6288     if (image->colorspace == CMYKColorspace)
6289       {
6290         map="CMYK";
6291         if (image->matte != MagickFalse)
6292           map="CMYKA";
6293       }
6294     normalize=MagickFalse;
6295     region.x=0;
6296     region.y=0;
6297     region.width=image->columns;
6298     region.height=1;
6299     if (items == 1)
6300       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6301     for (i=2; i < items; i+=2)
6302     {
6303       attribute=(char *) SvPV(ST(i-1),na);
6304       switch (*attribute)
6305       {
6306         case 'g':
6307         case 'G':
6308         {
6309           if (LocaleCompare(attribute,"geometry") == 0)
6310             {
6311               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6312               break;
6313             }
6314           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6315             attribute);
6316           break;
6317         }
6318         case 'H':
6319         case 'h':
6320         {
6321           if (LocaleCompare(attribute,"height") == 0)
6322             {
6323               region.height=SvIV(ST(i));
6324               break;
6325             }
6326           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6327             attribute);
6328           break;
6329         }
6330         case 'M':
6331         case 'm':
6332         {
6333           if (LocaleCompare(attribute,"map") == 0)
6334             {
6335               map=SvPV(ST(i),na);
6336               break;
6337             }
6338           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6339             attribute);
6340           break;
6341         }
6342         case 'N':
6343         case 'n':
6344         {
6345           if (LocaleCompare(attribute,"normalize") == 0)
6346             {
6347               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6348                 SvPV(ST(i),na));
6349               if (option < 0)
6350                 {
6351                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6352                     SvPV(ST(i),na));
6353                   break;
6354                 }
6355              normalize=option != 0 ? MagickTrue : MagickFalse;
6356              break;
6357             }
6358           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6359             attribute);
6360           break;
6361         }
6362         case 'W':
6363         case 'w':
6364         {
6365           if (LocaleCompare(attribute,"width") == 0)
6366             {
6367               region.width=SvIV(ST(i));
6368               break;
6369             }
6370           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6371             attribute);
6372           break;
6373         }
6374         case 'x':
6375         case 'X':
6376         {
6377           if (LocaleCompare(attribute,"x") == 0)
6378             {
6379               region.x=SvIV(ST(i));
6380               break;
6381             }
6382           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6383             attribute);
6384           break;
6385         }
6386         case 'y':
6387         case 'Y':
6388         {
6389           if (LocaleCompare(attribute,"y") == 0)
6390             {
6391               region.y=SvIV(ST(i));
6392               break;
6393             }
6394           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6395             attribute);
6396           break;
6397         }
6398         default:
6399         {
6400           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6401             attribute);
6402           break;
6403         }
6404       }
6405     }
6406     if (normalize != MagickFalse)
6407       {
6408         float
6409           *pixels;
6410
6411         pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6412           region.height*sizeof(*pixels));
6413         if (pixels == (float *) NULL)
6414           {
6415             ThrowPerlException(exception,ResourceLimitError,
6416               "MemoryAllocationFailed",PackageName);
6417             goto PerlException;
6418           }
6419         status=ExportImagePixels(image,region.x,region.y,region.width,
6420           region.height,map,FloatPixel,pixels,exception);
6421         if (status == MagickFalse)
6422           PUSHs(&sv_undef);
6423         else
6424           {
6425             EXTEND(sp,strlen(map)*region.width*region.height);
6426             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6427               PUSHs(sv_2mortal(newSVnv(pixels[i])));
6428           }
6429         pixels=(float *) RelinquishMagickMemory(pixels);
6430       }
6431     else
6432       {
6433         Quantum
6434           *pixels;
6435
6436         pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6437           region.height*sizeof(*pixels));
6438         if (pixels == (Quantum *) NULL)
6439           {
6440             ThrowPerlException(exception,ResourceLimitError,
6441               "MemoryAllocationFailed",PackageName);
6442             goto PerlException;
6443           }
6444         status=ExportImagePixels(image,region.x,region.y,region.width,
6445           region.height,map,QuantumPixel,pixels,exception);
6446         if (status == MagickFalse)
6447           PUSHs(&sv_undef);
6448         else
6449           {
6450             EXTEND(sp,strlen(map)*region.width*region.height);
6451             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6452               PUSHs(sv_2mortal(newSViv(pixels[i])));
6453           }
6454         pixels=(Quantum *) RelinquishMagickMemory(pixels);
6455       }
6456
6457   PerlException:
6458     InheritPerlException(exception,perl_exception);
6459     exception=DestroyExceptionInfo(exception);
6460     SvREFCNT_dec(perl_exception);
6461   }
6462 \f
6463 #
6464 ###############################################################################
6465 #                                                                             #
6466 #                                                                             #
6467 #                                                                             #
6468 #   I m a g e T o B l o b                                                     #
6469 #                                                                             #
6470 #                                                                             #
6471 #                                                                             #
6472 ###############################################################################
6473 #
6474 #
6475 void
6476 ImageToBlob(ref,...)
6477   Image::Magick ref=NO_INIT
6478   ALIAS:
6479     ImageToBlob  = 1
6480     imagetoblob  = 2
6481     toblob       = 3
6482     blob         = 4
6483   PPCODE:
6484   {
6485     char
6486       filename[MaxTextExtent];
6487
6488     ExceptionInfo
6489       *exception;
6490
6491     Image
6492       *image,
6493       *next;
6494
6495     register ssize_t
6496       i;
6497
6498     struct PackageInfo
6499       *info,
6500       *package_info;
6501
6502     size_t
6503       length;
6504
6505     ssize_t
6506       scene;
6507
6508     SV
6509       *perl_exception,
6510       *reference;
6511
6512     void
6513       *blob;
6514
6515     PERL_UNUSED_VAR(ref);
6516     PERL_UNUSED_VAR(ix);
6517     exception=AcquireExceptionInfo();
6518     perl_exception=newSVpv("",0);
6519     package_info=(struct PackageInfo *) NULL;
6520     if (sv_isobject(ST(0)) == 0)
6521       {
6522         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6523           PackageName);
6524         goto PerlException;
6525       }
6526     reference=SvRV(ST(0));
6527     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6528     if (image == (Image *) NULL)
6529       {
6530         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6531           PackageName);
6532         goto PerlException;
6533       }
6534     package_info=ClonePackageInfo(info,exception);
6535     for (i=2; i < items; i+=2)
6536       SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6537     (void) CopyMagickString(filename,package_info->image_info->filename,
6538       MaxTextExtent);
6539     scene=0;
6540     for (next=image; next; next=next->next)
6541     {
6542       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
6543       next->scene=scene++;
6544     }
6545     SetImageInfo(package_info->image_info,(unsigned int)
6546       GetImageListLength(image),&image->exception);
6547     EXTEND(sp,(ssize_t) GetImageListLength(image));
6548     for ( ; image; image=image->next)
6549     {
6550       length=0;
6551       blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6552       if (blob != (char *) NULL)
6553         {
6554           PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6555           blob=(unsigned char *) RelinquishMagickMemory(blob);
6556         }
6557       if (package_info->image_info->adjoin)
6558         break;
6559     }
6560
6561   PerlException:
6562     if (package_info != (struct PackageInfo *) NULL)
6563       DestroyPackageInfo(package_info);
6564     InheritPerlException(exception,perl_exception);
6565     exception=DestroyExceptionInfo(exception);
6566     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6567   }
6568 \f
6569 #
6570 ###############################################################################
6571 #                                                                             #
6572 #                                                                             #
6573 #                                                                             #
6574 #   L a y e r s                                                               #
6575 #                                                                             #
6576 #                                                                             #
6577 #                                                                             #
6578 ###############################################################################
6579 #
6580 #
6581 void
6582 Layers(ref,...)
6583   Image::Magick ref=NO_INIT
6584   ALIAS:
6585     Layers                = 1
6586     layers           = 2
6587     OptimizeImageLayers   = 3
6588     optimizelayers        = 4
6589     optimizeimagelayers   = 5
6590   PPCODE:
6591   {
6592     AV
6593       *av;
6594
6595     char
6596       *attribute;
6597
6598     CompositeOperator
6599       compose;
6600
6601     ExceptionInfo
6602       *exception;
6603
6604     HV
6605       *hv;
6606
6607     Image
6608       *image,
6609       *layers;
6610
6611     ImageLayerMethod
6612       method;
6613
6614     register ssize_t
6615       i;
6616
6617     ssize_t
6618       option,
6619       sp;
6620
6621     struct PackageInfo
6622       *info;
6623
6624     SV
6625       *av_reference,
6626       *perl_exception,
6627       *reference,
6628       *rv,
6629       *sv;
6630
6631     PERL_UNUSED_VAR(ref);
6632     PERL_UNUSED_VAR(ix);
6633     exception=AcquireExceptionInfo();
6634     perl_exception=newSVpv("",0);
6635     sv=NULL;
6636     if (sv_isobject(ST(0)) == 0)
6637       {
6638         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6639           PackageName);
6640         goto PerlException;
6641       }
6642     reference=SvRV(ST(0));
6643     hv=SvSTASH(reference);
6644     av=newAV();
6645     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
6646     SvREFCNT_dec(av);
6647     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6648     if (image == (Image *) NULL)
6649       {
6650         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6651           PackageName);
6652         goto PerlException;
6653       }
6654     compose=image->compose;
6655     method=OptimizeLayer;
6656     for (i=2; i < items; i+=2)
6657     {
6658       attribute=(char *) SvPV(ST(i-1),na);
6659       switch (*attribute)
6660       {
6661         case 'C':
6662         case 'c':
6663         {
6664           if (LocaleCompare(attribute,"compose") == 0)
6665             {
6666               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
6667                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
6668               if (sp < 0)
6669                 {
6670                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6671                     SvPV(ST(i),na));
6672                   break;
6673                 }
6674               compose=(CompositeOperator) sp;
6675               break;
6676             }
6677           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6678             attribute);
6679           break;
6680         }
6681         case 'M':
6682         case 'm':
6683         {
6684           if (LocaleCompare(attribute,"method") == 0)
6685             {
6686               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
6687                 SvPV(ST(i),na));
6688               if (option < 0)
6689                 {
6690                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6691                     SvPV(ST(i),na));
6692                   break;
6693                 }
6694               method=(ImageLayerMethod) option;
6695               break;
6696             }
6697           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6698             attribute);
6699           break;
6700         }
6701         default:
6702         {
6703           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6704             attribute);
6705           break;
6706         }
6707       }
6708     }
6709     layers=(Image *) NULL;
6710     switch (method)
6711     {
6712       case CompareAnyLayer:
6713       case CompareClearLayer:
6714       case CompareOverlayLayer:
6715       default:
6716       {
6717         layers=CompareImagesLayers(image,method,exception);
6718         break;
6719       }
6720       case MergeLayer:
6721       case FlattenLayer:
6722       case MosaicLayer:
6723       {
6724         layers=MergeImageLayers(image,method,exception);
6725         break;
6726       }
6727       case DisposeLayer:
6728       {
6729         layers=DisposeImages(image,exception);
6730         break;
6731       }
6732       case OptimizeImageLayer:
6733       {
6734         layers=OptimizeImageLayers(image,exception);
6735         break;
6736       }
6737       case OptimizePlusLayer:
6738       {
6739         layers=OptimizePlusImageLayers(image,exception);
6740         break;
6741       }
6742       case OptimizeTransLayer:
6743       {
6744         OptimizeImageTransparency(image,exception);
6745         InheritException(&(image->exception),exception);
6746         break;
6747       }
6748       case RemoveDupsLayer:
6749       {
6750         RemoveDuplicateLayers(&image,exception);
6751         InheritException(&(image->exception),exception);
6752         break;
6753       }
6754       case RemoveZeroLayer:
6755       {
6756         RemoveZeroDelayLayers(&image,exception);
6757         InheritException(&(image->exception),exception);
6758         break;
6759       }
6760       case OptimizeLayer:
6761       {
6762         QuantizeInfo
6763           *quantize_info;
6764
6765         /*
6766           General Purpose, GIF Animation Optimizer.
6767         */
6768         layers=CoalesceImages(image,exception);
6769         if (layers == (Image *) NULL)
6770           break;
6771         InheritException(&(layers->exception),exception);
6772         image=layers;
6773         layers=OptimizeImageLayers(image,exception);
6774         if (layers == (Image *) NULL)
6775           break;
6776         InheritException(&(layers->exception),exception);
6777         image=DestroyImageList(image);
6778         image=layers;
6779         layers=(Image *) NULL;
6780         OptimizeImageTransparency(image,exception);
6781         InheritException(&(image->exception),exception);
6782         quantize_info=AcquireQuantizeInfo(info->image_info);
6783         (void) RemapImages(quantize_info,image,(Image *) NULL,exception);
6784         quantize_info=DestroyQuantizeInfo(quantize_info);
6785         break;
6786       }
6787       case CompositeLayer:
6788       {
6789         Image
6790           *source;
6791
6792         RectangleInfo
6793           geometry;
6794
6795         /*
6796           Split image sequence at the first 'NULL:' image.
6797         */
6798         source=image;
6799         while (source != (Image *) NULL)
6800         {
6801           source=GetNextImageInList(source);
6802           if ((source != (Image *) NULL) &&
6803               (LocaleCompare(source->magick,"NULL") == 0))
6804             break;
6805         }
6806         if (source != (Image *) NULL)
6807           {
6808             if ((GetPreviousImageInList(source) == (Image *) NULL) ||
6809                 (GetNextImageInList(source) == (Image *) NULL))
6810               source=(Image *) NULL;
6811             else
6812               {
6813                 /*
6814                   Separate the two lists, junk the null: image.
6815                 */
6816                 source=SplitImageList(source->previous);
6817                 DeleteImageFromList(&source);
6818               }
6819           }
6820         if (source == (Image *) NULL)
6821           {
6822             (void) ThrowMagickException(exception,GetMagickModule(),
6823               OptionError,"MissingNullSeparator","layers Composite");
6824             break;
6825           }
6826         /*
6827           Adjust offset with gravity and virtual canvas.
6828         */
6829         SetGeometry(image,&geometry);
6830         (void) ParseAbsoluteGeometry(image->geometry,&geometry);
6831         geometry.width=source->page.width != 0 ? source->page.width :
6832           source->columns;
6833         geometry.height=source->page.height != 0 ? source->page.height :
6834           source->rows;
6835         GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
6836           image->columns,image->page.height != 0 ? image->page.height :
6837           image->rows,image->gravity,&geometry);
6838         CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
6839         source=DestroyImageList(source);
6840         InheritException(&(image->exception),exception);
6841         break;
6842       }
6843     }
6844     if (layers != (Image *) NULL)
6845       {
6846         InheritException(&(layers->exception),exception);
6847         image=layers;
6848       }
6849     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
6850       goto PerlException;
6851     for ( ; image; image=image->next)
6852     {
6853       AddImageToRegistry(sv,image);
6854       rv=newRV(sv);
6855       av_push(av,sv_bless(rv,hv));
6856       SvREFCNT_dec(sv);
6857     }
6858     exception=DestroyExceptionInfo(exception);
6859     ST(0)=av_reference;
6860     SvREFCNT_dec(perl_exception);
6861     XSRETURN(1);
6862
6863   PerlException:
6864     InheritPerlException(exception,perl_exception);
6865     exception=DestroyExceptionInfo(exception);
6866     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
6867     SvPOK_on(perl_exception);
6868     ST(0)=sv_2mortal(perl_exception);
6869     XSRETURN(1);
6870   }
6871 \f
6872 #
6873 ###############################################################################
6874 #                                                                             #
6875 #                                                                             #
6876 #                                                                             #
6877 #   M a g i c k T o M i m e                                                   #
6878 #                                                                             #
6879 #                                                                             #
6880 #                                                                             #
6881 ###############################################################################
6882 #
6883 #
6884 SV *
6885 MagickToMime(ref,name)
6886   Image::Magick ref=NO_INIT
6887   char *name
6888   ALIAS:
6889     magicktomime = 1
6890   CODE:
6891   {
6892     char
6893       *mime;
6894
6895     PERL_UNUSED_VAR(ref);
6896     PERL_UNUSED_VAR(ix);
6897     mime=MagickToMime(name);
6898     RETVAL=newSVpv(mime,0);
6899     mime=(char *) RelinquishMagickMemory(mime);
6900   }
6901   OUTPUT:
6902     RETVAL
6903 \f
6904 #
6905 ###############################################################################
6906 #                                                                             #
6907 #                                                                             #
6908 #                                                                             #
6909 #   M o g r i f y                                                             #
6910 #                                                                             #
6911 #                                                                             #
6912 #                                                                             #
6913 ###############################################################################
6914 #
6915 #
6916 void
6917 Mogrify(ref,...)
6918   Image::Magick ref=NO_INIT
6919   ALIAS:
6920     Comment            =   1
6921     CommentImage       =   2
6922     Label              =   3
6923     LabelImage         =   4
6924     AddNoise           =   5
6925     AddNoiseImage      =   6
6926     Colorize           =   7
6927     ColorizeImage      =   8
6928     Border             =   9
6929     BorderImage        =  10
6930     Blur               =  11
6931     BlurImage          =  12
6932     Chop               =  13
6933     ChopImage          =  14
6934     Crop               =  15
6935     CropImage          =  16
6936     Despeckle          =  17
6937     DespeckleImage     =  18
6938     Edge               =  19
6939     EdgeImage          =  20
6940     Emboss             =  21
6941     EmbossImage        =  22
6942     Enhance            =  23
6943     EnhanceImage       =  24
6944     Flip               =  25
6945     FlipImage          =  26
6946     Flop               =  27
6947     FlopImage          =  28
6948     Frame              =  29
6949     FrameImage         =  30
6950     Implode            =  31
6951     ImplodeImage       =  32
6952     Magnify            =  33
6953     MagnifyImage       =  34
6954     MedianFilter       =  35
6955     MedianConvolveImage  =  36
6956     Minify             =  37
6957     MinifyImage        =  38
6958     OilPaint           =  39
6959     OilPaintImage      =  40
6960     ReduceNoise        =  41
6961     ReduceNoiseImage   =  42
6962     Roll               =  43
6963     RollImage          =  44
6964     Rotate             =  45
6965     RotateImage        =  46
6966     Sample             =  47
6967     SampleImage        =  48
6968     Scale              =  49
6969     ScaleImage         =  50
6970     Shade              =  51
6971     ShadeImage         =  52
6972     Sharpen            =  53
6973     SharpenImage       =  54
6974     Shear              =  55
6975     ShearImage         =  56
6976     Spread             =  57
6977     SpreadImage        =  58
6978     Swirl              =  59
6979     SwirlImage         =  60
6980     Resize             =  61
6981     ResizeImage        =  62
6982     Zoom               =  63
6983     ZoomImage          =  64
6984     Annotate           =  65
6985     AnnotateImage      =  66
6986     ColorFloodfill     =  67
6987     ColorFloodfillImage=  68
6988     Composite          =  69
6989     CompositeImage     =  70
6990     Contrast           =  71
6991     ContrastImage      =  72
6992     CycleColormap      =  73
6993     CycleColormapImage =  74
6994     Draw               =  75
6995     DrawImage          =  76
6996     Equalize           =  77
6997     EqualizeImage      =  78
6998     Gamma              =  79
6999     GammaImage         =  80
7000     Map                =  81
7001     MapImage           =  82
7002     MatteFloodfill     =  83
7003     MatteFloodfillImage=  84
7004     Modulate           =  85
7005     ModulateImage      =  86
7006     Negate             =  87
7007     NegateImage        =  88
7008     Normalize          =  89
7009     NormalizeImage     =  90
7010     NumberColors       =  91
7011     NumberColorsImage  =  92
7012     Opaque             =  93
7013     OpaqueImage        =  94
7014     Quantize           =  95
7015     QuantizeImage      =  96
7016     Raise              =  97
7017     RaiseImage         =  98
7018     Segment            =  99
7019     SegmentImage       = 100
7020     Signature          = 101
7021     SignatureImage     = 102
7022     Solarize           = 103
7023     SolarizeImage      = 104
7024     Sync               = 105
7025     SyncImage          = 106
7026     Texture            = 107
7027     TextureImage       = 108
7028     Evaluate           = 109
7029     EvaluateImage      = 110
7030     Transparent        = 111
7031     TransparentImage   = 112
7032     Threshold          = 113
7033     ThresholdImage     = 114
7034     Charcoal           = 115
7035     CharcoalImage      = 116
7036     Trim               = 117
7037     TrimImage          = 118
7038     Wave               = 119
7039     WaveImage          = 120
7040     Separate           = 121
7041     SeparateImage      = 122
7042     Stereo             = 125
7043     StereoImage        = 126
7044     Stegano            = 127
7045     SteganoImage       = 128
7046     Deconstruct        = 129
7047     DeconstructImage   = 130
7048     GaussianBlur       = 131
7049     GaussianBlurImage  = 132
7050     Convolve           = 133
7051     ConvolveImage      = 134
7052     Profile            = 135
7053     ProfileImage       = 136
7054     UnsharpMask        = 137
7055     UnsharpMaskImage   = 138
7056     MotionBlur         = 139
7057     MotionBlurImage    = 140
7058     OrderedDither      = 141
7059     OrderedDitherImage = 142
7060     Shave              = 143
7061     ShaveImage         = 144
7062     Level              = 145
7063     LevelImage         = 146
7064     Clip               = 147
7065     ClipImage          = 148
7066     AffineTransform    = 149
7067     AffineTransformImage = 150
7068     Difference         = 151
7069     DifferenceImage    = 152
7070     AdaptiveThreshold  = 153
7071     AdaptiveThresholdImage = 154
7072     Resample           = 155
7073     ResampleImage      = 156
7074     Describe           = 157
7075     DescribeImage      = 158
7076     BlackThreshold     = 159
7077     BlackThresholdImage= 160
7078     WhiteThreshold     = 161
7079     WhiteThresholdImage= 162
7080     RadialBlur         = 163
7081     RadialBlurImage    = 164
7082     Thumbnail          = 165
7083     ThumbnailImage     = 166
7084     Strip              = 167
7085     StripImage         = 168
7086     Tint               = 169
7087     TintImage          = 170
7088     Channel            = 171
7089     ChannelImage       = 172
7090     Splice             = 173
7091     SpliceImage        = 174
7092     Posterize          = 175
7093     PosterizeImage     = 176
7094     Shadow             = 177
7095     ShadowImage        = 178
7096     Identify           = 179
7097     IdentifyImage      = 180
7098     SepiaTone          = 181
7099     SepiaToneImage     = 182
7100     SigmoidalContrast  = 183
7101     SigmoidalContrastImage = 184
7102     Extent             = 185
7103     ExtentImage        = 186
7104     Vignette           = 187
7105     VignetteImage      = 188
7106     ContrastStretch    = 189
7107     ContrastStretchImage = 190
7108     Sans0              = 191
7109     Sans0Image         = 192
7110     Sans1              = 193
7111     Sans1Image         = 194
7112     AdaptiveSharpen    = 195
7113     AdaptiveSharpenImage = 196
7114     Transpose          = 197
7115     TransposeImage     = 198
7116     Transverse         = 199
7117     TransverseImage    = 200
7118     AutoOrient         = 201
7119     AutoOrientImage    = 202
7120     AdaptiveBlur       = 203
7121     AdaptiveBlurImage  = 204
7122     Sketch             = 205
7123     SketchImage        = 206
7124     UniqueColors       = 207
7125     UniqueColorsImage  = 208
7126     AdaptiveResize     = 209
7127     AdaptiveResizeImage= 210
7128     ClipMask           = 211
7129     ClipMaskImage      = 212
7130     LinearStretch      = 213
7131     LinearStretchImage = 214
7132     RecolorImage       = 215
7133     Recolor            = 216
7134     Mask               = 217
7135     MaskImage          = 218
7136     Polaroid           = 219
7137     PolaroidImage      = 220
7138     FloodfillPaint     = 221
7139     FloodfillPaintImage= 222
7140     Distort            = 223
7141     DistortImage       = 224
7142     Clut               = 225
7143     ClutImage          = 226
7144     LiquidRescale      = 227
7145     LiquidRescaleImage = 228
7146     Encipher           = 229
7147     EncipherImage      = 230
7148     Decipher           = 231
7149     DecipherImage      = 232
7150     Deskew             = 233
7151     DeskewImage        = 234
7152     Remap              = 235
7153     RemapImage         = 236
7154     SparseColor        = 237
7155     SparseColorImage   = 238
7156     Function           = 239
7157     FunctionImage      = 240
7158     SelectiveBlur      = 241
7159     SelectiveBlurImage = 242
7160     HaldClut           = 243
7161     HaldClutImage      = 244
7162     BlueShift          = 245
7163     BlueShiftImage     = 246
7164     ForwardFourierTransform  = 247
7165     ForwardFourierTransformImage = 248
7166     InverseFourierTransform = 249
7167     InverseFourierTransformImage = 250
7168     ColorDecisionList  = 251
7169     ColorDecisionListImage = 252
7170     AutoGamma          = 253
7171     AutoGammaImage     = 254
7172     AutoLevel          = 255
7173     AutoLevelImage     = 256
7174     LevelColors        = 257
7175     LevelImageColors   = 258
7176     Clamp              = 259
7177     ClampImage         = 260
7178     BrightnessContrast = 263
7179     BrightnessContrastImage = 264
7180     Morphology         = 265
7181     MorphologyImage    = 266
7182     ColorMatrix        = 267
7183     ColorMatrixImage   = 268
7184     Color              = 269
7185     ColorImage         = 270
7186     Mode               = 271
7187     ModeImage          = 272
7188     Statistic          = 273
7189     StatisticImage     = 274
7190     MogrifyRegion      = 666
7191   PPCODE:
7192   {
7193     AffineMatrix
7194       affine,
7195       current;
7196
7197     char
7198       attribute_flag[MaxArguments],
7199       message[MaxTextExtent];
7200
7201     ChannelType
7202       channel,
7203       channel_mask;
7204
7205     CompositeOperator
7206       compose;
7207
7208     const char
7209       *attribute,
7210       *value;
7211
7212     double
7213       angle;
7214
7215     ExceptionInfo
7216       *exception;
7217
7218     GeometryInfo
7219       geometry_info;
7220
7221     Image
7222       *image,
7223       *next,
7224       *region_image;
7225
7226     MagickBooleanType
7227       status;
7228
7229     MagickStatusType
7230       flags;
7231
7232     PixelPacket
7233       fill_color;
7234
7235     RectangleInfo
7236       geometry,
7237       region_info;
7238
7239     register ssize_t
7240       i;
7241
7242     ssize_t
7243       base,
7244       j,
7245       number_images;
7246
7247     struct Methods
7248       *rp;
7249
7250     struct PackageInfo
7251       *info;
7252
7253     SV
7254       *perl_exception,
7255       **pv,
7256       *reference,
7257       **reference_vector;
7258
7259     struct ArgumentList
7260       argument_list[MaxArguments];
7261
7262     PERL_UNUSED_VAR(ref);
7263     PERL_UNUSED_VAR(ix);
7264     exception=AcquireExceptionInfo();
7265     perl_exception=newSVpv("",0);
7266     reference_vector=NULL;
7267     region_image=NULL;
7268     number_images=0;
7269     base=2;
7270     if (sv_isobject(ST(0)) == 0)
7271       {
7272         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7273           PackageName);
7274         goto PerlException;
7275       }
7276     reference=SvRV(ST(0));
7277     region_info.width=0;
7278     region_info.height=0;
7279     region_info.x=0;
7280     region_info.y=0;
7281     region_image=(Image *) NULL;
7282     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7283     if (ix && (ix != 666))
7284       {
7285         /*
7286           Called as Method(...)
7287         */
7288         ix=(ix+1)/2;
7289         rp=(&Methods[ix-1]);
7290         attribute=rp->name;
7291       }
7292     else
7293       {
7294         /*
7295           Called as Mogrify("Method",...)
7296         */
7297         attribute=(char *) SvPV(ST(1),na);
7298         if (ix)
7299           {
7300             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7301             attribute=(char *) SvPV(ST(2),na);
7302             base++;
7303           }
7304         for (rp=Methods; ; rp++)
7305         {
7306           if (rp >= EndOf(Methods))
7307             {
7308               ThrowPerlException(exception,OptionError,
7309                 "UnrecognizedPerlMagickMethod",attribute);
7310               goto PerlException;
7311             }
7312           if (strEQcase(attribute,rp->name))
7313             break;
7314         }
7315         ix=rp-Methods+1;
7316         base++;
7317       }
7318     if (image == (Image *) NULL)
7319       {
7320         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7321         goto PerlException;
7322       }
7323     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7324     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7325     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7326     {
7327       Arguments
7328         *pp,
7329         *qq;
7330
7331       ssize_t
7332         ssize_test;
7333
7334       struct ArgumentList
7335         *al;
7336
7337       SV
7338         *sv;
7339
7340       sv=NULL;
7341       ssize_test=0;
7342       pp=(Arguments *) NULL;
7343       qq=rp->arguments;
7344       if (i == items)
7345         {
7346           pp=rp->arguments,
7347           sv=ST(i-1);
7348         }
7349       else
7350         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7351         {
7352           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7353             break;
7354           if (strEQcase(attribute,qq->method) > ssize_test)
7355             {
7356               pp=qq;
7357               ssize_test=strEQcase(attribute,qq->method);
7358             }
7359         }
7360       if (pp == (Arguments *) NULL)
7361         {
7362           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7363             attribute);
7364           goto continue_outer_loop;
7365         }
7366       al=(&argument_list[pp-rp->arguments]);
7367       switch (pp->type)
7368       {
7369         case ArrayReference:
7370         {
7371           if (SvTYPE(sv) != SVt_RV)
7372             {
7373               (void) FormatLocaleString(message,MaxTextExtent,
7374                 "invalid %.60s value",pp->method);
7375               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7376               goto continue_outer_loop;
7377             }
7378           al->array_reference=SvRV(sv);
7379           break;
7380         }
7381         case RealReference:
7382         {
7383           al->real_reference=SvNV(sv);
7384           break;
7385         }
7386         case FileReference:
7387         {
7388           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7389           break;
7390         }
7391         case ImageReference:
7392         {
7393           if (!sv_isobject(sv) ||
7394               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7395                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7396             {
7397               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7398                 PackageName);
7399               goto PerlException;
7400             }
7401           break;
7402         }
7403         case IntegerReference:
7404         {
7405           al->integer_reference=SvIV(sv);
7406           break;
7407         }
7408         case StringReference:
7409         {
7410           al->string_reference=(char *) SvPV(sv,al->length);
7411           if (sv_isobject(sv))
7412             al->image_reference=SetupList(aTHX_ SvRV(sv),
7413               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7414           break;
7415         }
7416         default:
7417         {
7418           /*
7419             Is a string; look up name.
7420           */
7421           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7422             {
7423               al->string_reference=(char *) SvPV(sv,al->length);
7424               al->integer_reference=(-1);
7425               break;
7426             }
7427           al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7428             MagickFalse,SvPV(sv,na));
7429           if (pp->type == MagickChannelOptions)
7430             al->integer_reference=ParseChannelOption(SvPV(sv,na));
7431           if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7432             {
7433               (void) FormatLocaleString(message,MaxTextExtent,
7434                 "invalid %.60s value",pp->method);
7435               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7436               goto continue_outer_loop;
7437             }
7438           break;
7439         }
7440       }
7441       attribute_flag[pp-rp->arguments]++;
7442       continue_outer_loop: ;
7443     }
7444     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7445     pv=reference_vector;
7446     SetGeometryInfo(&geometry_info);
7447     channel=DefaultChannels;
7448     for (next=image; next; next=next->next)
7449     {
7450       image=next;
7451       SetGeometry(image,&geometry);
7452       if ((region_info.width*region_info.height) != 0)
7453         {
7454           region_image=image;
7455           image=CropImage(image,&region_info,exception);
7456         }
7457       switch (ix)
7458       {
7459         default:
7460         {
7461           (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double) ix);
7462           ThrowPerlException(exception,OptionError,
7463             "UnrecognizedPerlMagickMethod",message);
7464           goto PerlException;
7465         }
7466         case 1:  /* Comment */
7467         {
7468           if (attribute_flag[0] == 0)
7469             argument_list[0].string_reference=(char *) NULL;
7470           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7471             info ? info->image_info : (ImageInfo *) NULL,image,
7472             argument_list[0].string_reference,exception));
7473           break;
7474         }
7475         case 2:  /* Label */
7476         {
7477           if (attribute_flag[0] == 0)
7478             argument_list[0].string_reference=(char *) NULL;
7479           (void) SetImageProperty(image,"label",InterpretImageProperties(
7480             info ? info->image_info : (ImageInfo *) NULL,image,
7481             argument_list[0].string_reference,exception));
7482           break;
7483         }
7484         case 3:  /* AddNoise */
7485         {
7486           if (attribute_flag[0] == 0)
7487             argument_list[0].integer_reference=UniformNoise;
7488           if (attribute_flag[1] != 0)
7489             channel=(ChannelType) argument_list[1].integer_reference;
7490           channel_mask=SetPixelChannelMask(image,channel);
7491           image=AddNoiseImage(image,(NoiseType)
7492             argument_list[0].integer_reference,exception);
7493           if (image != (Image *) NULL)
7494             (void) SetPixelChannelMask(image,channel_mask);
7495           break;
7496         }
7497         case 4:  /* Colorize */
7498         {
7499           PixelPacket
7500             target;
7501
7502           (void) GetOneVirtualPixel(image,0,0,&target,exception);
7503           if (attribute_flag[0] != 0)
7504             (void) QueryColorDatabase(argument_list[0].string_reference,&target,
7505               exception);
7506           if (attribute_flag[1] == 0)
7507             argument_list[1].string_reference="100%";
7508           image=ColorizeImage(image,argument_list[1].string_reference,target,
7509             exception);
7510           break;
7511         }
7512         case 5:  /* Border */
7513         {
7514           geometry.width=0;
7515           geometry.height=0;
7516           if (attribute_flag[0] != 0)
7517             {
7518               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7519                 &geometry,exception);
7520               if ((flags & HeightValue) == 0)
7521                 geometry.height=geometry.width;
7522             }
7523           if (attribute_flag[1] != 0)
7524             geometry.width=argument_list[1].integer_reference;
7525           if (attribute_flag[2] != 0)
7526             geometry.height=argument_list[2].integer_reference;
7527           if (attribute_flag[3] != 0)
7528             QueryColorDatabase(argument_list[3].string_reference,
7529               &image->border_color,exception);
7530           if (attribute_flag[4] != 0)
7531             QueryColorDatabase(argument_list[4].string_reference,
7532               &image->border_color,exception);
7533           if (attribute_flag[5] != 0)
7534             QueryColorDatabase(argument_list[5].string_reference,
7535               &image->border_color,exception);
7536           if (attribute_flag[6] != 0)
7537             image->compose=(CompositeOperator) argument_list[6].integer_reference;
7538           image=BorderImage(image,&geometry,exception);
7539           break;
7540         }
7541         case 6:  /* Blur */
7542         {
7543           if (attribute_flag[0] != 0)
7544             {
7545               flags=ParseGeometry(argument_list[0].string_reference,
7546                 &geometry_info);
7547               if ((flags & SigmaValue) == 0)
7548                 geometry_info.sigma=1.0;
7549             }
7550           if (attribute_flag[1] != 0)
7551             geometry_info.rho=argument_list[1].real_reference;
7552           if (attribute_flag[2] != 0)
7553             geometry_info.sigma=argument_list[2].real_reference;
7554           if (attribute_flag[3] != 0)
7555             channel=(ChannelType) argument_list[3].integer_reference;
7556           channel_mask=SetPixelChannelMask(image,channel);
7557           image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
7558             exception);
7559           if (image != (Image *) NULL)
7560             (void) SetPixelChannelMask(image,channel_mask);
7561           break;
7562         }
7563         case 7:  /* Chop */
7564         {
7565           if (attribute_flag[0] != 0)
7566             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7567               &geometry,exception);
7568           if (attribute_flag[1] != 0)
7569             geometry.width=argument_list[1].integer_reference;
7570           if (attribute_flag[2] != 0)
7571             geometry.height=argument_list[2].integer_reference;
7572           if (attribute_flag[3] != 0)
7573             geometry.x=argument_list[3].integer_reference;
7574           if (attribute_flag[4] != 0)
7575             geometry.y=argument_list[4].integer_reference;
7576           image=ChopImage(image,&geometry,exception);
7577           break;
7578         }
7579         case 8:  /* Crop */
7580         {
7581           if (attribute_flag[6] != 0)
7582             image->gravity=(GravityType) argument_list[6].integer_reference;
7583           if (attribute_flag[0] != 0)
7584             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7585               &geometry,exception);
7586           if (attribute_flag[1] != 0)
7587             geometry.width=argument_list[1].integer_reference;
7588           if (attribute_flag[2] != 0)
7589             geometry.height=argument_list[2].integer_reference;
7590           if (attribute_flag[3] != 0)
7591             geometry.x=argument_list[3].integer_reference;
7592           if (attribute_flag[4] != 0)
7593             geometry.y=argument_list[4].integer_reference;
7594           if (attribute_flag[5] != 0)
7595             image->fuzz=
7596               SiPrefixToDouble(argument_list[5].string_reference,QuantumRange);
7597           image=CropImage(image,&geometry,exception);
7598           break;
7599         }
7600         case 9:  /* Despeckle */
7601         {
7602           image=DespeckleImage(image,exception);
7603           break;
7604         }
7605         case 10:  /* Edge */
7606         {
7607           if (attribute_flag[0] != 0)
7608             geometry_info.rho=argument_list[0].real_reference;
7609           image=EdgeImage(image,geometry_info.rho,exception);
7610           break;
7611         }
7612         case 11:  /* Emboss */
7613         {
7614           if (attribute_flag[0] != 0)
7615             {
7616               flags=ParseGeometry(argument_list[0].string_reference,
7617                 &geometry_info);
7618               if ((flags & SigmaValue) == 0)
7619                 geometry_info.sigma=1.0;
7620             }
7621           if (attribute_flag[1] != 0)
7622             geometry_info.rho=argument_list[1].real_reference;
7623           if (attribute_flag[2] != 0)
7624             geometry_info.sigma=argument_list[2].real_reference;
7625           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
7626             exception);
7627           break;
7628         }
7629         case 12:  /* Enhance */
7630         {
7631           image=EnhanceImage(image,exception);
7632           break;
7633         }
7634         case 13:  /* Flip */
7635         {
7636           image=FlipImage(image,exception);
7637           break;
7638         }
7639         case 14:  /* Flop */
7640         {
7641           image=FlopImage(image,exception);
7642           break;
7643         }
7644         case 15:  /* Frame */
7645         {
7646           FrameInfo
7647             frame_info;
7648
7649           if (attribute_flag[0] != 0)
7650             {
7651               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7652                 &geometry,exception);
7653               if ((flags & HeightValue) == 0)
7654                 geometry.height=geometry.width;
7655               frame_info.width=geometry.width;
7656               frame_info.height=geometry.height;
7657               frame_info.outer_bevel=geometry.x;
7658               frame_info.inner_bevel=geometry.y;
7659             }
7660           if (attribute_flag[1] != 0)
7661             frame_info.width=argument_list[1].integer_reference;
7662           if (attribute_flag[2] != 0)
7663             frame_info.height=argument_list[2].integer_reference;
7664           if (attribute_flag[3] != 0)
7665             frame_info.inner_bevel=argument_list[3].integer_reference;
7666           if (attribute_flag[4] != 0)
7667             frame_info.outer_bevel=argument_list[4].integer_reference;
7668           if (attribute_flag[5] != 0)
7669             QueryColorDatabase(argument_list[5].string_reference,&fill_color,
7670               exception);
7671           if (attribute_flag[6] != 0)
7672             QueryColorDatabase(argument_list[6].string_reference,&fill_color,
7673               exception);
7674           frame_info.x=(ssize_t) frame_info.width;
7675           frame_info.y=(ssize_t) frame_info.height;
7676           frame_info.width=image->columns+2*frame_info.x;
7677           frame_info.height=image->rows+2*frame_info.y;
7678           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
7679             image->matte_color=fill_color;
7680           if (attribute_flag[7] != 0)
7681             image->compose=(CompositeOperator) argument_list[7].integer_reference;
7682           image=FrameImage(image,&frame_info,exception);
7683           break;
7684         }
7685         case 16:  /* Implode */
7686         {
7687           if (attribute_flag[0] == 0)
7688             argument_list[0].real_reference=0.5;
7689           if (attribute_flag[1] != 0)
7690             image->interpolate=(InterpolatePixelMethod)
7691               argument_list[1].integer_reference;
7692           image=ImplodeImage(image,argument_list[0].real_reference,
7693             exception);
7694           break;
7695         }
7696         case 17:  /* Magnify */
7697         {
7698           image=MagnifyImage(image,exception);
7699           break;
7700         }
7701         case 18:  /* MedianFilter */
7702         {
7703           if (attribute_flag[0] != 0)
7704             {
7705               flags=ParseGeometry(argument_list[0].string_reference,
7706                 &geometry_info);
7707               if ((flags & SigmaValue) == 0)
7708                 geometry_info.sigma=1.0;
7709             }
7710           if (attribute_flag[1] != 0)
7711             geometry_info.rho=argument_list[1].real_reference;
7712           if (attribute_flag[2] != 0)
7713             geometry_info.sigma=argument_list[2].real_reference;
7714           if (attribute_flag[3] != 0)
7715             channel=(ChannelType) argument_list[3].integer_reference;
7716           channel_mask=SetPixelChannelMask(image,channel);
7717           image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
7718             (size_t) geometry_info.sigma,exception);
7719           if (image != (Image *) NULL)
7720             (void) SetPixelChannelMask(image,channel_mask);
7721           break;
7722         }
7723         case 19:  /* Minify */
7724         {
7725           image=MinifyImage(image,exception);
7726           break;
7727         }
7728         case 20:  /* OilPaint */
7729         {
7730           if (attribute_flag[0] == 0)
7731             argument_list[0].real_reference=0.0;
7732           if (attribute_flag[1] == 0)
7733             argument_list[1].real_reference=1.0;
7734           image=OilPaintImage(image,argument_list[0].real_reference,
7735             argument_list[1].real_reference,exception);
7736           break;
7737         }
7738         case 21:  /* ReduceNoise */
7739         {
7740           if (attribute_flag[0] != 0)
7741             {
7742               flags=ParseGeometry(argument_list[0].string_reference,
7743                 &geometry_info);
7744               if ((flags & SigmaValue) == 0)
7745                 geometry_info.sigma=1.0;
7746             }
7747           if (attribute_flag[1] != 0)
7748             geometry_info.rho=argument_list[1].real_reference;
7749           if (attribute_flag[2] != 0)
7750             geometry_info.sigma=argument_list[2].real_reference;
7751           if (attribute_flag[3] != 0)
7752             channel=(ChannelType) argument_list[3].integer_reference;
7753           channel_mask=SetPixelChannelMask(image,channel);
7754           image=StatisticImage(image,NonpeakStatistic,(size_t)
7755             geometry_info.rho,(size_t) geometry_info.sigma,exception);
7756           if (image != (Image *) NULL)
7757             (void) SetPixelChannelMask(image,channel_mask);
7758           break;
7759         }
7760         case 22:  /* Roll */
7761         {
7762           if (attribute_flag[0] != 0)
7763             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7764               &geometry,exception);
7765           if (attribute_flag[1] != 0)
7766             geometry.x=argument_list[1].integer_reference;
7767           if (attribute_flag[2] != 0)
7768             geometry.y=argument_list[2].integer_reference;
7769           image=RollImage(image,geometry.x,geometry.y,exception);
7770           break;
7771         }
7772         case 23:  /* Rotate */
7773         {
7774           if (attribute_flag[0] == 0)
7775             argument_list[0].real_reference=90.0;
7776           if (attribute_flag[1] != 0)
7777             QueryColorDatabase(argument_list[1].string_reference,
7778               &image->background_color,exception);
7779           if (attribute_flag[2] != 0)
7780             QueryColorDatabase(argument_list[2].string_reference,
7781               &image->background_color,exception);
7782           if (attribute_flag[3] != 0)
7783             QueryColorDatabase(argument_list[3].string_reference,
7784               &image->background_color,exception);
7785           image=RotateImage(image,argument_list[0].real_reference,exception);
7786           break;
7787         }
7788         case 24:  /* Sample */
7789         {
7790           if (attribute_flag[0] != 0)
7791             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7792               &geometry,exception);
7793           if (attribute_flag[1] != 0)
7794             geometry.width=argument_list[1].integer_reference;
7795           if (attribute_flag[2] != 0)
7796             geometry.height=argument_list[2].integer_reference;
7797           image=SampleImage(image,geometry.width,geometry.height,exception);
7798           break;
7799         }
7800         case 25:  /* Scale */
7801         {
7802           if (attribute_flag[0] != 0)
7803             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7804               &geometry,exception);
7805           if (attribute_flag[1] != 0)
7806             geometry.width=argument_list[1].integer_reference;
7807           if (attribute_flag[2] != 0)
7808             geometry.height=argument_list[2].integer_reference;
7809           image=ScaleImage(image,geometry.width,geometry.height,exception);
7810           break;
7811         }
7812         case 26:  /* Shade */
7813         {
7814           if (attribute_flag[0] != 0)
7815             {
7816               flags=ParseGeometry(argument_list[0].string_reference,
7817                 &geometry_info);
7818               if ((flags & SigmaValue) == 0)
7819                 geometry_info.sigma=0.0;
7820             }
7821           if (attribute_flag[1] != 0)
7822             geometry_info.rho=argument_list[1].real_reference;
7823           if (attribute_flag[2] != 0)
7824             geometry_info.sigma=argument_list[2].real_reference;
7825           image=ShadeImage(image,
7826             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
7827             geometry_info.rho,geometry_info.sigma,exception);
7828           break;
7829         }
7830         case 27:  /* Sharpen */
7831         {
7832           if (attribute_flag[0] != 0)
7833             {
7834               flags=ParseGeometry(argument_list[0].string_reference,
7835                 &geometry_info);
7836               if ((flags & SigmaValue) == 0)
7837                 geometry_info.sigma=1.0;
7838             }
7839           if (attribute_flag[1] != 0)
7840             geometry_info.rho=argument_list[1].real_reference;
7841           if (attribute_flag[2] != 0)
7842             geometry_info.sigma=argument_list[2].real_reference;
7843           if (attribute_flag[3] != 0)
7844             channel=(ChannelType) argument_list[3].integer_reference;
7845           channel_mask=SetPixelChannelMask(image,channel);
7846           image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
7847             exception);
7848           if (image != (Image *) NULL)
7849             (void) SetPixelChannelMask(image,channel_mask);
7850           break;
7851         }
7852         case 28:  /* Shear */
7853         {
7854           if (attribute_flag[0] != 0)
7855             {
7856               flags=ParseGeometry(argument_list[0].string_reference,
7857                 &geometry_info);
7858               if ((flags & SigmaValue) == 0)
7859                 geometry_info.sigma=geometry_info.rho;
7860             }
7861           if (attribute_flag[1] != 0)
7862             geometry_info.rho=argument_list[1].real_reference;
7863           if (attribute_flag[2] != 0)
7864             geometry_info.sigma=argument_list[2].real_reference;
7865           if (attribute_flag[3] != 0)
7866             QueryColorDatabase(argument_list[3].string_reference,
7867               &image->background_color,exception);
7868           if (attribute_flag[4] != 0)
7869             QueryColorDatabase(argument_list[4].string_reference,
7870               &image->background_color,exception);
7871           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
7872             exception);
7873           break;
7874         }
7875         case 29:  /* Spread */
7876         {
7877           if (attribute_flag[0] == 0)
7878             argument_list[0].real_reference=1.0;
7879           image=SpreadImage(image,argument_list[0].real_reference,exception);
7880           break;
7881         }
7882         case 30:  /* Swirl */
7883         {
7884           if (attribute_flag[0] == 0)
7885             argument_list[0].real_reference=50.0;
7886           if (attribute_flag[1] != 0)
7887             image->interpolate=(InterpolatePixelMethod)
7888               argument_list[1].integer_reference;
7889           image=SwirlImage(image,argument_list[0].real_reference,exception);
7890           break;
7891         }
7892         case 31:  /* Resize */
7893         case 32:  /* Zoom */
7894         {
7895           if (attribute_flag[0] != 0)
7896             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7897               &geometry,exception);
7898           if (attribute_flag[1] != 0)
7899             geometry.width=argument_list[1].integer_reference;
7900           if (attribute_flag[2] != 0)
7901             geometry.height=argument_list[2].integer_reference;
7902           if (attribute_flag[3] == 0)
7903             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
7904           if (attribute_flag[4] != 0)
7905             SetImageArtifact(image,"filter:support",
7906               argument_list[4].string_reference);
7907           if (attribute_flag[5] == 0)
7908             argument_list[5].real_reference=1.0;
7909           image=ResizeImage(image,geometry.width,geometry.height,
7910             (FilterTypes) argument_list[3].integer_reference,
7911             argument_list[5].real_reference,exception);
7912           break;
7913         }
7914         case 33:  /* Annotate */
7915         {
7916           DrawInfo
7917             *draw_info;
7918
7919           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
7920             (DrawInfo *) NULL);
7921           if (attribute_flag[0] != 0)
7922             {
7923               char
7924                 *text;
7925
7926               text=InterpretImageProperties(info ? info->image_info :
7927                 (ImageInfo *) NULL,image,argument_list[0].string_reference,
7928                 exception);
7929               (void) CloneString(&draw_info->text,text);
7930               text=DestroyString(text);
7931             }
7932           if (attribute_flag[1] != 0)
7933             (void) CloneString(&draw_info->font,
7934               argument_list[1].string_reference);
7935           if (attribute_flag[2] != 0)
7936             draw_info->pointsize=argument_list[2].real_reference;
7937           if (attribute_flag[3] != 0)
7938             (void) CloneString(&draw_info->density,
7939               argument_list[3].string_reference);
7940           if (attribute_flag[4] != 0)
7941             (void) QueryColorDatabase(argument_list[4].string_reference,
7942               &draw_info->undercolor,exception);
7943           if (attribute_flag[5] != 0)
7944             {
7945               (void) QueryColorDatabase(argument_list[5].string_reference,
7946                 &draw_info->stroke,exception);
7947               if (argument_list[5].image_reference != (Image *) NULL)
7948                 draw_info->stroke_pattern=CloneImage(
7949                   argument_list[5].image_reference,0,0,MagickTrue,exception);
7950             }
7951           if (attribute_flag[6] != 0)
7952             {
7953               (void) QueryColorDatabase(argument_list[6].string_reference,
7954                 &draw_info->fill,exception);
7955               if (argument_list[6].image_reference != (Image *) NULL)
7956                 draw_info->fill_pattern=CloneImage(
7957                   argument_list[6].image_reference,0,0,MagickTrue,exception);
7958             }
7959           if (attribute_flag[7] != 0)
7960             {
7961               (void) CloneString(&draw_info->geometry,
7962                 argument_list[7].string_reference);
7963               flags=ParsePageGeometry(image,argument_list[7].string_reference,
7964                 &geometry,exception);
7965               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
7966                 geometry_info.sigma=geometry_info.xi;
7967             }
7968           if (attribute_flag[8] != 0)
7969             (void) QueryColorDatabase(argument_list[8].string_reference,
7970               &draw_info->fill,exception);
7971           if (attribute_flag[11] != 0)
7972             draw_info->gravity=(GravityType) argument_list[11].integer_reference;
7973           if (attribute_flag[25] != 0)
7974             {
7975               AV
7976                 *av;
7977
7978               av=(AV *) argument_list[25].array_reference;
7979               if ((av_len(av) != 3) && (av_len(av) != 5))
7980                 {
7981                   ThrowPerlException(exception,OptionError,
7982                     "affine matrix must have 4 or 6 elements",PackageName);
7983                   goto PerlException;
7984                 }
7985               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
7986               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
7987               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
7988               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
7989               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
7990                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
7991                 {
7992                   ThrowPerlException(exception,OptionError,
7993                     "affine matrix is singular",PackageName);
7994                    goto PerlException;
7995                 }
7996               if (av_len(av) == 5)
7997                 {
7998                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
7999                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8000                 }
8001             }
8002           for (j=12; j < 17; j++)
8003           {
8004             if (attribute_flag[j] == 0)
8005               continue;
8006             value=argument_list[j].string_reference;
8007             angle=argument_list[j].real_reference;
8008             current=draw_info->affine;
8009             GetAffineMatrix(&affine);
8010             switch (j)
8011             {
8012               case 12:
8013               {
8014                 /*
8015                   Translate.
8016                 */
8017                 flags=ParseGeometry(value,&geometry_info);
8018                 affine.tx=geometry_info.xi;
8019                 affine.ty=geometry_info.psi;
8020                 if ((flags & PsiValue) == 0)
8021                   affine.ty=affine.tx;
8022                 break;
8023               }
8024               case 13:
8025               {
8026                 /*
8027                   Scale.
8028                 */
8029                 flags=ParseGeometry(value,&geometry_info);
8030                 affine.sx=geometry_info.rho;
8031                 affine.sy=geometry_info.sigma;
8032                 if ((flags & SigmaValue) == 0)
8033                   affine.sy=affine.sx;
8034                 break;
8035               }
8036               case 14:
8037               {
8038                 /*
8039                   Rotate.
8040                 */
8041                 if (angle == 0.0)
8042                   break;
8043                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8044                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8045                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8046                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8047                 break;
8048               }
8049               case 15:
8050               {
8051                 /*
8052                   SkewX.
8053                 */
8054                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8055                 break;
8056               }
8057               case 16:
8058               {
8059                 /*
8060                   SkewY.
8061                 */
8062                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8063                 break;
8064               }
8065             }
8066             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8067             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8068             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8069             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8070             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8071               current.tx;
8072             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8073               current.ty;
8074           }
8075           if (attribute_flag[9] == 0)
8076             argument_list[9].real_reference=0.0;
8077           if (attribute_flag[10] == 0)
8078             argument_list[10].real_reference=0.0;
8079           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8080             {
8081               char
8082                 geometry[MaxTextExtent];
8083
8084               (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
8085                 (double) argument_list[9].real_reference+draw_info->affine.tx,
8086                 (double) argument_list[10].real_reference+draw_info->affine.ty);
8087               (void) CloneString(&draw_info->geometry,geometry);
8088             }
8089           if (attribute_flag[17] != 0)
8090             draw_info->stroke_width=argument_list[17].real_reference;
8091           if (attribute_flag[18] != 0)
8092             {
8093               draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8094                 MagickTrue : MagickFalse;
8095               draw_info->stroke_antialias=draw_info->text_antialias;
8096             }
8097           if (attribute_flag[19] != 0)
8098             (void) CloneString(&draw_info->family,
8099               argument_list[19].string_reference);
8100           if (attribute_flag[20] != 0)
8101             draw_info->style=(StyleType) argument_list[20].integer_reference;
8102           if (attribute_flag[21] != 0)
8103             draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8104           if (attribute_flag[22] != 0)
8105             draw_info->weight=argument_list[22].integer_reference;
8106           if (attribute_flag[23] != 0)
8107             draw_info->align=(AlignType) argument_list[23].integer_reference;
8108           if (attribute_flag[24] != 0)
8109             (void) CloneString(&draw_info->encoding,
8110               argument_list[24].string_reference);
8111           if (attribute_flag[25] != 0)
8112             draw_info->fill_pattern=CloneImage(
8113               argument_list[25].image_reference,0,0,MagickTrue,exception);
8114           if (attribute_flag[26] != 0)
8115             draw_info->fill_pattern=CloneImage(
8116               argument_list[26].image_reference,0,0,MagickTrue,exception);
8117           if (attribute_flag[27] != 0)
8118             draw_info->stroke_pattern=CloneImage(
8119               argument_list[27].image_reference,0,0,MagickTrue,exception);
8120           if (attribute_flag[29] != 0)
8121             draw_info->kerning=argument_list[29].real_reference;
8122           if (attribute_flag[30] != 0)
8123             draw_info->interline_spacing=argument_list[30].real_reference;
8124           if (attribute_flag[31] != 0)
8125             draw_info->interword_spacing=argument_list[31].real_reference;
8126           if (attribute_flag[32] != 0)
8127             draw_info->direction=(DirectionType)
8128               argument_list[32].integer_reference;
8129           (void) AnnotateImage(image,draw_info,exception);
8130           draw_info=DestroyDrawInfo(draw_info);
8131           break;
8132         }
8133         case 34:  /* ColorFloodfill */
8134         {
8135           DrawInfo
8136             *draw_info;
8137
8138           MagickBooleanType
8139             invert;
8140
8141           PixelInfo
8142             target;
8143
8144           draw_info=CloneDrawInfo(info ? info->image_info :
8145             (ImageInfo *) NULL,(DrawInfo *) NULL);
8146           if (attribute_flag[0] != 0)
8147             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8148               &geometry,exception);
8149           if (attribute_flag[1] != 0)
8150             geometry.x=argument_list[1].integer_reference;
8151           if (attribute_flag[2] != 0)
8152             geometry.y=argument_list[2].integer_reference;
8153           if (attribute_flag[3] != 0)
8154             (void) QueryColorDatabase(argument_list[3].string_reference,
8155               &draw_info->fill,exception);
8156           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
8157             exception);
8158           invert=MagickFalse;
8159           if (attribute_flag[4] != 0)
8160             {
8161               QueryMagickColor(argument_list[4].string_reference,&target,
8162                 exception);
8163               invert=MagickTrue;
8164             }
8165           if (attribute_flag[5] != 0)
8166             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
8167               QuantumRange);
8168           if (attribute_flag[6] != 0)
8169             invert=(MagickBooleanType) argument_list[6].integer_reference;
8170           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8171             geometry.y,invert,exception);
8172           draw_info=DestroyDrawInfo(draw_info);
8173           break;
8174         }
8175         case 35:  /* Composite */
8176         {
8177           char
8178             composite_geometry[MaxTextExtent];
8179
8180           Image
8181             *composite_image,
8182             *rotate_image;
8183
8184           compose=OverCompositeOp;
8185           if (attribute_flag[0] != 0)
8186             composite_image=argument_list[0].image_reference;
8187           else
8188             {
8189               ThrowPerlException(exception,OptionError,
8190                 "CompositeImageRequired",PackageName);
8191               goto PerlException;
8192             }
8193           /*
8194             Parameter Handling used for BOTH normal and tiled composition.
8195           */
8196           if (attribute_flag[1] != 0) /* compose */
8197             compose=(CompositeOperator) argument_list[1].integer_reference;
8198           if (attribute_flag[6] != 0) /* opacity  */
8199             {
8200               if (compose != DissolveCompositeOp)
8201                 (void) SetImageOpacity(composite_image,(Quantum)
8202                   SiPrefixToDouble(argument_list[6].string_reference,
8203                   QuantumRange));
8204               else
8205                 {
8206                   CacheView
8207                     *composite_view;
8208
8209                   double
8210                     opacity;
8211
8212                   MagickBooleanType
8213                     sync;
8214
8215                   register ssize_t
8216                     x;
8217
8218                   register Quantum
8219                     *q;
8220
8221                   ssize_t
8222                     y;
8223
8224                   /*
8225                     Handle dissolve composite operator (patch by
8226                     Kevin A. McGrail).
8227                   */
8228                   (void) CloneString(&image->geometry,
8229                     argument_list[6].string_reference);
8230                   opacity=(Quantum) SiPrefixToDouble(
8231                     argument_list[6].string_reference,QuantumRange);
8232                   if (composite_image->matte != MagickTrue)
8233                     (void) SetImageOpacity(composite_image,OpaqueAlpha);
8234                   composite_view=AcquireCacheView(composite_image);
8235                   for (y=0; y < (ssize_t) composite_image->rows ; y++)
8236                   {
8237                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8238                       composite_image->columns,1,exception);
8239                     for (x=0; x < (ssize_t) composite_image->columns; x++)
8240                     {
8241                       if (GetPixelAlpha(image,q) == OpaqueAlpha)
8242                         SetPixelAlpha(composite_image,ClampToQuantum(opacity),q);
8243                       q+=GetPixelChannels(composite_image);
8244                     }
8245                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8246                     if (sync == MagickFalse)
8247                       break;
8248                   }
8249                   composite_view=DestroyCacheView(composite_view);
8250                 }
8251             }
8252           if (attribute_flag[9] != 0)    /* "color=>" */
8253             QueryColorDatabase(argument_list[9].string_reference,
8254               &composite_image->background_color,exception);
8255           if (attribute_flag[12] != 0) /* "interpolate=>" */
8256             image->interpolate=(InterpolatePixelMethod)
8257               argument_list[12].integer_reference;
8258           if (attribute_flag[13] != 0)   /* "args=>" */
8259             (void) SetImageArtifact(composite_image,"compose:args",
8260               argument_list[13].string_reference);
8261           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8262             (void) SetImageArtifact(composite_image,"compose:args",
8263               argument_list[14].string_reference);
8264           /*
8265             Tiling Composition (with orthogonal rotate).
8266           */
8267           rotate_image=(Image *) NULL;
8268           if (attribute_flag[8] != 0)   /* "rotate=>" */
8269             {
8270                /*
8271                  Rotate image.
8272                */
8273                rotate_image=RotateImage(composite_image,
8274                  argument_list[8].real_reference,exception);
8275                if (rotate_image == (Image *) NULL)
8276                  break;
8277             }
8278           if (attribute_flag[7] && argument_list[7].integer_reference) /* tile */
8279             {
8280               ssize_t
8281                 x,
8282                 y;
8283
8284               /*
8285                 Tile the composite image.
8286               */
8287              if (attribute_flag[8] != 0)   /* "tile=>" */
8288                (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8289                  "false");
8290              else
8291                (void) SetImageArtifact(composite_image,
8292                  "compose:outside-overlay","false");
8293              for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8294                 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8295                 {
8296                   if (attribute_flag[8] != 0) /* rotate */
8297                     (void) CompositeImage(image,compose,rotate_image,x,y);
8298                   else
8299                     (void) CompositeImage(image,compose,composite_image,x,y);
8300                 }
8301               if (attribute_flag[8] != 0) /* rotate */
8302                 rotate_image=DestroyImage(rotate_image);
8303               break;
8304             }
8305           /*
8306             Parameter Handling used used ONLY for normal composition.
8307           */
8308           if (attribute_flag[5] != 0) /* gravity */
8309             image->gravity=(GravityType) argument_list[5].integer_reference;
8310           if (attribute_flag[2] != 0) /* geometry offset */
8311             {
8312               SetGeometry(image,&geometry);
8313               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8314                 &geometry);
8315               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8316                 &geometry);
8317             }
8318           if (attribute_flag[3] != 0) /* x offset */
8319             geometry.x=argument_list[3].integer_reference;
8320           if (attribute_flag[4] != 0) /* y offset */
8321             geometry.y=argument_list[4].integer_reference;
8322           if (attribute_flag[10] != 0) /* mask */
8323             {
8324               if ((image->compose == DisplaceCompositeOp) ||
8325                   (image->compose == DistortCompositeOp))
8326                 {
8327                   /*
8328                     Merge Y displacement into X displacement image.
8329                   */
8330                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8331                     &image->exception);
8332                   (void) CompositeImage(composite_image,CopyGreenCompositeOp,
8333                     argument_list[10].image_reference,0,0);
8334                 }
8335               else
8336                 {
8337                   /*
8338                     Set a blending mask for the composition.
8339                   */
8340                   image->mask=CloneImage(argument_list[10].image_reference,0,0,
8341                     MagickTrue,&image->exception);
8342                   (void) NegateImage(image->mask,MagickFalse,exception);
8343                 }
8344             }
8345           if (attribute_flag[11] != 0) /* channel */
8346             channel=(ChannelType) argument_list[11].integer_reference;
8347           /*
8348             Composite two images (normal composition).
8349           */
8350           (void) FormatLocaleString(composite_geometry,MaxTextExtent,
8351             "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8352             (double) composite_image->rows,(double) geometry.x,(double)
8353             geometry.y);
8354           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8355             exception);
8356           channel_mask=SetPixelChannelMask(image,channel);
8357           if (attribute_flag[8] == 0) /* no rotate */
8358             CompositeImage(image,compose,composite_image,geometry.x,geometry.y);
8359           else
8360             {
8361               /*
8362                 Position adjust rotated image then composite.
8363               */
8364               geometry.x-=(ssize_t) (rotate_image->columns-
8365                 composite_image->columns)/2;
8366               geometry.y-=(ssize_t) (rotate_image->rows-
8367                 composite_image->rows)/2;
8368               CompositeImage(image,compose,rotate_image,geometry.x,geometry.y);
8369               rotate_image=DestroyImage(rotate_image);
8370             }
8371           if (attribute_flag[10] != 0) /* mask */
8372             {
8373               if ((image->compose == DisplaceCompositeOp) ||
8374                   (image->compose == DistortCompositeOp))
8375                 composite_image=DestroyImage(composite_image);
8376               else
8377                 image->mask=DestroyImage(image->mask);
8378             }
8379           (void) SetPixelChannelMask(image,channel_mask);
8380           break;
8381         }
8382         case 36:  /* Contrast */
8383         {
8384           if (attribute_flag[0] == 0)
8385             argument_list[0].integer_reference=0;
8386           (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8387             MagickTrue : MagickFalse,exception);
8388           break;
8389         }
8390         case 37:  /* CycleColormap */
8391         {
8392           if (attribute_flag[0] == 0)
8393             argument_list[0].integer_reference=6;
8394           (void) CycleColormapImage(image,argument_list[0].integer_reference,
8395             exception);
8396           break;
8397         }
8398         case 38:  /* Draw */
8399         {
8400           DrawInfo
8401             *draw_info;
8402
8403           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8404             (DrawInfo *) NULL);
8405           (void) CloneString(&draw_info->primitive,"point");
8406           if (attribute_flag[0] != 0)
8407             {
8408               if (argument_list[0].integer_reference < 0)
8409                 (void) CloneString(&draw_info->primitive,
8410                   argument_list[0].string_reference);
8411               else
8412                 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8413                   MagickPrimitiveOptions,argument_list[0].integer_reference));
8414             }
8415           if (attribute_flag[1] != 0)
8416             {
8417               if (LocaleCompare(draw_info->primitive,"path") == 0)
8418                 {
8419                   (void) ConcatenateString(&draw_info->primitive," '");
8420                   ConcatenateString(&draw_info->primitive,
8421                     argument_list[1].string_reference);
8422                   (void) ConcatenateString(&draw_info->primitive,"'");
8423                 }
8424               else
8425                 {
8426                   (void) ConcatenateString(&draw_info->primitive," ");
8427                   ConcatenateString(&draw_info->primitive,
8428                     argument_list[1].string_reference);
8429                 }
8430             }
8431           if (attribute_flag[2] != 0)
8432             {
8433               (void) ConcatenateString(&draw_info->primitive," ");
8434               (void) ConcatenateString(&draw_info->primitive,
8435                 CommandOptionToMnemonic(MagickMethodOptions,
8436                 argument_list[2].integer_reference));
8437             }
8438           if (attribute_flag[3] != 0)
8439             {
8440               (void) QueryColorDatabase(argument_list[3].string_reference,
8441                 &draw_info->stroke,exception);
8442               if (argument_list[3].image_reference != (Image *) NULL)
8443                 draw_info->stroke_pattern=CloneImage(
8444                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8445             }
8446           if (attribute_flag[4] != 0)
8447             {
8448               (void) QueryColorDatabase(argument_list[4].string_reference,
8449                 &draw_info->fill,exception);
8450               if (argument_list[4].image_reference != (Image *) NULL)
8451                 draw_info->fill_pattern=CloneImage(
8452                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8453             }
8454           if (attribute_flag[5] != 0)
8455             draw_info->stroke_width=argument_list[5].real_reference;
8456           if (attribute_flag[6] != 0)
8457             (void) CloneString(&draw_info->font,
8458               argument_list[6].string_reference);
8459           if (attribute_flag[7] != 0)
8460             (void) QueryColorDatabase(argument_list[7].string_reference,
8461               &draw_info->border_color,exception);
8462           if (attribute_flag[8] != 0)
8463             draw_info->affine.tx=argument_list[8].real_reference;
8464           if (attribute_flag[9] != 0)
8465             draw_info->affine.ty=argument_list[9].real_reference;
8466           if (attribute_flag[20] != 0)
8467             {
8468               AV
8469                 *av;
8470
8471               av=(AV *) argument_list[20].array_reference;
8472               if ((av_len(av) != 3) && (av_len(av) != 5))
8473                 {
8474                   ThrowPerlException(exception,OptionError,
8475                     "affine matrix must have 4 or 6 elements",PackageName);
8476                   goto PerlException;
8477                 }
8478               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8479               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8480               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8481               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8482               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8483                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8484                 {
8485                   ThrowPerlException(exception,OptionError,
8486                     "affine matrix is singular",PackageName);
8487                    goto PerlException;
8488                 }
8489               if (av_len(av) == 5)
8490                 {
8491                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8492                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8493                 }
8494             }
8495           for (j=10; j < 15; j++)
8496           {
8497             if (attribute_flag[j] == 0)
8498               continue;
8499             value=argument_list[j].string_reference;
8500             angle=argument_list[j].real_reference;
8501             current=draw_info->affine;
8502             GetAffineMatrix(&affine);
8503             switch (j)
8504             {
8505               case 10:
8506               {
8507                 /*
8508                   Translate.
8509                 */
8510                 flags=ParseGeometry(value,&geometry_info);
8511                 affine.tx=geometry_info.xi;
8512                 affine.ty=geometry_info.psi;
8513                 if ((flags & PsiValue) == 0)
8514                   affine.ty=affine.tx;
8515                 break;
8516               }
8517               case 11:
8518               {
8519                 /*
8520                   Scale.
8521                 */
8522                 flags=ParseGeometry(value,&geometry_info);
8523                 affine.sx=geometry_info.rho;
8524                 affine.sy=geometry_info.sigma;
8525                 if ((flags & SigmaValue) == 0)
8526                   affine.sy=affine.sx;
8527                 break;
8528               }
8529               case 12:
8530               {
8531                 /*
8532                   Rotate.
8533                 */
8534                 if (angle == 0.0)
8535                   break;
8536                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8537                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8538                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8539                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8540                 break;
8541               }
8542               case 13:
8543               {
8544                 /*
8545                   SkewX.
8546                 */
8547                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8548                 break;
8549               }
8550               case 14:
8551               {
8552                 /*
8553                   SkewY.
8554                 */
8555                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8556                 break;
8557               }
8558             }
8559             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8560             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8561             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8562             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8563             draw_info->affine.tx=
8564               current.sx*affine.tx+current.ry*affine.ty+current.tx;
8565             draw_info->affine.ty=
8566               current.rx*affine.tx+current.sy*affine.ty+current.ty;
8567           }
8568           if (attribute_flag[15] != 0)
8569             draw_info->fill_pattern=CloneImage(
8570               argument_list[15].image_reference,0,0,MagickTrue,exception);
8571           if (attribute_flag[16] != 0)
8572             draw_info->pointsize=argument_list[16].real_reference;
8573           if (attribute_flag[17] != 0)
8574             {
8575               draw_info->stroke_antialias=argument_list[17].integer_reference != 0
8576                 ? MagickTrue : MagickFalse;
8577               draw_info->text_antialias=draw_info->stroke_antialias;
8578             }
8579           if (attribute_flag[18] != 0)
8580             (void) CloneString(&draw_info->density,
8581               argument_list[18].string_reference);
8582           if (attribute_flag[19] != 0)
8583             draw_info->stroke_width=argument_list[19].real_reference;
8584           if (attribute_flag[21] != 0)
8585             draw_info->dash_offset=argument_list[21].real_reference;
8586           if (attribute_flag[22] != 0)
8587             {
8588               AV
8589                 *av;
8590
8591               av=(AV *) argument_list[22].array_reference;
8592               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
8593                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
8594               if (draw_info->dash_pattern != (double *) NULL)
8595                 {
8596                   for (i=0; i <= av_len(av); i++)
8597                     draw_info->dash_pattern[i]=(double)
8598                       SvNV(*(av_fetch(av,i,0)));
8599                   draw_info->dash_pattern[i]=0.0;
8600                 }
8601             }
8602           if (attribute_flag[23] != 0)
8603             image->interpolate=(InterpolatePixelMethod)
8604               argument_list[23].integer_reference;
8605           if ((attribute_flag[24] != 0) &&
8606               (draw_info->fill_pattern != (Image *) NULL))
8607             flags=ParsePageGeometry(draw_info->fill_pattern,
8608               argument_list[24].string_reference,
8609               &draw_info->fill_pattern->tile_offset,exception);
8610           if (attribute_flag[25] != 0)
8611             {
8612               (void) ConcatenateString(&draw_info->primitive," '");
8613               (void) ConcatenateString(&draw_info->primitive,
8614                 argument_list[25].string_reference);
8615               (void) ConcatenateString(&draw_info->primitive,"'");
8616             }
8617           if (attribute_flag[26] != 0)
8618             draw_info->fill_pattern=CloneImage(
8619               argument_list[26].image_reference,0,0,MagickTrue,exception);
8620           if (attribute_flag[27] != 0)
8621             draw_info->stroke_pattern=CloneImage(
8622               argument_list[27].image_reference,0,0,MagickTrue,exception);
8623           if (attribute_flag[28] != 0)
8624             (void) CloneString(&draw_info->primitive,
8625               argument_list[28].string_reference);
8626           if (attribute_flag[29] != 0)
8627             draw_info->kerning=argument_list[29].real_reference;
8628           if (attribute_flag[30] != 0)
8629             draw_info->interline_spacing=argument_list[30].real_reference;
8630           if (attribute_flag[31] != 0)
8631             draw_info->interword_spacing=argument_list[31].real_reference;
8632           if (attribute_flag[32] != 0)
8633             draw_info->direction=(DirectionType)
8634               argument_list[32].integer_reference;
8635           DrawImage(image,draw_info,exception);
8636           draw_info=DestroyDrawInfo(draw_info);
8637           break;
8638         }
8639         case 39:  /* Equalize */
8640         {
8641           if (attribute_flag[0] != 0)
8642             channel=(ChannelType) argument_list[0].integer_reference;
8643           channel_mask=SetPixelChannelMask(image,channel);
8644           EqualizeImage(image,exception);
8645           (void) SetPixelChannelMask(image,channel_mask);
8646           break;
8647         }
8648         case 40:  /* Gamma */
8649         {
8650           if (attribute_flag[1] != 0)
8651             channel=(ChannelType) argument_list[1].integer_reference;
8652           if (attribute_flag[2] == 0)
8653             argument_list[2].real_reference=1.0;
8654           if (attribute_flag[3] == 0)
8655             argument_list[3].real_reference=1.0;
8656           if (attribute_flag[4] == 0)
8657             argument_list[4].real_reference=1.0;
8658           if (attribute_flag[0] == 0)
8659             {
8660               (void) FormatLocaleString(message,MaxTextExtent,
8661                 "%.15g,%.15g,%.15g",(double) argument_list[2].real_reference,
8662                 (double) argument_list[3].real_reference,
8663                 (double) argument_list[4].real_reference);
8664               argument_list[0].string_reference=message;
8665             }
8666           (void) GammaImage(image,InterpretLocaleValue(
8667             argument_list[0].string_reference,(char **) NULL),exception);
8668           break;
8669         }
8670         case 41:  /* Map */
8671         {
8672           QuantizeInfo
8673             *quantize_info;
8674
8675           if (attribute_flag[0] == 0)
8676             {
8677               ThrowPerlException(exception,OptionError,"MapImageRequired",
8678                 PackageName);
8679               goto PerlException;
8680             }
8681           quantize_info=AcquireQuantizeInfo(info->image_info);
8682           if (attribute_flag[1] != 0)
8683             quantize_info->dither=(MagickBooleanType)
8684               argument_list[1].integer_reference;
8685           if (attribute_flag[2] != 0)
8686             quantize_info->dither_method=(DitherMethod)
8687               argument_list[2].integer_reference;
8688           (void) RemapImages(quantize_info,image,
8689             argument_list[0].image_reference,exception);
8690           quantize_info=DestroyQuantizeInfo(quantize_info);
8691           break;
8692         }
8693         case 42:  /* MatteFloodfill */
8694         {
8695           DrawInfo
8696             *draw_info;
8697
8698           MagickBooleanType
8699             invert;
8700
8701           PixelInfo
8702             target;
8703
8704           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8705             (DrawInfo *) NULL);
8706           if (attribute_flag[0] != 0)
8707             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8708               &geometry,exception);
8709           if (attribute_flag[1] != 0)
8710             geometry.x=argument_list[1].integer_reference;
8711           if (attribute_flag[2] != 0)
8712             geometry.y=argument_list[2].integer_reference;
8713           if (image->matte == MagickFalse)
8714             (void) SetImageOpacity(image,OpaqueAlpha);
8715           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
8716             exception);
8717           if (attribute_flag[4] != 0)
8718             QueryMagickColor(argument_list[4].string_reference,&target,
8719               exception);
8720           if (attribute_flag[3] != 0)
8721             target.alpha=SiPrefixToDouble(argument_list[3].string_reference,
8722               QuantumRange);
8723           if (attribute_flag[5] != 0)
8724             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
8725               QuantumRange);
8726           invert=MagickFalse;
8727           if (attribute_flag[6] != 0)
8728             invert=(MagickBooleanType) argument_list[6].integer_reference;
8729           channel_mask=SetPixelChannelMask(image,AlphaChannel);
8730           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8731             geometry.y,invert,exception);
8732           (void) SetPixelChannelMask(image,channel_mask);
8733           draw_info=DestroyDrawInfo(draw_info);
8734           break;
8735         }
8736         case 43:  /* Modulate */
8737         {
8738           char
8739             modulate[MaxTextExtent];
8740
8741           geometry_info.rho=100.0;
8742           geometry_info.sigma=100.0;
8743           geometry_info.xi=100.0;
8744           if (attribute_flag[0] != 0)
8745             (void)ParseGeometry(argument_list[0].string_reference,
8746               &geometry_info);
8747           if (attribute_flag[1] != 0)
8748             geometry_info.xi=argument_list[1].real_reference;
8749           if (attribute_flag[2] != 0)
8750             geometry_info.sigma=argument_list[2].real_reference;
8751           if (attribute_flag[3] != 0)
8752             {
8753               geometry_info.sigma=argument_list[3].real_reference;
8754               SetImageArtifact(image,"modulate:colorspace","HWB");
8755             }
8756           if (attribute_flag[4] != 0)
8757             {
8758               geometry_info.rho=argument_list[4].real_reference;
8759               SetImageArtifact(image,"modulate:colorspace","HSB");
8760             }
8761           if (attribute_flag[5] != 0)
8762             {
8763               geometry_info.sigma=argument_list[5].real_reference;
8764               SetImageArtifact(image,"modulate:colorspace","HSL");
8765             }
8766           if (attribute_flag[6] != 0)
8767             {
8768               geometry_info.rho=argument_list[6].real_reference;
8769               SetImageArtifact(image,"modulate:colorspace","HWB");
8770             }
8771           (void) FormatLocaleString(modulate,MaxTextExtent,"%.15g,%.15g,%.15g",
8772             geometry_info.rho,geometry_info.sigma,geometry_info.xi);
8773           (void) ModulateImage(image,modulate,exception);
8774           break;
8775         }
8776         case 44:  /* Negate */
8777         {
8778           if (attribute_flag[0] == 0)
8779             argument_list[0].integer_reference=0;
8780           if (attribute_flag[1] != 0)
8781             channel=(ChannelType) argument_list[1].integer_reference;
8782           channel_mask=SetPixelChannelMask(image,channel);
8783           (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
8784             MagickTrue : MagickFalse,exception);
8785           (void) SetPixelChannelMask(image,channel_mask);
8786           break;
8787         }
8788         case 45:  /* Normalize */
8789         {
8790           if (attribute_flag[0] != 0)
8791             channel=(ChannelType) argument_list[0].integer_reference;
8792           channel_mask=SetPixelChannelMask(image,channel);
8793           NormalizeImage(image,exception);
8794           (void) SetPixelChannelMask(image,channel_mask);
8795           break;
8796         }
8797         case 46:  /* NumberColors */
8798           break;
8799         case 47:  /* Opaque */
8800         {
8801           MagickBooleanType
8802             invert;
8803
8804           PixelInfo
8805             fill_color,
8806             target;
8807
8808           (void) QueryMagickColor("none",&target,exception);
8809           (void) QueryMagickColor("none",&fill_color,exception);
8810           if (attribute_flag[0] != 0)
8811             (void) QueryMagickColor(argument_list[0].string_reference,
8812               &target,exception);
8813           if (attribute_flag[1] != 0)
8814             (void) QueryMagickColor(argument_list[1].string_reference,
8815               &fill_color,exception);
8816           if (attribute_flag[2] != 0)
8817             image->fuzz=SiPrefixToDouble(argument_list[2].string_reference,
8818               QuantumRange);
8819           if (attribute_flag[3] != 0)
8820             channel=(ChannelType) argument_list[3].integer_reference;
8821           invert=MagickFalse;
8822           if (attribute_flag[4] != 0)
8823             invert=(MagickBooleanType) argument_list[4].integer_reference;
8824           channel_mask=SetPixelChannelMask(image,channel);
8825           (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
8826           (void) SetPixelChannelMask(image,channel_mask);
8827           break;
8828         }
8829         case 48:  /* Quantize */
8830         {
8831           QuantizeInfo
8832             *quantize_info;
8833
8834           quantize_info=AcquireQuantizeInfo(info->image_info);
8835           if (attribute_flag[0] != 0)
8836             quantize_info->number_colors=(size_t)
8837               argument_list[0].integer_reference;
8838           if (attribute_flag[1] != 0)
8839             quantize_info->tree_depth=(size_t)
8840               argument_list[1].integer_reference;
8841           if (attribute_flag[2] != 0)
8842             quantize_info->colorspace=(ColorspaceType)
8843               argument_list[2].integer_reference;
8844           if (attribute_flag[3] != 0)
8845             quantize_info->dither=argument_list[3].integer_reference != 0 ?
8846               MagickTrue : MagickFalse;
8847           if (attribute_flag[4] != 0)
8848             quantize_info->measure_error=
8849               argument_list[4].integer_reference != 0 ? MagickTrue : MagickFalse;
8850           if (attribute_flag[5] != 0)
8851             (void) QueryColorDatabase(argument_list[5].string_reference,
8852               &image->transparent_color,exception);
8853           if (attribute_flag[5] && argument_list[5].integer_reference)
8854             {
8855               (void) QuantizeImages(quantize_info,image,exception);
8856               goto PerlException;
8857             }
8858           if (attribute_flag[6] != 0)
8859             quantize_info->dither_method=(DitherMethod)
8860               argument_list[6].integer_reference;
8861           if ((image->storage_class == DirectClass) ||
8862               (image->colors > quantize_info->number_colors) ||
8863               (quantize_info->colorspace == GRAYColorspace))
8864             (void) QuantizeImage(quantize_info,image,exception);
8865           else
8866             CompressImageColormap(image,exception);
8867           quantize_info=DestroyQuantizeInfo(quantize_info);
8868           break;
8869         }
8870         case 49:  /* Raise */
8871         {
8872           if (attribute_flag[0] != 0)
8873             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8874               &geometry,exception);
8875           if (attribute_flag[1] != 0)
8876             geometry.width=argument_list[1].integer_reference;
8877           if (attribute_flag[2] != 0)
8878             geometry.height=argument_list[2].integer_reference;
8879           if (attribute_flag[3] == 0)
8880             argument_list[3].integer_reference=1;
8881           (void) RaiseImage(image,&geometry,
8882             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8883             exception);
8884           break;
8885         }
8886         case 50:  /* Segment */
8887         {
8888           ColorspaceType
8889             colorspace;
8890
8891           double
8892             cluster_threshold,
8893             smoothing_threshold;
8894
8895           MagickBooleanType
8896             verbose;
8897
8898           cluster_threshold=1.0;
8899           smoothing_threshold=1.5;
8900           colorspace=RGBColorspace;
8901           verbose=MagickFalse;
8902           if (attribute_flag[0] != 0)
8903             {
8904               flags=ParseGeometry(argument_list[0].string_reference,
8905                 &geometry_info);
8906               cluster_threshold=geometry_info.rho;
8907               if (flags & SigmaValue)
8908                 smoothing_threshold=geometry_info.sigma;
8909             }
8910           if (attribute_flag[1] != 0)
8911             cluster_threshold=argument_list[1].real_reference;
8912           if (attribute_flag[2] != 0)
8913             smoothing_threshold=argument_list[2].real_reference;
8914           if (attribute_flag[3] != 0)
8915             colorspace=(ColorspaceType) argument_list[3].integer_reference;
8916           if (attribute_flag[4] != 0)
8917             verbose=argument_list[4].integer_reference != 0 ?
8918               MagickTrue : MagickFalse;
8919           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
8920             smoothing_threshold,exception);
8921           break;
8922         }
8923         case 51:  /* Signature */
8924         {
8925           (void) SignatureImage(image,exception);
8926           break;
8927         }
8928         case 52:  /* Solarize */
8929         {
8930           geometry_info.rho=QuantumRange/2.0;
8931           if (attribute_flag[0] != 0)
8932             flags=ParseGeometry(argument_list[0].string_reference,
8933               &geometry_info);
8934           if (attribute_flag[1] != 0)
8935             geometry_info.rho=SiPrefixToDouble(
8936              argument_list[1].string_reference,QuantumRange);
8937           (void) SolarizeImage(image,geometry_info.rho,exception);
8938           break;
8939         }
8940         case 53:  /* Sync */
8941         {
8942           (void) SyncImage(image);
8943           break;
8944         }
8945         case 54:  /* Texture */
8946         {
8947           if (attribute_flag[0] == 0)
8948             break;
8949           TextureImage(image,argument_list[0].image_reference);
8950           break;
8951         }
8952         case 55:  /* Evalute */
8953         {
8954           MagickEvaluateOperator
8955             op;
8956
8957           op=SetEvaluateOperator;
8958           if (attribute_flag[0] == MagickFalse)
8959             argument_list[0].real_reference=0.0;
8960           if (attribute_flag[1] != MagickFalse)
8961             op=(MagickEvaluateOperator) argument_list[1].integer_reference;
8962           if (attribute_flag[2] != MagickFalse)
8963             channel=(ChannelType) argument_list[2].integer_reference;
8964           channel_mask=SetPixelChannelMask(image,channel);
8965           (void) EvaluateImage(image,op,argument_list[0].real_reference,
8966             exception);
8967           (void) SetPixelChannelMask(image,channel_mask);
8968           break;
8969         }
8970         case 56:  /* Transparent */
8971         {
8972           double
8973             opacity;
8974
8975           MagickBooleanType
8976             invert;
8977
8978           PixelInfo
8979             target;
8980
8981           (void) QueryMagickColor("none",&target,exception);
8982           if (attribute_flag[0] != 0)
8983             (void) QueryMagickColor(argument_list[0].string_reference,&target,
8984               exception);
8985           opacity=TransparentAlpha;
8986           if (attribute_flag[1] != 0)
8987             opacity=SiPrefixToDouble(argument_list[1].string_reference,
8988               QuantumRange);
8989           if (attribute_flag[2] != 0)
8990             image->fuzz=SiPrefixToDouble(argument_list[2].string_reference,
8991               QuantumRange);
8992           if (attribute_flag[3] == 0)
8993             argument_list[3].integer_reference=0;
8994           invert=MagickFalse;
8995           if (attribute_flag[3] != 0)
8996             invert=(MagickBooleanType) argument_list[3].integer_reference;
8997           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
8998             invert,exception);
8999           break;
9000         }
9001         case 57:  /* Threshold */
9002         {
9003           double
9004             threshold;
9005
9006           if (attribute_flag[0] == 0)
9007             argument_list[0].string_reference="50%";
9008           if (attribute_flag[1] != 0)
9009             channel=(ChannelType) argument_list[1].integer_reference;
9010           threshold=SiPrefixToDouble(argument_list[0].string_reference,
9011             QuantumRange);
9012           channel_mask=SetPixelChannelMask(image,channel);
9013           (void) BilevelImage(image,threshold);
9014           (void) SetPixelChannelMask(image,channel_mask);
9015           break;
9016         }
9017         case 58:  /* Charcoal */
9018         {
9019           if (attribute_flag[0] != 0)
9020             {
9021               flags=ParseGeometry(argument_list[0].string_reference,
9022                 &geometry_info);
9023               if ((flags & SigmaValue) == 0)
9024                 geometry_info.sigma=1.0;
9025             }
9026           if (attribute_flag[1] != 0)
9027             geometry_info.rho=argument_list[1].real_reference;
9028           if (attribute_flag[2] != 0)
9029             geometry_info.sigma=argument_list[2].real_reference;
9030           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9031             exception);
9032           break;
9033         }
9034         case 59:  /* Trim */
9035         {
9036           if (attribute_flag[0] != 0)
9037             image->fuzz=SiPrefixToDouble(argument_list[0].string_reference,
9038               QuantumRange);
9039           image=TrimImage(image,exception);
9040           break;
9041         }
9042         case 60:  /* Wave */
9043         {
9044           if (attribute_flag[0] != 0)
9045             {
9046               flags=ParseGeometry(argument_list[0].string_reference,
9047                 &geometry_info);
9048               if ((flags & SigmaValue) == 0)
9049                 geometry_info.sigma=1.0;
9050             }
9051           if (attribute_flag[1] != 0)
9052             geometry_info.rho=argument_list[1].real_reference;
9053           if (attribute_flag[2] != 0)
9054             geometry_info.sigma=argument_list[2].real_reference;
9055           if (attribute_flag[3] != 0)
9056             image->interpolate=(InterpolatePixelMethod)
9057               argument_list[3].integer_reference;
9058           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9059             exception);
9060           break;
9061         }
9062         case 61:  /* Separate */
9063         {
9064           if (attribute_flag[0] != 0)
9065             channel=(ChannelType) argument_list[0].integer_reference;
9066           channel_mask=SetPixelChannelMask(image,channel);
9067           (void) SeparateImage(image);
9068           (void) SetPixelChannelMask(image,channel_mask);
9069           break;
9070         }
9071         case 63:  /* Stereo */
9072         {
9073           if (attribute_flag[0] == 0)
9074             {
9075               ThrowPerlException(exception,OptionError,"StereoImageRequired",
9076                 PackageName);
9077               goto PerlException;
9078             }
9079           if (attribute_flag[1] != 0)
9080             geometry.x=argument_list[1].integer_reference;
9081           if (attribute_flag[2] != 0)
9082             geometry.y=argument_list[2].integer_reference;
9083           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9084             geometry.x,geometry.y,exception);
9085           break;
9086         }
9087         case 64:  /* Stegano */
9088         {
9089           if (attribute_flag[0] == 0)
9090             {
9091               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9092                 PackageName);
9093               goto PerlException;
9094             }
9095           if (attribute_flag[1] == 0)
9096             argument_list[1].integer_reference=0;
9097           image->offset=argument_list[1].integer_reference;
9098           image=SteganoImage(image,argument_list[0].image_reference,exception);
9099           break;
9100         }
9101         case 65:  /* Deconstruct */
9102         {
9103           image=CompareImagesLayers(image,CompareAnyLayer,exception);
9104           break;
9105         }
9106         case 66:  /* GaussianBlur */
9107         {
9108           if (attribute_flag[0] != 0)
9109             {
9110               flags=ParseGeometry(argument_list[0].string_reference,
9111                 &geometry_info);
9112               if ((flags & SigmaValue) == 0)
9113                 geometry_info.sigma=1.0;
9114             }
9115           if (attribute_flag[1] != 0)
9116             geometry_info.rho=argument_list[1].real_reference;
9117           if (attribute_flag[2] != 0)
9118             geometry_info.sigma=argument_list[2].real_reference;
9119           if (attribute_flag[3] != 0)
9120             channel=(ChannelType) argument_list[3].integer_reference;
9121           channel_mask=SetPixelChannelMask(image,channel);
9122           image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9123             exception);
9124           if (image != (Image *) NULL)
9125             (void) SetPixelChannelMask(image,channel_mask);
9126           break;
9127         }
9128         case 67:  /* Convolve */
9129         {
9130           KernelInfo
9131             *kernel;
9132
9133           kernel=(KernelInfo *) NULL;
9134           if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9135             break;
9136           if (attribute_flag[0] != 0)
9137             {
9138               AV
9139                 *av;
9140
9141               size_t
9142                 order;
9143
9144               kernel=AcquireKernelInfo((const char *) NULL);
9145               if (kernel == (KernelInfo *) NULL)
9146                 break;
9147               av=(AV *) argument_list[0].array_reference;
9148               order=(size_t) sqrt(av_len(av)+1);
9149               kernel->width=order;
9150               kernel->height=order;
9151               kernel->values=(double *) AcquireQuantumMemory(order,order*
9152                 sizeof(*kernel->values));
9153               if (kernel->values == (double *) NULL)
9154                 {
9155                   kernel=DestroyKernelInfo(kernel);
9156                   ThrowPerlException(exception,ResourceLimitFatalError,
9157                     "MemoryAllocationFailed",PackageName);
9158                   goto PerlException;
9159                 }
9160               for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9161                 kernel->values[j]=(double) SvNV(*(av_fetch(av,j,0)));
9162               for ( ; j < (ssize_t) (order*order); j++)
9163                 kernel->values[j]=0.0;
9164             }
9165           if (attribute_flag[1] != 0)
9166             channel=(ChannelType) argument_list[1].integer_reference;
9167           if (attribute_flag[2] != 0)
9168             image->bias=SiPrefixToDouble(argument_list[2].string_reference,
9169               QuantumRange);
9170           if (attribute_flag[3] != 0)
9171             {
9172               kernel=AcquireKernelInfo(argument_list[3].string_reference);
9173               if (kernel == (KernelInfo *) NULL)
9174                 break;
9175             }
9176           channel_mask=SetPixelChannelMask(image,channel);
9177           kernel->bias=image->bias;
9178           image=ConvolveImage(image,kernel,exception);
9179           if (image != (Image *) NULL)
9180             (void) SetPixelChannelMask(image,channel_mask);
9181           kernel=DestroyKernelInfo(kernel);
9182           break;
9183         }
9184         case 68:  /* Profile */
9185         {
9186           const char
9187             *name;
9188
9189           Image
9190             *profile_image;
9191
9192           ImageInfo
9193             *profile_info;
9194
9195           StringInfo
9196             *profile;
9197
9198           name="*";
9199           if (attribute_flag[0] != 0)
9200             name=argument_list[0].string_reference;
9201           if (attribute_flag[2] != 0)
9202             image->rendering_intent=(RenderingIntent)
9203               argument_list[2].integer_reference;
9204           if (attribute_flag[3] != 0)
9205             image->black_point_compensation=
9206               argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9207           if (attribute_flag[1] != 0)
9208             {
9209               if (argument_list[1].length == 0)
9210                 {
9211                   /*
9212                     Remove a profile from the image.
9213                   */
9214                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9215                     MagickTrue);
9216                   break;
9217                 }
9218               /*
9219                 Associate user supplied profile with the image.
9220               */
9221               profile=AcquireStringInfo(argument_list[1].length);
9222               SetStringInfoDatum(profile,(const unsigned char *)
9223                 argument_list[1].string_reference);
9224               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9225                 (size_t) GetStringInfoLength(profile),MagickFalse);
9226               profile=DestroyStringInfo(profile);
9227               break;
9228             }
9229           /*
9230             Associate a profile with the image.
9231           */
9232           profile_info=
9233             CloneImageInfo(info ? info->image_info : (ImageInfo *) NULL);
9234           (void) CopyMagickString(profile_info->filename,name,MaxTextExtent);
9235           profile_image=ReadImages(profile_info,&image->exception);
9236           if (profile_image == (Image *) NULL)
9237             break;
9238           ResetImageProfileIterator(profile_image);
9239           name=GetNextImageProfile(profile_image);
9240           while (name != (const char *) NULL)
9241           {
9242             const StringInfo
9243               *profile;
9244
9245             profile=GetImageProfile(profile_image,name);
9246             if (profile != (const StringInfo *) NULL)
9247               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9248                 (size_t) GetStringInfoLength(profile),MagickFalse);
9249             name=GetNextImageProfile(profile_image);
9250           }
9251           profile_image=DestroyImage(profile_image);
9252           profile_info=DestroyImageInfo(profile_info);
9253           break;
9254         }
9255         case 69:  /* UnsharpMask */
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               if ((flags & XiValue) == 0)
9264                 geometry_info.xi=1.0;
9265               if ((flags & PsiValue) == 0)
9266                 geometry_info.psi=0.5;
9267             }
9268           if (attribute_flag[1] != 0)
9269             geometry_info.rho=argument_list[1].real_reference;
9270           if (attribute_flag[2] != 0)
9271             geometry_info.sigma=argument_list[2].real_reference;
9272           if (attribute_flag[3] != 0)
9273             geometry_info.xi=argument_list[3].real_reference;
9274           if (attribute_flag[4] != 0)
9275             geometry_info.psi=argument_list[4].real_reference;
9276           if (attribute_flag[5] != 0)
9277             channel=(ChannelType) argument_list[5].integer_reference;
9278           channel_mask=SetPixelChannelMask(image,channel);
9279           image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9280             geometry_info.xi,geometry_info.psi,exception);
9281           if (image != (Image *) NULL)
9282             (void) SetPixelChannelMask(image,channel_mask);
9283           break;
9284         }
9285         case 70:  /* MotionBlur */
9286         {
9287           if (attribute_flag[0] != 0)
9288             {
9289               flags=ParseGeometry(argument_list[0].string_reference,
9290                 &geometry_info);
9291               if ((flags & SigmaValue) == 0)
9292                 geometry_info.sigma=1.0;
9293               if ((flags & XiValue) == 0)
9294                 geometry_info.xi=1.0;
9295             }
9296           if (attribute_flag[1] != 0)
9297             geometry_info.rho=argument_list[1].real_reference;
9298           if (attribute_flag[2] != 0)
9299             geometry_info.sigma=argument_list[2].real_reference;
9300           if (attribute_flag[3] != 0)
9301             geometry_info.xi=argument_list[3].real_reference;
9302           if (attribute_flag[4] != 0)
9303             channel=(ChannelType) argument_list[4].integer_reference;
9304           channel_mask=SetPixelChannelMask(image,channel);
9305           image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9306             geometry_info.xi,exception);
9307           if (image != (Image *) NULL)
9308             (void) SetPixelChannelMask(image,channel_mask);
9309           break;
9310         }
9311         case 71:  /* OrderedDither */
9312         {
9313           if (attribute_flag[0] == 0)
9314             argument_list[0].string_reference="o8x8";
9315           if (attribute_flag[1] != 0)
9316             channel=(ChannelType) argument_list[1].integer_reference;
9317           channel_mask=SetPixelChannelMask(image,channel);
9318           (void) OrderedPosterizeImage(image,argument_list[0].string_reference,
9319             exception);
9320           (void) SetPixelChannelMask(image,channel_mask);
9321           break;
9322         }
9323         case 72:  /* Shave */
9324         {
9325           if (attribute_flag[0] != 0)
9326             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9327               &geometry,exception);
9328           if (attribute_flag[1] != 0)
9329             geometry.width=argument_list[1].integer_reference;
9330           if (attribute_flag[2] != 0)
9331             geometry.height=argument_list[2].integer_reference;
9332           image=ShaveImage(image,&geometry,exception);
9333           break;
9334         }
9335         case 73:  /* Level */
9336         {
9337           double
9338             black_point,
9339             gamma,
9340             white_point;
9341
9342           black_point=0.0;
9343           white_point=(MagickRealType) image->columns*image->rows;
9344           gamma=1.0;
9345           if (attribute_flag[0] != 0)
9346             {
9347               flags=ParseGeometry(argument_list[0].string_reference,
9348                 &geometry_info);
9349               black_point=geometry_info.rho;
9350               if ((flags & SigmaValue) != 0)
9351                 white_point=geometry_info.sigma;
9352               if ((flags & XiValue) != 0)
9353                 gamma=geometry_info.xi;
9354               if ((flags & PercentValue) != 0)
9355                 {
9356                   black_point*=(double) (QuantumRange/100.0);
9357                   white_point*=(double) (QuantumRange/100.0);
9358                 }
9359               if ((flags & SigmaValue) == 0)
9360                 white_point=(double) QuantumRange-black_point;
9361             }
9362           if (attribute_flag[1] != 0)
9363             black_point=argument_list[1].real_reference;
9364           if (attribute_flag[2] != 0)
9365             white_point=argument_list[2].real_reference;
9366           if (attribute_flag[3] != 0)
9367             gamma=argument_list[3].real_reference;
9368           if (attribute_flag[4] != 0)
9369             channel=(ChannelType) argument_list[4].integer_reference;
9370           if (attribute_flag[5] != 0)
9371             {
9372               argument_list[0].real_reference=argument_list[5].real_reference;
9373               attribute_flag[0]=attribute_flag[5];
9374             }
9375           channel_mask=SetPixelChannelMask(image,channel);
9376           (void) LevelImage(image,black_point,white_point,gamma,exception);
9377           (void) SetPixelChannelMask(image,channel_mask);
9378           break;
9379         }
9380         case 74:  /* Clip */
9381         {
9382           if (attribute_flag[0] == 0)
9383             argument_list[0].string_reference="#1";
9384           if (attribute_flag[1] == 0)
9385             argument_list[1].integer_reference=MagickTrue;
9386           (void) ClipImagePath(image,argument_list[0].string_reference,
9387             argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse,
9388             exception);
9389           break;
9390         }
9391         case 75:  /* AffineTransform */
9392         {
9393           DrawInfo
9394             *draw_info;
9395
9396           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9397             (DrawInfo *) NULL);
9398           if (attribute_flag[0] != 0)
9399             {
9400               AV
9401                 *av;
9402
9403               av=(AV *) argument_list[0].array_reference;
9404               if ((av_len(av) != 3) && (av_len(av) != 5))
9405                 {
9406                   ThrowPerlException(exception,OptionError,
9407                     "affine matrix must have 4 or 6 elements",PackageName);
9408                   goto PerlException;
9409                 }
9410               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9411               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9412               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9413               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9414               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9415                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9416                 {
9417                   ThrowPerlException(exception,OptionError,
9418                     "affine matrix is singular",PackageName);
9419                    goto PerlException;
9420                 }
9421               if (av_len(av) == 5)
9422                 {
9423                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9424                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9425                 }
9426             }
9427           for (j=1; j < 6; j++)
9428           {
9429             if (attribute_flag[j] == 0)
9430               continue;
9431             value=argument_list[j].string_reference;
9432             angle=argument_list[j].real_reference;
9433             current=draw_info->affine;
9434             GetAffineMatrix(&affine);
9435             switch (j)
9436             {
9437               case 1:
9438               {
9439                 /*
9440                   Translate.
9441                 */
9442                 flags=ParseGeometry(value,&geometry_info);
9443                 affine.tx=geometry_info.xi;
9444                 affine.ty=geometry_info.psi;
9445                 if ((flags & PsiValue) == 0)
9446                   affine.ty=affine.tx;
9447                 break;
9448               }
9449               case 2:
9450               {
9451                 /*
9452                   Scale.
9453                 */
9454                 flags=ParseGeometry(value,&geometry_info);
9455                 affine.sx=geometry_info.rho;
9456                 affine.sy=geometry_info.sigma;
9457                 if ((flags & SigmaValue) == 0)
9458                   affine.sy=affine.sx;
9459                 break;
9460               }
9461               case 3:
9462               {
9463                 /*
9464                   Rotate.
9465                 */
9466                 if (angle == 0.0)
9467                   break;
9468                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9469                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9470                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9471                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9472                 break;
9473               }
9474               case 4:
9475               {
9476                 /*
9477                   SkewX.
9478                 */
9479                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9480                 break;
9481               }
9482               case 5:
9483               {
9484                 /*
9485                   SkewY.
9486                 */
9487                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9488                 break;
9489               }
9490             }
9491             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9492             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9493             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9494             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9495             draw_info->affine.tx=
9496               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9497             draw_info->affine.ty=
9498               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9499           }
9500           if (attribute_flag[6] != 0)
9501             image->interpolate=(InterpolatePixelMethod)
9502               argument_list[6].integer_reference;
9503           if (attribute_flag[7] != 0)
9504             QueryColorDatabase(argument_list[7].string_reference,
9505               &image->background_color,exception);
9506           image=AffineTransformImage(image,&draw_info->affine,exception);
9507           draw_info=DestroyDrawInfo(draw_info);
9508           break;
9509         }
9510         case 76:  /* Difference */
9511         {
9512           if (attribute_flag[0] == 0)
9513             {
9514               ThrowPerlException(exception,OptionError,
9515                 "ReferenceImageRequired",PackageName);
9516               goto PerlException;
9517             }
9518           if (attribute_flag[1] != 0)
9519             image->fuzz=SiPrefixToDouble(argument_list[1].string_reference,
9520               QuantumRange);
9521           (void) IsImagesEqual(image,argument_list[0].image_reference,
9522             exception);
9523           break;
9524         }
9525         case 77:  /* AdaptiveThreshold */
9526         {
9527           if (attribute_flag[0] != 0)
9528             {
9529               flags=ParseGeometry(argument_list[0].string_reference,
9530                 &geometry_info);
9531               if ((flags & PercentValue) != 0)
9532                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9533             }
9534           if (attribute_flag[1] != 0)
9535             geometry_info.rho=argument_list[1].integer_reference;
9536           if (attribute_flag[2] != 0)
9537             geometry_info.sigma=argument_list[2].integer_reference;
9538           if (attribute_flag[3] != 0)
9539             geometry_info.xi=argument_list[3].integer_reference;;
9540           image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
9541             (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
9542           break;
9543         }
9544         case 78:  /* Resample */
9545         {
9546           size_t
9547             height,
9548             width;
9549
9550           if (attribute_flag[0] != 0)
9551             {
9552               flags=ParseGeometry(argument_list[0].string_reference,
9553                 &geometry_info);
9554               if ((flags & SigmaValue) == 0)
9555                 geometry_info.sigma=geometry_info.rho;
9556             }
9557           if (attribute_flag[1] != 0)
9558             geometry_info.rho=argument_list[1].real_reference;
9559           if (attribute_flag[2] != 0)
9560             geometry_info.sigma=argument_list[2].real_reference;
9561           if (attribute_flag[3] == 0)
9562             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
9563           if (attribute_flag[4] == 0)
9564             SetImageArtifact(image,"filter:support",
9565               argument_list[4].string_reference);
9566           if (attribute_flag[5] != 0)
9567             argument_list[5].real_reference=1.0;
9568           width=(size_t) (geometry_info.rho*image->columns/
9569             (image->x_resolution == 0.0 ? 72.0 : image->x_resolution)+0.5);
9570           height=(size_t) (geometry_info.sigma*image->rows/
9571             (image->y_resolution == 0.0 ? 72.0 : image->y_resolution)+0.5);
9572           image=ResizeImage(image,width,height,(FilterTypes)
9573             argument_list[3].integer_reference,argument_list[5].real_reference,
9574             exception);
9575           if (image != (Image *) NULL)
9576             {
9577               image->x_resolution=geometry_info.rho;
9578               image->y_resolution=geometry_info.sigma;
9579             }
9580           break;
9581         }
9582         case 79:  /* Describe */
9583         {
9584           if (attribute_flag[0] == 0)
9585             argument_list[0].file_reference=(FILE *) NULL;
9586           if (attribute_flag[1] != 0)
9587             (void) SetImageArtifact(image,"identify:features",
9588               argument_list[1].string_reference);
9589           (void) IdentifyImage(image,argument_list[0].file_reference,
9590             MagickTrue,exception);
9591           break;
9592         }
9593         case 80:  /* BlackThreshold */
9594         {
9595           if (attribute_flag[0] == 0)
9596             argument_list[0].string_reference="50%";
9597           if (attribute_flag[2] != 0)
9598             channel=(ChannelType) argument_list[2].integer_reference;
9599           channel_mask=SetPixelChannelMask(image,channel);
9600           BlackThresholdImage(image,argument_list[0].string_reference,
9601             exception);
9602           (void) SetPixelChannelMask(image,channel_mask);
9603           break;
9604         }
9605         case 81:  /* WhiteThreshold */
9606         {
9607           if (attribute_flag[0] == 0)
9608             argument_list[0].string_reference="50%";
9609           if (attribute_flag[2] != 0)
9610             channel=(ChannelType) argument_list[2].integer_reference;
9611           channel_mask=SetPixelChannelMask(image,channel);
9612           WhiteThresholdImage(image,argument_list[0].string_reference,
9613             exception);
9614           (void) SetPixelChannelMask(image,channel_mask);
9615           break;
9616         }
9617         case 82:  /* RadialBlur */
9618         {
9619           if (attribute_flag[0] != 0)
9620             {
9621               flags=ParseGeometry(argument_list[0].string_reference,
9622                 &geometry_info);
9623               if ((flags & SigmaValue) == 0)
9624                 geometry_info.sigma=1.0;
9625             }
9626           if (attribute_flag[1] != 0)
9627             geometry_info.rho=argument_list[1].real_reference;
9628           if (attribute_flag[2] != 0)
9629             channel=(ChannelType) argument_list[2].integer_reference;
9630           channel_mask=SetPixelChannelMask(image,channel);
9631           image=RadialBlurImage(image,geometry_info.rho,exception);
9632           if (image != (Image *) NULL)
9633             (void) SetPixelChannelMask(image,channel_mask);
9634           break;
9635         }
9636         case 83:  /* Thumbnail */
9637         {
9638           if (attribute_flag[0] != 0)
9639             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
9640               &geometry,exception);
9641           if (attribute_flag[1] != 0)
9642             geometry.width=argument_list[1].integer_reference;
9643           if (attribute_flag[2] != 0)
9644             geometry.height=argument_list[2].integer_reference;
9645           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
9646           break;
9647         }
9648         case 84:  /* Strip */
9649         {
9650           (void) StripImage(image);
9651           break;
9652         }
9653         case 85:  /* Tint */
9654         {
9655           PixelPacket
9656             target;
9657
9658           (void) GetOneVirtualPixel(image,0,0,&target,exception);
9659           if (attribute_flag[0] != 0)
9660             (void) QueryColorDatabase(argument_list[0].string_reference,&target,
9661               exception);
9662           if (attribute_flag[1] == 0)
9663             argument_list[1].string_reference="100";
9664           image=TintImage(image,argument_list[1].string_reference,target,
9665             exception);
9666           break;
9667         }
9668         case 86:  /* Channel */
9669         {
9670           if (attribute_flag[0] != 0)
9671             channel=(ChannelType) argument_list[0].integer_reference;
9672           channel_mask=SetPixelChannelMask(image,channel);
9673           (void) SeparateImage(image);
9674           (void) SetPixelChannelMask(image,channel_mask);
9675           break;
9676         }
9677         case 87:  /* Splice */
9678         {
9679           if (attribute_flag[0] != 0)
9680             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
9681               &geometry,exception);
9682           if (attribute_flag[1] != 0)
9683             geometry.width=argument_list[1].integer_reference;
9684           if (attribute_flag[2] != 0)
9685             geometry.height=argument_list[2].integer_reference;
9686           if (attribute_flag[3] != 0)
9687             geometry.x=argument_list[3].integer_reference;
9688           if (attribute_flag[4] != 0)
9689             geometry.y=argument_list[4].integer_reference;
9690           if (attribute_flag[5] != 0)
9691             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
9692               QuantumRange);
9693           if (attribute_flag[6] != 0)
9694             (void) QueryColorDatabase(argument_list[6].string_reference,
9695               &image->background_color,exception);
9696           if (attribute_flag[7] != 0)
9697             image->gravity=(GravityType) argument_list[7].integer_reference;
9698           image=SpliceImage(image,&geometry,exception);
9699           break;
9700         }
9701         case 88:  /* Posterize */
9702         {
9703           if (attribute_flag[0] == 0)
9704             argument_list[0].integer_reference=3;
9705           if (attribute_flag[1] == 0)
9706             argument_list[1].integer_reference=0;
9707           (void) PosterizeImage(image,argument_list[0].integer_reference,
9708             argument_list[1].integer_reference ? MagickTrue : MagickFalse,
9709             exception);
9710           break;
9711         }
9712         case 89:  /* Shadow */
9713         {
9714           if (attribute_flag[0] != 0)
9715             {
9716               flags=ParseGeometry(argument_list[0].string_reference,
9717                 &geometry_info);
9718               if ((flags & SigmaValue) == 0)
9719                 geometry_info.sigma=1.0;
9720               if ((flags & XiValue) == 0)
9721                 geometry_info.xi=4.0;
9722               if ((flags & PsiValue) == 0)
9723                 geometry_info.psi=4.0;
9724             }
9725           if (attribute_flag[1] != 0)
9726             geometry_info.rho=argument_list[1].real_reference;
9727           if (attribute_flag[2] != 0)
9728             geometry_info.sigma=argument_list[2].real_reference;
9729           if (attribute_flag[3] != 0)
9730             geometry_info.xi=argument_list[3].integer_reference;
9731           if (attribute_flag[4] != 0)
9732             geometry_info.psi=argument_list[4].integer_reference;
9733           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
9734             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-
9735             0.5),exception);
9736           break;
9737         }
9738         case 90:  /* Identify */
9739         {
9740           if (attribute_flag[0] == 0)
9741             argument_list[0].file_reference=(FILE *) NULL;
9742           if (attribute_flag[1] != 0)
9743             (void) SetImageArtifact(image,"identify:features",
9744               argument_list[1].string_reference);
9745           if ((attribute_flag[2] != 0) &&
9746               (argument_list[2].integer_reference != 0))
9747             (void) SetImageArtifact(image,"identify:unique","true");
9748           (void) IdentifyImage(image,argument_list[0].file_reference,
9749             MagickTrue,exception);
9750           break;
9751         }
9752         case 91:  /* SepiaTone */
9753         {
9754           if (attribute_flag[0] == 0)
9755             argument_list[0].real_reference=80.0*QuantumRange/100.0;
9756           image=SepiaToneImage(image,argument_list[0].real_reference,
9757             exception);
9758           break;
9759         }
9760         case 92:  /* SigmoidalContrast */
9761         {
9762           MagickBooleanType
9763             sharpen;
9764
9765           if (attribute_flag[0] != 0)
9766             {
9767               flags=ParseGeometry(argument_list[0].string_reference,
9768                 &geometry_info);
9769               if ((flags & SigmaValue) == 0)
9770                 geometry_info.sigma=QuantumRange/2.0;
9771               if ((flags & PercentValue) != 0)
9772                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
9773             }
9774           if (attribute_flag[1] != 0)
9775             geometry_info.rho=argument_list[1].real_reference;
9776           if (attribute_flag[2] != 0)
9777             geometry_info.sigma=argument_list[2].real_reference;
9778           if (attribute_flag[3] != 0)
9779             channel=(ChannelType) argument_list[3].integer_reference;
9780           sharpen=MagickTrue;
9781           if (attribute_flag[4] != 0)
9782             sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
9783               MagickFalse;
9784           channel_mask=SetPixelChannelMask(image,channel);
9785           (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
9786             geometry_info.sigma,exception);
9787           (void) SetPixelChannelMask(image,channel_mask);
9788           break;
9789         }
9790         case 93:  /* Extent */
9791         {
9792           if (attribute_flag[7] != 0)
9793             image->gravity=(GravityType) argument_list[7].integer_reference;
9794           if (attribute_flag[0] != 0)
9795             {
9796               int
9797                 flags;
9798
9799               flags=ParseGravityGeometry(image,
9800                 argument_list[0].string_reference,&geometry,exception);
9801               (void) flags;
9802               if (geometry.width == 0)
9803                 geometry.width=image->columns;
9804               if (geometry.height == 0)
9805                 geometry.height=image->rows;
9806             }
9807           if (attribute_flag[1] != 0)
9808             geometry.width=argument_list[1].integer_reference;
9809           if (attribute_flag[2] != 0)
9810             geometry.height=argument_list[2].integer_reference;
9811           if (attribute_flag[3] != 0)
9812             geometry.x=argument_list[3].integer_reference;
9813           if (attribute_flag[4] != 0)
9814             geometry.y=argument_list[4].integer_reference;
9815           if (attribute_flag[5] != 0)
9816             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
9817               QuantumRange);
9818           if (attribute_flag[6] != 0)
9819             (void) QueryColorDatabase(argument_list[6].string_reference,
9820               &image->background_color,exception);
9821           image=ExtentImage(image,&geometry,exception);
9822           break;
9823         }
9824         case 94:  /* Vignette */
9825         {
9826           if (attribute_flag[0] != 0)
9827             {
9828               flags=ParseGeometry(argument_list[0].string_reference,
9829                 &geometry_info);
9830               if ((flags & SigmaValue) == 0)
9831                 geometry_info.sigma=1.0;
9832               if ((flags & XiValue) == 0)
9833                 geometry_info.xi=0.1*image->columns;
9834               if ((flags & PsiValue) == 0)
9835                 geometry_info.psi=0.1*image->rows;
9836             }
9837           if (attribute_flag[1] != 0)
9838             geometry_info.rho=argument_list[1].real_reference;
9839           if (attribute_flag[2] != 0)
9840             geometry_info.sigma=argument_list[2].real_reference;
9841           if (attribute_flag[3] != 0)
9842             geometry_info.xi=argument_list[3].integer_reference;
9843           if (attribute_flag[4] != 0)
9844             geometry_info.psi=argument_list[4].integer_reference;
9845           if (attribute_flag[5] != 0)
9846             (void) QueryColorDatabase(argument_list[5].string_reference,
9847               &image->background_color,exception);
9848           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
9849             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-
9850             0.5),exception);
9851           break;
9852         }
9853         case 95:  /* ContrastStretch */
9854         {
9855           double
9856             black_point,
9857             white_point;
9858
9859           black_point=0.0;
9860           white_point=(MagickRealType) image->columns*image->rows;
9861           if (attribute_flag[0] != 0)
9862             {
9863               flags=ParseGeometry(argument_list[0].string_reference,
9864                 &geometry_info);
9865               black_point=geometry_info.rho;
9866               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
9867                 black_point;
9868               if ((flags & PercentValue) != 0)
9869                 {
9870                   black_point*=(double) image->columns*image->rows/100.0;
9871                   white_point*=(double) image->columns*image->rows/100.0;
9872                 }
9873               white_point=(MagickRealType) image->columns*image->rows-
9874                 white_point;
9875             }
9876           if (attribute_flag[1] != 0)
9877             black_point=argument_list[1].real_reference;
9878           if (attribute_flag[2] != 0)
9879             white_point=argument_list[2].real_reference;
9880           if (attribute_flag[4] != 0)
9881             channel=(ChannelType) argument_list[4].integer_reference;
9882           channel_mask=SetPixelChannelMask(image,channel);
9883           (void) ContrastStretchImage(image,black_point,white_point,exception);
9884           (void) SetPixelChannelMask(image,channel_mask);
9885           break;
9886         }
9887         case 96:  /* Sans0 */
9888         {
9889           break;
9890         }
9891         case 97:  /* Sans1 */
9892         {
9893           break;
9894         }
9895         case 98:  /* AdaptiveSharpen */
9896         {
9897           if (attribute_flag[0] != 0)
9898             {
9899               flags=ParseGeometry(argument_list[0].string_reference,
9900                 &geometry_info);
9901               if ((flags & SigmaValue) == 0)
9902                 geometry_info.sigma=1.0;
9903             }
9904           if (attribute_flag[1] != 0)
9905             geometry_info.rho=argument_list[1].real_reference;
9906           if (attribute_flag[2] != 0)
9907             geometry_info.sigma=argument_list[2].real_reference;
9908           if (attribute_flag[3] != 0)
9909             channel=(ChannelType) argument_list[3].integer_reference;
9910           channel_mask=SetPixelChannelMask(image,channel);
9911           image=AdaptiveSharpenImage(image,geometry_info.rho,
9912             geometry_info.sigma,exception);
9913           if (image != (Image *) NULL)
9914             (void) SetPixelChannelMask(image,channel_mask);
9915           break;
9916         }
9917         case 99:  /* Transpose */
9918         {
9919           image=TransposeImage(image,exception);
9920           break;
9921         }
9922         case 100:  /* Tranverse */
9923         {
9924           image=TransverseImage(image,exception);
9925           break;
9926         }
9927         case 101:  /* AutoOrient */
9928         {
9929           switch (image->orientation)
9930           {
9931             case TopRightOrientation:
9932             {
9933               image=FlopImage(image,exception);
9934               break;
9935             }
9936             case BottomRightOrientation:
9937             {
9938               image=RotateImage(image,180.0,exception);
9939               break;
9940             }
9941             case BottomLeftOrientation:
9942             {
9943               image=FlipImage(image,exception);
9944               break;
9945             }
9946             case LeftTopOrientation:
9947             {
9948               image=TransposeImage(image,exception);
9949               break;
9950             }
9951             case RightTopOrientation:
9952             {
9953               image=RotateImage(image,90.0,exception);
9954               break;
9955             }
9956             case RightBottomOrientation:
9957             {
9958               image=TransverseImage(image,exception);
9959               break;
9960             }
9961             case LeftBottomOrientation:
9962             {
9963               image=RotateImage(image,270.0,exception);
9964               break;
9965             }
9966             default:
9967               break;
9968           }
9969           break;
9970         }
9971         case 102:  /* AdaptiveBlur */
9972         {
9973           if (attribute_flag[0] != 0)
9974             {
9975               flags=ParseGeometry(argument_list[0].string_reference,
9976                 &geometry_info);
9977               if ((flags & SigmaValue) == 0)
9978                 geometry_info.sigma=1.0;
9979             }
9980           if (attribute_flag[1] != 0)
9981             geometry_info.rho=argument_list[1].real_reference;
9982           if (attribute_flag[2] != 0)
9983             geometry_info.sigma=argument_list[2].real_reference;
9984           if (attribute_flag[3] != 0)
9985             channel=(ChannelType) argument_list[3].integer_reference;
9986           channel_mask=SetPixelChannelMask(image,channel);
9987           image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
9988             exception);
9989           if (image != (Image *) NULL)
9990             (void) SetPixelChannelMask(image,channel_mask);
9991           break;
9992         }
9993         case 103:  /* Sketch */
9994         {
9995           if (attribute_flag[0] != 0)
9996             {
9997               flags=ParseGeometry(argument_list[0].string_reference,
9998                 &geometry_info);
9999               if ((flags & SigmaValue) == 0)
10000                 geometry_info.sigma=1.0;
10001               if ((flags & XiValue) == 0)
10002                 geometry_info.xi=1.0;
10003             }
10004           if (attribute_flag[1] != 0)
10005             geometry_info.rho=argument_list[1].real_reference;
10006           if (attribute_flag[2] != 0)
10007             geometry_info.sigma=argument_list[2].real_reference;
10008           if (attribute_flag[3] != 0)
10009             geometry_info.xi=argument_list[3].real_reference;
10010           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10011             geometry_info.xi,exception);
10012           break;
10013         }
10014         case 104:  /* UniqueColors */
10015         {
10016           image=UniqueImageColors(image,exception);
10017           break;
10018         }
10019         case 105:  /* AdaptiveResize */
10020         {
10021           if (attribute_flag[0] != 0)
10022             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10023               &geometry,exception);
10024           if (attribute_flag[1] != 0)
10025             geometry.width=argument_list[1].integer_reference;
10026           if (attribute_flag[2] != 0)
10027             geometry.height=argument_list[2].integer_reference;
10028           if (attribute_flag[3] != 0)
10029             image->filter=(FilterTypes) argument_list[4].integer_reference;
10030           if (attribute_flag[4] != 0)
10031             SetImageArtifact(image,"filter:support",
10032               argument_list[4].string_reference);
10033           if (attribute_flag[5] != 0)
10034             image->blur=argument_list[5].real_reference;
10035           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10036             exception);
10037           break;
10038         }
10039         case 106:  /* ClipMask */
10040         {
10041           if (attribute_flag[0] == 0)
10042             {
10043               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10044                 PackageName);
10045               goto PerlException;
10046             }
10047           image->clip_mask=CloneImage(argument_list[0].image_reference,0,0,
10048             MagickTrue,exception);
10049           (void) NegateImage(image->clip_mask,MagickFalse,exception);
10050           break;
10051         }
10052         case 107:  /* LinearStretch */
10053         {
10054            double
10055              black_point,
10056              white_point;
10057
10058            black_point=0.0;
10059            white_point=(MagickRealType) image->columns*image->rows;
10060            if (attribute_flag[0] != 0)
10061              {
10062                flags=ParseGeometry(argument_list[0].string_reference,
10063                  &geometry_info);
10064                if ((flags & SigmaValue) != 0)
10065                   white_point=geometry_info.sigma;
10066                if ((flags & PercentValue) != 0)
10067                  {
10068                    black_point*=(double) image->columns*image->rows/100.0;
10069                    white_point*=(double) image->columns*image->rows/100.0;
10070                  }
10071                if ((flags & SigmaValue) == 0)
10072                  white_point=(double) image->columns*image->rows-black_point;
10073              }
10074           if (attribute_flag[1] != 0)
10075             black_point=argument_list[1].real_reference;
10076           if (attribute_flag[2] != 0)
10077             white_point=argument_list[2].real_reference;
10078           (void) LinearStretchImage(image,black_point,white_point,exception);
10079           break;
10080         }
10081         case 109:  /* Mask */
10082         {
10083           if (attribute_flag[0] == 0)
10084             {
10085               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10086                 PackageName);
10087               goto PerlException;
10088             }
10089           image->mask=CloneImage(argument_list[0].image_reference,0,0,
10090             MagickTrue,exception);
10091           (void) NegateImage(image->mask,MagickFalse,exception);
10092           break;
10093         }
10094         case 110:  /* Polaroid */
10095         {
10096           DrawInfo
10097             *draw_info;
10098
10099           double
10100             angle;
10101
10102           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10103             (DrawInfo *) NULL);
10104           if (attribute_flag[0] != 0)
10105             (void) SetImageProperty(image,"caption",InterpretImageProperties(
10106               info ? info->image_info : (ImageInfo *) NULL,image,
10107               argument_list[0].string_reference,exception));
10108           angle=0.0;
10109           if (attribute_flag[1] != 0)
10110             angle=argument_list[1].real_reference;
10111           if (attribute_flag[2] != 0)
10112             (void) CloneString(&draw_info->font,
10113               argument_list[2].string_reference);
10114           if (attribute_flag[3] != 0)
10115             (void) QueryColorDatabase(argument_list[3].string_reference,
10116               &draw_info->stroke,exception);
10117           if (attribute_flag[4] != 0)
10118             (void) QueryColorDatabase(argument_list[4].string_reference,
10119               &draw_info->fill,exception);
10120           if (attribute_flag[5] != 0)
10121             draw_info->stroke_width=argument_list[5].real_reference;
10122           if (attribute_flag[6] != 0)
10123             draw_info->pointsize=argument_list[6].real_reference;
10124           if (attribute_flag[7] != 0)
10125             draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10126           if (attribute_flag[8] != 0)
10127             (void) QueryColorDatabase(argument_list[8].string_reference,
10128               &image->background_color,exception);
10129           image=PolaroidImage(image,draw_info,angle,exception);
10130           draw_info=DestroyDrawInfo(draw_info);
10131           break;
10132         }
10133         case 111:  /* FloodfillPaint */
10134         {
10135           DrawInfo
10136             *draw_info;
10137
10138           MagickBooleanType
10139             invert;
10140
10141           PixelInfo
10142             target;
10143
10144           draw_info=CloneDrawInfo(info ? info->image_info :
10145             (ImageInfo *) NULL,(DrawInfo *) NULL);
10146           if (attribute_flag[0] != 0)
10147             flags=ParsePageGeometry(image,argument_list[0].string_reference,
10148               &geometry,exception);
10149           if (attribute_flag[1] != 0)
10150             geometry.x=argument_list[1].integer_reference;
10151           if (attribute_flag[2] != 0)
10152             geometry.y=argument_list[2].integer_reference;
10153           if (attribute_flag[3] != 0)
10154             (void) QueryColorDatabase(argument_list[3].string_reference,
10155               &draw_info->fill,exception);
10156           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
10157             exception);
10158           if (attribute_flag[4] != 0)
10159             QueryMagickColor(argument_list[4].string_reference,&target,
10160               exception);
10161           if (attribute_flag[5] != 0)
10162             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
10163               QuantumRange);
10164           if (attribute_flag[6] != 0)
10165             channel=(ChannelType) argument_list[6].integer_reference;
10166           invert=MagickFalse;
10167           if (attribute_flag[7] != 0)
10168             invert=(MagickBooleanType) argument_list[7].integer_reference;
10169           channel_mask=SetPixelChannelMask(image,channel);
10170           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10171             geometry.y,invert,exception);
10172           (void) SetPixelChannelMask(image,channel_mask);
10173           draw_info=DestroyDrawInfo(draw_info);
10174           break;
10175         }
10176         case 112:  /* Distort */
10177         {
10178           AV
10179             *av;
10180
10181           double
10182             *coordinates;
10183
10184           DistortImageMethod
10185             method;
10186
10187           size_t
10188             number_coordinates;
10189
10190           VirtualPixelMethod
10191             virtual_pixel;
10192
10193           if (attribute_flag[0] == 0)
10194             break;
10195           method=UndefinedDistortion;
10196           if (attribute_flag[1] != 0)
10197             method=(DistortImageMethod) argument_list[1].integer_reference;
10198           av=(AV *) argument_list[0].array_reference;
10199           number_coordinates=(size_t) av_len(av)+1;
10200           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10201             sizeof(*coordinates));
10202           if (coordinates == (double *) NULL)
10203             {
10204               ThrowPerlException(exception,ResourceLimitFatalError,
10205                 "MemoryAllocationFailed",PackageName);
10206               goto PerlException;
10207             }
10208           for (j=0; j < (ssize_t) number_coordinates; j++)
10209             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10210           virtual_pixel=UndefinedVirtualPixelMethod;
10211           if (attribute_flag[2] != 0)
10212             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10213               argument_list[2].integer_reference);
10214           image=DistortImage(image,method,number_coordinates,coordinates,
10215             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10216             exception);
10217           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10218             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10219           coordinates=(double *) RelinquishMagickMemory(coordinates);
10220           break;
10221         }
10222         case 113:  /* Clut */
10223         {
10224           if (attribute_flag[0] == 0)
10225             {
10226               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10227                 PackageName);
10228               goto PerlException;
10229             }
10230           if (attribute_flag[1] != 0)
10231             channel=(ChannelType) argument_list[1].integer_reference;
10232           channel_mask=SetPixelChannelMask(image,channel);
10233           (void) ClutImage(image,argument_list[0].image_reference,exception);
10234           (void) SetPixelChannelMask(image,channel_mask);
10235           break;
10236         }
10237         case 114:  /* LiquidRescale */
10238         {
10239           if (attribute_flag[0] != 0)
10240             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10241               &geometry,exception);
10242           if (attribute_flag[1] != 0)
10243             geometry.width=argument_list[1].integer_reference;
10244           if (attribute_flag[2] != 0)
10245             geometry.height=argument_list[2].integer_reference;
10246           if (attribute_flag[3] == 0)
10247             argument_list[3].real_reference=1.0;
10248           if (attribute_flag[4] == 0)
10249             argument_list[4].real_reference=0.0;
10250           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10251             argument_list[3].real_reference,argument_list[4].real_reference,
10252             exception);
10253           break;
10254         }
10255         case 115:  /* EncipherImage */
10256         {
10257           (void) EncipherImage(image,argument_list[0].string_reference,
10258             exception);
10259           break;
10260         }
10261         case 116:  /* DecipherImage */
10262         {
10263           (void) DecipherImage(image,argument_list[0].string_reference,
10264             exception);
10265           break;
10266         }
10267         case 117:  /* Deskew */
10268         {
10269           geometry_info.rho=QuantumRange/2.0;
10270           if (attribute_flag[0] != 0)
10271             flags=ParseGeometry(argument_list[0].string_reference,
10272               &geometry_info);
10273           if (attribute_flag[1] != 0)
10274             geometry_info.rho=SiPrefixToDouble(
10275               argument_list[1].string_reference,QuantumRange);
10276           image=DeskewImage(image,geometry_info.rho,exception);
10277           break;
10278         }
10279         case 118:  /* Remap */
10280         {
10281           QuantizeInfo
10282             *quantize_info;
10283
10284           if (attribute_flag[0] == 0)
10285             {
10286               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10287                 PackageName);
10288               goto PerlException;
10289             }
10290           quantize_info=AcquireQuantizeInfo(info->image_info);
10291           if (attribute_flag[1] != 0)
10292             quantize_info->dither=(MagickBooleanType)
10293               argument_list[1].integer_reference;
10294           if (attribute_flag[2] != 0)
10295             quantize_info->dither_method=(DitherMethod)
10296               argument_list[2].integer_reference;
10297           (void) RemapImages(quantize_info,image,
10298             argument_list[0].image_reference,exception);
10299           quantize_info=DestroyQuantizeInfo(quantize_info);
10300           break;
10301         }
10302         case 119:  /* SparseColor */
10303         {
10304           AV
10305             *av;
10306
10307           double
10308             *coordinates;
10309
10310           SparseColorMethod
10311             method;
10312
10313           size_t
10314             number_coordinates;
10315
10316           VirtualPixelMethod
10317             virtual_pixel;
10318
10319           if (attribute_flag[0] == 0)
10320             break;
10321           method=UndefinedColorInterpolate;
10322           if (attribute_flag[1] != 0)
10323             method=(SparseColorMethod) argument_list[1].integer_reference;
10324           av=(AV *) argument_list[0].array_reference;
10325           number_coordinates=(size_t) av_len(av)+1;
10326           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10327             sizeof(*coordinates));
10328           if (coordinates == (double *) NULL)
10329             {
10330               ThrowPerlException(exception,ResourceLimitFatalError,
10331                 "MemoryAllocationFailed",PackageName);
10332               goto PerlException;
10333             }
10334           for (j=0; j < (ssize_t) number_coordinates; j++)
10335             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10336           virtual_pixel=UndefinedVirtualPixelMethod;
10337           if (attribute_flag[2] != 0)
10338             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10339               argument_list[2].integer_reference);
10340           if (attribute_flag[3] != 0)
10341             channel=(ChannelType) argument_list[3].integer_reference;
10342           channel_mask=SetPixelChannelMask(image,channel);
10343           image=SparseColorImage(image,method,number_coordinates,coordinates,
10344             exception);
10345           if (image != (Image *) NULL)
10346             (void) SetPixelChannelMask(image,channel_mask);
10347           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10348             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10349           coordinates=(double *) RelinquishMagickMemory(coordinates);
10350           break;
10351         }
10352         case 120:  /* Function */
10353         {
10354           AV
10355             *av;
10356
10357           double
10358             *parameters;
10359
10360           MagickFunction
10361             function;
10362
10363           size_t
10364             number_parameters;
10365
10366           VirtualPixelMethod
10367             virtual_pixel;
10368
10369           if (attribute_flag[0] == 0)
10370             break;
10371           function=UndefinedFunction;
10372           if (attribute_flag[1] != 0)
10373             function=(MagickFunction) argument_list[1].integer_reference;
10374           av=(AV *) argument_list[0].array_reference;
10375           number_parameters=(size_t) av_len(av)+1;
10376           parameters=(double *) AcquireQuantumMemory(number_parameters,
10377             sizeof(*parameters));
10378           if (parameters == (double *) NULL)
10379             {
10380               ThrowPerlException(exception,ResourceLimitFatalError,
10381                 "MemoryAllocationFailed",PackageName);
10382               goto PerlException;
10383             }
10384           for (j=0; j < (ssize_t) number_parameters; j++)
10385             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10386           virtual_pixel=UndefinedVirtualPixelMethod;
10387           if (attribute_flag[2] != 0)
10388             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10389               argument_list[2].integer_reference);
10390           (void) FunctionImage(image,function,number_parameters,parameters,
10391             exception);
10392           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10393             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10394           parameters=(double *) RelinquishMagickMemory(parameters);
10395           break;
10396         }
10397         case 121:  /* SelectiveBlur */
10398         {
10399           if (attribute_flag[0] != 0)
10400             {
10401               flags=ParseGeometry(argument_list[0].string_reference,
10402                 &geometry_info);
10403               if ((flags & SigmaValue) == 0)
10404                 geometry_info.sigma=1.0;
10405               if ((flags & PercentValue) != 0)
10406                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10407             }
10408           if (attribute_flag[1] != 0)
10409             geometry_info.rho=argument_list[1].real_reference;
10410           if (attribute_flag[2] != 0)
10411             geometry_info.sigma=argument_list[2].real_reference;
10412           if (attribute_flag[3] != 0)
10413             geometry_info.xi=argument_list[3].integer_reference;;
10414           if (attribute_flag[4] != 0)
10415             channel=(ChannelType) argument_list[4].integer_reference;
10416           channel_mask=SetPixelChannelMask(image,channel);
10417           image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10418             geometry_info.xi,exception);
10419           if (image != (Image *) NULL)
10420             (void) SetPixelChannelMask(image,channel_mask);
10421           break;
10422         }
10423         case 122:  /* HaldClut */
10424         {
10425           if (attribute_flag[0] == 0)
10426             {
10427               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10428                 PackageName);
10429               goto PerlException;
10430             }
10431           if (attribute_flag[1] != 0)
10432             channel=(ChannelType) argument_list[1].integer_reference;
10433           channel_mask=SetPixelChannelMask(image,channel);
10434           (void) HaldClutImage(image,argument_list[0].image_reference,
10435             exception);
10436           (void) SetPixelChannelMask(image,channel_mask);
10437           break;
10438         }
10439         case 123:  /* BlueShift */
10440         {
10441           if (attribute_flag[0] != 0)
10442             (void) ParseGeometry(argument_list[0].string_reference,
10443               &geometry_info);
10444           image=BlueShiftImage(image,geometry_info.rho,exception);
10445           break;
10446         }
10447         case 124:  /* ForwardFourierTransformImage */
10448         {
10449           image=ForwardFourierTransformImage(image,
10450             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10451             exception);
10452           break;
10453         }
10454         case 125:  /* InverseFourierTransformImage */
10455         {
10456           image=InverseFourierTransformImage(image,image->next,
10457             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10458             exception);
10459           break;
10460         }
10461         case 126:  /* ColorDecisionList */
10462         {
10463           if (attribute_flag[0] == 0)
10464             argument_list[0].string_reference=(char *) NULL;
10465           (void) ColorDecisionListImage(image,
10466             argument_list[0].string_reference,exception);
10467           break;
10468         }
10469         case 127:  /* AutoGamma */
10470         {
10471           if (attribute_flag[0] != 0)
10472             channel=(ChannelType) argument_list[0].integer_reference;
10473           channel_mask=SetPixelChannelMask(image,channel);
10474           (void) AutoGammaImage(image,exception);
10475           (void) SetPixelChannelMask(image,channel_mask);
10476           break;
10477         }
10478         case 128:  /* AutoLevel */
10479         {
10480           if (attribute_flag[0] != 0)
10481             channel=(ChannelType) argument_list[0].integer_reference;
10482           channel_mask=SetPixelChannelMask(image,channel);
10483           (void) AutoLevelImage(image,exception);
10484           (void) SetPixelChannelMask(image,channel_mask);
10485           break;
10486         }
10487         case 129:  /* LevelColors */
10488         {
10489           PixelInfo
10490             black_point,
10491             white_point;
10492
10493           (void) QueryMagickColor("#000000",&black_point,exception);
10494           (void) QueryMagickColor("#ffffff",&white_point,exception);
10495           if (attribute_flag[1] != 0)
10496              (void) QueryMagickColor(argument_list[1].string_reference,
10497                &black_point,exception);
10498           if (attribute_flag[2] != 0)
10499              (void) QueryMagickColor(argument_list[2].string_reference,
10500                &white_point,exception);
10501           if (attribute_flag[3] != 0)
10502             channel=(ChannelType) argument_list[3].integer_reference;
10503           channel_mask=SetPixelChannelMask(image,channel);
10504           (void) LevelImageColors(image,&black_point,&white_point,
10505             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10506             exception);
10507           (void) SetPixelChannelMask(image,channel_mask);
10508           break;
10509         }
10510         case 130:  /* Clamp */
10511         {
10512           if (attribute_flag[0] != 0)
10513             channel=(ChannelType) argument_list[0].integer_reference;
10514           channel_mask=SetPixelChannelMask(image,channel);
10515           (void) ClampImage(image);
10516           (void) SetPixelChannelMask(image,channel_mask);
10517           break;
10518         }
10519         case 132:  /* BrightnessContrast */
10520         {
10521           double
10522             brightness,
10523             contrast;
10524
10525           brightness=0.0;
10526           contrast=0.0;
10527           if (attribute_flag[0] != 0)
10528             {
10529               flags=ParseGeometry(argument_list[0].string_reference,
10530                 &geometry_info);
10531               brightness=geometry_info.rho;
10532               if ((flags & SigmaValue) == 0)
10533                 contrast=geometry_info.sigma;
10534             }
10535           if (attribute_flag[1] != 0)
10536             brightness=argument_list[1].real_reference;
10537           if (attribute_flag[2] != 0)
10538             contrast=argument_list[2].real_reference;
10539           if (attribute_flag[4] != 0)
10540             channel=(ChannelType) argument_list[4].integer_reference;
10541           channel_mask=SetPixelChannelMask(image,channel);
10542           (void) BrightnessContrastImage(image,brightness,contrast,exception);
10543           (void) SetPixelChannelMask(image,channel_mask);
10544           break;
10545         }
10546         case 133:  /* Morphology */
10547         {
10548           KernelInfo
10549             *kernel;
10550
10551           MorphologyMethod
10552             method;
10553
10554           ssize_t
10555             iterations;
10556
10557           if (attribute_flag[0] == 0)
10558             break;
10559           kernel=AcquireKernelInfo(argument_list[0].string_reference);
10560           if (kernel == (KernelInfo *) NULL)
10561             break;
10562           if (attribute_flag[1] != 0)
10563             channel=(ChannelType) argument_list[1].integer_reference;
10564           method=UndefinedMorphology;
10565           if (attribute_flag[2] != 0)
10566             method=argument_list[2].integer_reference;
10567           iterations=1;
10568           if (attribute_flag[3] != 0)
10569             iterations=argument_list[4].integer_reference;
10570           channel_mask=SetPixelChannelMask(image,channel);
10571           image=MorphologyImage(image,method,iterations,kernel,exception);
10572           if (image != (Image *) NULL)
10573             (void) SetPixelChannelMask(image,channel_mask);
10574           kernel=DestroyKernelInfo(kernel);
10575           break;
10576         }
10577         case 108:  /* Recolor */
10578         case 134:  /* ColorMatrix */
10579         {
10580           AV
10581             *av;
10582
10583           double
10584             *color_matrix;
10585
10586           KernelInfo
10587             *kernel_info;
10588
10589           size_t
10590             order;
10591
10592           if (attribute_flag[0] == 0)
10593             break;
10594           av=(AV *) argument_list[0].array_reference;
10595           if (av == (AV *) NULL)
10596             break;
10597           order=(size_t) sqrt(av_len(av)+1);
10598           color_matrix=(double *) AcquireQuantumMemory(order,order*
10599             sizeof(*color_matrix));
10600           if (color_matrix == (double *) NULL)
10601             {
10602               ThrowPerlException(exception,ResourceLimitFatalError,
10603                 "MemoryAllocationFailed",PackageName);
10604               goto PerlException;
10605            }
10606           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10607             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10608           for ( ; j < (ssize_t) (order*order); j++)
10609             color_matrix[j]=0.0;
10610           kernel_info=AcquireKernelInfo((const char *) NULL);
10611           if (kernel_info == (KernelInfo *) NULL)
10612             break;
10613           kernel_info->width=order;
10614           kernel_info->height=order;
10615           kernel_info->values=color_matrix;
10616           image=ColorMatrixImage(image,kernel_info,exception);
10617           kernel_info->values=(double *) NULL;
10618           kernel_info=DestroyKernelInfo(kernel_info);
10619           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10620           break;
10621         }
10622         case 135:  /* Color */
10623         {
10624           PixelInfo
10625             color;
10626
10627           (void) QueryMagickColor("none",&color,exception);
10628           if (attribute_flag[0] != 0)
10629             (void) QueryMagickColor(argument_list[0].string_reference,
10630               &color,exception);
10631           (void) SetImageColor(image,&color);
10632           break;
10633         }
10634         case 136:  /* Mode */
10635         {
10636           if (attribute_flag[0] != 0)
10637             {
10638               flags=ParseGeometry(argument_list[0].string_reference,
10639                 &geometry_info);
10640               if ((flags & SigmaValue) == 0)
10641                 geometry_info.sigma=1.0;
10642             }
10643           if (attribute_flag[1] != 0)
10644             geometry_info.rho=argument_list[1].real_reference;
10645           if (attribute_flag[2] != 0)
10646             geometry_info.sigma=argument_list[2].real_reference;
10647           if (attribute_flag[3] != 0)
10648             channel=(ChannelType) argument_list[3].integer_reference;
10649           channel_mask=SetPixelChannelMask(image,channel);
10650           image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
10651             (size_t) geometry_info.sigma,exception);
10652           if (image != (Image *) NULL)
10653             (void) SetPixelChannelMask(image,channel_mask);
10654           break;
10655         }
10656         case 137:  /* Statistic */
10657         {
10658           StatisticType
10659             statistic;
10660
10661           statistic=UndefinedStatistic;
10662           if (attribute_flag[0] != 0)
10663             {
10664               flags=ParseGeometry(argument_list[0].string_reference,
10665                 &geometry_info);
10666               if ((flags & SigmaValue) == 0)
10667                 geometry_info.sigma=1.0;
10668             }
10669           if (attribute_flag[1] != 0)
10670             geometry_info.rho=argument_list[1].real_reference;
10671           if (attribute_flag[2] != 0)
10672             geometry_info.sigma=argument_list[2].real_reference;
10673           if (attribute_flag[3] != 0)
10674             channel=(ChannelType) argument_list[3].integer_reference;
10675           if (attribute_flag[4] != 0)
10676             statistic=(StatisticType) argument_list[4].integer_reference;
10677           channel_mask=SetPixelChannelMask(image,channel);
10678           image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
10679             (size_t) geometry_info.sigma,exception);
10680           if (image != (Image *) NULL)
10681             (void) SetPixelChannelMask(image,channel_mask);
10682           break;
10683         }
10684       }
10685       if (next != (Image *) NULL)
10686         (void) CatchImageException(next);
10687       if (region_image != (Image *) NULL)
10688         {
10689           /*
10690             Composite region.
10691           */ 
10692           status=CompositeImage(region_image,CopyCompositeOp,image,
10693             region_info.x,region_info.y);
10694           (void) status;
10695           (void) CatchImageException(region_image);
10696           image=DestroyImage(image);
10697           image=region_image;
10698         }
10699       if (image != (Image *) NULL)
10700         {
10701           number_images++;
10702           if (next && (next != image))
10703             {
10704               image->next=next->next;
10705               if (image->next != (Image *) NULL)
10706                 image->next->previous=image;
10707               DeleteImageFromRegistry(*pv,next);
10708             }
10709           sv_setiv(*pv,(IV) image);
10710           next=image;
10711         }
10712       if (*pv)
10713         pv++;
10714     }
10715
10716   PerlException:
10717     if (reference_vector)
10718       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
10719     InheritPerlException(exception,perl_exception);
10720     exception=DestroyExceptionInfo(exception);
10721     sv_setiv(perl_exception,(IV) number_images);
10722     SvPOK_on(perl_exception);
10723     ST(0)=sv_2mortal(perl_exception);
10724     XSRETURN(1);
10725   }
10726 \f
10727 #
10728 ###############################################################################
10729 #                                                                             #
10730 #                                                                             #
10731 #                                                                             #
10732 #   M o n t a g e                                                             #
10733 #                                                                             #
10734 #                                                                             #
10735 #                                                                             #
10736 ###############################################################################
10737 #
10738 #
10739 void
10740 Montage(ref,...)
10741   Image::Magick ref=NO_INIT
10742   ALIAS:
10743     MontageImage  = 1
10744     montage       = 2
10745     montageimage  = 3
10746   PPCODE:
10747   {
10748     AV
10749       *av;
10750
10751     char
10752       *attribute;
10753
10754     ExceptionInfo
10755       *exception;
10756
10757     HV
10758       *hv;
10759
10760     Image
10761       *image,
10762       *next;
10763
10764     PixelInfo
10765       transparent_color;
10766
10767     MontageInfo
10768       *montage_info;
10769
10770     register ssize_t
10771       i;
10772
10773     ssize_t
10774       sp;
10775
10776     struct PackageInfo
10777       *info;
10778
10779     SV
10780       *av_reference,
10781       *perl_exception,
10782       *reference,
10783       *rv,
10784       *sv;
10785
10786     PERL_UNUSED_VAR(ref);
10787     PERL_UNUSED_VAR(ix);
10788     exception=AcquireExceptionInfo();
10789     perl_exception=newSVpv("",0);
10790     sv=NULL;
10791     attribute=NULL;
10792     if (sv_isobject(ST(0)) == 0)
10793       {
10794         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
10795           PackageName);
10796         goto PerlException;
10797       }
10798     reference=SvRV(ST(0));
10799     hv=SvSTASH(reference);
10800     av=newAV();
10801     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
10802     SvREFCNT_dec(av);
10803     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
10804     if (image == (Image *) NULL)
10805       {
10806         ThrowPerlException(exception,OptionError,"NoImagesDefined",
10807           PackageName);
10808         goto PerlException;
10809       }
10810     /*
10811       Get options.
10812     */
10813     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
10814     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
10815     (void) QueryMagickColor("none",&transparent_color,exception);
10816     for (i=2; i < items; i+=2)
10817     {
10818       attribute=(char *) SvPV(ST(i-1),na);
10819       switch (*attribute)
10820       {
10821         case 'B':
10822         case 'b':
10823         {
10824           if (LocaleCompare(attribute,"background") == 0)
10825             {
10826               (void) QueryColorDatabase(SvPV(ST(i),na),
10827                 &montage_info->background_color,exception);
10828               for (next=image; next; next=next->next)
10829                 next->background_color=montage_info->background_color;
10830               break;
10831             }
10832           if (LocaleCompare(attribute,"border") == 0)
10833             {
10834               montage_info->border_width=SvIV(ST(i));
10835               break;
10836             }
10837           if (LocaleCompare(attribute,"bordercolor") == 0)
10838             {
10839               (void) QueryColorDatabase(SvPV(ST(i),na),
10840                 &montage_info->border_color,exception);
10841               for (next=image; next; next=next->next)
10842                 next->border_color=montage_info->border_color;
10843               break;
10844             }
10845           if (LocaleCompare(attribute,"borderwidth") == 0)
10846             {
10847               montage_info->border_width=SvIV(ST(i));
10848               break;
10849             }
10850           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10851             attribute);
10852           break;
10853         }
10854         case 'C':
10855         case 'c':
10856         {
10857           if (LocaleCompare(attribute,"compose") == 0)
10858             {
10859               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
10860                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
10861               if (sp < 0)
10862                 {
10863                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
10864                     SvPV(ST(i),na));
10865                   break;
10866                 }
10867               for (next=image; next; next=next->next)
10868                 next->compose=(CompositeOperator) sp;
10869               break;
10870             }
10871           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10872             attribute);
10873           break;
10874         }
10875         case 'F':
10876         case 'f':
10877         {
10878           if (LocaleCompare(attribute,"fill") == 0)
10879             {
10880               (void) QueryColorDatabase(SvPV(ST(i),na),&montage_info->fill,
10881                 exception);
10882               break;
10883             }
10884           if (LocaleCompare(attribute,"font") == 0)
10885             {
10886               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
10887               break;
10888             }
10889           if (LocaleCompare(attribute,"frame") == 0)
10890             {
10891               char
10892                 *p;
10893
10894               p=SvPV(ST(i),na);
10895               if (IsGeometry(p) == MagickFalse)
10896                 {
10897                   ThrowPerlException(exception,OptionError,"MissingGeometry",
10898                     p);
10899                   break;
10900                 }
10901               (void) CloneString(&montage_info->frame,p);
10902               if (*p == '\0')
10903                 montage_info->frame=(char *) NULL;
10904               break;
10905             }
10906           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10907             attribute);
10908           break;
10909         }
10910         case 'G':
10911         case 'g':
10912         {
10913           if (LocaleCompare(attribute,"geometry") == 0)
10914             {
10915               char
10916                 *p;
10917
10918               p=SvPV(ST(i),na);
10919               if (IsGeometry(p) == MagickFalse)
10920                 {
10921                   ThrowPerlException(exception,OptionError,"MissingGeometry",
10922                     p);
10923                   break;
10924                 }
10925              (void) CloneString(&montage_info->geometry,p);
10926              if (*p == '\0')
10927                montage_info->geometry=(char *) NULL;
10928              break;
10929            }
10930          if (LocaleCompare(attribute,"gravity") == 0)
10931            {
10932              ssize_t
10933                in;
10934
10935              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
10936                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
10937              if (in < 0)
10938                {
10939                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
10940                    SvPV(ST(i),na));
10941                  return;
10942                }
10943              montage_info->gravity=(GravityType) in;
10944              for (next=image; next; next=next->next)
10945                next->gravity=(GravityType) in;
10946              break;
10947            }
10948           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10949             attribute);
10950           break;
10951         }
10952         case 'L':
10953         case 'l':
10954         {
10955           if (LocaleCompare(attribute,"label") == 0)
10956             {
10957               for (next=image; next; next=next->next)
10958                 (void) SetImageProperty(next,"label",InterpretImageProperties(
10959                   info ? info->image_info : (ImageInfo *) NULL,next,
10960                   SvPV(ST(i),na),exception));
10961               break;
10962             }
10963           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10964             attribute);
10965           break;
10966         }
10967         case 'M':
10968         case 'm':
10969         {
10970           if (LocaleCompare(attribute,"mattecolor") == 0)
10971             {
10972               (void) QueryColorDatabase(SvPV(ST(i),na),
10973                 &montage_info->matte_color,exception);
10974               for (next=image; next; next=next->next)
10975                 next->matte_color=montage_info->matte_color;
10976               break;
10977             }
10978           if (LocaleCompare(attribute,"mode") == 0)
10979             {
10980               ssize_t
10981                 in;
10982
10983               in=!SvPOK(ST(i)) ? SvIV(ST(i)) :
10984                 ParseCommandOption(MagickModeOptions,MagickFalse,SvPV(ST(i),na));
10985               switch (in)
10986               {
10987                 default:
10988                 {
10989                   ThrowPerlException(exception,OptionError,
10990                     "UnrecognizedModeType",SvPV(ST(i),na));
10991                   break;
10992                 }
10993                 case FrameMode:
10994                 {
10995                   (void) CloneString(&montage_info->frame,"15x15+3+3");
10996                   montage_info->shadow=MagickTrue;
10997                   break;
10998                 }
10999                 case UnframeMode:
11000                 {
11001                   montage_info->frame=(char *) NULL;
11002                   montage_info->shadow=MagickFalse;
11003                   montage_info->border_width=0;
11004                   break;
11005                 }
11006                 case ConcatenateMode:
11007                 {
11008                   montage_info->frame=(char *) NULL;
11009                   montage_info->shadow=MagickFalse;
11010                   (void) CloneString(&montage_info->geometry,"+0+0");
11011                   montage_info->border_width=0;
11012                 }
11013               }
11014               break;
11015             }
11016           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11017             attribute);
11018           break;
11019         }
11020         case 'P':
11021         case 'p':
11022         {
11023           if (LocaleCompare(attribute,"pointsize") == 0)
11024             {
11025               montage_info->pointsize=SvIV(ST(i));
11026               break;
11027             }
11028           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11029             attribute);
11030           break;
11031         }
11032         case 'S':
11033         case 's':
11034         {
11035           if (LocaleCompare(attribute,"shadow") == 0)
11036             {
11037               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11038                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11039               if (sp < 0)
11040                 {
11041                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11042                     SvPV(ST(i),na));
11043                   break;
11044                 }
11045              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11046              break;
11047             }
11048           if (LocaleCompare(attribute,"stroke") == 0)
11049             {
11050               (void) QueryColorDatabase(SvPV(ST(i),na),&montage_info->stroke,
11051                 exception);
11052               break;
11053             }
11054           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11055             attribute);
11056           break;
11057         }
11058         case 'T':
11059         case 't':
11060         {
11061           if (LocaleCompare(attribute,"texture") == 0)
11062             {
11063               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11064               break;
11065             }
11066           if (LocaleCompare(attribute,"tile") == 0)
11067             {
11068               char *p=SvPV(ST(i),na);
11069               if (IsGeometry(p) == MagickFalse)
11070                 {
11071                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11072                     p);
11073                   break;
11074                 }
11075               (void) CloneString(&montage_info->tile,p);
11076               if (*p == '\0')
11077                 montage_info->tile=(char *) NULL;
11078               break;
11079             }
11080           if (LocaleCompare(attribute,"title") == 0)
11081             {
11082               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11083               break;
11084             }
11085           if (LocaleCompare(attribute,"transparent") == 0)
11086             {
11087               PixelInfo
11088                 transparent_color;
11089
11090               QueryMagickColor(SvPV(ST(i),na),&transparent_color,exception);
11091               for (next=image; next; next=next->next)
11092                 (void) TransparentPaintImage(next,&transparent_color,
11093                   TransparentAlpha,MagickFalse,exception);
11094               break;
11095             }
11096           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11097             attribute);
11098           break;
11099         }
11100         default:
11101         {
11102           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11103             attribute);
11104           break;
11105         }
11106       }
11107     }
11108     image=MontageImageList(info->image_info,montage_info,image,exception);
11109     montage_info=DestroyMontageInfo(montage_info);
11110     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11111       goto PerlException;
11112     if (transparent_color.alpha != TransparentAlpha)
11113       for (next=image; next; next=next->next)
11114         (void) TransparentPaintImage(next,&transparent_color,
11115           TransparentAlpha,MagickFalse,exception);
11116     for (  ; image; image=image->next)
11117     {
11118       AddImageToRegistry(sv,image);
11119       rv=newRV(sv);
11120       av_push(av,sv_bless(rv,hv));
11121       SvREFCNT_dec(sv);
11122     }
11123     exception=DestroyExceptionInfo(exception);
11124     ST(0)=av_reference;
11125     SvREFCNT_dec(perl_exception);
11126     XSRETURN(1);
11127
11128   PerlException:
11129     InheritPerlException(exception,perl_exception);
11130     exception=DestroyExceptionInfo(exception);
11131     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11132     SvPOK_on(perl_exception);
11133     ST(0)=sv_2mortal(perl_exception);
11134     XSRETURN(1);
11135   }
11136 \f
11137 #
11138 ###############################################################################
11139 #                                                                             #
11140 #                                                                             #
11141 #                                                                             #
11142 #   M o r p h                                                                 #
11143 #                                                                             #
11144 #                                                                             #
11145 #                                                                             #
11146 ###############################################################################
11147 #
11148 #
11149 void
11150 Morph(ref,...)
11151   Image::Magick ref=NO_INIT
11152   ALIAS:
11153     MorphImage  = 1
11154     morph       = 2
11155     morphimage  = 3
11156   PPCODE:
11157   {
11158     AV
11159       *av;
11160
11161     char
11162       *attribute;
11163
11164     ExceptionInfo
11165       *exception;
11166
11167     HV
11168       *hv;
11169
11170     Image
11171       *image;
11172
11173     register ssize_t
11174       i;
11175
11176     ssize_t
11177       number_frames;
11178
11179     struct PackageInfo
11180       *info;
11181
11182     SV
11183       *av_reference,
11184       *perl_exception,
11185       *reference,
11186       *rv,
11187       *sv;
11188
11189     PERL_UNUSED_VAR(ref);
11190     PERL_UNUSED_VAR(ix);
11191     exception=AcquireExceptionInfo();
11192     perl_exception=newSVpv("",0);
11193     sv=NULL;
11194     av=NULL;
11195     attribute=NULL;
11196     if (sv_isobject(ST(0)) == 0)
11197       {
11198         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11199           PackageName);
11200         goto PerlException;
11201       }
11202     reference=SvRV(ST(0));
11203     hv=SvSTASH(reference);
11204     av=newAV();
11205     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11206     SvREFCNT_dec(av);
11207     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11208     if (image == (Image *) NULL)
11209       {
11210         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11211           PackageName);
11212         goto PerlException;
11213       }
11214     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11215     /*
11216       Get attribute.
11217     */
11218     number_frames=30;
11219     for (i=2; i < items; i+=2)
11220     {
11221       attribute=(char *) SvPV(ST(i-1),na);
11222       switch (*attribute)
11223       {
11224         case 'F':
11225         case 'f':
11226         {
11227           if (LocaleCompare(attribute,"frames") == 0)
11228             {
11229               number_frames=SvIV(ST(i));
11230               break;
11231             }
11232           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11233             attribute);
11234           break;
11235         }
11236         default:
11237         {
11238           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11239             attribute);
11240           break;
11241         }
11242       }
11243     }
11244     image=MorphImages(image,number_frames,exception);
11245     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11246       goto PerlException;
11247     for ( ; image; image=image->next)
11248     {
11249       AddImageToRegistry(sv,image);
11250       rv=newRV(sv);
11251       av_push(av,sv_bless(rv,hv));
11252       SvREFCNT_dec(sv);
11253     }
11254     exception=DestroyExceptionInfo(exception);
11255     ST(0)=av_reference;
11256     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11257     XSRETURN(1);
11258
11259   PerlException:
11260     InheritPerlException(exception,perl_exception);
11261     exception=DestroyExceptionInfo(exception);
11262     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11263     SvPOK_on(perl_exception);
11264     ST(0)=sv_2mortal(perl_exception);
11265     XSRETURN(1);
11266   }
11267 \f
11268 #
11269 ###############################################################################
11270 #                                                                             #
11271 #                                                                             #
11272 #                                                                             #
11273 #   M o s a i c                                                               #
11274 #                                                                             #
11275 #                                                                             #
11276 #                                                                             #
11277 ###############################################################################
11278 #
11279 #
11280 void
11281 Mosaic(ref)
11282   Image::Magick ref=NO_INIT
11283   ALIAS:
11284     MosaicImage   = 1
11285     mosaic        = 2
11286     mosaicimage   = 3
11287   PPCODE:
11288   {
11289     AV
11290       *av;
11291
11292     ExceptionInfo
11293       *exception;
11294
11295     HV
11296       *hv;
11297
11298     Image
11299       *image;
11300
11301     struct PackageInfo
11302       *info;
11303
11304     SV
11305       *perl_exception,
11306       *reference,
11307       *rv,
11308       *sv;
11309
11310     PERL_UNUSED_VAR(ref);
11311     PERL_UNUSED_VAR(ix);
11312     exception=AcquireExceptionInfo();
11313     perl_exception=newSVpv("",0);
11314     sv=NULL;
11315     if (sv_isobject(ST(0)) == 0)
11316       {
11317         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11318           PackageName);
11319         goto PerlException;
11320       }
11321     reference=SvRV(ST(0));
11322     hv=SvSTASH(reference);
11323     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11324     if (image == (Image *) NULL)
11325       {
11326         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11327           PackageName);
11328         goto PerlException;
11329       }
11330     image=MergeImageLayers(image,MosaicLayer,exception);
11331     /*
11332       Create blessed Perl array for the returned image.
11333     */
11334     av=newAV();
11335     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11336     SvREFCNT_dec(av);
11337     AddImageToRegistry(sv,image);
11338     rv=newRV(sv);
11339     av_push(av,sv_bless(rv,hv));
11340     SvREFCNT_dec(sv);
11341     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11342     (void) CopyMagickString(info->image_info->filename,image->filename,
11343       MaxTextExtent);
11344     SetImageInfo(info->image_info,0,&image->exception);
11345     exception=DestroyExceptionInfo(exception);
11346     SvREFCNT_dec(perl_exception);
11347     XSRETURN(1);
11348
11349   PerlException:
11350     InheritPerlException(exception,perl_exception);
11351     exception=DestroyExceptionInfo(exception);
11352     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11353     SvPOK_on(perl_exception);  /* return messages in string context */
11354     ST(0)=sv_2mortal(perl_exception);
11355     XSRETURN(1);
11356   }
11357 \f
11358 #
11359 ###############################################################################
11360 #                                                                             #
11361 #                                                                             #
11362 #                                                                             #
11363 #   P i n g                                                                   #
11364 #                                                                             #
11365 #                                                                             #
11366 #                                                                             #
11367 ###############################################################################
11368 #
11369 #
11370 void
11371 Ping(ref,...)
11372   Image::Magick ref=NO_INIT
11373   ALIAS:
11374     PingImage  = 1
11375     ping       = 2
11376     pingimage  = 3
11377   PPCODE:
11378   {
11379     AV
11380       *av;
11381
11382     char
11383       **keep,
11384       **list;
11385
11386     ExceptionInfo
11387       *exception;
11388
11389     Image
11390       *image,
11391       *next;
11392
11393     int
11394       n;
11395
11396     MagickBooleanType
11397       status;
11398
11399     register char
11400       **p;
11401
11402     register ssize_t
11403       i;
11404
11405     ssize_t
11406       ac;
11407
11408     STRLEN
11409       *length;
11410
11411     struct PackageInfo
11412       *info,
11413       *package_info;
11414
11415     SV
11416       *perl_exception,
11417       *reference;
11418
11419     size_t
11420       count;
11421
11422     PERL_UNUSED_VAR(ref);
11423     PERL_UNUSED_VAR(ix);
11424     exception=AcquireExceptionInfo();
11425     perl_exception=newSVpv("",0);
11426     package_info=(struct PackageInfo *) NULL;
11427     ac=(items < 2) ? 1 : items-1;
11428     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
11429     keep=list;
11430     length=(STRLEN *) NULL;
11431     if (list == (char **) NULL)
11432       {
11433         ThrowPerlException(exception,ResourceLimitError,
11434           "MemoryAllocationFailed",PackageName);
11435         goto PerlException;
11436       }
11437     keep=list;
11438     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
11439     if (length == (STRLEN *) NULL)
11440       {
11441         ThrowPerlException(exception,ResourceLimitError,
11442           "MemoryAllocationFailed",PackageName);
11443         goto PerlException;
11444       }
11445     if (sv_isobject(ST(0)) == 0)
11446       {
11447         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11448           PackageName);
11449         goto PerlException;
11450       }
11451     reference=SvRV(ST(0));
11452     if (SvTYPE(reference) != SVt_PVAV)
11453       {
11454         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11455           PackageName);
11456         goto PerlException;
11457       }
11458     av=(AV *) reference;
11459     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11460       exception);
11461     package_info=ClonePackageInfo(info,exception);
11462     n=1;
11463     if (items <= 1)
11464       *list=(char *) (*package_info->image_info->filename ?
11465         package_info->image_info->filename : "XC:black");
11466     else
11467       for (n=0, i=0; i < ac; i++)
11468       {
11469         list[n]=(char *) SvPV(ST(i+1),length[n]);
11470         if ((items >= 3) && strEQcase(list[n],"blob"))
11471           {
11472             void
11473               *blob;
11474
11475             i++;
11476             blob=(void *) (SvPV(ST(i+1),length[n]));
11477             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
11478           }
11479         if ((items >= 3) && strEQcase(list[n],"filename"))
11480           continue;
11481         if ((items >= 3) && strEQcase(list[n],"file"))
11482           {
11483             FILE
11484               *file;
11485
11486             PerlIO
11487               *io_info;
11488
11489             i++;
11490             io_info=IoIFP(sv_2io(ST(i+1)));
11491             if (io_info == (PerlIO *) NULL)
11492               {
11493                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11494                   PackageName);
11495                 continue;
11496               }
11497             file=PerlIO_findFILE(io_info);
11498             if (file == (FILE *) NULL)
11499               {
11500                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11501                   PackageName);
11502                 continue;
11503               }
11504             SetImageInfoFile(package_info->image_info,file);
11505           }
11506         if ((items >= 3) && strEQcase(list[n],"magick"))
11507           continue;
11508         n++;
11509       }
11510     list[n]=(char *) NULL;
11511     keep=list;
11512     status=ExpandFilenames(&n,&list);
11513     if (status == MagickFalse)
11514       {
11515         ThrowPerlException(exception,ResourceLimitError,
11516           "MemoryAllocationFailed",PackageName);
11517         goto PerlException;
11518       }
11519     count=0;
11520     for (i=0; i < n; i++)
11521     {
11522       (void) CopyMagickString(package_info->image_info->filename,list[i],
11523         MaxTextExtent);
11524       image=PingImage(package_info->image_info,exception);
11525       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11526         break;
11527       if ((package_info->image_info->file != (FILE *) NULL) ||
11528           (package_info->image_info->blob != (void *) NULL))
11529         DisassociateImageStream(image);
11530       count+=GetImageListLength(image);
11531       EXTEND(sp,4*count);
11532       for (next=image; next; next=next->next)
11533       {
11534         PUSHs(sv_2mortal(newSViv(next->columns)));
11535         PUSHs(sv_2mortal(newSViv(next->rows)));
11536         PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
11537         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
11538       }
11539       image=DestroyImageList(image);
11540     }
11541     /*
11542       Free resources.
11543     */
11544     for (i=0; i < n; i++)
11545       if (list[i] != (char *) NULL)
11546         for (p=keep; list[i] != *p++; )
11547           if (*p == NULL)
11548             {
11549               list[i]=(char *) RelinquishMagickMemory(list[i]);
11550               break;
11551             }
11552
11553   PerlException:
11554     if (package_info != (struct PackageInfo *) NULL)
11555       DestroyPackageInfo(package_info);
11556     if (list && (list != keep))
11557       list=(char **) RelinquishMagickMemory(list);
11558     if (keep)
11559       keep=(char **) RelinquishMagickMemory(keep);
11560     if (length)
11561       length=(STRLEN *) RelinquishMagickMemory(length);
11562     InheritPerlException(exception,perl_exception);
11563     exception=DestroyExceptionInfo(exception);
11564     SvREFCNT_dec(perl_exception);  /* throw away all errors */
11565   }
11566 \f
11567 #
11568 ###############################################################################
11569 #                                                                             #
11570 #                                                                             #
11571 #                                                                             #
11572 #   P r e v i e w                                                             #
11573 #                                                                             #
11574 #                                                                             #
11575 #                                                                             #
11576 ###############################################################################
11577 #
11578 #
11579 void
11580 Preview(ref,...)
11581   Image::Magick ref=NO_INIT
11582   ALIAS:
11583     PreviewImage = 1
11584     preview      = 2
11585     previewimage = 3
11586   PPCODE:
11587   {
11588     AV
11589       *av;
11590
11591     ExceptionInfo
11592       *exception;
11593
11594     HV
11595       *hv;
11596
11597     Image
11598       *image,
11599       *preview_image;
11600
11601     PreviewType
11602       preview_type;
11603
11604     struct PackageInfo
11605       *info;
11606
11607     SV
11608       *av_reference,
11609       *perl_exception,
11610       *reference,
11611       *rv,
11612       *sv;
11613
11614     PERL_UNUSED_VAR(ref);
11615     PERL_UNUSED_VAR(ix);
11616     exception=AcquireExceptionInfo();
11617     perl_exception=newSVpv("",0);
11618     sv=NULL;
11619     av=NULL;
11620     if (sv_isobject(ST(0)) == 0)
11621       {
11622         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11623           PackageName);
11624         goto PerlException;
11625       }
11626     reference=SvRV(ST(0));
11627     hv=SvSTASH(reference);
11628     av=newAV();
11629     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11630     SvREFCNT_dec(av);
11631     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11632     if (image == (Image *) NULL)
11633       {
11634         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11635           PackageName);
11636         goto PerlException;
11637       }
11638     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11639     preview_type=GammaPreview;
11640     if (items > 1)
11641       preview_type=(PreviewType)
11642         ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
11643     for ( ; image; image=image->next)
11644     {
11645       preview_image=PreviewImage(image,preview_type,exception);
11646       if (preview_image == (Image *) NULL)
11647         goto PerlException;
11648       AddImageToRegistry(sv,preview_image);
11649       rv=newRV(sv);
11650       av_push(av,sv_bless(rv,hv));
11651       SvREFCNT_dec(sv);
11652     }
11653     exception=DestroyExceptionInfo(exception);
11654     ST(0)=av_reference;
11655     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11656     XSRETURN(1);
11657
11658   PerlException:
11659     InheritPerlException(exception,perl_exception);
11660     exception=DestroyExceptionInfo(exception);
11661     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11662     SvPOK_on(perl_exception);
11663     ST(0)=sv_2mortal(perl_exception);
11664     XSRETURN(1);
11665   }
11666 \f
11667 #
11668 ###############################################################################
11669 #                                                                             #
11670 #                                                                             #
11671 #                                                                             #
11672 #   Q u e r y C o l o r                                                       #
11673 #                                                                             #
11674 #                                                                             #
11675 #                                                                             #
11676 ###############################################################################
11677 #
11678 #
11679 void
11680 QueryColor(ref,...)
11681   Image::Magick ref=NO_INIT
11682   ALIAS:
11683     querycolor = 1
11684   PPCODE:
11685   {
11686     char
11687       *name;
11688
11689     ExceptionInfo
11690       *exception;
11691
11692     PixelInfo
11693       color;
11694
11695     register ssize_t
11696       i;
11697
11698     SV
11699       *perl_exception;
11700
11701     PERL_UNUSED_VAR(ref);
11702     PERL_UNUSED_VAR(ix);
11703     exception=AcquireExceptionInfo();
11704     perl_exception=newSVpv("",0);
11705     if (items == 1)
11706       {
11707         const ColorInfo
11708           **colorlist;
11709
11710         size_t
11711           colors;
11712
11713         colorlist=GetColorInfoList("*",&colors,exception);
11714         EXTEND(sp,colors);
11715         for (i=0; i < (ssize_t) colors; i++)
11716         {
11717           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
11718         }
11719         colorlist=(const ColorInfo **)
11720           RelinquishMagickMemory((ColorInfo **) colorlist);
11721         goto PerlException;
11722       }
11723     EXTEND(sp,5*items);
11724     for (i=1; i < items; i++)
11725     {
11726       name=(char *) SvPV(ST(i),na);
11727       if (QueryMagickColor(name,&color,exception) == MagickFalse)
11728         {
11729           PUSHs(&sv_undef);
11730           continue;
11731         }
11732       PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
11733       PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
11734       PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
11735       if (color.colorspace == CMYKColorspace)
11736         PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
11737       if (color.matte != MagickFalse)
11738         PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
11739     }
11740
11741   PerlException:
11742     InheritPerlException(exception,perl_exception);
11743     exception=DestroyExceptionInfo(exception);
11744     SvREFCNT_dec(perl_exception);
11745   }
11746 \f
11747 #
11748 ###############################################################################
11749 #                                                                             #
11750 #                                                                             #
11751 #                                                                             #
11752 #   Q u e r y C o l o r N a m e                                               #
11753 #                                                                             #
11754 #                                                                             #
11755 #                                                                             #
11756 ###############################################################################
11757 #
11758 #
11759 void
11760 QueryColorname(ref,...)
11761   Image::Magick ref=NO_INIT
11762   ALIAS:
11763     querycolorname = 1
11764   PPCODE:
11765   {
11766     AV
11767       *av;
11768
11769     char
11770       message[MaxTextExtent];
11771
11772     ExceptionInfo
11773       *exception;
11774
11775     Image
11776       *image;
11777
11778     PixelPacket
11779       target_color;
11780
11781     register ssize_t
11782       i;
11783
11784     struct PackageInfo
11785       *info;
11786
11787     SV
11788       *perl_exception,
11789       *reference;  /* reference is the SV* of ref=SvIV(reference) */
11790
11791     PERL_UNUSED_VAR(ref);
11792     PERL_UNUSED_VAR(ix);
11793     exception=AcquireExceptionInfo();
11794     perl_exception=newSVpv("",0);
11795     reference=SvRV(ST(0));
11796     av=(AV *) reference;
11797     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11798       exception);
11799     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11800     if (image == (Image *) NULL)
11801       {
11802         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11803           PackageName);
11804         goto PerlException;
11805       }
11806     EXTEND(sp,items);
11807     for (i=1; i < items; i++)
11808     {
11809       (void) QueryColorDatabase(SvPV(ST(i),na),&target_color,exception);
11810       (void) QueryColorname(image,&target_color,SVGCompliance,message,
11811         exception);
11812       PUSHs(sv_2mortal(newSVpv(message,0)));
11813     }
11814
11815   PerlException:
11816     InheritPerlException(exception,perl_exception);
11817     exception=DestroyExceptionInfo(exception);
11818     SvREFCNT_dec(perl_exception);
11819   }
11820 \f
11821 #
11822 ###############################################################################
11823 #                                                                             #
11824 #                                                                             #
11825 #                                                                             #
11826 #   Q u e r y F o n t                                                         #
11827 #                                                                             #
11828 #                                                                             #
11829 #                                                                             #
11830 ###############################################################################
11831 #
11832 #
11833 void
11834 QueryFont(ref,...)
11835   Image::Magick ref=NO_INIT
11836   ALIAS:
11837     queryfont = 1
11838   PPCODE:
11839   {
11840     char
11841       *name,
11842       message[MaxTextExtent];
11843
11844     ExceptionInfo
11845       *exception;
11846
11847     register ssize_t
11848       i;
11849
11850     SV
11851       *perl_exception;
11852
11853     volatile const TypeInfo
11854       *type_info;
11855
11856     PERL_UNUSED_VAR(ref);
11857     PERL_UNUSED_VAR(ix);
11858     exception=AcquireExceptionInfo();
11859     perl_exception=newSVpv("",0);
11860     if (items == 1)
11861       {
11862         const TypeInfo
11863           **typelist;
11864
11865         size_t
11866           types;
11867
11868         typelist=GetTypeInfoList("*",&types,exception);
11869         EXTEND(sp,types);
11870         for (i=0; i < (ssize_t) types; i++)
11871         {
11872           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
11873         }
11874         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
11875           typelist);
11876         goto PerlException;
11877       }
11878     EXTEND(sp,10*items);
11879     for (i=1; i < items; i++)
11880     {
11881       name=(char *) SvPV(ST(i),na);
11882       type_info=GetTypeInfo(name,exception);
11883       if (type_info == (TypeInfo *) NULL)
11884         {
11885           PUSHs(&sv_undef);
11886           continue;
11887         }
11888       if (type_info->name == (char *) NULL)
11889         PUSHs(&sv_undef);
11890       else
11891         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
11892       if (type_info->description == (char *) NULL)
11893         PUSHs(&sv_undef);
11894       else
11895         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
11896       if (type_info->family == (char *) NULL)
11897         PUSHs(&sv_undef);
11898       else
11899         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
11900       if (type_info->style == UndefinedStyle)
11901         PUSHs(&sv_undef);
11902       else
11903         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
11904           type_info->style),0)));
11905       if (type_info->stretch == UndefinedStretch)
11906         PUSHs(&sv_undef);
11907       else
11908         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
11909           type_info->stretch),0)));
11910       (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
11911         type_info->weight);
11912       PUSHs(sv_2mortal(newSVpv(message,0)));
11913       if (type_info->encoding == (char *) NULL)
11914         PUSHs(&sv_undef);
11915       else
11916         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
11917       if (type_info->foundry == (char *) NULL)
11918         PUSHs(&sv_undef);
11919       else
11920         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
11921       if (type_info->format == (char *) NULL)
11922         PUSHs(&sv_undef);
11923       else
11924         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
11925       if (type_info->metrics == (char *) NULL)
11926         PUSHs(&sv_undef);
11927       else
11928         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
11929       if (type_info->glyphs == (char *) NULL)
11930         PUSHs(&sv_undef);
11931       else
11932         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
11933     }
11934
11935   PerlException:
11936     InheritPerlException(exception,perl_exception);
11937     exception=DestroyExceptionInfo(exception);
11938     SvREFCNT_dec(perl_exception);
11939   }
11940 \f
11941 #
11942 ###############################################################################
11943 #                                                                             #
11944 #                                                                             #
11945 #                                                                             #
11946 #   Q u e r y F o n t M e t r i c s                                           #
11947 #                                                                             #
11948 #                                                                             #
11949 #                                                                             #
11950 ###############################################################################
11951 #
11952 #
11953 void
11954 QueryFontMetrics(ref,...)
11955   Image::Magick ref=NO_INIT
11956   ALIAS:
11957     queryfontmetrics = 1
11958   PPCODE:
11959   {
11960     AffineMatrix
11961       affine,
11962       current;
11963
11964     AV
11965       *av;
11966
11967     char
11968       *attribute;
11969
11970     double
11971       x,
11972       y;
11973
11974     DrawInfo
11975       *draw_info;
11976
11977     ExceptionInfo
11978       *exception;
11979
11980     GeometryInfo
11981       geometry_info;
11982
11983     Image
11984       *image;
11985
11986     MagickBooleanType
11987       status;
11988
11989     MagickStatusType
11990       flags;
11991
11992     register ssize_t
11993       i;
11994
11995     ssize_t
11996       type;
11997
11998     struct PackageInfo
11999       *info,
12000       *package_info;
12001
12002     SV
12003       *perl_exception,
12004       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12005
12006     TypeMetric
12007       metrics;
12008
12009     PERL_UNUSED_VAR(ref);
12010     PERL_UNUSED_VAR(ix);
12011     exception=AcquireExceptionInfo();
12012     package_info=(struct PackageInfo *) NULL;
12013     perl_exception=newSVpv("",0);
12014     reference=SvRV(ST(0));
12015     av=(AV *) reference;
12016     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12017       exception);
12018     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12019     if (image == (Image *) NULL)
12020       {
12021         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12022           PackageName);
12023         goto PerlException;
12024       }
12025     package_info=ClonePackageInfo(info,exception);
12026     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12027     CloneString(&draw_info->text,"");
12028     current=draw_info->affine;
12029     GetAffineMatrix(&affine);
12030     x=0.0;
12031     y=0.0;
12032     EXTEND(sp,7*items);
12033     for (i=2; i < items; i+=2)
12034     {
12035       attribute=(char *) SvPV(ST(i-1),na);
12036       switch (*attribute)
12037       {
12038         case 'A':
12039         case 'a':
12040         {
12041           if (LocaleCompare(attribute,"antialias") == 0)
12042             {
12043               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12044                 SvPV(ST(i),na));
12045               if (type < 0)
12046                 {
12047                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12048                     SvPV(ST(i),na));
12049                   break;
12050                 }
12051               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12052               break;
12053             }
12054           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12055             attribute);
12056           break;
12057         }
12058         case 'd':
12059         case 'D':
12060         {
12061           if (LocaleCompare(attribute,"density") == 0)
12062             {
12063               CloneString(&draw_info->density,SvPV(ST(i),na));
12064               break;
12065             }
12066           if (LocaleCompare(attribute,"direction") == 0)
12067             {
12068               draw_info->direction=(DirectionType) ParseCommandOption(
12069                 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12070               break;
12071             }
12072           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12073             attribute);
12074           break;
12075         }
12076         case 'e':
12077         case 'E':
12078         {
12079           if (LocaleCompare(attribute,"encoding") == 0)
12080             {
12081               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12082               break;
12083             }
12084           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12085             attribute);
12086           break;
12087         }
12088         case 'f':
12089         case 'F':
12090         {
12091           if (LocaleCompare(attribute,"family") == 0)
12092             {
12093               CloneString(&draw_info->family,SvPV(ST(i),na));
12094               break;
12095             }
12096           if (LocaleCompare(attribute,"fill") == 0)
12097             {
12098               if (info)
12099                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->fill,
12100                   &image->exception);
12101               break;
12102             }
12103           if (LocaleCompare(attribute,"font") == 0)
12104             {
12105               CloneString(&draw_info->font,SvPV(ST(i),na));
12106               break;
12107             }
12108           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12109             attribute);
12110           break;
12111         }
12112         case 'g':
12113         case 'G':
12114         {
12115           if (LocaleCompare(attribute,"geometry") == 0)
12116             {
12117               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12118               break;
12119             }
12120           if (LocaleCompare(attribute,"gravity") == 0)
12121             {
12122               draw_info->gravity=(GravityType) ParseCommandOption(
12123                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12124               break;
12125             }
12126           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12127             attribute);
12128           break;
12129         }
12130         case 'i':
12131         case 'I':
12132         {
12133           if (LocaleCompare(attribute,"interline-spacing") == 0)
12134             {
12135               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12136               draw_info->interline_spacing=geometry_info.rho;
12137               break;
12138             }
12139           if (LocaleCompare(attribute,"interword-spacing") == 0)
12140             {
12141               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12142               draw_info->interword_spacing=geometry_info.rho;
12143               break;
12144             }
12145           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12146             attribute);
12147           break;
12148         }
12149         case 'k':
12150         case 'K':
12151         {
12152           if (LocaleCompare(attribute,"kerning") == 0)
12153             {
12154               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12155               draw_info->kerning=geometry_info.rho;
12156               break;
12157             }
12158           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12159             attribute);
12160           break;
12161         }
12162         case 'p':
12163         case 'P':
12164         {
12165           if (LocaleCompare(attribute,"pointsize") == 0)
12166             {
12167               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12168               draw_info->pointsize=geometry_info.rho;
12169               break;
12170             }
12171           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12172             attribute);
12173           break;
12174         }
12175         case 'r':
12176         case 'R':
12177         {
12178           if (LocaleCompare(attribute,"rotate") == 0)
12179             {
12180               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12181               affine.rx=geometry_info.rho;
12182               affine.ry=geometry_info.sigma;
12183               if ((flags & SigmaValue) == 0)
12184                 affine.ry=affine.rx;
12185               break;
12186             }
12187           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12188             attribute);
12189           break;
12190         }
12191         case 's':
12192         case 'S':
12193         {
12194           if (LocaleCompare(attribute,"scale") == 0)
12195             {
12196               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12197               affine.sx=geometry_info.rho;
12198               affine.sy=geometry_info.sigma;
12199               if ((flags & SigmaValue) == 0)
12200                 affine.sy=affine.sx;
12201               break;
12202             }
12203           if (LocaleCompare(attribute,"skew") == 0)
12204             {
12205               double
12206                 x_angle,
12207                 y_angle;
12208
12209               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12210               x_angle=geometry_info.rho;
12211               y_angle=geometry_info.sigma;
12212               if ((flags & SigmaValue) == 0)
12213                 y_angle=x_angle;
12214               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12215               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12216               break;
12217             }
12218           if (LocaleCompare(attribute,"stroke") == 0)
12219             {
12220               if (info)
12221                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->stroke,
12222                   &image->exception);
12223               break;
12224             }
12225           if (LocaleCompare(attribute,"style") == 0)
12226             {
12227               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12228                 SvPV(ST(i),na));
12229               if (type < 0)
12230                 {
12231                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12232                     SvPV(ST(i),na));
12233                   break;
12234                 }
12235               draw_info->style=(StyleType) type;
12236               break;
12237             }
12238           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12239             attribute);
12240           break;
12241         }
12242         case 't':
12243         case 'T':
12244         {
12245           if (LocaleCompare(attribute,"text") == 0)
12246             {
12247               CloneString(&draw_info->text,SvPV(ST(i),na));
12248               break;
12249             }
12250           if (LocaleCompare(attribute,"translate") == 0)
12251             {
12252               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12253               affine.tx=geometry_info.rho;
12254               affine.ty=geometry_info.sigma;
12255               if ((flags & SigmaValue) == 0)
12256                 affine.ty=affine.tx;
12257               break;
12258             }
12259           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12260             attribute);
12261           break;
12262         }
12263         case 'w':
12264         case 'W':
12265         {
12266           if (LocaleCompare(attribute,"weight") == 0)
12267             {
12268               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12269               draw_info->weight=(size_t) geometry_info.rho;
12270               break;
12271             }
12272           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12273             attribute);
12274           break;
12275         }
12276         case 'x':
12277         case 'X':
12278         {
12279           if (LocaleCompare(attribute,"x") == 0)
12280             {
12281               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12282               x=geometry_info.rho;
12283               break;
12284             }
12285           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12286             attribute);
12287           break;
12288         }
12289         case 'y':
12290         case 'Y':
12291         {
12292           if (LocaleCompare(attribute,"y") == 0)
12293             {
12294               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12295               y=geometry_info.rho;
12296               break;
12297             }
12298           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12299             attribute);
12300           break;
12301         }
12302         default:
12303         {
12304           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12305             attribute);
12306           break;
12307         }
12308       }
12309     }
12310     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12311     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12312     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12313     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12314     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12315     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12316     if (draw_info->geometry == (char *) NULL)
12317       {
12318         draw_info->geometry=AcquireString((char *) NULL);
12319         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12320           "%.15g,%.15g",x,y);
12321       }
12322     status=GetTypeMetrics(image,draw_info,&metrics,exception);
12323     (void) CatchImageException(image);
12324     if (status == MagickFalse)
12325       PUSHs(&sv_undef);
12326     else
12327       {
12328         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12329         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12330         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12331         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12332         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12333         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12334         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12335         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12336         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12337         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12338         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12339         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12340         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12341       }
12342     draw_info=DestroyDrawInfo(draw_info);
12343
12344   PerlException:
12345     if (package_info != (struct PackageInfo *) NULL)
12346       DestroyPackageInfo(package_info);
12347     InheritPerlException(exception,perl_exception);
12348     exception=DestroyExceptionInfo(exception);
12349     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12350   }
12351 \f
12352 #
12353 ###############################################################################
12354 #                                                                             #
12355 #                                                                             #
12356 #                                                                             #
12357 #   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                         #
12358 #                                                                             #
12359 #                                                                             #
12360 #                                                                             #
12361 ###############################################################################
12362 #
12363 #
12364 void
12365 QueryMultilineFontMetrics(ref,...)
12366   Image::Magick ref=NO_INIT
12367   ALIAS:
12368     querymultilinefontmetrics = 1
12369   PPCODE:
12370   {
12371     AffineMatrix
12372       affine,
12373       current;
12374
12375     AV
12376       *av;
12377
12378     char
12379       *attribute;
12380
12381     double
12382       x,
12383       y;
12384
12385     DrawInfo
12386       *draw_info;
12387
12388     ExceptionInfo
12389       *exception;
12390
12391     GeometryInfo
12392       geometry_info;
12393
12394     Image
12395       *image;
12396
12397     MagickBooleanType
12398       status;
12399
12400     MagickStatusType
12401       flags;
12402
12403     register ssize_t
12404       i;
12405
12406     ssize_t
12407       type;
12408
12409     struct PackageInfo
12410       *info,
12411       *package_info;
12412
12413     SV
12414       *perl_exception,
12415       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12416
12417     TypeMetric
12418       metrics;
12419
12420     PERL_UNUSED_VAR(ref);
12421     PERL_UNUSED_VAR(ix);
12422     exception=AcquireExceptionInfo();
12423     package_info=(struct PackageInfo *) NULL;
12424     perl_exception=newSVpv("",0);
12425     reference=SvRV(ST(0));
12426     av=(AV *) reference;
12427     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12428       exception);
12429     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12430     if (image == (Image *) NULL)
12431       {
12432         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12433           PackageName);
12434         goto PerlException;
12435       }
12436     package_info=ClonePackageInfo(info,exception);
12437     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12438     CloneString(&draw_info->text,"");
12439     current=draw_info->affine;
12440     GetAffineMatrix(&affine);
12441     x=0.0;
12442     y=0.0;
12443     EXTEND(sp,7*items);
12444     for (i=2; i < items; i+=2)
12445     {
12446       attribute=(char *) SvPV(ST(i-1),na);
12447       switch (*attribute)
12448       {
12449         case 'A':
12450         case 'a':
12451         {
12452           if (LocaleCompare(attribute,"antialias") == 0)
12453             {
12454               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12455                 SvPV(ST(i),na));
12456               if (type < 0)
12457                 {
12458                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12459                     SvPV(ST(i),na));
12460                   break;
12461                 }
12462               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12463               break;
12464             }
12465           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12466             attribute);
12467           break;
12468         }
12469         case 'd':
12470         case 'D':
12471         {
12472           if (LocaleCompare(attribute,"density") == 0)
12473             {
12474               CloneString(&draw_info->density,SvPV(ST(i),na));
12475               break;
12476             }
12477           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12478             attribute);
12479           break;
12480         }
12481         case 'e':
12482         case 'E':
12483         {
12484           if (LocaleCompare(attribute,"encoding") == 0)
12485             {
12486               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12487               break;
12488             }
12489           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12490             attribute);
12491           break;
12492         }
12493         case 'f':
12494         case 'F':
12495         {
12496           if (LocaleCompare(attribute,"family") == 0)
12497             {
12498               CloneString(&draw_info->family,SvPV(ST(i),na));
12499               break;
12500             }
12501           if (LocaleCompare(attribute,"fill") == 0)
12502             {
12503               if (info)
12504                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->fill,
12505                   &image->exception);
12506               break;
12507             }
12508           if (LocaleCompare(attribute,"font") == 0)
12509             {
12510               CloneString(&draw_info->font,SvPV(ST(i),na));
12511               break;
12512             }
12513           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12514             attribute);
12515           break;
12516         }
12517         case 'g':
12518         case 'G':
12519         {
12520           if (LocaleCompare(attribute,"geometry") == 0)
12521             {
12522               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12523               break;
12524             }
12525           if (LocaleCompare(attribute,"gravity") == 0)
12526             {
12527               draw_info->gravity=(GravityType) ParseCommandOption(
12528                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12529               break;
12530             }
12531           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12532             attribute);
12533           break;
12534         }
12535         case 'p':
12536         case 'P':
12537         {
12538           if (LocaleCompare(attribute,"pointsize") == 0)
12539             {
12540               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12541               draw_info->pointsize=geometry_info.rho;
12542               break;
12543             }
12544           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12545             attribute);
12546           break;
12547         }
12548         case 'r':
12549         case 'R':
12550         {
12551           if (LocaleCompare(attribute,"rotate") == 0)
12552             {
12553               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12554               affine.rx=geometry_info.rho;
12555               affine.ry=geometry_info.sigma;
12556               if ((flags & SigmaValue) == 0)
12557                 affine.ry=affine.rx;
12558               break;
12559             }
12560           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12561             attribute);
12562           break;
12563         }
12564         case 's':
12565         case 'S':
12566         {
12567           if (LocaleCompare(attribute,"scale") == 0)
12568             {
12569               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12570               affine.sx=geometry_info.rho;
12571               affine.sy=geometry_info.sigma;
12572               if ((flags & SigmaValue) == 0)
12573                 affine.sy=affine.sx;
12574               break;
12575             }
12576           if (LocaleCompare(attribute,"skew") == 0)
12577             {
12578               double
12579                 x_angle,
12580                 y_angle;
12581
12582               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12583               x_angle=geometry_info.rho;
12584               y_angle=geometry_info.sigma;
12585               if ((flags & SigmaValue) == 0)
12586                 y_angle=x_angle;
12587               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12588               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12589               break;
12590             }
12591           if (LocaleCompare(attribute,"stroke") == 0)
12592             {
12593               if (info)
12594                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->stroke,
12595                   &image->exception);
12596               break;
12597             }
12598           if (LocaleCompare(attribute,"style") == 0)
12599             {
12600               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12601                 SvPV(ST(i),na));
12602               if (type < 0)
12603                 {
12604                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12605                     SvPV(ST(i),na));
12606                   break;
12607                 }
12608               draw_info->style=(StyleType) type;
12609               break;
12610             }
12611           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12612             attribute);
12613           break;
12614         }
12615         case 't':
12616         case 'T':
12617         {
12618           if (LocaleCompare(attribute,"text") == 0)
12619             {
12620               CloneString(&draw_info->text,SvPV(ST(i),na));
12621               break;
12622             }
12623           if (LocaleCompare(attribute,"translate") == 0)
12624             {
12625               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12626               affine.tx=geometry_info.rho;
12627               affine.ty=geometry_info.sigma;
12628               if ((flags & SigmaValue) == 0)
12629                 affine.ty=affine.tx;
12630               break;
12631             }
12632           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12633             attribute);
12634           break;
12635         }
12636         case 'w':
12637         case 'W':
12638         {
12639           if (LocaleCompare(attribute,"weight") == 0)
12640             {
12641               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12642               draw_info->weight=(size_t) geometry_info.rho;
12643               break;
12644             }
12645           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12646             attribute);
12647           break;
12648         }
12649         case 'x':
12650         case 'X':
12651         {
12652           if (LocaleCompare(attribute,"x") == 0)
12653             {
12654               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12655               x=geometry_info.rho;
12656               break;
12657             }
12658           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12659             attribute);
12660           break;
12661         }
12662         case 'y':
12663         case 'Y':
12664         {
12665           if (LocaleCompare(attribute,"y") == 0)
12666             {
12667               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12668               y=geometry_info.rho;
12669               break;
12670             }
12671           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12672             attribute);
12673           break;
12674         }
12675         default:
12676         {
12677           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12678             attribute);
12679           break;
12680         }
12681       }
12682     }
12683     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12684     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12685     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12686     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12687     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12688     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12689     if (draw_info->geometry == (char *) NULL)
12690       {
12691         draw_info->geometry=AcquireString((char *) NULL);
12692         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12693           "%.15g,%.15g",x,y);
12694       }
12695     status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
12696     (void) CatchException(exception);
12697     if (status == MagickFalse)
12698       PUSHs(&sv_undef);
12699     else
12700       {
12701         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12702         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12703         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12704         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12705         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12706         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12707         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12708         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12709         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12710         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12711         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12712         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12713         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12714       }
12715     draw_info=DestroyDrawInfo(draw_info);
12716
12717   PerlException:
12718     if (package_info != (struct PackageInfo *) NULL)
12719       DestroyPackageInfo(package_info);
12720     InheritPerlException(exception,perl_exception);
12721     exception=DestroyExceptionInfo(exception);
12722     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12723   }
12724 \f
12725 #
12726 ###############################################################################
12727 #                                                                             #
12728 #                                                                             #
12729 #                                                                             #
12730 #   Q u e r y F o r m a t                                                     #
12731 #                                                                             #
12732 #                                                                             #
12733 #                                                                             #
12734 ###############################################################################
12735 #
12736 #
12737 void
12738 QueryFormat(ref,...)
12739   Image::Magick ref=NO_INIT
12740   ALIAS:
12741     queryformat = 1
12742   PPCODE:
12743   {
12744     char
12745       *name;
12746
12747     ExceptionInfo
12748       *exception;
12749
12750     register ssize_t
12751       i;
12752
12753     SV
12754       *perl_exception;
12755
12756     volatile const MagickInfo
12757       *magick_info;
12758
12759     PERL_UNUSED_VAR(ref);
12760     PERL_UNUSED_VAR(ix);
12761     exception=AcquireExceptionInfo();
12762     perl_exception=newSVpv("",0);
12763     if (items == 1)
12764       {
12765         char
12766           format[MaxTextExtent];
12767
12768         const MagickInfo
12769           **format_list;
12770
12771         size_t
12772           types;
12773
12774         format_list=GetMagickInfoList("*",&types,exception);
12775         EXTEND(sp,types);
12776         for (i=0; i < (ssize_t) types; i++)
12777         {
12778           (void) CopyMagickString(format,format_list[i]->name,MaxTextExtent);
12779           LocaleLower(format);
12780           PUSHs(sv_2mortal(newSVpv(format,0)));
12781         }
12782         format_list=(const MagickInfo **)
12783           RelinquishMagickMemory((MagickInfo *) format_list);
12784         goto PerlException;
12785       }
12786     EXTEND(sp,8*items);
12787     for (i=1; i < items; i++)
12788     {
12789       name=(char *) SvPV(ST(i),na);
12790       magick_info=GetMagickInfo(name,exception);
12791       if (magick_info == (const MagickInfo *) NULL)
12792         {
12793           PUSHs(&sv_undef);
12794           continue;
12795         }
12796       PUSHs(sv_2mortal(newSViv(magick_info->adjoin)));
12797       PUSHs(sv_2mortal(newSViv(magick_info->blob_support)));
12798       PUSHs(sv_2mortal(newSViv(magick_info->raw)));
12799       PUSHs(sv_2mortal(newSViv((long) magick_info->decoder)));
12800       PUSHs(sv_2mortal(newSViv((long) magick_info->encoder)));
12801       if (magick_info->description == (char *) NULL)
12802         PUSHs(&sv_undef);
12803       else
12804         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
12805       if (magick_info->module == (char *) NULL)
12806         PUSHs(&sv_undef);
12807       else
12808         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
12809     }
12810
12811   PerlException:
12812     InheritPerlException(exception,perl_exception);
12813     exception=DestroyExceptionInfo(exception);
12814     SvREFCNT_dec(perl_exception);
12815   }
12816 \f
12817 #
12818 ###############################################################################
12819 #                                                                             #
12820 #                                                                             #
12821 #                                                                             #
12822 #   Q u e r y O p t i o n                                                     #
12823 #                                                                             #
12824 #                                                                             #
12825 #                                                                             #
12826 ###############################################################################
12827 #
12828 #
12829 void
12830 QueryOption(ref,...)
12831   Image::Magick ref=NO_INIT
12832   ALIAS:
12833     queryoption = 1
12834   PPCODE:
12835   {
12836     char
12837       **options;
12838
12839     ExceptionInfo
12840       *exception;
12841
12842     register ssize_t
12843       i;
12844
12845     ssize_t
12846       j,
12847       option;
12848
12849     SV
12850       *perl_exception;
12851
12852     PERL_UNUSED_VAR(ref);
12853     PERL_UNUSED_VAR(ix);
12854     exception=AcquireExceptionInfo();
12855     perl_exception=newSVpv("",0);
12856     EXTEND(sp,8*items);
12857     for (i=1; i < items; i++)
12858     {
12859       option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
12860         SvPV(ST(i),na));
12861       options=GetCommandOptions((CommandOption) option);
12862       if (options == (char **) NULL)
12863         PUSHs(&sv_undef);
12864       else
12865         {
12866           for (j=0; options[j] != (char *) NULL; j++)
12867             PUSHs(sv_2mortal(newSVpv(options[j],0)));
12868           options=DestroyStringList(options);
12869         }
12870     }
12871
12872     InheritPerlException(exception,perl_exception);
12873     exception=DestroyExceptionInfo(exception);
12874     SvREFCNT_dec(perl_exception);
12875   }
12876 \f
12877 #
12878 ###############################################################################
12879 #                                                                             #
12880 #                                                                             #
12881 #                                                                             #
12882 #   R e a d                                                                   #
12883 #                                                                             #
12884 #                                                                             #
12885 #                                                                             #
12886 ###############################################################################
12887 #
12888 #
12889 void
12890 Read(ref,...)
12891   Image::Magick ref=NO_INIT
12892   ALIAS:
12893     ReadImage  = 1
12894     read       = 2
12895     readimage  = 3
12896   PPCODE:
12897   {
12898     AV
12899       *av;
12900
12901     char
12902       **keep,
12903       **list;
12904
12905     ExceptionInfo
12906       *exception;
12907
12908     HV
12909       *hv;
12910
12911     Image
12912       *image;
12913
12914     int
12915       n;
12916
12917     MagickBooleanType
12918       status;
12919
12920     register char
12921       **p;
12922
12923     register ssize_t
12924       i;
12925
12926     ssize_t
12927       ac,
12928       number_images;
12929
12930     STRLEN
12931       *length;
12932
12933     struct PackageInfo
12934       *info,
12935       *package_info;
12936
12937     SV
12938       *perl_exception,  /* Perl variable for storing messages */
12939       *reference,
12940       *rv,
12941       *sv;
12942
12943     PERL_UNUSED_VAR(ref);
12944     PERL_UNUSED_VAR(ix);
12945     exception=AcquireExceptionInfo();
12946     perl_exception=newSVpv("",0);
12947     sv=NULL;
12948     package_info=(struct PackageInfo *) NULL;
12949     number_images=0;
12950     ac=(items < 2) ? 1 : items-1;
12951     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
12952     keep=list;
12953     length=(STRLEN *) NULL;
12954     if (list == (char **) NULL)
12955       {
12956         ThrowPerlException(exception,ResourceLimitError,
12957           "MemoryAllocationFailed",PackageName);
12958         goto PerlException;
12959       }
12960     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
12961     if (length == (STRLEN *) NULL)
12962       {
12963         ThrowPerlException(exception,ResourceLimitError,
12964           "MemoryAllocationFailed",PackageName);
12965         goto PerlException;
12966       }
12967     if (sv_isobject(ST(0)) == 0)
12968       {
12969         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12970           PackageName);
12971         goto PerlException;
12972       }
12973     reference=SvRV(ST(0));
12974     hv=SvSTASH(reference);
12975     if (SvTYPE(reference) != SVt_PVAV)
12976       {
12977         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12978           PackageName);
12979         goto PerlException;
12980       }
12981     av=(AV *) reference;
12982     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12983       exception);
12984     package_info=ClonePackageInfo(info,exception);
12985     n=1;
12986     if (items <= 1)
12987       *list=(char *) (*package_info->image_info->filename ?
12988         package_info->image_info->filename : "XC:black");
12989     else
12990       for (n=0, i=0; i < ac; i++)
12991       {
12992         list[n]=(char *) SvPV(ST(i+1),length[n]);
12993         if ((items >= 3) && strEQcase(list[n],"blob"))
12994           {
12995             void
12996               *blob;
12997
12998             i++;
12999             blob=(void *) (SvPV(ST(i+1),length[n]));
13000             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13001           }
13002         if ((items >= 3) && strEQcase(list[n],"filename"))
13003           continue;
13004         if ((items >= 3) && strEQcase(list[n],"file"))
13005           {
13006             FILE
13007               *file;
13008
13009             PerlIO
13010               *io_info;
13011
13012             i++;
13013             io_info=IoIFP(sv_2io(ST(i+1)));
13014             if (io_info == (PerlIO *) NULL)
13015               {
13016                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13017                   PackageName);
13018                 continue;
13019               }
13020             file=PerlIO_findFILE(io_info);
13021             if (file == (FILE *) NULL)
13022               {
13023                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13024                   PackageName);
13025                 continue;
13026               }
13027             SetImageInfoFile(package_info->image_info,file);
13028           }
13029         if ((items >= 3) && strEQcase(list[n],"magick"))
13030           continue;
13031         n++;
13032       }
13033     list[n]=(char *) NULL;
13034     keep=list;
13035     status=ExpandFilenames(&n,&list);
13036     if (status == MagickFalse)
13037       {
13038         ThrowPerlException(exception,ResourceLimitError,
13039           "MemoryAllocationFailed",PackageName);
13040         goto PerlException;
13041       }
13042     number_images=0;
13043     for (i=0; i < n; i++)
13044     {
13045       if ((package_info->image_info->file != (FILE *) NULL) ||
13046           (package_info->image_info->blob != (void *) NULL))
13047         {
13048           image=ReadImages(package_info->image_info,exception);
13049           if (image != (Image *) NULL)
13050             DisassociateImageStream(image);
13051         }
13052       else
13053         {
13054           (void) CopyMagickString(package_info->image_info->filename,list[i],
13055             MaxTextExtent);
13056           image=ReadImages(package_info->image_info,exception);
13057         }
13058       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
13059         break;
13060       for ( ; image; image=image->next)
13061       {
13062         AddImageToRegistry(sv,image);
13063         rv=newRV(sv);
13064         av_push(av,sv_bless(rv,hv));
13065         SvREFCNT_dec(sv);
13066         number_images++;
13067       }
13068     }
13069     /*
13070       Free resources.
13071     */
13072     for (i=0; i < n; i++)
13073       if (list[i] != (char *) NULL)
13074         for (p=keep; list[i] != *p++; )
13075           if (*p == (char *) NULL)
13076             {
13077               list[i]=(char *) RelinquishMagickMemory(list[i]);
13078               break;
13079             }
13080
13081   PerlException:
13082     if (package_info != (struct PackageInfo *) NULL)
13083       DestroyPackageInfo(package_info);
13084     if (list && (list != keep))
13085       list=(char **) RelinquishMagickMemory(list);
13086     if (keep)
13087       keep=(char **) RelinquishMagickMemory(keep);
13088     if (length)
13089       length=(STRLEN *) RelinquishMagickMemory(length);
13090     InheritPerlException(exception,perl_exception);
13091     exception=DestroyExceptionInfo(exception);
13092     sv_setiv(perl_exception,(IV) number_images);
13093     SvPOK_on(perl_exception);
13094     ST(0)=sv_2mortal(perl_exception);
13095     XSRETURN(1);
13096   }
13097 \f
13098 #
13099 ###############################################################################
13100 #                                                                             #
13101 #                                                                             #
13102 #                                                                             #
13103 #   R e m o t e                                                               #
13104 #                                                                             #
13105 #                                                                             #
13106 #                                                                             #
13107 ###############################################################################
13108 #
13109 #
13110 void
13111 Remote(ref,...)
13112   Image::Magick ref=NO_INIT
13113   ALIAS:
13114     RemoteCommand  = 1
13115     remote         = 2
13116     remoteCommand  = 3
13117   PPCODE:
13118   {
13119     AV
13120       *av;
13121
13122     ExceptionInfo
13123       *exception;
13124
13125     register ssize_t
13126       i;
13127
13128     SV
13129       *perl_exception,
13130       *reference;
13131
13132     struct PackageInfo
13133       *info;
13134
13135     PERL_UNUSED_VAR(ref);
13136     PERL_UNUSED_VAR(ix);
13137     exception=AcquireExceptionInfo();
13138     perl_exception=newSVpv("",0);
13139     reference=SvRV(ST(0));
13140     av=(AV *) reference;
13141     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13142       exception);
13143     for (i=1; i < items; i++)
13144       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13145         SvPV(ST(i),na),exception);
13146     InheritPerlException(exception,perl_exception);
13147     exception=DestroyExceptionInfo(exception);
13148     SvREFCNT_dec(perl_exception);    /* throw away all errors */
13149   }
13150 \f
13151 #
13152 ###############################################################################
13153 #                                                                             #
13154 #                                                                             #
13155 #                                                                             #
13156 #   S e t                                                                     #
13157 #                                                                             #
13158 #                                                                             #
13159 #                                                                             #
13160 ###############################################################################
13161 #
13162 #
13163 void
13164 Set(ref,...)
13165   Image::Magick ref=NO_INIT
13166   ALIAS:
13167     SetAttributes  = 1
13168     SetAttribute   = 2
13169     set            = 3
13170     setattributes  = 4
13171     setattribute   = 5
13172   PPCODE:
13173   {
13174     ExceptionInfo
13175       *exception;
13176
13177     Image
13178       *image;
13179
13180     register ssize_t
13181       i;
13182
13183     struct PackageInfo
13184       *info;
13185
13186     SV
13187       *perl_exception,
13188       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13189
13190     PERL_UNUSED_VAR(ref);
13191     PERL_UNUSED_VAR(ix);
13192     exception=AcquireExceptionInfo();
13193     perl_exception=newSVpv("",0);
13194     if (sv_isobject(ST(0)) == 0)
13195       {
13196         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13197           PackageName);
13198         goto PerlException;
13199       }
13200     reference=SvRV(ST(0));
13201     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13202     if (items == 2)
13203       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13204     else
13205       for (i=2; i < items; i+=2)
13206         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13207
13208   PerlException:
13209     InheritPerlException(exception,perl_exception);
13210     exception=DestroyExceptionInfo(exception);
13211     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13212     SvPOK_on(perl_exception);
13213     ST(0)=sv_2mortal(perl_exception);
13214     XSRETURN(1);
13215   }
13216 \f
13217 #
13218 ###############################################################################
13219 #                                                                             #
13220 #                                                                             #
13221 #                                                                             #
13222 #   S e t P i x e l                                                           #
13223 #                                                                             #
13224 #                                                                             #
13225 #                                                                             #
13226 ###############################################################################
13227 #
13228 #
13229 void
13230 SetPixel(ref,...)
13231   Image::Magick ref=NO_INIT
13232   ALIAS:
13233     setpixel = 1
13234     setPixel = 2
13235   PPCODE:
13236   {
13237     AV
13238       *av;
13239
13240     char
13241       *attribute;
13242
13243     ChannelType
13244       channel,
13245       channel_mask;
13246
13247     ExceptionInfo
13248       *exception;
13249
13250     Image
13251       *image;
13252
13253     MagickBooleanType
13254       normalize;
13255
13256     RectangleInfo
13257       region;
13258
13259     register ssize_t
13260       i;
13261
13262     register Quantum
13263       *q;
13264
13265     ssize_t
13266       option;
13267
13268     struct PackageInfo
13269       *info;
13270
13271     SV
13272       *perl_exception,
13273       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13274
13275     PERL_UNUSED_VAR(ref);
13276     PERL_UNUSED_VAR(ix);
13277     exception=AcquireExceptionInfo();
13278     perl_exception=newSVpv("",0);
13279     reference=SvRV(ST(0));
13280     av=(AV *) reference;
13281     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13282       exception);
13283     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13284     if (image == (Image *) NULL)
13285       {
13286         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13287           PackageName);
13288         goto PerlException;
13289       }
13290     av=(AV *) NULL;
13291     normalize=MagickTrue;
13292     region.x=0;
13293     region.y=0;
13294     region.width=image->columns;
13295     region.height=1;
13296     if (items == 1)
13297       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13298     channel=DefaultChannels;
13299     for (i=2; i < items; i+=2)
13300     {
13301       attribute=(char *) SvPV(ST(i-1),na);
13302       switch (*attribute)
13303       {
13304         case 'C':
13305         case 'c':
13306         {
13307           if (LocaleCompare(attribute,"channel") == 0)
13308             {
13309               ssize_t
13310                 option;
13311
13312               option=ParseChannelOption(SvPV(ST(i),na));
13313               if (option < 0)
13314                 {
13315                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13316                     SvPV(ST(i),na));
13317                   return;
13318                 }
13319               channel=(ChannelType) option;
13320               break;
13321             }
13322           if (LocaleCompare(attribute,"color") == 0)
13323             {
13324               if (SvTYPE(ST(i)) != SVt_RV)
13325                 {
13326                   char
13327                     message[MaxTextExtent];
13328
13329                   (void) FormatLocaleString(message,MaxTextExtent,
13330                     "invalid %.60s value",attribute);
13331                   ThrowPerlException(exception,OptionError,message,
13332                     SvPV(ST(i),na));
13333                 }
13334               av=(AV *) SvRV(ST(i));
13335               break;
13336             }
13337           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13338             attribute);
13339           break;
13340         }
13341         case 'g':
13342         case 'G':
13343         {
13344           if (LocaleCompare(attribute,"geometry") == 0)
13345             {
13346               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
13347               break;
13348             }
13349           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13350             attribute);
13351           break;
13352         }
13353         case 'N':
13354         case 'n':
13355         {
13356           if (LocaleCompare(attribute,"normalize") == 0)
13357             {
13358               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13359                 SvPV(ST(i),na));
13360               if (option < 0)
13361                 {
13362                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13363                     SvPV(ST(i),na));
13364                   break;
13365                 }
13366              normalize=option != 0 ? MagickTrue : MagickFalse;
13367              break;
13368             }
13369           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13370             attribute);
13371           break;
13372         }
13373         case 'x':
13374         case 'X':
13375         {
13376           if (LocaleCompare(attribute,"x") == 0)
13377             {
13378               region.x=SvIV(ST(i));
13379               break;
13380             }
13381           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13382             attribute);
13383           break;
13384         }
13385         case 'y':
13386         case 'Y':
13387         {
13388           if (LocaleCompare(attribute,"y") == 0)
13389             {
13390               region.y=SvIV(ST(i));
13391               break;
13392             }
13393           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13394             attribute);
13395           break;
13396         }
13397         default:
13398         {
13399           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13400             attribute);
13401           break;
13402         }
13403       }
13404     }
13405     (void) SetImageStorageClass(image,DirectClass,exception);
13406     channel_mask=SetPixelChannelMask(image,channel);
13407     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
13408     if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
13409         (SvTYPE(av) != SVt_PVAV))
13410       PUSHs(&sv_undef);
13411     else
13412       {
13413         double
13414           scale;
13415
13416         register ssize_t
13417           i;
13418
13419         i=0;
13420         scale=1.0;
13421         if (normalize != MagickFalse)
13422           scale=QuantumRange;
13423         if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
13424             (i <= av_len(av)))
13425           {
13426             SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
13427               av_fetch(av,i,0)))),q);
13428             i++;
13429           }
13430         if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
13431             (i <= av_len(av)))
13432           {
13433             SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
13434               av_fetch(av,i,0)))),q);
13435             i++;
13436           }
13437         if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
13438             (i <= av_len(av)))
13439           {
13440             SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
13441               av_fetch(av,i,0)))),q);
13442             i++;
13443           }
13444         if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
13445             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
13446           {
13447             SetPixelBlack(image,ClampToQuantum(scale*
13448               SvNV(*(av_fetch(av,i,0)))),q);
13449             i++;
13450           }
13451         if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
13452             (i <= av_len(av)))
13453           {
13454             SetPixelAlpha(image,ClampToQuantum(scale*
13455               SvNV(*(av_fetch(av,i,0)))),q);
13456             i++;
13457           }
13458         (void) SyncAuthenticPixels(image,exception);
13459       }
13460     (void) SetPixelChannelMask(image,channel_mask);
13461
13462   PerlException:
13463     InheritPerlException(exception,perl_exception);
13464     exception=DestroyExceptionInfo(exception);
13465     SvREFCNT_dec(perl_exception);
13466   }
13467 \f
13468 #
13469 ###############################################################################
13470 #                                                                             #
13471 #                                                                             #
13472 #                                                                             #
13473 #   S m u s h                                                                 #
13474 #                                                                             #
13475 #                                                                             #
13476 #                                                                             #
13477 ###############################################################################
13478 #
13479 #
13480 void
13481 Smush(ref,...)
13482   Image::Magick ref=NO_INIT
13483   ALIAS:
13484     SmushImage  = 1
13485     smush       = 2
13486     smushimage  = 3
13487   PPCODE:
13488   {
13489     AV
13490       *av;
13491
13492     char
13493       *attribute;
13494
13495     ExceptionInfo
13496       *exception;
13497
13498     HV
13499       *hv;
13500
13501     Image
13502       *image;
13503
13504     register ssize_t
13505       i;
13506
13507     ssize_t
13508       offset,
13509       stack;
13510
13511     struct PackageInfo
13512       *info;
13513
13514     SV
13515       *av_reference,
13516       *perl_exception,
13517       *reference,
13518       *rv,
13519       *sv;
13520
13521     PERL_UNUSED_VAR(ref);
13522     PERL_UNUSED_VAR(ix);
13523     exception=AcquireExceptionInfo();
13524     perl_exception=newSVpv("",0);
13525     sv=NULL;
13526     attribute=NULL;
13527     av=NULL;
13528     if (sv_isobject(ST(0)) == 0)
13529       {
13530         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13531           PackageName);
13532         goto PerlException;
13533       }
13534     reference=SvRV(ST(0));
13535     hv=SvSTASH(reference);
13536     av=newAV();
13537     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13538     SvREFCNT_dec(av);
13539     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13540     if (image == (Image *) NULL)
13541       {
13542         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13543           PackageName);
13544         goto PerlException;
13545       }
13546     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13547     /*
13548       Get options.
13549     */
13550     offset=0;
13551     stack=MagickTrue;
13552     for (i=2; i < items; i+=2)
13553     {
13554       attribute=(char *) SvPV(ST(i-1),na);
13555       switch (*attribute)
13556       {
13557         case 'O':
13558         case 'o':
13559         {
13560           if (LocaleCompare(attribute,"offset") == 0)
13561             {
13562               offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
13563               break;
13564             }
13565           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13566             attribute);
13567           break;
13568         }
13569         case 'S':
13570         case 's':
13571         {
13572           if (LocaleCompare(attribute,"stack") == 0)
13573             {
13574               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13575                 SvPV(ST(i),na));
13576               if (stack < 0)
13577                 {
13578                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13579                     SvPV(ST(i),na));
13580                   return;
13581                 }
13582               break;
13583             }
13584           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13585             attribute);
13586           break;
13587         }
13588         default:
13589         {
13590           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13591             attribute);
13592           break;
13593         }
13594       }
13595     }
13596     image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
13597       exception);
13598     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
13599       goto PerlException;
13600     for ( ; image; image=image->next)
13601     {
13602       AddImageToRegistry(sv,image);
13603       rv=newRV(sv);
13604       av_push(av,sv_bless(rv,hv));
13605       SvREFCNT_dec(sv);
13606     }
13607     exception=DestroyExceptionInfo(exception);
13608     ST(0)=av_reference;
13609     SvREFCNT_dec(perl_exception);
13610     XSRETURN(1);
13611
13612   PerlException:
13613     InheritPerlException(exception,perl_exception);
13614     exception=DestroyExceptionInfo(exception);
13615     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
13616     SvPOK_on(perl_exception);
13617     ST(0)=sv_2mortal(perl_exception);
13618     XSRETURN(1);
13619   }
13620 \f
13621 #
13622 ###############################################################################
13623 #                                                                             #
13624 #                                                                             #
13625 #                                                                             #
13626 #   S t a t i s t i c s                                                       #
13627 #                                                                             #
13628 #                                                                             #
13629 #                                                                             #
13630 ###############################################################################
13631 #
13632 #
13633 void
13634 Statistics(ref,...)
13635   Image::Magick ref=NO_INIT
13636   ALIAS:
13637     StatisticsImage = 1
13638     statistics      = 2
13639     statisticsimage = 3
13640   PPCODE:
13641   {
13642 #define ChannelStatistics(channel) \
13643 { \
13644   (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
13645     (double) channel_statistics[channel].depth); \
13646   PUSHs(sv_2mortal(newSVpv(message,0))); \
13647   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13648     channel_statistics[channel].minima/scale); \
13649   PUSHs(sv_2mortal(newSVpv(message,0))); \
13650   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13651     channel_statistics[channel].maxima/scale); \
13652   PUSHs(sv_2mortal(newSVpv(message,0))); \
13653   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13654     channel_statistics[channel].mean/scale); \
13655   PUSHs(sv_2mortal(newSVpv(message,0))); \
13656   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13657     channel_statistics[channel].standard_deviation/scale); \
13658   PUSHs(sv_2mortal(newSVpv(message,0))); \
13659   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13660     channel_statistics[channel].kurtosis); \
13661   PUSHs(sv_2mortal(newSVpv(message,0))); \
13662   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13663     channel_statistics[channel].skewness); \
13664   PUSHs(sv_2mortal(newSVpv(message,0))); \
13665 }
13666
13667     AV
13668       *av;
13669
13670     char
13671       message[MaxTextExtent];
13672
13673     ChannelStatistics
13674       *channel_statistics;
13675
13676     double
13677       scale;
13678
13679     ExceptionInfo
13680       *exception;
13681
13682     Image
13683       *image;
13684
13685     ssize_t
13686       count;
13687
13688     struct PackageInfo
13689       *info;
13690
13691     SV
13692       *perl_exception,
13693       *reference;
13694
13695     PERL_UNUSED_VAR(ref);
13696     PERL_UNUSED_VAR(ix);
13697     exception=AcquireExceptionInfo();
13698     perl_exception=newSVpv("",0);
13699     av=NULL;
13700     if (sv_isobject(ST(0)) == 0)
13701       {
13702         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13703           PackageName);
13704         goto PerlException;
13705       }
13706     reference=SvRV(ST(0));
13707     av=newAV();
13708     SvREFCNT_dec(av);
13709     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13710     if (image == (Image *) NULL)
13711       {
13712         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13713           PackageName);
13714         goto PerlException;
13715       }
13716     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13717     count=0;
13718     for ( ; image; image=image->next)
13719     {
13720       channel_statistics=GetImageStatistics(image,&image->exception);
13721       if (channel_statistics == (ChannelStatistics *) NULL)
13722         continue;
13723       count++;
13724       EXTEND(sp,35*count);
13725       scale=(double) QuantumRange;
13726       ChannelStatistics(RedChannel);
13727       ChannelStatistics(GreenChannel);
13728       ChannelStatistics(BlueChannel);
13729       if (image->colorspace == CMYKColorspace)
13730         ChannelStatistics(BlackChannel);
13731       if (image->matte != MagickFalse)
13732         ChannelStatistics(AlphaChannel);
13733       channel_statistics=(ChannelStatistics *)
13734         RelinquishMagickMemory(channel_statistics);
13735     }
13736
13737   PerlException:
13738     InheritPerlException(exception,perl_exception);
13739     exception=DestroyExceptionInfo(exception);
13740     SvREFCNT_dec(perl_exception);
13741   }
13742 \f
13743 #
13744 ###############################################################################
13745 #                                                                             #
13746 #                                                                             #
13747 #                                                                             #
13748 #   S y n c A u t h e n t i c P i x e l s                                     #
13749 #                                                                             #
13750 #                                                                             #
13751 #                                                                             #
13752 ###############################################################################
13753 #
13754 #
13755 void
13756 SyncAuthenticPixels(ref,...)
13757   Image::Magick ref = NO_INIT
13758   ALIAS:
13759     Syncauthenticpixels = 1
13760     SyncImagePixels = 2
13761     syncimagepixels = 3
13762   CODE:
13763   {
13764     ExceptionInfo
13765       *exception;
13766
13767     Image
13768       *image;
13769
13770     MagickBooleanType
13771       status;
13772
13773     struct PackageInfo
13774       *info;
13775
13776     SV
13777       *perl_exception,
13778       *reference;
13779
13780     PERL_UNUSED_VAR(ref);
13781     PERL_UNUSED_VAR(ix);
13782     exception=AcquireExceptionInfo();
13783     perl_exception=newSVpv("",0);
13784     if (sv_isobject(ST(0)) == 0)
13785       {
13786         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13787           PackageName);
13788         goto PerlException;
13789       }
13790
13791     reference=SvRV(ST(0));
13792     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13793     if (image == (Image *) NULL)
13794       {
13795         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13796           PackageName);
13797         goto PerlException;
13798       }
13799
13800     status=SyncAuthenticPixels(image,exception);
13801     if (status != MagickFalse)
13802       return;
13803     InheritException(exception,&image->exception);
13804
13805   PerlException:
13806     InheritPerlException(exception,perl_exception);
13807     exception=DestroyExceptionInfo(exception);
13808     SvREFCNT_dec(perl_exception);  /* throw away all errors */
13809   }
13810 \f
13811 #
13812 ###############################################################################
13813 #                                                                             #
13814 #                                                                             #
13815 #                                                                             #
13816 #   T r a n s f o r m                                                         #
13817 #                                                                             #
13818 #                                                                             #
13819 #                                                                             #
13820 ###############################################################################
13821 #
13822 #
13823 void
13824 Transform(ref,...)
13825   Image::Magick ref=NO_INIT
13826   ALIAS:
13827     TransformImage = 1
13828     transform      = 2
13829     transformimage = 3
13830   PPCODE:
13831   {
13832     AV
13833       *av;
13834
13835     char
13836       *attribute,
13837       *crop_geometry,
13838       *geometry;
13839
13840     ExceptionInfo
13841       *exception;
13842
13843     HV
13844       *hv;
13845
13846     Image
13847       *clone,
13848       *image;
13849
13850     register ssize_t
13851       i;
13852
13853     struct PackageInfo
13854       *info;
13855
13856     SV
13857       *av_reference,
13858       *perl_exception,
13859       *reference,
13860       *rv,
13861       *sv;
13862
13863     PERL_UNUSED_VAR(ref);
13864     PERL_UNUSED_VAR(ix);
13865     exception=AcquireExceptionInfo();
13866     perl_exception=newSVpv("",0);
13867     sv=NULL;
13868     av=NULL;
13869     attribute=NULL;
13870     if (sv_isobject(ST(0)) == 0)
13871       {
13872         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13873           PackageName);
13874         goto PerlException;
13875       }
13876     reference=SvRV(ST(0));
13877     hv=SvSTASH(reference);
13878     av=newAV();
13879     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13880     SvREFCNT_dec(av);
13881     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13882     if (image == (Image *) NULL)
13883       {
13884         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13885           PackageName);
13886         goto PerlException;
13887       }
13888     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13889     /*
13890       Get attribute.
13891     */
13892     crop_geometry=(char *) NULL;
13893     geometry=(char *) NULL;
13894     for (i=2; i < items; i+=2)
13895     {
13896       attribute=(char *) SvPV(ST(i-1),na);
13897       switch (*attribute)
13898       {
13899         case 'c':
13900         case 'C':
13901         {
13902           if (LocaleCompare(attribute,"crop") == 0)
13903             {
13904               crop_geometry=SvPV(ST(i),na);
13905               break;
13906             }
13907           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13908             attribute);
13909           break;
13910         }
13911         case 'g':
13912         case 'G':
13913         {
13914           if (LocaleCompare(attribute,"geometry") == 0)
13915             {
13916               geometry=SvPV(ST(i),na);
13917               break;
13918             }
13919          if (LocaleCompare(attribute,"gravity") == 0)
13920            {
13921              Image
13922                *next;
13923
13924              ssize_t
13925                in;
13926
13927              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
13928                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13929              if (in < 0)
13930                {
13931                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
13932                    SvPV(ST(i),na));
13933                  return;
13934                }
13935              for (next=image; next; next=next->next)
13936                next->gravity=(GravityType) in;
13937              break;
13938            }
13939           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13940             attribute);
13941           break;
13942         }
13943         default:
13944         {
13945           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13946             attribute);
13947           break;
13948         }
13949       }
13950     }
13951     for ( ; image; image=image->next)
13952     {
13953       clone=CloneImage(image,0,0,MagickTrue,exception);
13954       if ((clone == (Image *) NULL) || (exception->severity >= ErrorException))
13955         goto PerlException;
13956       TransformImage(&clone,crop_geometry,geometry);
13957       for ( ; clone; clone=clone->next)
13958       {
13959         AddImageToRegistry(sv,clone);
13960         rv=newRV(sv);
13961         av_push(av,sv_bless(rv,hv));
13962         SvREFCNT_dec(sv);
13963       }
13964     }
13965     exception=DestroyExceptionInfo(exception);
13966     ST(0)=av_reference;
13967     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13968     XSRETURN(1);
13969
13970   PerlException:
13971     InheritPerlException(exception,perl_exception);
13972     exception=DestroyExceptionInfo(exception);
13973     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
13974     SvPOK_on(perl_exception);
13975     ST(0)=sv_2mortal(perl_exception);
13976     XSRETURN(1);
13977   }
13978 \f
13979 #
13980 ###############################################################################
13981 #                                                                             #
13982 #                                                                             #
13983 #                                                                             #
13984 #   W r i t e                                                                 #
13985 #                                                                             #
13986 #                                                                             #
13987 #                                                                             #
13988 ###############################################################################
13989 #
13990 #
13991 void
13992 Write(ref,...)
13993   Image::Magick ref=NO_INIT
13994   ALIAS:
13995     WriteImage    = 1
13996     write         = 2
13997     writeimage    = 3
13998   PPCODE:
13999   {
14000     char
14001       filename[MaxTextExtent];
14002
14003     ExceptionInfo
14004       *exception;
14005
14006     Image
14007       *image,
14008       *next;
14009
14010     register ssize_t
14011       i;
14012
14013     ssize_t
14014       number_images,
14015       scene;
14016
14017     struct PackageInfo
14018       *info,
14019       *package_info;
14020
14021     SV
14022       *perl_exception,
14023       *reference;
14024
14025     PERL_UNUSED_VAR(ref);
14026     PERL_UNUSED_VAR(ix);
14027     exception=AcquireExceptionInfo();
14028     perl_exception=newSVpv("",0);
14029     number_images=0;
14030     package_info=(struct PackageInfo *) NULL;
14031     if (sv_isobject(ST(0)) == 0)
14032       {
14033         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14034           PackageName);
14035         goto PerlException;
14036       }
14037     reference=SvRV(ST(0));
14038     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14039     if (image == (Image *) NULL)
14040       {
14041         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14042           PackageName);
14043         goto PerlException;
14044       }
14045     package_info=ClonePackageInfo(info,exception);
14046     if (items == 2)
14047       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14048     else
14049       if (items > 2)
14050         for (i=2; i < items; i+=2)
14051           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14052             exception);
14053     (void) CopyMagickString(filename,package_info->image_info->filename,
14054       MaxTextExtent);
14055     scene=0;
14056     for (next=image; next; next=next->next)
14057     {
14058       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
14059       next->scene=scene++;
14060     }
14061     SetImageInfo(package_info->image_info,(unsigned int)
14062       GetImageListLength(image),&image->exception);
14063     for (next=image; next; next=next->next)
14064     {
14065       (void) WriteImage(package_info->image_info,next,exception);
14066       number_images++;
14067       if (package_info->image_info->adjoin)
14068         break;
14069     }
14070
14071   PerlException:
14072     if (package_info != (struct PackageInfo *) NULL)
14073       DestroyPackageInfo(package_info);
14074     InheritPerlException(exception,perl_exception);
14075     exception=DestroyExceptionInfo(exception);
14076     sv_setiv(perl_exception,(IV) number_images);
14077     SvPOK_on(perl_exception);
14078     ST(0)=sv_2mortal(perl_exception);
14079     XSRETURN(1);
14080   }