]> 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}, {"blend", StringReference} } },
212     { "Border", { {"geometry", StringReference}, {"width", IntegerReference},
213       {"height", IntegerReference}, {"fill", StringReference},
214       {"bordercolor", StringReference}, {"color", StringReference},
215       {"compose", MagickComposeOptions} } },
216     { "Blur", { {"geometry", StringReference}, {"radius", RealReference},
217       {"sigma", RealReference}, {"bias", RealReference},
218       {"channel", MagickChannelOptions} } },
219     { "Chop", { {"geometry", StringReference}, {"width", IntegerReference},
220       {"height", IntegerReference}, {"x", IntegerReference},
221       {"y", IntegerReference} } },
222     { "Crop", { {"geometry", StringReference}, {"width", IntegerReference},
223       {"height", IntegerReference}, {"x", IntegerReference},
224       {"y", IntegerReference}, {"fuzz", StringReference},
225       {"gravity", MagickGravityOptions} } },
226     { "Despeckle", },
227     { "Edge", { {"radius", RealReference} } },
228     { "Emboss", { {"geometry", StringReference}, {"radius", RealReference},
229       {"sigma", RealReference} } },
230     { "Enhance", },
231     { "Flip", },
232     { "Flop", },
233     { "Frame", { {"geometry", StringReference}, {"width", IntegerReference},
234       {"height", IntegerReference}, {"inner", IntegerReference},
235       {"outer", IntegerReference}, {"fill", StringReference},
236       {"color", StringReference}, {"compose", MagickComposeOptions} } },
237     { "Implode", { {"amount", RealReference},
238       {"interpolate", MagickInterpolateOptions} } },
239     { "Magnify", },
240     { "MedianFilter", { {"geometry", StringReference},
241       {"width", IntegerReference}, {"height", IntegerReference},
242       {"channel", MagickChannelOptions} } },
243     { "Minify", },
244     { "OilPaint", { {"radius", RealReference}, {"sigma", RealReference} } },
245     { "ReduceNoise", { {"geometry", StringReference},
246       {"width", IntegerReference},{"height", IntegerReference},
247       {"channel", MagickChannelOptions} } },
248     { "Roll", { {"geometry", StringReference}, {"x", IntegerReference},
249       {"y", IntegerReference} } },
250     { "Rotate", { {"degrees", RealReference}, {"fill", StringReference},
251       {"color", StringReference}, {"background", StringReference} } },
252     { "Sample", { {"geometry", StringReference}, {"width", IntegerReference},
253       {"height", IntegerReference} } },
254     { "Scale", { {"geometry", StringReference}, {"width", IntegerReference},
255       {"height", IntegerReference} } },
256     { "Shade", { {"geometry", StringReference}, {"azimuth", RealReference},
257       {"elevation", RealReference}, {"gray", MagickBooleanOptions} } },
258     { "Sharpen", { {"geometry", StringReference}, {"radius", RealReference},
259       {"sigma", RealReference}, {"bias", RealReference},
260       {"channel", MagickChannelOptions} } },
261     { "Shear", { {"geometry", StringReference}, {"x", RealReference},
262       {"y", RealReference}, { "fill", StringReference},
263       {"color", StringReference} } },
264     { "Spread", { {"radius", RealReference},
265       {"interpolate", MagickInterpolateOptions} } },
266     { "Swirl", { {"degrees", RealReference},
267       {"interpolate", MagickInterpolateOptions} } },
268     { "Resize", { {"geometry", StringReference}, {"width", IntegerReference},
269       {"height", IntegerReference}, {"filter", MagickFilterOptions},
270       {"support", StringReference }, {"blur", RealReference } } },
271     { "Zoom", { {"geometry", StringReference}, {"width", IntegerReference},
272       {"height", IntegerReference}, {"filter", MagickFilterOptions},
273       {"support", RealReference }, {"blur", RealReference } } },
274     { "Annotate", { {"text", StringReference}, {"font", StringReference},
275       {"pointsize", RealReference}, {"density", StringReference},
276       {"undercolor", StringReference}, {"stroke", StringReference},
277       {"fill", StringReference}, {"geometry", StringReference},
278       {"pen", StringReference}, {"x", RealReference},
279       {"y", RealReference}, {"gravity", MagickGravityOptions},
280       {"translate", StringReference}, {"scale", StringReference},
281       {"rotate", RealReference}, {"skewX", RealReference},
282       {"skewY", RealReference}, {"strokewidth", RealReference},
283       {"antialias", MagickBooleanOptions}, {"family", StringReference},
284       {"style", MagickStyleOptions}, {"stretch", MagickStretchOptions},
285       {"weight", IntegerReference}, {"align", MagickAlignOptions},
286       {"encoding", StringReference}, {"affine", ArrayReference},
287       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
288       {"tile", ImageReference}, {"kerning", RealReference},
289       {"interline-spacing", RealReference},
290       {"interword-spacing", RealReference},
291       {"direction", MagickDirectionOptions} } },
292     { "ColorFloodfill", { {"geometry", StringReference},
293       {"x", IntegerReference}, {"y", IntegerReference},
294       {"fill", StringReference}, {"bordercolor", StringReference},
295       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
296     { "Composite", { {"image", ImageReference},
297       {"compose", MagickComposeOptions}, {"geometry", StringReference},
298       {"x", IntegerReference}, {"y", IntegerReference},
299       {"gravity", MagickGravityOptions}, {"opacity", StringReference},
300       {"tile", MagickBooleanOptions}, {"rotate", RealReference},
301       {"color", StringReference}, {"mask", ImageReference},
302       {"channel", MagickChannelOptions},
303       {"interpolate", MagickInterpolateOptions}, {"args", StringReference},
304       {"blend", StringReference} } },
305     { "Contrast", { {"sharpen", MagickBooleanOptions} } },
306     { "CycleColormap", { {"display", IntegerReference} } },
307     { "Draw", { {"primitive", MagickPrimitiveOptions},
308       {"points", StringReference}, {"method", MagickMethodOptions},
309       {"stroke", StringReference}, {"fill", StringReference},
310       {"strokewidth", RealReference}, {"font", StringReference},
311       {"bordercolor", StringReference}, {"x", RealReference},
312       {"y", RealReference}, {"translate", StringReference},
313       {"scale", StringReference}, {"rotate", RealReference},
314       {"skewX", RealReference}, {"skewY", RealReference},
315       {"tile", ImageReference}, {"pointsize", RealReference},
316       {"antialias", MagickBooleanOptions}, {"density", StringReference},
317       {"linewidth", RealReference}, {"affine", ArrayReference},
318       {"stroke-dashoffset", RealReference},
319       {"stroke-dasharray", ArrayReference},
320       {"interpolate", MagickInterpolateOptions},
321       {"origin", StringReference}, {"text", StringReference},
322       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
323       {"vector-graphics", StringReference}, {"kerning", RealReference},
324       {"interline-spacing", RealReference},
325       {"interword-spacing", RealReference},
326       {"direction", MagickDirectionOptions} } },
327     { "Equalize", { {"channel", MagickChannelOptions} } },
328     { "Gamma", { {"gamma", StringReference}, {"channel", MagickChannelOptions},
329       {"red", RealReference}, {"green", RealReference},
330       {"blue", RealReference} } },
331     { "Map", { {"image", ImageReference}, {"dither", MagickBooleanOptions},
332       {"dither-method", MagickDitherOptions} } },
333     { "MatteFloodfill", { {"geometry", StringReference},
334       {"x", IntegerReference}, {"y", IntegerReference},
335       {"opacity", StringReference}, {"bordercolor", StringReference},
336       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
337     { "Modulate", { {"factor", StringReference}, {"hue", RealReference},
338       {"saturation", RealReference}, {"whiteness", RealReference},
339       {"brightness", RealReference}, {"lightness", RealReference},
340       {"blackness", RealReference} } },
341     { "Negate", { {"gray", MagickBooleanOptions},
342       {"channel", MagickChannelOptions} } },
343     { "Normalize", { {"channel", MagickChannelOptions} } },
344     { "NumberColors", },
345     { "Opaque", { {"color", StringReference}, {"fill", StringReference},
346       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
347       {"invert", MagickBooleanOptions} } },
348     { "Quantize", { {"colors", IntegerReference},
349       {"treedepth", IntegerReference}, {"colorspace", MagickColorspaceOptions},
350       {"dither", MagickBooleanOptions}, {"measure", MagickBooleanOptions},
351       {"global", MagickBooleanOptions}, {"transparent-color", StringReference},
352       {"dither-method", MagickDitherOptions} } },
353     { "Raise", { {"geometry", StringReference}, {"width", IntegerReference},
354       {"height", IntegerReference}, {"raise", MagickBooleanOptions} } },
355     { "Segment", { {"geometry", StringReference},
356       {"cluster-threshold", RealReference},
357       {"smoothing-threshold", RealReference},
358       {"colorspace", MagickColorspaceOptions},
359       {"verbose", MagickBooleanOptions} } },
360     { "Signature", },
361     { "Solarize", { {"geometry", StringReference},
362       {"threshold", StringReference} } },
363     { "Sync", },
364     { "Texture", { {"texture", ImageReference} } },
365     { "Evaluate", { {"value", RealReference},
366       {"operator", MagickEvaluateOptions},
367       {"channel", MagickChannelOptions} } },
368     { "Transparent", { {"color", StringReference}, {"opacity", StringReference},
369       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
370     { "Threshold", { {"threshold", StringReference},
371       {"channel", MagickChannelOptions} } },
372     { "Charcoal", { {"geometry", StringReference}, {"radius", RealReference},
373       {"sigma", RealReference}, {"biabias", RealReference} } },
374     { "Trim", { {"fuzz", StringReference} } },
375     { "Wave", { {"geometry", StringReference}, {"amplitude", RealReference},
376       {"wavelength", RealReference},
377       {"interpolate", MagickInterpolateOptions} } },
378     { "Separate", { {"channel", MagickChannelOptions} } },
379     { "Condense", },
380     { "Stereo", { {"image", ImageReference}, {"x", IntegerReference},
381       {"y", IntegerReference} } },
382     { "Stegano", { {"image", ImageReference}, {"offset", IntegerReference} } },
383     { "Deconstruct", },
384     { "GaussianBlur", { {"geometry", StringReference},
385       {"radius", RealReference}, {"sigma", RealReference},
386       {"bias", RealReference}, {"channel", MagickChannelOptions} } },
387     { "Convolve", { {"coefficients", ArrayReference},
388       {"channel", MagickChannelOptions}, {"bias", StringReference},
389       {"kernel", StringReference} } },
390     { "Profile", { {"name", StringReference}, {"profile", StringReference},
391       { "rendering-intent", MagickIntentOptions},
392       { "black-point-compensation", MagickBooleanOptions} } },
393     { "UnsharpMask", { {"geometry", StringReference},
394       {"radius", RealReference}, {"sigma", RealReference},
395       {"amount", RealReference}, {"threshold", RealReference},
396       {"channel", MagickChannelOptions} } },
397     { "MotionBlur", { {"geometry", StringReference},
398       {"radius", RealReference}, {"sigma", RealReference},
399       {"angle", RealReference}, {"bias", RealReference},
400       {"channel", MagickChannelOptions} } },
401     { "OrderedDither", { {"threshold", StringReference},
402       {"channel", MagickChannelOptions} } },
403     { "Shave", { {"geometry", StringReference}, {"width", IntegerReference},
404       {"height", IntegerReference} } },
405     { "Level", { {"levels", StringReference}, {"black-point", RealReference},
406       {"white-point", RealReference}, {"gamma", RealReference},
407       {"channel", MagickChannelOptions}, {"level", StringReference} } },
408     { "Clip", { {"id", StringReference}, {"inside", MagickBooleanOptions} } },
409     { "AffineTransform", { {"affine", ArrayReference},
410       {"translate", StringReference}, {"scale", StringReference},
411       {"rotate", RealReference}, {"skewX", RealReference},
412       {"skewY", RealReference}, {"interpolate", MagickInterpolateOptions},
413       {"background", StringReference} } },
414     { "Difference", { {"image", ImageReference}, {"fuzz", StringReference} } },
415     { "AdaptiveThreshold", { {"geometry", StringReference},
416       {"width", IntegerReference}, {"height", IntegerReference},
417       {"bias", RealReference} } },
418     { "Resample", { {"density", StringReference}, {"x", RealReference},
419       {"y", RealReference}, {"filter", MagickFilterOptions},
420       {"support", RealReference }, {"blur", RealReference } } },
421     { "Describe", { {"file", FileReference} } },
422     { "BlackThreshold", { {"threshold", StringReference},
423       {"channel", MagickChannelOptions} } },
424     { "WhiteThreshold", { {"threshold", StringReference},
425       {"channel", MagickChannelOptions} } },
426     { "RadialBlur", { {"geometry", StringReference}, {"angle", RealReference},
427       {"bias", RealReference}, {"channel", MagickChannelOptions} } },
428     { "Thumbnail", { {"geometry", StringReference}, {"width", IntegerReference},
429       {"height", IntegerReference} } },
430     { "Strip", },
431     { "Tint", { {"fill", StringReference}, {"blend", StringReference} } },
432     { "Channel", { {"channel", MagickChannelOptions} } },
433     { "Splice", { {"geometry", StringReference}, {"width", IntegerReference},
434       {"height", IntegerReference}, {"x", IntegerReference},
435       {"y", IntegerReference}, {"fuzz", StringReference},
436       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
437     { "Posterize", { {"levels", IntegerReference},
438       {"dither", MagickBooleanOptions} } },
439     { "Shadow", { {"geometry", StringReference}, {"opacity", RealReference},
440       {"sigma", RealReference}, {"x", IntegerReference},
441       {"y", IntegerReference} } },
442     { "Identify", { {"file", FileReference}, {"features", StringReference},
443       {"unique", MagickBooleanOptions} } },
444     { "SepiaTone", { {"threshold", RealReference} } },
445     { "SigmoidalContrast", { {"geometry", StringReference},
446       {"contrast", RealReference}, {"mid-point", RealReference},
447       {"channel", MagickChannelOptions}, {"sharpen", MagickBooleanOptions} } },
448     { "Extent", { {"geometry", StringReference}, {"width", IntegerReference},
449       {"height", IntegerReference}, {"x", IntegerReference},
450       {"y", IntegerReference}, {"fuzz", StringReference},
451       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
452     { "Vignette", { {"geometry", StringReference}, {"radius", RealReference},
453       {"sigma", RealReference}, {"x", IntegerReference},
454       {"y", IntegerReference}, {"background", StringReference} } },
455     { "ContrastStretch", { {"levels", StringReference},
456       {"black-point", RealReference},{"white-point", RealReference},
457       {"channel", MagickChannelOptions} } },
458     { "Sans0", },
459     { "Sans1", },
460     { "AdaptiveSharpen", { {"geometry", StringReference},
461       {"radius", RealReference}, {"sigma", RealReference},
462       {"bias", RealReference}, {"channel", MagickChannelOptions} } },
463     { "Transpose", },
464     { "Transverse", },
465     { "AutoOrient", },
466     { "AdaptiveBlur", { {"geometry", StringReference},
467       {"radius", RealReference}, {"sigma", RealReference},
468       {"bias", RealReference}, {"channel", MagickChannelOptions} } },
469     { "Sketch", { {"geometry", StringReference},
470       {"radius", RealReference}, {"sigma", RealReference},
471       {"angle", RealReference}, {"bias", RealReference} } },
472     { "UniqueColors", },
473     { "AdaptiveResize", { {"geometry", StringReference},
474       {"width", IntegerReference}, {"height", IntegerReference},
475       {"filter", MagickFilterOptions}, {"support", StringReference },
476       {"blur", RealReference }, {"interpolate", MagickInterpolateOptions} } },
477     { "ClipMask", { {"mask", ImageReference} } },
478     { "LinearStretch", { {"levels", StringReference},
479       {"black-point", RealReference},{"white-point", RealReference} } },
480     { "Recolor", { {"matrix", ArrayReference} } },
481     { "Mask", { {"mask", ImageReference} } },
482     { "Polaroid", { {"caption", StringReference}, {"angle", RealReference},
483       {"font", StringReference}, {"stroke", StringReference},
484       {"fill", StringReference}, {"strokewidth", RealReference},
485       {"pointsize", RealReference}, {"gravity", MagickGravityOptions},
486       {"background", StringReference},
487       {"interpolate", MagickInterpolateOptions} } },
488     { "FloodfillPaint", { {"geometry", StringReference},
489       {"x", IntegerReference}, {"y", IntegerReference},
490       {"fill", StringReference}, {"bordercolor", StringReference},
491       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
492       {"invert", MagickBooleanOptions} } },
493     { "Distort", { {"points", ArrayReference}, {"method", MagickDistortOptions},
494       {"virtual-pixel", MagickVirtualPixelOptions},
495       {"best-fit", MagickBooleanOptions} } },
496     { "Clut", { {"image", ImageReference},
497       {"interpolate", MagickInterpolateOptions},
498       {"channel", MagickChannelOptions} } },
499     { "LiquidRescale", { {"geometry", StringReference},
500       {"width", IntegerReference}, {"height", IntegerReference},
501       {"delta-x", RealReference}, {"rigidity", RealReference } } },
502     { "Encipher", { {"passphrase", StringReference} } },
503     { "Decipher", { {"passphrase", StringReference} } },
504     { "Deskew", { {"geometry", StringReference},
505       {"threshold", StringReference} } },
506     { "Remap", { {"image", ImageReference}, {"dither", MagickBooleanOptions},
507       {"dither-method", MagickDitherOptions} } },
508     { "SparseColor", { {"points", ArrayReference},
509       {"method", MagickSparseColorOptions},
510       {"virtual-pixel", MagickVirtualPixelOptions},
511       {"channel", MagickChannelOptions} } },
512     { "Function", { {"parameters", ArrayReference},
513       {"function", MagickFunctionOptions},
514       {"virtual-pixel", MagickVirtualPixelOptions} } },
515     { "SelectiveBlur", { {"geometry", StringReference},
516       {"radius", RealReference}, {"sigma", RealReference},
517       {"threshold", RealReference}, {"bias", RealReference},
518       {"channel", MagickChannelOptions} } },
519     { "HaldClut", { {"image", ImageReference},
520       {"channel", MagickChannelOptions} } },
521     { "BlueShift", { {"factor", StringReference} } },
522     { "ForwardFourierTransform", { {"magnitude", MagickBooleanOptions} } },
523     { "InverseFourierTransform", { {"magnitude", MagickBooleanOptions} } },
524     { "ColorDecisionList", {
525       {"color-correction-collection", StringReference} } },
526     { "AutoGamma", { {"channel", MagickChannelOptions} } },
527     { "AutoLevel", { {"channel", MagickChannelOptions} } },
528     { "LevelColors", { {"invert", MagickBooleanOptions},
529       {"black-point", StringReference}, {"white-point", StringReference},
530       {"channel", MagickChannelOptions}, {"invert", MagickBooleanOptions} } },
531     { "Clamp", { {"channel", MagickChannelOptions} } },
532     { "BrightnessContrast", { {"levels", StringReference},
533       {"brightness", RealReference},{"contrast", RealReference},
534       {"channel", MagickChannelOptions} } },
535     { "Morphology", { {"kernel", StringReference},
536       {"channel", MagickChannelOptions}, {"method", MagickMorphologyOptions},
537       {"iterations", IntegerReference} } },
538     { "ColorMatrix", { {"matrix", ArrayReference} } },
539     { "Color", { {"color", StringReference} } },
540     { "Mode", { {"geometry", StringReference},
541       {"width", IntegerReference},{"height", IntegerReference},
542       {"channel", MagickChannelOptions} } },
543     { "Statistic", { {"geometry", StringReference},
544       {"width", IntegerReference},{"height", IntegerReference},
545       {"channel", MagickChannelOptions}, {"type", MagickStatisticOptions} } }
546   };
547
548 static SplayTreeInfo
549   *magick_registry = (SplayTreeInfo *) NULL;
550 \f
551 /*
552   Forward declarations.
553 */
554 static Image
555   *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
556
557 static ssize_t
558   strEQcase(const char *,const char *);
559 \f
560 /*
561 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
562 %                                                                             %
563 %                                                                             %
564 %                                                                             %
565 %   C l o n e P a c k a g e I n f o                                           %
566 %                                                                             %
567 %                                                                             %
568 %                                                                             %
569 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
570 %
571 %  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
572 %  a new one.
573 %
574 %  The format of the ClonePackageInfo routine is:
575 %
576 %      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
577 %        exception)
578 %
579 %  A description of each parameter follows:
580 %
581 %    o info: a structure of type info.
582 %
583 %    o exception: Return any errors or warnings in this structure.
584 %
585 */
586 static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
587   ExceptionInfo *exception)
588 {
589   struct PackageInfo
590     *clone_info;
591
592   clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
593   if (clone_info == (struct PackageInfo *) NULL)
594     {
595       ThrowPerlException(exception,ResourceLimitError,
596         "UnableToClonePackageInfo",PackageName);
597       return((struct PackageInfo *) NULL);
598     }
599   if (info == (struct PackageInfo *) NULL)
600     {
601       clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
602       return(clone_info);
603     }
604   *clone_info=(*info);
605   clone_info->image_info=CloneImageInfo(info->image_info);
606   return(clone_info);
607 }
608 \f
609 /*
610 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
611 %                                                                             %
612 %                                                                             %
613 %                                                                             %
614 %   c o n s t a n t                                                           %
615 %                                                                             %
616 %                                                                             %
617 %                                                                             %
618 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
619 %
620 %  constant() returns a double value for the specified name.
621 %
622 %  The format of the constant routine is:
623 %
624 %      double constant(char *name,ssize_t sans)
625 %
626 %  A description of each parameter follows:
627 %
628 %    o value: Method constant returns a double value for the specified name.
629 %
630 %    o name: The name of the constant.
631 %
632 %    o sans: This integer value is not used.
633 %
634 */
635 static double constant(char *name,ssize_t sans)
636 {
637   (void) sans;
638   errno=0;
639   switch (*name)
640   {
641     case 'B':
642     {
643       if (strEQ(name,"BlobError"))
644         return(BlobError);
645       if (strEQ(name,"BlobWarning"))
646         return(BlobWarning);
647       break;
648     }
649     case 'C':
650     {
651       if (strEQ(name,"CacheError"))
652         return(CacheError);
653       if (strEQ(name,"CacheWarning"))
654         return(CacheWarning);
655       if (strEQ(name,"CoderError"))
656         return(CoderError);
657       if (strEQ(name,"CoderWarning"))
658         return(CoderWarning);
659       if (strEQ(name,"ConfigureError"))
660         return(ConfigureError);
661       if (strEQ(name,"ConfigureWarning"))
662         return(ConfigureWarning);
663       if (strEQ(name,"CorruptImageError"))
664         return(CorruptImageError);
665       if (strEQ(name,"CorruptImageWarning"))
666         return(CorruptImageWarning);
667       break;
668     }
669     case 'D':
670     {
671       if (strEQ(name,"DelegateError"))
672         return(DelegateError);
673       if (strEQ(name,"DelegateWarning"))
674         return(DelegateWarning);
675       if (strEQ(name,"DrawError"))
676         return(DrawError);
677       if (strEQ(name,"DrawWarning"))
678         return(DrawWarning);
679       break;
680     }
681     case 'E':
682     {
683       if (strEQ(name,"ErrorException"))
684         return(ErrorException);
685       if (strEQ(name,"ExceptionError"))
686         return(CoderError);
687       if (strEQ(name,"ExceptionWarning"))
688         return(CoderWarning);
689       break;
690     }
691     case 'F':
692     {
693       if (strEQ(name,"FatalErrorException"))
694         return(FatalErrorException);
695       if (strEQ(name,"FileOpenError"))
696         return(FileOpenError);
697       if (strEQ(name,"FileOpenWarning"))
698         return(FileOpenWarning);
699       break;
700     }
701     case 'I':
702     {
703       if (strEQ(name,"ImageError"))
704         return(ImageError);
705       if (strEQ(name,"ImageWarning"))
706         return(ImageWarning);
707       break;
708     }
709     case 'M':
710     {
711       if (strEQ(name,"MaxRGB"))
712         return(QuantumRange);
713       if (strEQ(name,"MissingDelegateError"))
714         return(MissingDelegateError);
715       if (strEQ(name,"MissingDelegateWarning"))
716         return(MissingDelegateWarning);
717       if (strEQ(name,"ModuleError"))
718         return(ModuleError);
719       if (strEQ(name,"ModuleWarning"))
720         return(ModuleWarning);
721       break;
722     }
723     case 'O':
724     {
725       if (strEQ(name,"Opaque"))
726         return(OpaqueAlpha);
727       if (strEQ(name,"OptionError"))
728         return(OptionError);
729       if (strEQ(name,"OptionWarning"))
730         return(OptionWarning);
731       break;
732     }
733     case 'Q':
734     {
735       if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
736         return(MAGICKCORE_QUANTUM_DEPTH);
737       if (strEQ(name,"QuantumDepth"))
738         return(MAGICKCORE_QUANTUM_DEPTH);
739       if (strEQ(name,"QuantumRange"))
740         return(QuantumRange);
741       break;
742     }
743     case 'R':
744     {
745       if (strEQ(name,"ResourceLimitError"))
746         return(ResourceLimitError);
747       if (strEQ(name,"ResourceLimitWarning"))
748         return(ResourceLimitWarning);
749       if (strEQ(name,"RegistryError"))
750         return(RegistryError);
751       if (strEQ(name,"RegistryWarning"))
752         return(RegistryWarning);
753       break;
754     }
755     case 'S':
756     {
757       if (strEQ(name,"StreamError"))
758         return(StreamError);
759       if (strEQ(name,"StreamWarning"))
760         return(StreamWarning);
761       if (strEQ(name,"Success"))
762         return(0);
763       break;
764     }
765     case 'T':
766     {
767       if (strEQ(name,"Transparent"))
768         return(TransparentAlpha);
769       if (strEQ(name,"TypeError"))
770         return(TypeError);
771       if (strEQ(name,"TypeWarning"))
772         return(TypeWarning);
773       break;
774     }
775     case 'W':
776     {
777       if (strEQ(name,"WarningException"))
778         return(WarningException);
779       break;
780     }
781     case 'X':
782     {
783       if (strEQ(name,"XServerError"))
784         return(XServerError);
785       if (strEQ(name,"XServerWarning"))
786         return(XServerWarning);
787       break;
788     }
789   }
790   errno=EINVAL;
791   return(0);
792 }
793 \f
794 /*
795 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
796 %                                                                             %
797 %                                                                             %
798 %                                                                             %
799 %   D e s t r o y P a c k a g e I n f o                                       %
800 %                                                                             %
801 %                                                                             %
802 %                                                                             %
803 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
804 %
805 %  Method DestroyPackageInfo frees a previously created info structure.
806 %
807 %  The format of the DestroyPackageInfo routine is:
808 %
809 %      DestroyPackageInfo(struct PackageInfo *info)
810 %
811 %  A description of each parameter follows:
812 %
813 %    o info: a structure of type info.
814 %
815 */
816 static void DestroyPackageInfo(struct PackageInfo *info)
817 {
818   info->image_info=DestroyImageInfo(info->image_info);
819   info=(struct PackageInfo *) RelinquishMagickMemory(info);
820 }
821 \f
822 /*
823 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
824 %                                                                             %
825 %                                                                             %
826 %                                                                             %
827 %   G e t L i s t                                                             %
828 %                                                                             %
829 %                                                                             %
830 %                                                                             %
831 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
832 %
833 %  Method GetList is recursively called by SetupList to traverse the
834 %  Image__Magick reference.  If building an reference_vector (see SetupList),
835 %  *current is the current position in *reference_vector and *last is the final
836 %  entry in *reference_vector.
837 %
838 %  The format of the GetList routine is:
839 %
840 %      GetList(info)
841 %
842 %  A description of each parameter follows:
843 %
844 %    o info: a structure of type info.
845 %
846 */
847 static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
848   ssize_t *current,ssize_t *last,ExceptionInfo *exception)
849 {
850   Image
851     *image;
852
853   if (reference == (SV *) NULL)
854     return(NULL);
855   switch (SvTYPE(reference))
856   {
857     case SVt_PVAV:
858     {
859       AV
860         *av;
861
862       Image
863         *head,
864         *previous;
865
866       register ssize_t
867         i;
868
869       ssize_t
870         n;
871
872       /*
873         Array of images.
874       */
875       previous=(Image *) NULL;
876       head=(Image *) NULL;
877       av=(AV *) reference;
878       n=av_len(av);
879       for (i=0; i <= n; i++)
880       {
881         SV
882           **rv;
883
884         rv=av_fetch(av,i,0);
885         if (rv && *rv && sv_isobject(*rv))
886           {
887             image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
888               exception);
889             if (image == (Image *) NULL)
890               continue;
891             if (image == previous)
892               {
893                 image=CloneImage(image,0,0,MagickTrue,exception);
894                 if (image == (Image *) NULL)
895                   return(NULL);
896               }
897             image->previous=previous;
898             *(previous ? &previous->next : &head)=image;
899             for (previous=image; previous->next; previous=previous->next) ;
900           }
901       }
902       return(head);
903     }
904     case SVt_PVMG:
905     {
906       /*
907         Blessed scalar, one image.
908       */
909       image=(Image *) SvIV(reference);
910       if (image == (Image *) NULL)
911         return(NULL);
912       image->previous=(Image *) NULL;
913       image->next=(Image *) NULL;
914       if (reference_vector)
915         {
916           if (*current == *last)
917             {
918               *last+=256;
919               if (*reference_vector == (SV **) NULL)
920                 *reference_vector=(SV **) AcquireQuantumMemory(*last,
921                   sizeof(*reference_vector));
922               else
923                 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
924                   *last,sizeof(*reference_vector));
925             }
926           if (*reference_vector == (SV **) NULL)
927             {
928               ThrowPerlException(exception,ResourceLimitError,
929                 "MemoryAllocationFailed",PackageName);
930               return((Image *) NULL);
931             }
932           (*reference_vector)[*current]=reference;
933           (*reference_vector)[++(*current)]=NULL;
934         }
935       return(image);
936     }
937     default:
938       break;
939   }
940   (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
941     (double) SvTYPE(reference));
942   return((Image *) NULL);
943 }
944 \f
945 /*
946 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
947 %                                                                             %
948 %                                                                             %
949 %                                                                             %
950 %   G e t P a c k a g e I n f o                                               %
951 %                                                                             %
952 %                                                                             %
953 %                                                                             %
954 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
955 %
956 %  Method GetPackageInfo looks up or creates an info structure for the given
957 %  Image__Magick reference.  If it does create a new one, the information in
958 %  package_info is used to initialize it.
959 %
960 %  The format of the GetPackageInfo routine is:
961 %
962 %      struct PackageInfo *GetPackageInfo(void *reference,
963 %        struct PackageInfo *package_info,ExceptionInfo *exception)
964 %
965 %  A description of each parameter follows:
966 %
967 %    o info: a structure of type info.
968 %
969 %    o exception: Return any errors or warnings in this structure.
970 %
971 */
972 static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
973   struct PackageInfo *package_info,ExceptionInfo *exception)
974 {
975   char
976     message[MaxTextExtent];
977
978   struct PackageInfo
979     *clone_info;
980
981   SV
982     *sv;
983
984   (void) FormatLocaleString(message,MaxTextExtent,"%s::package%s%p",
985     PackageName,XS_VERSION,reference);
986   sv=perl_get_sv(message,(TRUE | 0x02));
987   if (sv == (SV *) NULL)
988     {
989       ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
990         message);
991       return(package_info);
992     }
993   if (SvREFCNT(sv) == 0)
994     (void) SvREFCNT_inc(sv);
995   if (SvIOKp(sv) && (clone_info=(struct PackageInfo *) SvIV(sv)))
996     return(clone_info);
997   clone_info=ClonePackageInfo(package_info,exception);
998   sv_setiv(sv,(IV) clone_info);
999   return(clone_info);
1000 }
1001 \f
1002 /*
1003 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1004 %                                                                             %
1005 %                                                                             %
1006 %                                                                             %
1007 %   S e t A t t r i b u t e                                                   %
1008 %                                                                             %
1009 %                                                                             %
1010 %                                                                             %
1011 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1012 %
1013 %  SetAttribute() sets the attribute to the value in sval.  This can change
1014 %  either or both of image or info.
1015 %
1016 %  The format of the SetAttribute routine is:
1017 %
1018 %      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1019 %        SV *sval,ExceptionInfo *exception)
1020 %
1021 %  A description of each parameter follows:
1022 %
1023 %    o list: a list of strings.
1024 %
1025 %    o string: a character string.
1026 %
1027 */
1028
1029 static double SiPrefixToDouble(const char *string,const double interval)
1030 {
1031   char
1032     *q;
1033
1034   double
1035     scale,
1036     value;
1037
1038   value=InterpretLocaleValue(string,&q);
1039   scale=1000.0;
1040   if ((*q != '\0') && (tolower((int) ((unsigned char) *(q+1))) == 'i'))
1041     scale=1024.0;
1042   switch (tolower((int) ((unsigned char) *q)))
1043   {
1044     case '%': value*=pow(scale,0)*interval/100.0; break;
1045     case 'k': value*=pow(scale,1); break;
1046     case 'm': value*=pow(scale,2); break;
1047     case 'g': value*=pow(scale,3); break;
1048     case 't': value*=pow(scale,4); break;
1049     case 'p': value*=pow(scale,5); break;
1050     case 'e': value*=pow(scale,6); break;
1051     case 'z': value*=pow(scale,7); break;
1052     case 'y': value*=pow(scale,8); break;
1053     default:  break;
1054   }
1055   return(value);
1056 }
1057
1058 static inline ssize_t StringToLong(const char *value)
1059 {
1060   return(strtol(value,(char **) NULL,10));
1061 }
1062
1063 static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1064   const char *attribute,SV *sval,ExceptionInfo *exception)
1065 {
1066   GeometryInfo
1067     geometry_info;
1068
1069   long
1070     x,
1071     y;
1072
1073   PixelInfo
1074     pixel;
1075
1076   MagickStatusType
1077     flags;
1078
1079   PixelPacket
1080     *color,
1081     target_color;
1082
1083   ssize_t
1084     sp;
1085
1086   switch (*attribute)
1087   {
1088     case 'A':
1089     case 'a':
1090     {
1091       if (LocaleCompare(attribute,"adjoin") == 0)
1092         {
1093           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1094             SvPV(sval,na)) : SvIV(sval);
1095           if (sp < 0)
1096             {
1097               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1098                 SvPV(sval,na));
1099               break;
1100             }
1101           if (info)
1102             info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1103           break;
1104         }
1105       if (LocaleCompare(attribute,"alpha") == 0)
1106         {
1107           sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaOptions,MagickFalse,
1108             SvPV(sval,na)) : SvIV(sval);
1109           if (sp < 0)
1110             {
1111               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1112                 SvPV(sval,na));
1113               break;
1114             }
1115           for ( ; image; image=image->next)
1116             (void) SetImageAlphaChannel(image,(AlphaChannelType) sp,exception);
1117           break;
1118         }
1119       if (LocaleCompare(attribute,"antialias") == 0)
1120         {
1121           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1122             SvPV(sval,na)) : SvIV(sval);
1123           if (sp < 0)
1124             {
1125               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1126                 SvPV(sval,na));
1127               break;
1128             }
1129           if (info)
1130             info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1131           break;
1132         }
1133       if (LocaleCompare(attribute,"area-limit") == 0)
1134         {
1135           MagickSizeType
1136             limit;
1137
1138           limit=MagickResourceInfinity;
1139           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1140             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1141           (void) SetMagickResourceLimit(AreaResource,limit);
1142           break;
1143         }
1144       if (LocaleCompare(attribute,"attenuate") == 0)
1145         {
1146           if (info)
1147             (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1148           break;
1149         }
1150       if (LocaleCompare(attribute,"authenticate") == 0)
1151         {
1152           if (info)
1153             (void) CloneString(&info->image_info->authenticate,SvPV(sval,na));
1154           break;
1155         }
1156       if (info)
1157         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1158       for ( ; image; image=image->next)
1159         SetImageProperty(image,attribute,SvPV(sval,na));
1160       break;
1161     }
1162     case 'B':
1163     case 'b':
1164     {
1165       if (LocaleCompare(attribute,"background") == 0)
1166         {
1167           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1168             exception);
1169           if (info)
1170             info->image_info->background_color=target_color;
1171           for ( ; image; image=image->next)
1172             image->background_color=target_color;
1173           break;
1174         }
1175       if (LocaleCompare(attribute,"bias") == 0)
1176         {
1177           for ( ; image; image=image->next)
1178             image->bias=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1179           break;
1180         }
1181       if (LocaleCompare(attribute,"blue-primary") == 0)
1182         {
1183           for ( ; image; image=image->next)
1184           {
1185             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1186             image->chromaticity.blue_primary.x=geometry_info.rho;
1187             image->chromaticity.blue_primary.y=geometry_info.sigma;
1188             if ((flags & SigmaValue) == 0)
1189               image->chromaticity.blue_primary.y=
1190                 image->chromaticity.blue_primary.x;
1191           }
1192           break;
1193         }
1194       if (LocaleCompare(attribute,"bordercolor") == 0)
1195         {
1196           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1197             exception);
1198           if (info)
1199             info->image_info->border_color=target_color;
1200           for ( ; image; image=image->next)
1201             image->border_color=target_color;
1202           break;
1203         }
1204       if (info)
1205         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1206       for ( ; image; image=image->next)
1207         SetImageProperty(image,attribute,SvPV(sval,na));
1208       break;
1209     }
1210     case 'C':
1211     case 'c':
1212     {
1213       if (LocaleCompare(attribute,"cache-threshold") == 0)
1214         {
1215           (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1216             SiPrefixToDouble(SvPV(sval,na),100.0));
1217           (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1218             (2*SiPrefixToDouble(SvPV(sval,na),100.0)));
1219           break;
1220         }
1221       if (LocaleCompare(attribute,"clip-mask") == 0)
1222         {
1223           Image
1224             *clip_mask;
1225
1226           clip_mask=(Image *) NULL;
1227           if (SvPOK(sval))
1228             clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1229           for ( ; image; image=image->next)
1230             SetImageClipMask(image,clip_mask,exception);
1231           break;
1232         }
1233       if (LocaleNCompare(attribute,"colormap",8) == 0)
1234         {
1235           for ( ; image; image=image->next)
1236           {
1237             int
1238               items;
1239
1240             long
1241               i;
1242
1243             if (image->storage_class == DirectClass)
1244               continue;
1245             i=0;
1246             items=sscanf(attribute,"%*[^[][%ld",&i);
1247             (void) items;
1248             if (i > (ssize_t) image->colors)
1249               i%=image->colors;
1250             if ((strchr(SvPV(sval,na),',') == 0) ||
1251                 (strchr(SvPV(sval,na),')') != 0))
1252               QueryColorCompliance(SvPV(sval,na),AllCompliance,
1253                 image->colormap+i,exception);
1254             else
1255               {
1256                 color=image->colormap+i;
1257                 pixel.red=color->red;
1258                 pixel.green=color->green;
1259                 pixel.blue=color->blue;
1260                 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1261                 pixel.red=geometry_info.rho;
1262                 pixel.green=geometry_info.sigma;
1263                 pixel.blue=geometry_info.xi;
1264                 color->red=ClampToQuantum(pixel.red);
1265                 color->green=ClampToQuantum(pixel.green);
1266                 color->blue=ClampToQuantum(pixel.blue);
1267               }
1268           }
1269           break;
1270         }
1271       if (LocaleCompare(attribute,"colorspace") == 0)
1272         {
1273           sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1274             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1275           if (sp < 0)
1276             {
1277               ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1278                 SvPV(sval,na));
1279               break;
1280             }
1281           for ( ; image; image=image->next)
1282             (void) TransformImageColorspace(image,(ColorspaceType) sp);
1283           break;
1284         }
1285       if (LocaleCompare(attribute,"comment") == 0)
1286         {
1287           for ( ; image; image=image->next)
1288             (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1289               info ? info->image_info : (ImageInfo *) NULL,image,
1290               SvPV(sval,na),exception));
1291           break;
1292         }
1293       if (LocaleCompare(attribute,"compression") == 0)
1294         {
1295           sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1296             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1297           if (sp < 0)
1298             {
1299               ThrowPerlException(exception,OptionError,
1300                 "UnrecognizedImageCompression",SvPV(sval,na));
1301               break;
1302             }
1303           if (info)
1304             info->image_info->compression=(CompressionType) sp;
1305           for ( ; image; image=image->next)
1306             image->compression=(CompressionType) sp;
1307           break;
1308         }
1309       if (info)
1310         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1311       for ( ; image; image=image->next)
1312         SetImageProperty(image,attribute,SvPV(sval,na));
1313       break;
1314     }
1315     case 'D':
1316     case 'd':
1317     {
1318       if (LocaleCompare(attribute,"debug") == 0)
1319         {
1320           SetLogEventMask(SvPV(sval,na));
1321           break;
1322         }
1323       if (LocaleCompare(attribute,"delay") == 0)
1324         {
1325           flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1326           for ( ; image; image=image->next)
1327           {
1328             image->delay=(size_t) floor(geometry_info.rho+0.5);
1329             if ((flags & SigmaValue) != 0)
1330               image->ticks_per_second=(ssize_t)
1331                 floor(geometry_info.sigma+0.5);
1332           }
1333           break;
1334         }
1335       if (LocaleCompare(attribute,"disk-limit") == 0)
1336         {
1337           MagickSizeType
1338             limit;
1339
1340           limit=MagickResourceInfinity;
1341           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1342             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1343           (void) SetMagickResourceLimit(DiskResource,limit);
1344           break;
1345         }
1346       if (LocaleCompare(attribute,"density") == 0)
1347         {
1348           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1349             {
1350               ThrowPerlException(exception,OptionError,"MissingGeometry",
1351                 SvPV(sval,na));
1352               break;
1353             }
1354           if (info)
1355             (void) CloneString(&info->image_info->density,SvPV(sval,na));
1356           for ( ; image; image=image->next)
1357           {
1358             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1359             image->x_resolution=geometry_info.rho;
1360             image->y_resolution=geometry_info.sigma;
1361             if ((flags & SigmaValue) == 0)
1362               image->y_resolution=image->x_resolution;
1363           }
1364           break;
1365         }
1366       if (LocaleCompare(attribute,"depth") == 0)
1367         {
1368           if (info)
1369             info->image_info->depth=SvIV(sval);
1370           for ( ; image; image=image->next)
1371             (void) SetImageDepth(image,SvIV(sval));
1372           break;
1373         }
1374       if (LocaleCompare(attribute,"dispose") == 0)
1375         {
1376           sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1377             SvPV(sval,na)) : SvIV(sval);
1378           if (sp < 0)
1379             {
1380               ThrowPerlException(exception,OptionError,
1381                 "UnrecognizedDisposeMethod",SvPV(sval,na));
1382               break;
1383             }
1384           for ( ; image; image=image->next)
1385             image->dispose=(DisposeType) sp;
1386           break;
1387         }
1388       if (LocaleCompare(attribute,"dither") == 0)
1389         {
1390           if (info)
1391             {
1392               sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1393                 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1394               if (sp < 0)
1395                 {
1396                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
1397                     SvPV(sval,na));
1398                   break;
1399                 }
1400               info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1401             }
1402           break;
1403         }
1404       if (LocaleCompare(attribute,"display") == 0)
1405         {
1406           display:
1407           if (info)
1408             (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1409           break;
1410         }
1411       if (info)
1412         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1413       for ( ; image; image=image->next)
1414         SetImageProperty(image,attribute,SvPV(sval,na));
1415       break;
1416     }
1417     case 'E':
1418     case 'e':
1419     {
1420       if (LocaleCompare(attribute,"endian") == 0)
1421         {
1422           sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1423             SvPV(sval,na)) : SvIV(sval);
1424           if (sp < 0)
1425             {
1426               ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1427                 SvPV(sval,na));
1428               break;
1429             }
1430           if (info)
1431             info->image_info->endian=(EndianType) sp;
1432           for ( ; image; image=image->next)
1433             image->endian=(EndianType) sp;
1434           break;
1435         }
1436       if (LocaleCompare(attribute,"extract") == 0)
1437         {
1438           /*
1439             Set image extract geometry.
1440           */
1441           (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1442           break;
1443         }
1444       if (info)
1445         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1446       for ( ; image; image=image->next)
1447         SetImageProperty(image,attribute,SvPV(sval,na));
1448       break;
1449     }
1450     case 'F':
1451     case 'f':
1452     {
1453       if (LocaleCompare(attribute,"filename") == 0)
1454         {
1455           if (info)
1456             (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1457               MaxTextExtent);
1458           for ( ; image; image=image->next)
1459             (void) CopyMagickString(image->filename,SvPV(sval,na),
1460               MaxTextExtent);
1461           break;
1462         }
1463       if (LocaleCompare(attribute,"file") == 0)
1464         {
1465           FILE
1466             *file;
1467
1468           PerlIO
1469             *io_info;
1470
1471           if (info == (struct PackageInfo *) NULL)
1472             break;
1473           io_info=IoIFP(sv_2io(sval));
1474           if (io_info == (PerlIO *) NULL)
1475             {
1476               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1477                 PackageName);
1478               break;
1479             }
1480           file=PerlIO_findFILE(io_info);
1481           if (file == (FILE *) NULL)
1482             {
1483               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1484                 PackageName);
1485               break;
1486             }
1487           SetImageInfoFile(info->image_info,file);
1488           break;
1489         }
1490       if (LocaleCompare(attribute,"fill") == 0)
1491         {
1492           if (info)
1493             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1494           break;
1495         }
1496       if (LocaleCompare(attribute,"font") == 0)
1497         {
1498           if (info)
1499             (void) CloneString(&info->image_info->font,SvPV(sval,na));
1500           break;
1501         }
1502       if (LocaleCompare(attribute,"foreground") == 0)
1503         break;
1504       if (LocaleCompare(attribute,"fuzz") == 0)
1505         {
1506           if (info)
1507             info->image_info->fuzz=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1508           for ( ; image; image=image->next)
1509             image->fuzz=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1510           break;
1511         }
1512       if (info)
1513         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1514       for ( ; image; image=image->next)
1515         SetImageProperty(image,attribute,SvPV(sval,na));
1516       break;
1517     }
1518     case 'G':
1519     case 'g':
1520     {
1521       if (LocaleCompare(attribute,"gamma") == 0)
1522         {
1523           for ( ; image; image=image->next)
1524             image->gamma=SvNV(sval);
1525           break;
1526         }
1527       if (LocaleCompare(attribute,"gravity") == 0)
1528         {
1529           sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1530             SvPV(sval,na)) : SvIV(sval);
1531           if (sp < 0)
1532             {
1533               ThrowPerlException(exception,OptionError,
1534                 "UnrecognizedGravityType",SvPV(sval,na));
1535               break;
1536             }
1537           if (info)
1538             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1539           for ( ; image; image=image->next)
1540             image->gravity=(GravityType) sp;
1541           break;
1542         }
1543       if (LocaleCompare(attribute,"green-primary") == 0)
1544         {
1545           for ( ; image; image=image->next)
1546           {
1547             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1548             image->chromaticity.green_primary.x=geometry_info.rho;
1549             image->chromaticity.green_primary.y=geometry_info.sigma;
1550             if ((flags & SigmaValue) == 0)
1551               image->chromaticity.green_primary.y=
1552                 image->chromaticity.green_primary.x;
1553           }
1554           break;
1555         }
1556       if (info)
1557         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1558       for ( ; image; image=image->next)
1559         SetImageProperty(image,attribute,SvPV(sval,na));
1560       break;
1561     }
1562     case 'I':
1563     case 'i':
1564     {
1565       if (LocaleNCompare(attribute,"index",5) == 0)
1566         {
1567           int
1568             items;
1569
1570           long
1571             index;
1572
1573           register Quantum
1574             *q;
1575
1576           CacheView
1577             *image_view;
1578
1579           for ( ; image; image=image->next)
1580           {
1581             if (image->storage_class != PseudoClass)
1582               continue;
1583             x=0;
1584             y=0;
1585             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1586             (void) items;
1587             image_view=AcquireCacheView(image);
1588             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1589             if (q != (Quantum *) NULL)
1590               {
1591                 items=sscanf(SvPV(sval,na),"%ld",&index);
1592                 if ((index >= 0) && (index < (ssize_t) image->colors))
1593                   SetPixelIndex(image,index,q);
1594                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1595               }
1596             image_view=DestroyCacheView(image_view);
1597           }
1598           break;
1599         }
1600       if (LocaleCompare(attribute,"iterations") == 0)
1601         {
1602   iterations:
1603           for ( ; image; image=image->next)
1604             image->iterations=SvIV(sval);
1605           break;
1606         }
1607       if (LocaleCompare(attribute,"interlace") == 0)
1608         {
1609           sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1610             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1611           if (sp < 0)
1612             {
1613               ThrowPerlException(exception,OptionError,
1614                 "UnrecognizedInterlaceType",SvPV(sval,na));
1615               break;
1616             }
1617           if (info)
1618             info->image_info->interlace=(InterlaceType) sp;
1619           for ( ; image; image=image->next)
1620             image->interlace=(InterlaceType) sp;
1621           break;
1622         }
1623       if (info)
1624         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1625       for ( ; image; image=image->next)
1626         SetImageProperty(image,attribute,SvPV(sval,na));
1627       break;
1628     }
1629     case 'L':
1630     case 'l':
1631     {
1632       if (LocaleCompare(attribute,"label") == 0)
1633         {
1634           for ( ; image; image=image->next)
1635             (void) SetImageProperty(image,"label",InterpretImageProperties(
1636               info ? info->image_info : (ImageInfo *) NULL,image,
1637               SvPV(sval,na),exception));
1638           break;
1639         }
1640       if (LocaleCompare(attribute,"loop") == 0)
1641         goto iterations;
1642       if (info)
1643         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1644       for ( ; image; image=image->next)
1645         SetImageProperty(image,attribute,SvPV(sval,na));
1646       break;
1647     }
1648     case 'M':
1649     case 'm':
1650     {
1651       if (LocaleCompare(attribute,"magick") == 0)
1652         {
1653           if (info)
1654             (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
1655               "%s:",SvPV(sval,na));
1656           for ( ; image; image=image->next)
1657             (void) CopyMagickString(image->magick,SvPV(sval,na),MaxTextExtent);
1658           break;
1659         }
1660       if (LocaleCompare(attribute,"map-limit") == 0)
1661         {
1662           MagickSizeType
1663             limit;
1664
1665           limit=MagickResourceInfinity;
1666           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1667             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1668           (void) SetMagickResourceLimit(MapResource,limit);
1669           break;
1670         }
1671       if (LocaleCompare(attribute,"mask") == 0)
1672         {
1673           Image
1674             *mask;
1675
1676           mask=(Image *) NULL;
1677           if (SvPOK(sval))
1678             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1679           for ( ; image; image=image->next)
1680             SetImageMask(image,mask,exception);
1681           break;
1682         }
1683       if (LocaleCompare(attribute,"mattecolor") == 0)
1684         {
1685           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1686             exception);
1687           if (info)
1688             info->image_info->matte_color=target_color;
1689           for ( ; image; image=image->next)
1690             image->matte_color=target_color;
1691           break;
1692         }
1693       if (LocaleCompare(attribute,"matte") == 0)
1694         {
1695           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1696             SvPV(sval,na)) : SvIV(sval);
1697           if (sp < 0)
1698             {
1699               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1700                 SvPV(sval,na));
1701               break;
1702             }
1703           for ( ; image; image=image->next)
1704             image->matte=sp != 0 ? MagickTrue : MagickFalse;
1705           break;
1706         }
1707       if (LocaleCompare(attribute,"memory-limit") == 0)
1708         {
1709           MagickSizeType
1710             limit;
1711
1712           limit=MagickResourceInfinity;
1713           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1714             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1715           (void) SetMagickResourceLimit(MemoryResource,limit);
1716           break;
1717         }
1718       if (LocaleCompare(attribute,"monochrome") == 0)
1719         {
1720           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1721             SvPV(sval,na)) : SvIV(sval);
1722           if (sp < 0)
1723             {
1724               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1725                 SvPV(sval,na));
1726               break;
1727             }
1728           if (info)
1729             info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1730           for ( ; image; image=image->next)
1731             (void) SetImageType(image,BilevelType,exception);
1732           break;
1733         }
1734       if (info)
1735         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1736       for ( ; image; image=image->next)
1737         SetImageProperty(image,attribute,SvPV(sval,na));
1738       break;
1739     }
1740     case 'O':
1741     case 'o':
1742     {
1743       if (LocaleCompare(attribute,"option") == 0)
1744         {
1745           if (info)
1746             DefineImageOption(info->image_info,SvPV(sval,na));
1747           break;
1748         }
1749       if (LocaleCompare(attribute,"orientation") == 0)
1750         {
1751           sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1752             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1753           if (sp < 0)
1754             {
1755               ThrowPerlException(exception,OptionError,
1756                 "UnrecognizedOrientationType",SvPV(sval,na));
1757               break;
1758             }
1759           if (info)
1760             info->image_info->orientation=(OrientationType) sp;
1761           for ( ; image; image=image->next)
1762             image->orientation=(OrientationType) sp;
1763           break;
1764         }
1765       if (info)
1766         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1767       for ( ; image; image=image->next)
1768         SetImageProperty(image,attribute,SvPV(sval,na));
1769       break;
1770     }
1771     case 'P':
1772     case 'p':
1773     {
1774       if (LocaleCompare(attribute,"page") == 0)
1775         {
1776           char
1777             *geometry;
1778
1779           geometry=GetPageGeometry(SvPV(sval,na));
1780           if (info)
1781             (void) CloneString(&info->image_info->page,geometry);
1782           for ( ; image; image=image->next)
1783             (void) ParsePageGeometry(image,geometry,&image->page,exception);
1784           geometry=(char *) RelinquishMagickMemory(geometry);
1785           break;
1786         }
1787       if (LocaleCompare(attribute,"pen") == 0)
1788         {
1789           if (info)
1790             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1791           break;
1792         }
1793       if (LocaleNCompare(attribute,"pixel",5) == 0)
1794         {
1795           int
1796             items;
1797
1798           PixelInfo
1799             pixel;
1800
1801           register Quantum
1802             *q;
1803
1804           CacheView
1805             *image_view;
1806
1807           for ( ; image; image=image->next)
1808           {
1809             if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1810               break;
1811             x=0;
1812             y=0;
1813             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1814             (void) items;
1815             image_view=AcquireCacheView(image);
1816             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1817             if (q != (Quantum *) NULL)
1818               {
1819                 if ((strchr(SvPV(sval,na),',') == 0) ||
1820                     (strchr(SvPV(sval,na),')') != 0))
1821                   QueryMagickColorCompliance(SvPV(sval,na),AllCompliance,
1822                     &pixel,exception);
1823                 else
1824                   {
1825                     GetPixelInfo(image,&pixel);
1826                     flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1827                     pixel.red=geometry_info.rho;
1828                     if ((flags & SigmaValue) != 0)
1829                       pixel.green=geometry_info.sigma;
1830                     if ((flags & XiValue) != 0)
1831                       pixel.blue=geometry_info.xi;
1832                     if ((flags & PsiValue) != 0)
1833                       pixel.alpha=geometry_info.psi;
1834                     if ((flags & ChiValue) != 0)
1835                       pixel.black=geometry_info.chi;
1836                   }
1837                 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1838                 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1839                 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1840                 if (image->colorspace == CMYKColorspace)
1841                   SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1842                 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1843                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1844               }
1845             image_view=DestroyCacheView(image_view);
1846           }
1847           break;
1848         }
1849       if (LocaleCompare(attribute,"pointsize") == 0)
1850         {
1851           if (info)
1852             {
1853               (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1854               info->image_info->pointsize=geometry_info.rho;
1855             }
1856           break;
1857         }
1858       if (LocaleCompare(attribute,"preview") == 0)
1859         {
1860           sp=SvPOK(sval) ? ParseCommandOption(MagickPreviewOptions,MagickFalse,
1861             SvPV(sval,na)) : SvIV(sval);
1862           if (sp < 0)
1863             {
1864               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1865                 SvPV(sval,na));
1866               break;
1867             }
1868           if (info)
1869             info->image_info->preview_type=(PreviewType) sp;
1870           break;
1871         }
1872       if (info)
1873         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1874       for ( ; image; image=image->next)
1875         SetImageProperty(image,attribute,SvPV(sval,na));
1876       break;
1877     }
1878     case 'Q':
1879     case 'q':
1880     {
1881       if (LocaleCompare(attribute,"quality") == 0)
1882         {
1883           if (info)
1884             info->image_info->quality=SvIV(sval);
1885           for ( ; image; image=image->next)
1886             image->quality=SvIV(sval);
1887           break;
1888         }
1889       if (info)
1890         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1891       for ( ; image; image=image->next)
1892         SetImageProperty(image,attribute,SvPV(sval,na));
1893       break;
1894     }
1895     case 'R':
1896     case 'r':
1897     {
1898       if (LocaleCompare(attribute,"red-primary") == 0)
1899         {
1900           for ( ; image; image=image->next)
1901           {
1902             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1903             image->chromaticity.red_primary.x=geometry_info.rho;
1904             image->chromaticity.red_primary.y=geometry_info.sigma;
1905             if ((flags & SigmaValue) == 0)
1906               image->chromaticity.red_primary.y=
1907                 image->chromaticity.red_primary.x;
1908           }
1909           break;
1910         }
1911       if (LocaleCompare(attribute,"render") == 0)
1912         {
1913           sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1914             SvPV(sval,na)) : SvIV(sval);
1915           if (sp < 0)
1916             {
1917               ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1918                 SvPV(sval,na));
1919               break;
1920             }
1921          for ( ; image; image=image->next)
1922            image->rendering_intent=(RenderingIntent) sp;
1923          break;
1924        }
1925       if (LocaleCompare(attribute,"repage") == 0)
1926         {
1927           RectangleInfo
1928             geometry;
1929
1930           for ( ; image; image=image->next)
1931           {
1932             flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
1933             if ((flags & WidthValue) != 0)
1934               {
1935                 if ((flags & HeightValue) == 0)
1936                   geometry.height=geometry.width;
1937                 image->page.width=geometry.width;
1938                 image->page.height=geometry.height;
1939               }
1940             if ((flags & AspectValue) != 0)
1941               {
1942                 if ((flags & XValue) != 0)
1943                   image->page.x+=geometry.x;
1944                 if ((flags & YValue) != 0)
1945                   image->page.y+=geometry.y;
1946               }
1947             else
1948               {
1949                 if ((flags & XValue) != 0)
1950                   {
1951                     image->page.x=geometry.x;
1952                     if (((flags & WidthValue) != 0) && (geometry.x > 0))
1953                       image->page.width=image->columns+geometry.x;
1954                   }
1955                 if ((flags & YValue) != 0)
1956                   {
1957                     image->page.y=geometry.y;
1958                     if (((flags & HeightValue) != 0) && (geometry.y > 0))
1959                       image->page.height=image->rows+geometry.y;
1960                   }
1961               }
1962           }
1963           break;
1964         }
1965       if (info)
1966         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1967       for ( ; image; image=image->next)
1968         SetImageProperty(image,attribute,SvPV(sval,na));
1969       break;
1970     }
1971     case 'S':
1972     case 's':
1973     {
1974       if (LocaleCompare(attribute,"sampling-factor") == 0)
1975         {
1976           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1977             {
1978               ThrowPerlException(exception,OptionError,"MissingGeometry",
1979                 SvPV(sval,na));
1980               break;
1981             }
1982           if (info)
1983             (void) CloneString(&info->image_info->sampling_factor,
1984               SvPV(sval,na));
1985           break;
1986         }
1987       if (LocaleCompare(attribute,"scene") == 0)
1988         {
1989           for ( ; image; image=image->next)
1990             image->scene=SvIV(sval);
1991           break;
1992         }
1993       if (LocaleCompare(attribute,"server") == 0)
1994         goto display;
1995       if (LocaleCompare(attribute,"size") == 0)
1996         {
1997           if (info)
1998             {
1999               if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2000                 {
2001                   ThrowPerlException(exception,OptionError,"MissingGeometry",
2002                     SvPV(sval,na));
2003                   break;
2004                 }
2005               (void) CloneString(&info->image_info->size,SvPV(sval,na));
2006             }
2007           break;
2008         }
2009       if (LocaleCompare(attribute,"stroke") == 0)
2010         {
2011           if (info)
2012             (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2013           break;
2014         }
2015       if (info)
2016         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2017       for ( ; image; image=image->next)
2018         SetImageProperty(image,attribute,SvPV(sval,na));
2019       break;
2020     }
2021     case 'T':
2022     case 't':
2023     {
2024       if (LocaleCompare(attribute,"texture") == 0)
2025         {
2026           if (info)
2027             (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2028           break;
2029         }
2030       if (LocaleCompare(attribute,"thread-limit") == 0)
2031         {
2032           MagickSizeType
2033             limit;
2034
2035           limit=MagickResourceInfinity;
2036           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2037             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
2038           (void) SetMagickResourceLimit(ThreadResource,limit);
2039           break;
2040         }
2041       if (LocaleCompare(attribute,"tile-offset") == 0)
2042         {
2043           char
2044             *geometry;
2045
2046           geometry=GetPageGeometry(SvPV(sval,na));
2047           if (info)
2048             (void) CloneString(&info->image_info->page,geometry);
2049           for ( ; image; image=image->next)
2050             (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2051               exception);
2052           geometry=(char *) RelinquishMagickMemory(geometry);
2053           break;
2054         }
2055       if (LocaleCompare(attribute,"time-limit") == 0)
2056         {
2057           MagickSizeType
2058             limit;
2059
2060           limit=MagickResourceInfinity;
2061           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2062             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
2063           (void) SetMagickResourceLimit(TimeResource,limit);
2064           break;
2065         }
2066       if (LocaleCompare(attribute,"transparent-color") == 0)
2067         {
2068           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
2069             exception);
2070           if (info)
2071             info->image_info->transparent_color=target_color;
2072           for ( ; image; image=image->next)
2073             image->transparent_color=target_color;
2074           break;
2075         }
2076       if (LocaleCompare(attribute,"type") == 0)
2077         {
2078           sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2079             SvPV(sval,na)) : SvIV(sval);
2080           if (sp < 0)
2081             {
2082               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2083                 SvPV(sval,na));
2084               break;
2085             }
2086           if (info)
2087             info->image_info->type=(ImageType) sp;
2088           for ( ; image; image=image->next)
2089             SetImageType(image,(ImageType) sp,exception);
2090           break;
2091         }
2092       if (info)
2093         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2094       for ( ; image; image=image->next)
2095         SetImageProperty(image,attribute,SvPV(sval,na));
2096       break;
2097     }
2098     case 'U':
2099     case 'u':
2100     {
2101       if (LocaleCompare(attribute,"units") == 0)
2102         {
2103           sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2104             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2105           if (sp < 0)
2106             {
2107               ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2108                 SvPV(sval,na));
2109               break;
2110             }
2111           if (info)
2112             info->image_info->units=(ResolutionType) sp;
2113           for ( ; image; image=image->next)
2114           {
2115             ResolutionType
2116               units;
2117
2118             units=(ResolutionType) sp;
2119             if (image->units != units)
2120               switch (image->units)
2121               {
2122                 case UndefinedResolution:
2123                 case PixelsPerInchResolution:
2124                 {
2125                   if (units == PixelsPerCentimeterResolution)
2126                     {
2127                       image->x_resolution*=2.54;
2128                       image->y_resolution*=2.54;
2129                     }
2130                   break;
2131                 }
2132                 case PixelsPerCentimeterResolution:
2133                 {
2134                   if (units == PixelsPerInchResolution)
2135                     {
2136                       image->x_resolution/=2.54;
2137                       image->y_resolution/=2.54;
2138                     }
2139                   break;
2140                 }
2141               }
2142             image->units=units;
2143           }
2144           break;
2145         }
2146       if (info)
2147         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2148       for ( ; image; image=image->next)
2149         SetImageProperty(image,attribute,SvPV(sval,na));
2150       break;
2151     }
2152     case 'V':
2153     case 'v':
2154     {
2155       if (LocaleCompare(attribute,"verbose") == 0)
2156         {
2157           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2158             SvPV(sval,na)) : SvIV(sval);
2159           if (sp < 0)
2160             {
2161               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2162                 SvPV(sval,na));
2163               break;
2164             }
2165           if (info)
2166             info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2167           break;
2168         }
2169       if (LocaleCompare(attribute,"view") == 0)
2170         {
2171           if (info)
2172             (void) CloneString(&info->image_info->view,SvPV(sval,na));
2173           break;
2174         }
2175       if (LocaleCompare(attribute,"virtual-pixel") == 0)
2176         {
2177           sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2178             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2179           if (sp < 0)
2180             {
2181               ThrowPerlException(exception,OptionError,
2182                 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2183               break;
2184             }
2185           if (info)
2186             info->image_info->virtual_pixel_method=(VirtualPixelMethod) sp;
2187           for ( ; image; image=image->next)
2188             SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp);
2189           break;
2190         }
2191       if (info)
2192         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2193       for ( ; image; image=image->next)
2194         SetImageProperty(image,attribute,SvPV(sval,na));
2195       break;
2196     }
2197     case 'W':
2198     case 'w':
2199     {
2200       if (LocaleCompare(attribute,"white-point") == 0)
2201         {
2202           for ( ; image; image=image->next)
2203           {
2204             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2205             image->chromaticity.white_point.x=geometry_info.rho;
2206             image->chromaticity.white_point.y=geometry_info.sigma;
2207             if ((flags & SigmaValue) == 0)
2208               image->chromaticity.white_point.y=
2209                 image->chromaticity.white_point.x;
2210           }
2211           break;
2212         }
2213       if (info)
2214         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2215       for ( ; image; image=image->next)
2216         SetImageProperty(image,attribute,SvPV(sval,na));
2217       break;
2218     }
2219     default:
2220     {
2221       if (info)
2222         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2223       for ( ; image; image=image->next)
2224         SetImageProperty(image,attribute,SvPV(sval,na));
2225       break;
2226     }
2227   }
2228 }
2229 \f
2230 /*
2231 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2232 %                                                                             %
2233 %                                                                             %
2234 %                                                                             %
2235 %   S e t u p L i s t                                                         %
2236 %                                                                             %
2237 %                                                                             %
2238 %                                                                             %
2239 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2240 %
2241 %  Method SetupList returns the list of all the images linked by their
2242 %  image->next and image->previous link lists for use with ImageMagick.  If
2243 %  info is non-NULL, an info structure is returned in *info.  If
2244 %  reference_vector is non-NULL,an array of SV* are returned in
2245 %  *reference_vector.  Reference_vector is used when the images are going to be
2246 %  replaced with new Image*'s.
2247 %
2248 %  The format of the SetupList routine is:
2249 %
2250 %      Image *SetupList(SV *reference,struct PackageInfo **info,
2251 %        SV ***reference_vector,ExceptionInfo *exception)
2252 %
2253 %  A description of each parameter follows:
2254 %
2255 %    o list: a list of strings.
2256 %
2257 %    o string: a character string.
2258 %
2259 %    o exception: Return any errors or warnings in this structure.
2260 %
2261 */
2262 static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2263   SV ***reference_vector,ExceptionInfo *exception)
2264 {
2265   Image
2266     *image;
2267
2268   ssize_t
2269     current,
2270     last;
2271
2272   if (reference_vector)
2273     *reference_vector=NULL;
2274   if (info)
2275     *info=NULL;
2276   current=0;
2277   last=0;
2278   image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2279   if (info && (SvTYPE(reference) == SVt_PVAV))
2280     *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2281       exception);
2282   return(image);
2283 }
2284 \f
2285 /*
2286 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2287 %                                                                             %
2288 %                                                                             %
2289 %                                                                             %
2290 %   s t r E Q c a s e                                                         %
2291 %                                                                             %
2292 %                                                                             %
2293 %                                                                             %
2294 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2295 %
2296 %  strEQcase() compares two strings and returns 0 if they are the
2297 %  same or if the second string runs out first.  The comparison is case
2298 %  insensitive.
2299 %
2300 %  The format of the strEQcase routine is:
2301 %
2302 %      ssize_t strEQcase(const char *p,const char *q)
2303 %
2304 %  A description of each parameter follows:
2305 %
2306 %    o p: a character string.
2307 %
2308 %    o q: a character string.
2309 %
2310 %
2311 */
2312 static ssize_t strEQcase(const char *p,const char *q)
2313 {
2314   char
2315     c;
2316
2317   register ssize_t
2318     i;
2319
2320   for (i=0 ; (c=(*q)) != 0; i++)
2321   {
2322     if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2323         (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2324       return(0);
2325     p++;
2326     q++;
2327   }
2328   return(((*q == 0) && (*p == 0)) ? i : 0);
2329 }
2330 \f
2331 /*
2332 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2333 %                                                                             %
2334 %                                                                             %
2335 %                                                                             %
2336 %   I m a g e : : M a g i c k                                                 %
2337 %                                                                             %
2338 %                                                                             %
2339 %                                                                             %
2340 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2341 %
2342 %
2343 */
2344 MODULE = Image::Magick PACKAGE = Image::Magick
2345
2346 PROTOTYPES: ENABLE
2347
2348 BOOT:
2349   MagickCoreGenesis("PerlMagick",MagickFalse);
2350   SetWarningHandler(NULL);
2351   SetErrorHandler(NULL);
2352   magick_registry=NewSplayTree((int (*)(const void *,const void *))
2353     NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2354
2355 void
2356 UNLOAD()
2357   PPCODE:
2358   {
2359     if (magick_registry != (SplayTreeInfo *) NULL)
2360       magick_registry=DestroySplayTree(magick_registry);
2361     MagickCoreTerminus();
2362   }
2363
2364 double
2365 constant(name,argument)
2366   char *name
2367   ssize_t argument
2368 \f
2369 #
2370 ###############################################################################
2371 #                                                                             #
2372 #                                                                             #
2373 #                                                                             #
2374 #   A n i m a t e                                                             #
2375 #                                                                             #
2376 #                                                                             #
2377 #                                                                             #
2378 ###############################################################################
2379 #
2380 #
2381 void
2382 Animate(ref,...)
2383   Image::Magick ref=NO_INIT
2384   ALIAS:
2385     AnimateImage  = 1
2386     animate       = 2
2387     animateimage  = 3
2388   PPCODE:
2389   {
2390     ExceptionInfo
2391       *exception;
2392
2393     Image
2394       *image;
2395
2396     register ssize_t
2397       i;
2398
2399     struct PackageInfo
2400       *info,
2401       *package_info;
2402
2403     SV
2404       *perl_exception,
2405       *reference;
2406
2407     PERL_UNUSED_VAR(ref);
2408     PERL_UNUSED_VAR(ix);
2409     exception=AcquireExceptionInfo();
2410     perl_exception=newSVpv("",0);
2411     package_info=(struct PackageInfo *) NULL;
2412     if (sv_isobject(ST(0)) == 0)
2413       {
2414         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2415           PackageName);
2416         goto PerlException;
2417       }
2418     reference=SvRV(ST(0));
2419     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2420     if (image == (Image *) NULL)
2421       {
2422         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2423           PackageName);
2424         goto PerlException;
2425       }
2426     package_info=ClonePackageInfo(info,exception);
2427     if (items == 2)
2428       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2429     else
2430       if (items > 2)
2431         for (i=2; i < items; i+=2)
2432           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2433             exception);
2434     (void) AnimateImages(package_info->image_info,image,exception);
2435     (void) CatchImageException(image);
2436
2437   PerlException:
2438     if (package_info != (struct PackageInfo *) NULL)
2439       DestroyPackageInfo(package_info);
2440     InheritPerlException(exception,perl_exception);
2441     exception=DestroyExceptionInfo(exception);
2442     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2443     SvPOK_on(perl_exception);
2444     ST(0)=sv_2mortal(perl_exception);
2445     XSRETURN(1);
2446   }
2447 \f
2448 #
2449 ###############################################################################
2450 #                                                                             #
2451 #                                                                             #
2452 #                                                                             #
2453 #   A p p e n d                                                               #
2454 #                                                                             #
2455 #                                                                             #
2456 #                                                                             #
2457 ###############################################################################
2458 #
2459 #
2460 void
2461 Append(ref,...)
2462   Image::Magick ref=NO_INIT
2463   ALIAS:
2464     AppendImage  = 1
2465     append       = 2
2466     appendimage  = 3
2467   PPCODE:
2468   {
2469     AV
2470       *av;
2471
2472     char
2473       *attribute;
2474
2475     ExceptionInfo
2476       *exception;
2477
2478     HV
2479       *hv;
2480
2481     Image
2482       *image;
2483
2484     register ssize_t
2485       i;
2486
2487     ssize_t
2488       stack;
2489
2490     struct PackageInfo
2491       *info;
2492
2493     SV
2494       *av_reference,
2495       *perl_exception,
2496       *reference,
2497       *rv,
2498       *sv;
2499
2500     PERL_UNUSED_VAR(ref);
2501     PERL_UNUSED_VAR(ix);
2502     exception=AcquireExceptionInfo();
2503     perl_exception=newSVpv("",0);
2504     sv=NULL;
2505     attribute=NULL;
2506     av=NULL;
2507     if (sv_isobject(ST(0)) == 0)
2508       {
2509         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2510           PackageName);
2511         goto PerlException;
2512       }
2513     reference=SvRV(ST(0));
2514     hv=SvSTASH(reference);
2515     av=newAV();
2516     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2517     SvREFCNT_dec(av);
2518     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2519     if (image == (Image *) NULL)
2520       {
2521         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2522           PackageName);
2523         goto PerlException;
2524       }
2525     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2526     /*
2527       Get options.
2528     */
2529     stack=MagickTrue;
2530     for (i=2; i < items; i+=2)
2531     {
2532       attribute=(char *) SvPV(ST(i-1),na);
2533       switch (*attribute)
2534       {
2535         case 'S':
2536         case 's':
2537         {
2538           if (LocaleCompare(attribute,"stack") == 0)
2539             {
2540               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2541                 SvPV(ST(i),na));
2542               if (stack < 0)
2543                 {
2544                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
2545                     SvPV(ST(i),na));
2546                   return;
2547                 }
2548               break;
2549             }
2550           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2551             attribute);
2552           break;
2553         }
2554         default:
2555         {
2556           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2557             attribute);
2558           break;
2559         }
2560       }
2561     }
2562     image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2563     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2564       goto PerlException;
2565     for ( ; image; image=image->next)
2566     {
2567       AddImageToRegistry(sv,image);
2568       rv=newRV(sv);
2569       av_push(av,sv_bless(rv,hv));
2570       SvREFCNT_dec(sv);
2571     }
2572     exception=DestroyExceptionInfo(exception);
2573     ST(0)=av_reference;
2574     SvREFCNT_dec(perl_exception);
2575     XSRETURN(1);
2576
2577   PerlException:
2578     InheritPerlException(exception,perl_exception);
2579     exception=DestroyExceptionInfo(exception);
2580     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2581     SvPOK_on(perl_exception);
2582     ST(0)=sv_2mortal(perl_exception);
2583     XSRETURN(1);
2584   }
2585 \f
2586 #
2587 ###############################################################################
2588 #                                                                             #
2589 #                                                                             #
2590 #                                                                             #
2591 #   A v e r a g e                                                             #
2592 #                                                                             #
2593 #                                                                             #
2594 #                                                                             #
2595 ###############################################################################
2596 #
2597 #
2598 void
2599 Average(ref)
2600   Image::Magick ref=NO_INIT
2601   ALIAS:
2602     AverageImage   = 1
2603     average        = 2
2604     averageimage   = 3
2605   PPCODE:
2606   {
2607     AV
2608       *av;
2609
2610     char
2611       *p;
2612
2613     ExceptionInfo
2614       *exception;
2615
2616     HV
2617       *hv;
2618
2619     Image
2620       *image;
2621
2622     struct PackageInfo
2623       *info;
2624
2625     SV
2626       *perl_exception,
2627       *reference,
2628       *rv,
2629       *sv;
2630
2631     PERL_UNUSED_VAR(ref);
2632     PERL_UNUSED_VAR(ix);
2633     exception=AcquireExceptionInfo();
2634     perl_exception=newSVpv("",0);
2635     sv=NULL;
2636     if (sv_isobject(ST(0)) == 0)
2637       {
2638         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2639           PackageName);
2640         goto PerlException;
2641       }
2642     reference=SvRV(ST(0));
2643     hv=SvSTASH(reference);
2644     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2645     if (image == (Image *) NULL)
2646       {
2647         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2648           PackageName);
2649         goto PerlException;
2650       }
2651     image=EvaluateImages(image,MeanEvaluateOperator,exception);
2652     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2653       goto PerlException;
2654     /*
2655       Create blessed Perl array for the returned image.
2656     */
2657     av=newAV();
2658     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2659     SvREFCNT_dec(av);
2660     AddImageToRegistry(sv,image);
2661     rv=newRV(sv);
2662     av_push(av,sv_bless(rv,hv));
2663     SvREFCNT_dec(sv);
2664     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2665     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
2666       "average-%.*s",(int) (MaxTextExtent-9),
2667       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2668     (void) CopyMagickString(image->filename,info->image_info->filename,
2669       MaxTextExtent);
2670     SetImageInfo(info->image_info,0,exception);
2671     exception=DestroyExceptionInfo(exception);
2672     SvREFCNT_dec(perl_exception);
2673     XSRETURN(1);
2674
2675   PerlException:
2676     InheritPerlException(exception,perl_exception);
2677     exception=DestroyExceptionInfo(exception);
2678     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2679     SvPOK_on(perl_exception);
2680     ST(0)=sv_2mortal(perl_exception);
2681     XSRETURN(1);
2682   }
2683 \f
2684 #
2685 ###############################################################################
2686 #                                                                             #
2687 #                                                                             #
2688 #                                                                             #
2689 #   B l o b T o I m a g e                                                     #
2690 #                                                                             #
2691 #                                                                             #
2692 #                                                                             #
2693 ###############################################################################
2694 #
2695 #
2696 void
2697 BlobToImage(ref,...)
2698   Image::Magick ref=NO_INIT
2699   ALIAS:
2700     BlobToImage  = 1
2701     blobtoimage  = 2
2702     blobto       = 3
2703   PPCODE:
2704   {
2705     AV
2706       *av;
2707
2708     char
2709       **keep,
2710       **list;
2711
2712     ExceptionInfo
2713       *exception;
2714
2715     HV
2716       *hv;
2717
2718     Image
2719       *image;
2720
2721     register char
2722       **p;
2723
2724     register ssize_t
2725       i;
2726
2727     ssize_t
2728       ac,
2729       n,
2730       number_images;
2731
2732     STRLEN
2733       *length;
2734
2735     struct PackageInfo
2736       *info;
2737
2738     SV
2739       *perl_exception,
2740       *reference,
2741       *rv,
2742       *sv;
2743
2744     PERL_UNUSED_VAR(ref);
2745     PERL_UNUSED_VAR(ix);
2746     exception=AcquireExceptionInfo();
2747     perl_exception=newSVpv("",0);
2748     sv=NULL;
2749     number_images=0;
2750     ac=(items < 2) ? 1 : items-1;
2751     length=(STRLEN *) NULL;
2752     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2753     if (list == (char **) NULL)
2754       {
2755         ThrowPerlException(exception,ResourceLimitError,
2756           "MemoryAllocationFailed",PackageName);
2757         goto PerlException;
2758       }
2759     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2760     if (length == (STRLEN *) NULL)
2761       {
2762         ThrowPerlException(exception,ResourceLimitError,
2763           "MemoryAllocationFailed",PackageName);
2764         goto PerlException;
2765       }
2766     if (sv_isobject(ST(0)) == 0)
2767       {
2768         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2769           PackageName);
2770         goto PerlException;
2771       }
2772     reference=SvRV(ST(0));
2773     hv=SvSTASH(reference);
2774     if (SvTYPE(reference) != SVt_PVAV)
2775       {
2776         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2777           PackageName);
2778         goto PerlException;
2779       }
2780     av=(AV *) reference;
2781     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2782       exception);
2783     n=1;
2784     if (items <= 1)
2785       {
2786         ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2787         goto PerlException;
2788       }
2789     for (n=0, i=0; i < ac; i++)
2790     {
2791       list[n]=(char *) (SvPV(ST(i+1),length[n]));
2792       if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2793         {
2794           list[n]=(char *) (SvPV(ST(i+2),length[n]));
2795           continue;
2796         }
2797       n++;
2798     }
2799     list[n]=(char *) NULL;
2800     keep=list;
2801     for (i=number_images=0; i < n; i++)
2802     {
2803       image=BlobToImage(info->image_info,list[i],length[i],exception);
2804       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2805         break;
2806       for ( ; image; image=image->next)
2807       {
2808         AddImageToRegistry(sv,image);
2809         rv=newRV(sv);
2810         av_push(av,sv_bless(rv,hv));
2811         SvREFCNT_dec(sv);
2812         number_images++;
2813       }
2814     }
2815     /*
2816       Free resources.
2817     */
2818     for (i=0; i < n; i++)
2819       if (list[i] != (char *) NULL)
2820         for (p=keep; list[i] != *p++; )
2821           if (*p == (char *) NULL)
2822             {
2823               list[i]=(char *) RelinquishMagickMemory(list[i]);
2824               break;
2825             }
2826
2827   PerlException:
2828     if (list)
2829       list=(char **) RelinquishMagickMemory(list);
2830     if (length)
2831       length=(STRLEN *) RelinquishMagickMemory(length);
2832     InheritPerlException(exception,perl_exception);
2833     exception=DestroyExceptionInfo(exception);
2834     sv_setiv(perl_exception,(IV) number_images);
2835     SvPOK_on(perl_exception);
2836     ST(0)=sv_2mortal(perl_exception);
2837     XSRETURN(1);
2838   }
2839 \f
2840 #
2841 ###############################################################################
2842 #                                                                             #
2843 #                                                                             #
2844 #                                                                             #
2845 #   C l o n e                                                                 #
2846 #                                                                             #
2847 #                                                                             #
2848 #                                                                             #
2849 ###############################################################################
2850 #
2851 #
2852 void
2853 Clone(ref)
2854   Image::Magick ref=NO_INIT
2855   ALIAS:
2856     CopyImage   = 1
2857     copy        = 2
2858     copyimage   = 3
2859     CloneImage  = 4
2860     clone       = 5
2861     cloneimage  = 6
2862     Clone       = 7
2863   PPCODE:
2864   {
2865     AV
2866       *av;
2867
2868     ExceptionInfo
2869       *exception;
2870
2871     HV
2872       *hv;
2873
2874     Image
2875       *clone,
2876       *image;
2877
2878     struct PackageInfo
2879       *info;
2880
2881     SV
2882       *perl_exception,
2883       *reference,
2884       *rv,
2885       *sv;
2886
2887     PERL_UNUSED_VAR(ref);
2888     PERL_UNUSED_VAR(ix);
2889     exception=AcquireExceptionInfo();
2890     perl_exception=newSVpv("",0);
2891     sv=NULL;
2892     if (sv_isobject(ST(0)) == 0)
2893       {
2894         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2895           PackageName);
2896         goto PerlException;
2897       }
2898     reference=SvRV(ST(0));
2899     hv=SvSTASH(reference);
2900     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2901     if (image == (Image *) NULL)
2902       {
2903         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2904           PackageName);
2905         goto PerlException;
2906       }
2907     /*
2908       Create blessed Perl array for the returned image.
2909     */
2910     av=newAV();
2911     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2912     SvREFCNT_dec(av);
2913     for ( ; image; image=image->next)
2914     {
2915       clone=CloneImage(image,0,0,MagickTrue,exception);
2916       if ((clone == (Image *) NULL) || (exception->severity >= ErrorException))
2917         break;
2918       AddImageToRegistry(sv,clone);
2919       rv=newRV(sv);
2920       av_push(av,sv_bless(rv,hv));
2921       SvREFCNT_dec(sv);
2922     }
2923     exception=DestroyExceptionInfo(exception);
2924     SvREFCNT_dec(perl_exception);
2925     XSRETURN(1);
2926
2927   PerlException:
2928     InheritPerlException(exception,perl_exception);
2929     exception=DestroyExceptionInfo(exception);
2930     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2931     SvPOK_on(perl_exception);
2932     ST(0)=sv_2mortal(perl_exception);
2933     XSRETURN(1);
2934   }
2935 \f
2936 #
2937 ###############################################################################
2938 #                                                                             #
2939 #                                                                             #
2940 #                                                                             #
2941 #   C L O N E                                                                 #
2942 #                                                                             #
2943 #                                                                             #
2944 #                                                                             #
2945 ###############################################################################
2946 #
2947 #
2948 void
2949 CLONE(ref,...)
2950   SV *ref;
2951   CODE:
2952   {
2953     PERL_UNUSED_VAR(ref);
2954     if (magick_registry != (SplayTreeInfo *) NULL)
2955       {
2956         register Image
2957           *p;
2958
2959         ResetSplayTreeIterator(magick_registry);
2960         p=(Image *) GetNextKeyInSplayTree(magick_registry);
2961         while (p != (Image *) NULL)
2962         {
2963           ReferenceImage(p);
2964           p=(Image *) GetNextKeyInSplayTree(magick_registry);
2965         }
2966       }
2967   }
2968 \f
2969 #
2970 ###############################################################################
2971 #                                                                             #
2972 #                                                                             #
2973 #                                                                             #
2974 #   C o a l e s c e                                                           #
2975 #                                                                             #
2976 #                                                                             #
2977 #                                                                             #
2978 ###############################################################################
2979 #
2980 #
2981 void
2982 Coalesce(ref)
2983   Image::Magick ref=NO_INIT
2984   ALIAS:
2985     CoalesceImage   = 1
2986     coalesce        = 2
2987     coalesceimage   = 3
2988   PPCODE:
2989   {
2990     AV
2991       *av;
2992
2993     ExceptionInfo
2994       *exception;
2995
2996     HV
2997       *hv;
2998
2999     Image
3000       *image;
3001
3002     struct PackageInfo
3003       *info;
3004
3005     SV
3006       *av_reference,
3007       *perl_exception,
3008       *reference,
3009       *rv,
3010       *sv;
3011
3012     PERL_UNUSED_VAR(ref);
3013     PERL_UNUSED_VAR(ix);
3014     exception=AcquireExceptionInfo();
3015     perl_exception=newSVpv("",0);
3016     sv=NULL;
3017     if (sv_isobject(ST(0)) == 0)
3018       {
3019         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3020           PackageName);
3021         goto PerlException;
3022       }
3023     reference=SvRV(ST(0));
3024     hv=SvSTASH(reference);
3025     av=newAV();
3026     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3027     SvREFCNT_dec(av);
3028     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3029     if (image == (Image *) NULL)
3030       {
3031         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3032           PackageName);
3033         goto PerlException;
3034       }
3035     image=CoalesceImages(image,exception);
3036     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3037       goto PerlException;
3038     for ( ; image; image=image->next)
3039     {
3040       AddImageToRegistry(sv,image);
3041       rv=newRV(sv);
3042       av_push(av,sv_bless(rv,hv));
3043       SvREFCNT_dec(sv);
3044     }
3045     exception=DestroyExceptionInfo(exception);
3046     ST(0)=av_reference;
3047     SvREFCNT_dec(perl_exception);
3048     XSRETURN(1);
3049
3050   PerlException:
3051     InheritPerlException(exception,perl_exception);
3052     exception=DestroyExceptionInfo(exception);
3053     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3054     SvPOK_on(perl_exception);
3055     ST(0)=sv_2mortal(perl_exception);
3056     XSRETURN(1);
3057   }
3058 \f
3059 #
3060 ###############################################################################
3061 #                                                                             #
3062 #                                                                             #
3063 #                                                                             #
3064 #   C o m p a r e                                                             #
3065 #                                                                             #
3066 #                                                                             #
3067 #                                                                             #
3068 ###############################################################################
3069 #
3070 #
3071 void
3072 Compare(ref,...)
3073   Image::Magick ref=NO_INIT
3074   ALIAS:
3075     CompareImages = 1
3076     compare      = 2
3077     compareimage = 3
3078   PPCODE:
3079   {
3080     AV
3081       *av;
3082
3083     char
3084       *attribute;
3085
3086     double
3087       distortion;
3088
3089     ExceptionInfo
3090       *exception;
3091
3092     HV
3093       *hv;
3094
3095     Image
3096       *difference_image,
3097       *image,
3098       *reconstruct_image;
3099
3100     MetricType
3101       metric;
3102
3103     register ssize_t
3104       i;
3105
3106     ssize_t
3107       option;
3108
3109     struct PackageInfo
3110       *info;
3111
3112     SV
3113       *av_reference,
3114       *perl_exception,
3115       *reference,
3116       *rv,
3117       *sv;
3118
3119     PERL_UNUSED_VAR(ref);
3120     PERL_UNUSED_VAR(ix);
3121     exception=AcquireExceptionInfo();
3122     perl_exception=newSVpv("",0);
3123     sv=NULL;
3124     av=NULL;
3125     attribute=NULL;
3126     if (sv_isobject(ST(0)) == 0)
3127       {
3128         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3129           PackageName);
3130         goto PerlException;
3131       }
3132     reference=SvRV(ST(0));
3133     hv=SvSTASH(reference);
3134     av=newAV();
3135     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3136     SvREFCNT_dec(av);
3137     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3138     if (image == (Image *) NULL)
3139       {
3140         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3141           PackageName);
3142         goto PerlException;
3143       }
3144     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3145     /*
3146       Get attribute.
3147     */
3148     reconstruct_image=image;
3149     metric=RootMeanSquaredErrorMetric;
3150     for (i=2; i < items; i+=2)
3151     {
3152       attribute=(char *) SvPV(ST(i-1),na);
3153       switch (*attribute)
3154       {
3155         case 'C':
3156         case 'c':
3157         {
3158           if (LocaleCompare(attribute,"channel") == 0)
3159             {
3160               ssize_t
3161                 option;
3162
3163               option=ParseChannelOption(SvPV(ST(i),na));
3164               if (option < 0)
3165                 {
3166                   ThrowPerlException(exception,OptionError,
3167                     "UnrecognizedType",SvPV(ST(i),na));
3168                   return;
3169                 }
3170               SetPixelChannelMap(image,(ChannelType) option);
3171               break;
3172             }
3173           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3174             attribute);
3175           break;
3176         }
3177         case 'F':
3178         case 'f':
3179         {
3180           if (LocaleCompare(attribute,"fuzz") == 0)
3181             {
3182               image->fuzz=SiPrefixToDouble(SvPV(ST(i),na),100.0);
3183               break;
3184             }
3185           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3186             attribute);
3187           break;
3188         }
3189         case 'I':
3190         case 'i':
3191         {
3192           if (LocaleCompare(attribute,"image") == 0)
3193             {
3194               reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3195                 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3196               break;
3197             }
3198           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3199             attribute);
3200           break;
3201         }
3202         case 'M':
3203         case 'm':
3204         {
3205           if (LocaleCompare(attribute,"metric") == 0)
3206             {
3207               option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3208                 SvPV(ST(i),na));
3209               if (option < 0)
3210                 {
3211                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3212                     SvPV(ST(i),na));
3213                   break;
3214                 }
3215               metric=(MetricType) option;
3216               break;
3217             }
3218           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3219             attribute);
3220           break;
3221         }
3222         default:
3223         {
3224           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3225             attribute);
3226           break;
3227         }
3228       }
3229     }
3230     difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3231       exception);
3232     if (difference_image != (Image *) NULL)
3233       {
3234         difference_image->error.mean_error_per_pixel=distortion;
3235         AddImageToRegistry(sv,difference_image);
3236         rv=newRV(sv);
3237         av_push(av,sv_bless(rv,hv));
3238         SvREFCNT_dec(sv);
3239       }
3240     exception=DestroyExceptionInfo(exception);
3241     ST(0)=av_reference;
3242     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3243     XSRETURN(1);
3244
3245   PerlException:
3246     InheritPerlException(exception,perl_exception);
3247     exception=DestroyExceptionInfo(exception);
3248     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3249     SvPOK_on(perl_exception);
3250     ST(0)=sv_2mortal(perl_exception);
3251     XSRETURN(1);
3252   }
3253 \f
3254 #
3255 ###############################################################################
3256 #                                                                             #
3257 #                                                                             #
3258 #                                                                             #
3259 #   C o m p a r e L a y e r s                                                 #
3260 #                                                                             #
3261 #                                                                             #
3262 #                                                                             #
3263 ###############################################################################
3264 #
3265 #
3266 void
3267 CompareLayers(ref)
3268   Image::Magick ref=NO_INIT
3269   ALIAS:
3270     CompareImagesLayers   = 1
3271     comparelayers        = 2
3272     compareimagelayers   = 3
3273   PPCODE:
3274   {
3275     AV
3276       *av;
3277
3278     char
3279       *attribute;
3280
3281     ExceptionInfo
3282       *exception;
3283
3284     HV
3285       *hv;
3286
3287     Image
3288       *image;
3289
3290     ImageLayerMethod
3291       method;
3292
3293     register ssize_t
3294       i;
3295
3296     ssize_t
3297       option;
3298
3299     struct PackageInfo
3300       *info;
3301
3302     SV
3303       *av_reference,
3304       *perl_exception,
3305       *reference,
3306       *rv,
3307       *sv;
3308
3309     PERL_UNUSED_VAR(ref);
3310     PERL_UNUSED_VAR(ix);
3311     exception=AcquireExceptionInfo();
3312     perl_exception=newSVpv("",0);
3313     sv=NULL;
3314     if (sv_isobject(ST(0)) == 0)
3315       {
3316         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3317           PackageName);
3318         goto PerlException;
3319       }
3320     reference=SvRV(ST(0));
3321     hv=SvSTASH(reference);
3322     av=newAV();
3323     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3324     SvREFCNT_dec(av);
3325     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3326     if (image == (Image *) NULL)
3327       {
3328         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3329           PackageName);
3330         goto PerlException;
3331       }
3332     method=CompareAnyLayer;
3333     for (i=2; i < items; i+=2)
3334     {
3335       attribute=(char *) SvPV(ST(i-1),na);
3336       switch (*attribute)
3337       {
3338         case 'M':
3339         case 'm':
3340         {
3341           if (LocaleCompare(attribute,"method") == 0)
3342             {
3343               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3344                 SvPV(ST(i),na));
3345               if (option < 0)
3346                 {
3347                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3348                     SvPV(ST(i),na));
3349                   break;
3350                 }
3351                method=(ImageLayerMethod) option;
3352               break;
3353             }
3354           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3355             attribute);
3356           break;
3357         }
3358         default:
3359         {
3360           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3361             attribute);
3362           break;
3363         }
3364       }
3365     }
3366     image=CompareImagesLayers(image,method,exception);
3367     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3368       goto PerlException;
3369     for ( ; image; image=image->next)
3370     {
3371       AddImageToRegistry(sv,image);
3372       rv=newRV(sv);
3373       av_push(av,sv_bless(rv,hv));
3374       SvREFCNT_dec(sv);
3375     }
3376     exception=DestroyExceptionInfo(exception);
3377     ST(0)=av_reference;
3378     SvREFCNT_dec(perl_exception);
3379     XSRETURN(1);
3380
3381   PerlException:
3382     InheritPerlException(exception,perl_exception);
3383     exception=DestroyExceptionInfo(exception);
3384     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3385     SvPOK_on(perl_exception);
3386     ST(0)=sv_2mortal(perl_exception);
3387     XSRETURN(1);
3388   }
3389 \f
3390 #
3391 ###############################################################################
3392 #                                                                             #
3393 #                                                                             #
3394 #                                                                             #
3395 #   D e s t r o y                                                             #
3396 #                                                                             #
3397 #                                                                             #
3398 #                                                                             #
3399 ###############################################################################
3400 #
3401 #
3402 void
3403 DESTROY(ref)
3404   Image::Magick ref=NO_INIT
3405   PPCODE:
3406   {
3407     SV
3408       *reference;
3409
3410     PERL_UNUSED_VAR(ref);
3411     if (sv_isobject(ST(0)) == 0)
3412       croak("ReferenceIsNotMyType");
3413     reference=SvRV(ST(0));
3414     switch (SvTYPE(reference))
3415     {
3416       case SVt_PVAV:
3417       {
3418         char
3419           message[MaxTextExtent];
3420
3421         const SV
3422           *key;
3423
3424         HV
3425           *hv;
3426
3427         GV
3428           **gvp;
3429
3430         struct PackageInfo
3431           *info;
3432
3433         SV
3434           *sv;
3435
3436         /*
3437           Array (AV *) reference
3438         */
3439         (void) FormatLocaleString(message,MaxTextExtent,"package%s%p",
3440           XS_VERSION,reference);
3441         hv=gv_stashpv(PackageName, FALSE);
3442         if (!hv)
3443           break;
3444         gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3445         if (!gvp)
3446           break;
3447         sv=GvSV(*gvp);
3448         if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3449           {
3450             info=(struct PackageInfo *) SvIV(sv);
3451             DestroyPackageInfo(info);
3452           }
3453         key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3454         (void) key;
3455         break;
3456       }
3457       case SVt_PVMG:
3458       {
3459         Image
3460           *image;
3461
3462         /*
3463           Blessed scalar = (Image *) SvIV(reference)
3464         */
3465         image=(Image *) SvIV(reference);
3466         if (image != (Image *) NULL)
3467           DeleteImageFromRegistry(reference,image);
3468         break;
3469       }
3470       default:
3471         break;
3472     }
3473   }
3474 \f
3475 #
3476 ###############################################################################
3477 #                                                                             #
3478 #                                                                             #
3479 #                                                                             #
3480 #   D i s p l a y                                                             #
3481 #                                                                             #
3482 #                                                                             #
3483 #                                                                             #
3484 ###############################################################################
3485 #
3486 #
3487 void
3488 Display(ref,...)
3489   Image::Magick ref=NO_INIT
3490   ALIAS:
3491     DisplayImage  = 1
3492     display       = 2
3493     displayimage  = 3
3494   PPCODE:
3495   {
3496     ExceptionInfo
3497       *exception;
3498
3499     Image
3500       *image;
3501
3502     register ssize_t
3503       i;
3504
3505     struct PackageInfo
3506       *info,
3507       *package_info;
3508
3509     SV
3510       *perl_exception,
3511       *reference;
3512
3513     PERL_UNUSED_VAR(ref);
3514     PERL_UNUSED_VAR(ix);
3515     exception=AcquireExceptionInfo();
3516     perl_exception=newSVpv("",0);
3517     package_info=(struct PackageInfo *) NULL;
3518     if (sv_isobject(ST(0)) == 0)
3519       {
3520         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3521           PackageName);
3522         goto PerlException;
3523       }
3524     reference=SvRV(ST(0));
3525     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3526     if (image == (Image *) NULL)
3527       {
3528         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3529           PackageName);
3530         goto PerlException;
3531       }
3532     package_info=ClonePackageInfo(info,exception);
3533     if (items == 2)
3534       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3535     else
3536       if (items > 2)
3537         for (i=2; i < items; i+=2)
3538           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3539             exception);
3540     (void) DisplayImages(package_info->image_info,image,exception);
3541     (void) CatchImageException(image);
3542
3543   PerlException:
3544     if (package_info != (struct PackageInfo *) NULL)
3545       DestroyPackageInfo(package_info);
3546     InheritPerlException(exception,perl_exception);
3547     exception=DestroyExceptionInfo(exception);
3548     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3549     SvPOK_on(perl_exception);
3550     ST(0)=sv_2mortal(perl_exception);
3551     XSRETURN(1);
3552   }
3553 \f
3554 #
3555 ###############################################################################
3556 #                                                                             #
3557 #                                                                             #
3558 #                                                                             #
3559 #   E v a l u a t e I m a g e s                                               #
3560 #                                                                             #
3561 #                                                                             #
3562 #                                                                             #
3563 ###############################################################################
3564 #
3565 #
3566 void
3567 EvaluateImages(ref)
3568   Image::Magick ref=NO_INIT
3569   ALIAS:
3570     EvaluateImages   = 1
3571     evaluateimages   = 2
3572   PPCODE:
3573   {
3574     AV
3575       *av;
3576
3577     char
3578       *attribute,
3579       *p;
3580
3581     ExceptionInfo
3582       *exception;
3583
3584     HV
3585       *hv;
3586
3587     Image
3588       *image;
3589
3590     MagickEvaluateOperator
3591       op;
3592
3593     register ssize_t
3594       i;
3595
3596     struct PackageInfo
3597       *info;
3598
3599     SV
3600       *perl_exception,
3601       *reference,
3602       *rv,
3603       *sv;
3604
3605     PERL_UNUSED_VAR(ref);
3606     PERL_UNUSED_VAR(ix);
3607     exception=AcquireExceptionInfo();
3608     perl_exception=newSVpv("",0);
3609     sv=NULL;
3610     if (sv_isobject(ST(0)) == 0)
3611       {
3612         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3613           PackageName);
3614         goto PerlException;
3615       }
3616     reference=SvRV(ST(0));
3617     hv=SvSTASH(reference);
3618     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3619     if (image == (Image *) NULL)
3620       {
3621         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3622           PackageName);
3623         goto PerlException;
3624       }
3625     op=MeanEvaluateOperator;
3626     if (items == 2)
3627       {
3628         ssize_t
3629           in;
3630
3631         in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
3632           SvPV(ST(1),na));
3633         if (in < 0)
3634           {
3635             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3636               SvPV(ST(1),na));
3637             return;
3638           }
3639         op=(MagickEvaluateOperator) in;
3640       }
3641     else
3642       for (i=2; i < items; i+=2)
3643       {
3644         attribute=(char *) SvPV(ST(i-1),na);
3645         switch (*attribute)
3646         {
3647           case 'O':
3648           case 'o':
3649           {
3650             if (LocaleCompare(attribute,"operator") == 0)
3651               {
3652                 ssize_t
3653                   in;
3654
3655                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3656                   MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
3657                 if (in < 0)
3658                   {
3659                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3660                       SvPV(ST(i),na));
3661                     return;
3662                   }
3663                 op=(MagickEvaluateOperator) in;
3664                 break;
3665               }
3666             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3667               attribute);
3668             break;
3669           }
3670           default:
3671           {
3672             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3673               attribute);
3674             break;
3675           }
3676         }
3677       }
3678     image=EvaluateImages(image,op,exception);
3679     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3680       goto PerlException;
3681     /*
3682       Create blessed Perl array for the returned image.
3683     */
3684     av=newAV();
3685     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3686     SvREFCNT_dec(av);
3687     AddImageToRegistry(sv,image);
3688     rv=newRV(sv);
3689     av_push(av,sv_bless(rv,hv));
3690     SvREFCNT_dec(sv);
3691     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3692     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
3693       "evaluate-%.*s",(int) (MaxTextExtent-9),
3694       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3695     (void) CopyMagickString(image->filename,info->image_info->filename,
3696       MaxTextExtent);
3697     SetImageInfo(info->image_info,0,exception);
3698     exception=DestroyExceptionInfo(exception);
3699     SvREFCNT_dec(perl_exception);
3700     XSRETURN(1);
3701
3702   PerlException:
3703     InheritPerlException(exception,perl_exception);
3704     exception=DestroyExceptionInfo(exception);
3705     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3706     SvPOK_on(perl_exception);
3707     ST(0)=sv_2mortal(perl_exception);
3708     XSRETURN(1);
3709   }
3710 \f
3711 #
3712 ###############################################################################
3713 #                                                                             #
3714 #                                                                             #
3715 #                                                                             #
3716 #   F e a t u r e s                                                           #
3717 #                                                                             #
3718 #                                                                             #
3719 #                                                                             #
3720 ###############################################################################
3721 #
3722 #
3723 void
3724 Features(ref,...)
3725   Image::Magick ref=NO_INIT
3726   ALIAS:
3727     FeaturesImage = 1
3728     features      = 2
3729     featuresimage = 3
3730   PPCODE:
3731   {
3732 #define ChannelFeatures(channel,direction) \
3733 { \
3734   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3735     channel_features[channel].angular_second_moment[direction]); \
3736   PUSHs(sv_2mortal(newSVpv(message,0))); \
3737   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3738     channel_features[channel].contrast[direction]); \
3739   PUSHs(sv_2mortal(newSVpv(message,0))); \
3740   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3741     channel_features[channel].contrast[direction]); \
3742   PUSHs(sv_2mortal(newSVpv(message,0))); \
3743   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3744     channel_features[channel].variance_sum_of_squares[direction]); \
3745   PUSHs(sv_2mortal(newSVpv(message,0))); \
3746   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3747     channel_features[channel].inverse_difference_moment[direction]); \
3748   PUSHs(sv_2mortal(newSVpv(message,0))); \
3749   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3750     channel_features[channel].sum_average[direction]); \
3751   PUSHs(sv_2mortal(newSVpv(message,0))); \
3752   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3753     channel_features[channel].sum_variance[direction]); \
3754   PUSHs(sv_2mortal(newSVpv(message,0))); \
3755   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3756     channel_features[channel].sum_entropy[direction]); \
3757   PUSHs(sv_2mortal(newSVpv(message,0))); \
3758   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3759     channel_features[channel].entropy[direction]); \
3760   PUSHs(sv_2mortal(newSVpv(message,0))); \
3761   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3762     channel_features[channel].difference_variance[direction]); \
3763   PUSHs(sv_2mortal(newSVpv(message,0))); \
3764   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3765     channel_features[channel].difference_entropy[direction]); \
3766   PUSHs(sv_2mortal(newSVpv(message,0))); \
3767   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3768     channel_features[channel].measure_of_correlation_1[direction]); \
3769   PUSHs(sv_2mortal(newSVpv(message,0))); \
3770   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3771     channel_features[channel].measure_of_correlation_2[direction]); \
3772   PUSHs(sv_2mortal(newSVpv(message,0))); \
3773   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3774     channel_features[channel].maximum_correlation_coefficient[direction]); \
3775   PUSHs(sv_2mortal(newSVpv(message,0))); \
3776 }
3777
3778     AV
3779       *av;
3780
3781     char
3782       *attribute,
3783       message[MaxTextExtent];
3784
3785     ChannelFeatures
3786       *channel_features;
3787
3788     double
3789       distance;
3790
3791     ExceptionInfo
3792       *exception;
3793
3794     Image
3795       *image;
3796
3797     register ssize_t
3798       i;
3799
3800     ssize_t
3801       count;
3802
3803     struct PackageInfo
3804       *info;
3805
3806     SV
3807       *perl_exception,
3808       *reference;
3809
3810     PERL_UNUSED_VAR(ref);
3811     PERL_UNUSED_VAR(ix);
3812     exception=AcquireExceptionInfo();
3813     perl_exception=newSVpv("",0);
3814     av=NULL;
3815     if (sv_isobject(ST(0)) == 0)
3816       {
3817         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3818           PackageName);
3819         goto PerlException;
3820       }
3821     reference=SvRV(ST(0));
3822     av=newAV();
3823     SvREFCNT_dec(av);
3824     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3825     if (image == (Image *) NULL)
3826       {
3827         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3828           PackageName);
3829         goto PerlException;
3830       }
3831     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3832     distance=1;
3833     for (i=2; i < items; i+=2)
3834     {
3835       attribute=(char *) SvPV(ST(i-1),na);
3836       switch (*attribute)
3837       {
3838         case 'D':
3839         case 'd':
3840         {
3841           if (LocaleCompare(attribute,"distance") == 0)
3842             {
3843               distance=StringToLong((char *) SvPV(ST(1),na));
3844               break;
3845             }
3846           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3847             attribute);
3848           break;
3849         }
3850         default:
3851         {
3852           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3853             attribute);
3854           break;
3855         }
3856       }
3857     }
3858     count=0;
3859     for ( ; image; image=image->next)
3860     {
3861       channel_features=GetImageFeatures(image,distance,
3862         &image->exception);
3863       if (channel_features == (ChannelFeatures *) NULL)
3864         continue;
3865       count++;
3866       EXTEND(sp,75*count);
3867       for (i=0; i < 4; i++)
3868       {
3869         ChannelFeatures(RedChannel,i);
3870         ChannelFeatures(GreenChannel,i);
3871         ChannelFeatures(BlueChannel,i);
3872         if (image->colorspace == CMYKColorspace)
3873           ChannelFeatures(BlackChannel,i);
3874         if (image->matte != MagickFalse)
3875           ChannelFeatures(AlphaChannel,i);
3876       }
3877       channel_features=(ChannelFeatures *)
3878         RelinquishMagickMemory(channel_features);
3879     }
3880
3881   PerlException:
3882     InheritPerlException(exception,perl_exception);
3883     exception=DestroyExceptionInfo(exception);
3884     SvREFCNT_dec(perl_exception);
3885   }
3886 \f
3887 #
3888 ###############################################################################
3889 #                                                                             #
3890 #                                                                             #
3891 #                                                                             #
3892 #   F l a t t e n                                                             #
3893 #                                                                             #
3894 #                                                                             #
3895 #                                                                             #
3896 ###############################################################################
3897 #
3898 #
3899 void
3900 Flatten(ref)
3901   Image::Magick ref=NO_INIT
3902   ALIAS:
3903     FlattenImage   = 1
3904     flatten        = 2
3905     flattenimage   = 3
3906   PPCODE:
3907   {
3908     AV
3909       *av;
3910
3911     char
3912       *attribute,
3913       *p;
3914
3915     ExceptionInfo
3916       *exception;
3917
3918     HV
3919       *hv;
3920
3921     Image
3922       *image;
3923
3924     PixelPacket
3925       background_color;
3926
3927     register ssize_t
3928       i;
3929
3930     struct PackageInfo
3931       *info;
3932
3933     SV
3934       *perl_exception,
3935       *reference,
3936       *rv,
3937       *sv;
3938
3939     PERL_UNUSED_VAR(ref);
3940     PERL_UNUSED_VAR(ix);
3941     exception=AcquireExceptionInfo();
3942     perl_exception=newSVpv("",0);
3943     sv=NULL;
3944     if (sv_isobject(ST(0)) == 0)
3945       {
3946         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3947           PackageName);
3948         goto PerlException;
3949       }
3950     reference=SvRV(ST(0));
3951     hv=SvSTASH(reference);
3952     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3953     if (image == (Image *) NULL)
3954       {
3955         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3956           PackageName);
3957         goto PerlException;
3958       }
3959     background_color=image->background_color;
3960     if (items == 2)
3961       (void) QueryColorCompliance((char *) SvPV(ST(1),na),AllCompliance,
3962         &background_color,exception);
3963     else
3964       for (i=2; i < items; i+=2)
3965       {
3966         attribute=(char *) SvPV(ST(i-1),na);
3967         switch (*attribute)
3968         {
3969           case 'B':
3970           case 'b':
3971           {
3972             if (LocaleCompare(attribute,"background") == 0)
3973               {
3974                 (void) QueryColorCompliance((char *) SvPV(ST(1),na),
3975                   AllCompliance,&background_color,exception);
3976                 break;
3977               }
3978             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3979               attribute);
3980             break;
3981           }
3982           default:
3983           {
3984             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3985               attribute);
3986             break;
3987           }
3988         }
3989       }
3990     image->background_color=background_color;
3991     image=MergeImageLayers(image,FlattenLayer,exception);
3992     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3993       goto PerlException;
3994     /*
3995       Create blessed Perl array for the returned image.
3996     */
3997     av=newAV();
3998     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3999     SvREFCNT_dec(av);
4000     AddImageToRegistry(sv,image);
4001     rv=newRV(sv);
4002     av_push(av,sv_bless(rv,hv));
4003     SvREFCNT_dec(sv);
4004     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4005     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
4006       "flatten-%.*s",(int) (MaxTextExtent-9),
4007       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4008     (void) CopyMagickString(image->filename,info->image_info->filename,
4009       MaxTextExtent);
4010     SetImageInfo(info->image_info,0,exception);
4011     exception=DestroyExceptionInfo(exception);
4012     SvREFCNT_dec(perl_exception);
4013     XSRETURN(1);
4014
4015   PerlException:
4016     InheritPerlException(exception,perl_exception);
4017     exception=DestroyExceptionInfo(exception);
4018     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4019     SvPOK_on(perl_exception);  /* return messages in string context */
4020     ST(0)=sv_2mortal(perl_exception);
4021     XSRETURN(1);
4022   }
4023 \f
4024 #
4025 ###############################################################################
4026 #                                                                             #
4027 #                                                                             #
4028 #                                                                             #
4029 #   F x                                                                       #
4030 #                                                                             #
4031 #                                                                             #
4032 #                                                                             #
4033 ###############################################################################
4034 #
4035 #
4036 void
4037 Fx(ref,...)
4038   Image::Magick ref=NO_INIT
4039   ALIAS:
4040     FxImage  = 1
4041     fx       = 2
4042     fximage  = 3
4043   PPCODE:
4044   {
4045     AV
4046       *av;
4047
4048     char
4049       *attribute,
4050       expression[MaxTextExtent];
4051
4052     ChannelType
4053       channel,
4054       channel_mask;
4055
4056     ExceptionInfo
4057       *exception;
4058
4059     HV
4060       *hv;
4061
4062     Image
4063       *image;
4064
4065     register ssize_t
4066       i;
4067
4068     struct PackageInfo
4069       *info;
4070
4071     SV
4072       *av_reference,
4073       *perl_exception,
4074       *reference,
4075       *rv,
4076       *sv;
4077
4078     PERL_UNUSED_VAR(ref);
4079     PERL_UNUSED_VAR(ix);
4080     exception=AcquireExceptionInfo();
4081     perl_exception=newSVpv("",0);
4082     sv=NULL;
4083     attribute=NULL;
4084     av=NULL;
4085     if (sv_isobject(ST(0)) == 0)
4086       {
4087         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4088           PackageName);
4089         goto PerlException;
4090       }
4091     reference=SvRV(ST(0));
4092     hv=SvSTASH(reference);
4093     av=newAV();
4094     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4095     SvREFCNT_dec(av);
4096     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4097     if (image == (Image *) NULL)
4098       {
4099         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4100           PackageName);
4101         goto PerlException;
4102       }
4103     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4104     /*
4105       Get options.
4106     */
4107     channel=DefaultChannels;
4108     (void) CopyMagickString(expression,"u",MaxTextExtent);
4109     if (items == 2)
4110       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MaxTextExtent);
4111     else
4112       for (i=2; i < items; i+=2)
4113       {
4114         attribute=(char *) SvPV(ST(i-1),na);
4115         switch (*attribute)
4116         {
4117           case 'C':
4118           case 'c':
4119           {
4120             if (LocaleCompare(attribute,"channel") == 0)
4121               {
4122                 ssize_t
4123                   option;
4124
4125                 option=ParseChannelOption(SvPV(ST(i),na));
4126                 if (option < 0)
4127                   {
4128                     ThrowPerlException(exception,OptionError,
4129                       "UnrecognizedType",SvPV(ST(i),na));
4130                     return;
4131                   }
4132                 channel=(ChannelType) option;
4133                 break;
4134               }
4135             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4136               attribute);
4137             break;
4138           }
4139           case 'E':
4140           case 'e':
4141           {
4142             if (LocaleCompare(attribute,"expression") == 0)
4143               {
4144                 (void) CopyMagickString(expression,SvPV(ST(i),na),
4145                   MaxTextExtent);
4146                 break;
4147               }
4148             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4149               attribute);
4150             break;
4151           }
4152           default:
4153           {
4154             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4155               attribute);
4156             break;
4157           }
4158         }
4159       }
4160     channel_mask=SetPixelChannelMask(image,channel);
4161     image=FxImage(image,expression,exception);
4162     if (image != (Image *) NULL)
4163       (void) SetPixelChannelMask(image,channel_mask);
4164     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
4165       goto PerlException;
4166     for ( ; image; image=image->next)
4167     {
4168       AddImageToRegistry(sv,image);
4169       rv=newRV(sv);
4170       av_push(av,sv_bless(rv,hv));
4171       SvREFCNT_dec(sv);
4172     }
4173     exception=DestroyExceptionInfo(exception);
4174     ST(0)=av_reference;
4175     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4176     XSRETURN(1);
4177
4178   PerlException:
4179     InheritPerlException(exception,perl_exception);
4180     exception=DestroyExceptionInfo(exception);
4181     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4182     SvPOK_on(perl_exception);
4183     ST(0)=sv_2mortal(perl_exception);
4184     XSRETURN(1);
4185   }
4186 \f
4187 #
4188 ###############################################################################
4189 #                                                                             #
4190 #                                                                             #
4191 #                                                                             #
4192 #   G e t                                                                     #
4193 #                                                                             #
4194 #                                                                             #
4195 #                                                                             #
4196 ###############################################################################
4197 #
4198 #
4199 void
4200 Get(ref,...)
4201   Image::Magick ref=NO_INIT
4202   ALIAS:
4203     GetAttributes = 1
4204     GetAttribute  = 2
4205     get           = 3
4206     getattributes = 4
4207     getattribute  = 5
4208   PPCODE:
4209   {
4210     char
4211       *attribute,
4212       color[MaxTextExtent];
4213
4214     const char
4215       *value;
4216
4217     ExceptionInfo
4218       *exception;
4219
4220     Image
4221       *image;
4222
4223     long
4224       j;
4225
4226     register ssize_t
4227       i;
4228
4229     struct PackageInfo
4230       *info;
4231
4232     SV
4233       *perl_exception,
4234       *reference,
4235       *s;
4236
4237     PERL_UNUSED_VAR(ref);
4238     PERL_UNUSED_VAR(ix);
4239     exception=AcquireExceptionInfo();
4240     perl_exception=newSVpv("",0);
4241     if (sv_isobject(ST(0)) == 0)
4242       {
4243         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4244           PackageName);
4245         XSRETURN_EMPTY;
4246       }
4247     reference=SvRV(ST(0));
4248     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4249     if (image == (Image *) NULL && !info)
4250       XSRETURN_EMPTY;
4251     EXTEND(sp,items);
4252     for (i=1; i < items; i++)
4253     {
4254       attribute=(char *) SvPV(ST(i),na);
4255       s=NULL;
4256       switch (*attribute)
4257       {
4258         case 'A':
4259         case 'a':
4260         {
4261           if (LocaleCompare(attribute,"adjoin") == 0)
4262             {
4263               if (info)
4264                 s=newSViv((ssize_t) info->image_info->adjoin);
4265               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4266               continue;
4267             }
4268           if (LocaleCompare(attribute,"antialias") == 0)
4269             {
4270               if (info)
4271                 s=newSViv((ssize_t) info->image_info->antialias);
4272               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4273               continue;
4274             }
4275           if (LocaleCompare(attribute,"area") == 0)
4276             {
4277               s=newSViv(GetMagickResource(AreaResource));
4278               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4279               continue;
4280             }
4281           if (LocaleCompare(attribute,"attenuate") == 0)
4282             {
4283               const char
4284                 *value;
4285
4286               value=GetImageProperty(image,attribute);
4287               if (value != (const char *) NULL)
4288                 s=newSVpv(value,0);
4289               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4290               continue;
4291             }
4292           if (LocaleCompare(attribute,"authenticate") == 0)
4293             {
4294               if (info)
4295                 s=newSVpv(info->image_info->authenticate,0);
4296               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4297               continue;
4298             }
4299           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4300             attribute);
4301           break;
4302         }
4303         case 'B':
4304         case 'b':
4305         {
4306           if (LocaleCompare(attribute,"background") == 0)
4307             {
4308               if (image == (Image *) NULL)
4309                 break;
4310               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4311                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4312                 image->background_color.red,image->background_color.green,
4313                 image->background_color.blue,image->background_color.alpha);
4314               s=newSVpv(color,0);
4315               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4316               continue;
4317             }
4318           if (LocaleCompare(attribute,"base-columns") == 0)
4319             {
4320               if (image != (Image *) NULL)
4321                 s=newSViv((ssize_t) image->magick_columns);
4322               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4323               continue;
4324             }
4325           if (LocaleCompare(attribute,"base-filename") == 0)
4326             {
4327               if (image != (Image *) NULL)
4328                 s=newSVpv(image->magick_filename,0);
4329               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4330               continue;
4331             }
4332           if (LocaleCompare(attribute,"base-height") == 0)
4333             {
4334               if (image != (Image *) NULL)
4335                 s=newSViv((ssize_t) image->magick_rows);
4336               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4337               continue;
4338             }
4339           if (LocaleCompare(attribute,"base-rows") == 0)
4340             {
4341               if (image != (Image *) NULL)
4342                 s=newSViv((ssize_t) image->magick_rows);
4343               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4344               continue;
4345             }
4346           if (LocaleCompare(attribute,"base-width") == 0)
4347             {
4348               if (image != (Image *) NULL)
4349                 s=newSViv((ssize_t) image->magick_columns);
4350               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4351               continue;
4352             }
4353           if (LocaleCompare(attribute,"bias") == 0)
4354             {
4355               if (image != (Image *) NULL)
4356                 s=newSVnv(image->bias);
4357               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4358               continue;
4359             }
4360           if (LocaleCompare(attribute,"blue-primary") == 0)
4361             {
4362               if (image == (Image *) NULL)
4363                 break;
4364               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4365                 image->chromaticity.blue_primary.x,
4366                 image->chromaticity.blue_primary.y);
4367               s=newSVpv(color,0);
4368               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4369               continue;
4370             }
4371           if (LocaleCompare(attribute,"bordercolor") == 0)
4372             {
4373               if (image == (Image *) NULL)
4374                 break;
4375               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4376                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4377                 image->border_color.red,image->border_color.green,
4378                 image->border_color.blue,image->border_color.alpha);
4379               s=newSVpv(color,0);
4380               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4381               continue;
4382             }
4383           if (LocaleCompare(attribute,"bounding-box") == 0)
4384             {
4385               char
4386                 geometry[MaxTextExtent];
4387
4388               RectangleInfo
4389                 page;
4390
4391               if (image == (Image *) NULL)
4392                 break;
4393               page=GetImageBoundingBox(image,&image->exception);
4394               (void) FormatLocaleString(geometry,MaxTextExtent,
4395                 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4396                 page.height,(double) page.x,(double) page.y);
4397               s=newSVpv(geometry,0);
4398               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4399               continue;
4400             }
4401           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4402             attribute);
4403           break;
4404         }
4405         case 'C':
4406         case 'c':
4407         {
4408           if (LocaleCompare(attribute,"class") == 0)
4409             {
4410               if (image == (Image *) NULL)
4411                 break;
4412               s=newSViv(image->storage_class);
4413               (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4414                 image->storage_class));
4415               SvIOK_on(s);
4416               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4417               continue;
4418             }
4419           if (LocaleCompare(attribute,"clip-mask") == 0)
4420             {
4421               if (image != (Image *) NULL)
4422                 {
4423                   SV
4424                     *sv;
4425
4426                   sv=NULL;
4427                   if (image->mask == (Image *) NULL)
4428                     ClipImage(image,exception);
4429                   if (image->mask != (Image *) NULL)
4430                     {
4431                       AddImageToRegistry(sv,image->mask);
4432                       s=sv_bless(newRV(sv),SvSTASH(reference));
4433                     }
4434                 }
4435               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4436               continue;
4437             }
4438           if (LocaleCompare(attribute,"clip-path") == 0)
4439             {
4440               if (image != (Image *) NULL)
4441                 {
4442                   SV
4443                     *sv;
4444
4445                   sv=NULL;
4446                   if (image->clip_mask == (Image *) NULL)
4447                     ClipImage(image,exception);
4448                   if (image->clip_mask != (Image *) NULL)
4449                     {
4450                       AddImageToRegistry(sv,image->clip_mask);
4451                       s=sv_bless(newRV(sv),SvSTASH(reference));
4452                     }
4453                 }
4454               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4455               continue;
4456             }
4457           if (LocaleCompare(attribute,"compression") == 0)
4458             {
4459               j=info ? info->image_info->compression : image ?
4460                 image->compression : UndefinedCompression;
4461               if (info)
4462                 if (info->image_info->compression == UndefinedCompression)
4463                   j=image->compression;
4464               s=newSViv(j);
4465               (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4466                 j));
4467               SvIOK_on(s);
4468               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4469               continue;
4470             }
4471           if (LocaleCompare(attribute,"colorspace") == 0)
4472             {
4473               j=image ? image->colorspace : RGBColorspace;
4474               s=newSViv(j);
4475               (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4476                 j));
4477               SvIOK_on(s);
4478               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4479               continue;
4480             }
4481           if (LocaleCompare(attribute,"colors") == 0)
4482             {
4483               if (image != (Image *) NULL)
4484                 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4485                   &image->exception));
4486               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4487               continue;
4488             }
4489           if (LocaleNCompare(attribute,"colormap",8) == 0)
4490             {
4491               int
4492                 items;
4493
4494               if (image == (Image *) NULL || !image->colormap)
4495                 break;
4496               j=0;
4497               items=sscanf(attribute,"%*[^[][%ld",&j);
4498               (void) items;
4499               if (j > (ssize_t) image->colors)
4500                 j%=image->colors;
4501               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4502                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4503                 image->colormap[j].red,image->colormap[j].green,
4504                 image->colormap[j].blue,image->colormap[j].alpha);
4505               s=newSVpv(color,0);
4506               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4507               continue;
4508             }
4509           if (LocaleCompare(attribute,"columns") == 0)
4510             {
4511               if (image != (Image *) NULL)
4512                 s=newSViv((ssize_t) image->columns);
4513               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4514               continue;
4515             }
4516           if (LocaleCompare(attribute,"comment") == 0)
4517             {
4518               const char
4519                 *value;
4520
4521               value=GetImageProperty(image,attribute);
4522               if (value != (const char *) NULL)
4523                 s=newSVpv(value,0);
4524               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4525               continue;
4526             }
4527           if (LocaleCompare(attribute,"copyright") == 0)
4528             {
4529               s=newSVpv(GetMagickCopyright(),0);
4530               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4531               continue;
4532             }
4533           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4534             attribute);
4535           break;
4536         }
4537         case 'D':
4538         case 'd':
4539         {
4540           if (LocaleCompare(attribute,"density") == 0)
4541             {
4542               char
4543                 geometry[MaxTextExtent];
4544
4545               if (image == (Image *) NULL)
4546                 break;
4547               (void) FormatLocaleString(geometry,MaxTextExtent,"%.15gx%.15g",
4548                 image->x_resolution,image->y_resolution);
4549               s=newSVpv(geometry,0);
4550               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4551               continue;
4552             }
4553           if (LocaleCompare(attribute,"delay") == 0)
4554             {
4555               if (image != (Image *) NULL)
4556                 s=newSViv((ssize_t) image->delay);
4557               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4558               continue;
4559             }
4560           if (LocaleCompare(attribute,"depth") == 0)
4561             {
4562               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4563               if (image != (Image *) NULL)
4564                 s=newSViv((ssize_t) GetImageDepth(image,&image->exception));
4565               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4566               continue;
4567             }
4568           if (LocaleCompare(attribute,"directory") == 0)
4569             {
4570               if (image && image->directory)
4571                 s=newSVpv(image->directory,0);
4572               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4573               continue;
4574             }
4575           if (LocaleCompare(attribute,"dispose") == 0)
4576             {
4577               if (image == (Image *) NULL)
4578                 break;
4579
4580               s=newSViv(image->dispose);
4581               (void) sv_setpv(s,
4582                 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
4583               SvIOK_on(s);
4584               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4585               continue;
4586             }
4587           if (LocaleCompare(attribute,"disk") == 0)
4588             {
4589               s=newSViv(GetMagickResource(DiskResource));
4590               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4591               continue;
4592             }
4593           if (LocaleCompare(attribute,"dither") == 0)
4594             {
4595               if (info)
4596                 s=newSViv((ssize_t) info->image_info->dither);
4597               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4598               continue;
4599             }
4600           if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4601             {
4602               if (info && info->image_info->server_name)
4603                 s=newSVpv(info->image_info->server_name,0);
4604               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4605               continue;
4606             }
4607           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4608             attribute);
4609           break;
4610         }
4611         case 'E':
4612         case 'e':
4613         {
4614           if (LocaleCompare(attribute,"elapsed-time") == 0)
4615             {
4616               if (image != (Image *) NULL)
4617                 s=newSVnv(GetElapsedTime(&image->timer));
4618               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4619               continue;
4620             }
4621           if (LocaleCompare(attribute,"endian") == 0)
4622             {
4623               j=info ? info->image_info->endian : image ? image->endian :
4624                 UndefinedEndian;
4625               s=newSViv(j);
4626               (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
4627               SvIOK_on(s);
4628               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4629               continue;
4630             }
4631           if (LocaleCompare(attribute,"error") == 0)
4632             {
4633               if (image != (Image *) NULL)
4634                 s=newSVnv(image->error.mean_error_per_pixel);
4635               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4636               continue;
4637             }
4638           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4639             attribute);
4640           break;
4641         }
4642         case 'F':
4643         case 'f':
4644         {
4645           if (LocaleCompare(attribute,"filesize") == 0)
4646             {
4647               if (image != (Image *) NULL)
4648                 s=newSViv((ssize_t) GetBlobSize(image));
4649               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4650               continue;
4651             }
4652           if (LocaleCompare(attribute,"filename") == 0)
4653             {
4654               if (info && info->image_info->filename &&
4655                   *info->image_info->filename)
4656                 s=newSVpv(info->image_info->filename,0);
4657               if (image != (Image *) NULL)
4658                 s=newSVpv(image->filename,0);
4659               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4660               continue;
4661             }
4662           if (LocaleCompare(attribute,"filter") == 0)
4663             {
4664               s=image ? newSViv(image->filter) : newSViv(0);
4665               (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
4666                 image->filter));
4667               SvIOK_on(s);
4668               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4669               continue;
4670             }
4671           if (LocaleCompare(attribute,"font") == 0)
4672             {
4673               if (info && info->image_info->font)
4674                 s=newSVpv(info->image_info->font,0);
4675               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4676               continue;
4677             }
4678           if (LocaleCompare(attribute,"foreground") == 0)
4679             continue;
4680           if (LocaleCompare(attribute,"format") == 0)
4681             {
4682               const MagickInfo
4683                 *magick_info;
4684
4685               magick_info=(const MagickInfo *) NULL;
4686               if (info && (*info->image_info->magick != '\0'))
4687                 magick_info=GetMagickInfo(info->image_info->magick,exception);
4688               if (image != (Image *) NULL)
4689                 magick_info=GetMagickInfo(image->magick,&image->exception);
4690               if ((magick_info != (const MagickInfo *) NULL) &&
4691                   (*magick_info->description != '\0'))
4692                 s=newSVpv((char *) magick_info->description,0);
4693               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4694               continue;
4695             }
4696           if (LocaleCompare(attribute,"fuzz") == 0)
4697             {
4698               if (info)
4699                 s=newSVnv(info->image_info->fuzz);
4700               if (image != (Image *) NULL)
4701                 s=newSVnv(image->fuzz);
4702               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4703               continue;
4704             }
4705           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4706             attribute);
4707           break;
4708         }
4709         case 'G':
4710         case 'g':
4711         {
4712           if (LocaleCompare(attribute,"gamma") == 0)
4713             {
4714               if (image != (Image *) NULL)
4715                 s=newSVnv(image->gamma);
4716               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4717               continue;
4718             }
4719           if (LocaleCompare(attribute,"geometry") == 0)
4720             {
4721               if (image && image->geometry)
4722                 s=newSVpv(image->geometry,0);
4723               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4724               continue;
4725             }
4726           if (LocaleCompare(attribute,"gravity") == 0)
4727             {
4728               s=image ? newSViv(image->gravity) : newSViv(0);
4729               (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
4730                 image->gravity));
4731               SvIOK_on(s);
4732               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4733               continue;
4734             }
4735           if (LocaleCompare(attribute,"green-primary") == 0)
4736             {
4737               if (image == (Image *) NULL)
4738                 break;
4739               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4740                 image->chromaticity.green_primary.x,
4741                 image->chromaticity.green_primary.y);
4742               s=newSVpv(color,0);
4743               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4744               continue;
4745             }
4746           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4747             attribute);
4748           break;
4749         }
4750         case 'H':
4751         case 'h':
4752         {
4753           if (LocaleCompare(attribute,"height") == 0)
4754             {
4755               if (image != (Image *) NULL)
4756                 s=newSViv((ssize_t) image->rows);
4757               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4758               continue;
4759             }
4760           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4761             attribute);
4762           break;
4763         }
4764         case 'I':
4765         case 'i':
4766         {
4767           if (LocaleCompare(attribute,"icc") == 0)
4768             {
4769               if (image != (Image *) NULL)
4770                 {
4771                   const StringInfo
4772                     *profile;
4773
4774                   profile=GetImageProfile(image,"icc");
4775                   if (profile != (StringInfo *) NULL)
4776                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4777                       GetStringInfoLength(profile));
4778                 }
4779               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4780               continue;
4781             }
4782           if (LocaleCompare(attribute,"icm") == 0)
4783             {
4784               if (image != (Image *) NULL)
4785                 {
4786                   const StringInfo
4787                     *profile;
4788
4789                   profile=GetImageProfile(image,"icm");
4790                   if (profile != (const StringInfo *) NULL)
4791                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4792                       GetStringInfoLength(profile));
4793                 }
4794               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4795               continue;
4796             }
4797           if (LocaleCompare(attribute,"id") == 0)
4798             {
4799               if (image != (Image *) NULL)
4800                 {
4801                   char
4802                     key[MaxTextExtent];
4803
4804                   MagickBooleanType
4805                     status;
4806
4807                   static ssize_t
4808                     id = 0;
4809
4810                   (void) FormatLocaleString(key,MaxTextExtent,"%.20g\n",(double)
4811                     id);
4812                   status=SetImageRegistry(ImageRegistryType,key,image,
4813                     &image->exception);
4814                   (void) status;
4815                   s=newSViv(id++);
4816                 }
4817               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4818               continue;
4819             }
4820           if (LocaleNCompare(attribute,"index",5) == 0)
4821             {
4822               char
4823                 name[MaxTextExtent];
4824
4825               int
4826                 items;
4827
4828               long
4829                 x,
4830                 y;
4831
4832               register const Quantum
4833                 *p;
4834
4835               CacheView
4836                 *image_view;
4837
4838               if (image == (Image *) NULL)
4839                 break;
4840               if (image->storage_class != PseudoClass)
4841                 break;
4842               x=0;
4843               y=0;
4844               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
4845               (void) items;
4846               image_view=AcquireCacheView(image);
4847               p=GetCacheViewVirtualPixels(image_view,x,y,1,1,&image->exception);
4848               if (p != (const Quantum *) NULL)
4849                 {
4850                   (void) FormatLocaleString(name,MaxTextExtent,QuantumFormat,
4851                     GetPixelIndex(image,p));
4852                   s=newSVpv(name,0);
4853                   PUSHs(s ? sv_2mortal(s) : &sv_undef);
4854                 }
4855               image_view=DestroyCacheView(image_view);
4856               continue;
4857             }
4858           if (LocaleCompare(attribute,"iptc") == 0)
4859             {
4860               if (image != (Image *) NULL)
4861                 {
4862                   const StringInfo
4863                     *profile;
4864
4865                   profile=GetImageProfile(image,"iptc");
4866                   if (profile != (const StringInfo *) NULL)
4867                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4868                       GetStringInfoLength(profile));
4869                 }
4870               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4871               continue;
4872             }
4873           if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
4874             {
4875               if (image != (Image *) NULL)
4876                 s=newSViv((ssize_t) image->iterations);
4877               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4878               continue;
4879             }
4880           if (LocaleCompare(attribute,"interlace") == 0)
4881             {
4882               j=info ? info->image_info->interlace : image ? image->interlace :
4883                 UndefinedInterlace;
4884               s=newSViv(j);
4885               (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
4886                 j));
4887               SvIOK_on(s);
4888               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4889               continue;
4890             }
4891           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4892             attribute);
4893           break;
4894         }
4895         case 'L':
4896         case 'l':
4897         {
4898           if (LocaleCompare(attribute,"label") == 0)
4899             {
4900               const char
4901                 *value;
4902
4903               if (image == (Image *) NULL)
4904                 break;
4905               value=GetImageProperty(image,"Label");
4906               if (value != (const char *) NULL)
4907                 s=newSVpv(value,0);
4908               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4909               continue;
4910             }
4911           if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
4912             {
4913               if (image != (Image *) NULL)
4914                 s=newSViv((ssize_t) image->iterations);
4915               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4916               continue;
4917             }
4918           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4919             attribute);
4920           break;
4921         }
4922         case 'M':
4923         case 'm':
4924         {
4925           if (LocaleCompare(attribute,"magick") == 0)
4926             {
4927               if (info && *info->image_info->magick)
4928                 s=newSVpv(info->image_info->magick,0);
4929               if (image != (Image *) NULL)
4930                 s=newSVpv(image->magick,0);
4931               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4932               continue;
4933             }
4934           if (LocaleCompare(attribute,"map") == 0)
4935             {
4936               s=newSViv(GetMagickResource(MapResource));
4937               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4938               continue;
4939             }
4940           if (LocaleCompare(attribute,"maximum-error") == 0)
4941             {
4942               if (image != (Image *) NULL)
4943                 s=newSVnv(image->error.normalized_maximum_error);
4944               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4945               continue;
4946             }
4947           if (LocaleCompare(attribute,"memory") == 0)
4948             {
4949               s=newSViv(GetMagickResource(MemoryResource));
4950               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4951               continue;
4952             }
4953           if (LocaleCompare(attribute,"mean-error") == 0)
4954             {
4955               if (image != (Image *) NULL)
4956                 s=newSVnv(image->error.normalized_mean_error);
4957               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4958               continue;
4959             }
4960           if (LocaleCompare(attribute,"mime") == 0)
4961             {
4962               if (info && *info->image_info->magick)
4963                 s=newSVpv(MagickToMime(info->image_info->magick),0);
4964               if (image != (Image *) NULL)
4965                 s=newSVpv(MagickToMime(image->magick),0);
4966               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4967               continue;
4968             }
4969           if (LocaleCompare(attribute,"mattecolor") == 0)
4970             {
4971               if (image == (Image *) NULL)
4972                 break;
4973               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4974                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4975                 image->matte_color.red,image->matte_color.green,
4976                 image->matte_color.blue,image->matte_color.alpha);
4977               s=newSVpv(color,0);
4978               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4979               continue;
4980             }
4981           if (LocaleCompare(attribute,"matte") == 0)
4982             {
4983               if (image != (Image *) NULL)
4984                 s=newSViv((ssize_t) image->matte);
4985               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4986               continue;
4987             }
4988           if (LocaleCompare(attribute,"mime") == 0)
4989             {
4990               const char
4991                 *magick;
4992
4993               magick=NULL;
4994               if (info && *info->image_info->magick)
4995                 magick=info->image_info->magick;
4996               if (image != (Image *) NULL)
4997                 magick=image->magick;
4998               if (magick)
4999                 {
5000                   char
5001                     *mime;
5002
5003                   mime=MagickToMime(magick);
5004                   s=newSVpv(mime,0);
5005                   mime=(char *) RelinquishMagickMemory(mime);
5006                 }
5007               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5008               continue;
5009             }
5010           if (LocaleCompare(attribute,"monochrome") == 0)
5011             {
5012               if (image == (Image *) NULL)
5013                 continue;
5014               j=info ? info->image_info->monochrome :
5015                 IsImageMonochrome(image,&image->exception);
5016               s=newSViv(j);
5017               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5018               continue;
5019             }
5020           if (LocaleCompare(attribute,"montage") == 0)
5021             {
5022               if (image && image->montage)
5023                 s=newSVpv(image->montage,0);
5024               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5025               continue;
5026             }
5027           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5028             attribute);
5029           break;
5030         }
5031         case 'O':
5032         case 'o':
5033         {
5034           if (LocaleCompare(attribute,"orientation") == 0)
5035             {
5036               j=info ? info->image_info->orientation : image ?
5037                 image->orientation : UndefinedOrientation;
5038               s=newSViv(j);
5039               (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5040                 j));
5041               SvIOK_on(s);
5042               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5043               continue;
5044             }
5045           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5046             attribute);
5047           break;
5048         }
5049         case 'P':
5050         case 'p':
5051         {
5052           if (LocaleCompare(attribute,"page") == 0)
5053             {
5054               if (info && info->image_info->page)
5055                 s=newSVpv(info->image_info->page,0);
5056               if (image != (Image *) NULL)
5057                 {
5058                   char
5059                     geometry[MaxTextExtent];
5060
5061                   (void) FormatLocaleString(geometry,MaxTextExtent,
5062                     "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5063                     (double) image->page.height,(double) image->page.x,(double)
5064                     image->page.y);
5065                   s=newSVpv(geometry,0);
5066                 }
5067               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5068               continue;
5069             }
5070           if (LocaleCompare(attribute,"page.x") == 0)
5071             {
5072               if (image != (Image *) NULL)
5073                 s=newSViv((ssize_t) image->page.x);
5074               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5075               continue;
5076             }
5077           if (LocaleCompare(attribute,"page.y") == 0)
5078             {
5079               if (image != (Image *) NULL)
5080                 s=newSViv((ssize_t) image->page.y);
5081               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5082               continue;
5083             }
5084           if (LocaleNCompare(attribute,"pixel",5) == 0)
5085             {
5086               char
5087                 tuple[MaxTextExtent];
5088
5089               int
5090                 items;
5091
5092               long
5093                 x,
5094                 y;
5095
5096               register const Quantum
5097                 *p;
5098
5099               if (image == (Image *) NULL)
5100                 break;
5101               x=0;
5102               y=0;
5103               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5104               (void) items;
5105               p=GetVirtualPixels(image,x,y,1,1,exception);
5106               if (image->colorspace != CMYKColorspace)
5107                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5108                   QuantumFormat "," QuantumFormat "," QuantumFormat,
5109                   GetPixelRed(image,p),GetPixelGreen(image,p),
5110                   GetPixelBlue(image,p),GetPixelAlpha(image,p));
5111               else
5112                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5113                   QuantumFormat "," QuantumFormat "," QuantumFormat ","
5114                   QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5115                   GetPixelBlue(image,p),GetPixelBlack(image,p),
5116                   GetPixelAlpha(image,p));
5117               s=newSVpv(tuple,0);
5118               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5119               continue;
5120             }
5121           if (LocaleCompare(attribute,"pointsize") == 0)
5122             {
5123               if (info)
5124                 s=newSViv((ssize_t) info->image_info->pointsize);
5125               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5126               continue;
5127             }
5128           if (LocaleCompare(attribute,"preview") == 0)
5129             {
5130               s=newSViv(info->image_info->preview_type);
5131               (void) sv_setpv(s,CommandOptionToMnemonic(MagickPreviewOptions,
5132                 info->image_info->preview_type));
5133               SvIOK_on(s);
5134               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5135               continue;
5136             }
5137           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5138             attribute);
5139           break;
5140         }
5141         case 'Q':
5142         case 'q':
5143         {
5144           if (LocaleCompare(attribute,"quality") == 0)
5145             {
5146               if (info)
5147                 s=newSViv((ssize_t) info->image_info->quality);
5148               if (image != (Image *) NULL)
5149                 s=newSViv((ssize_t) image->quality);
5150               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5151               continue;
5152             }
5153           if (LocaleCompare(attribute,"quantum") == 0)
5154             {
5155               if (info)
5156                 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5157               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5158               continue;
5159             }
5160           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5161             attribute);
5162           break;
5163         }
5164         case 'R':
5165         case 'r':
5166         {
5167           if (LocaleCompare(attribute,"rendering-intent") == 0)
5168             {
5169               s=newSViv(image->rendering_intent);
5170               (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5171                 image->rendering_intent));
5172               SvIOK_on(s);
5173               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5174               continue;
5175             }
5176           if (LocaleCompare(attribute,"red-primary") == 0)
5177             {
5178               if (image == (Image *) NULL)
5179                 break;
5180               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5181                 image->chromaticity.red_primary.x,
5182                 image->chromaticity.red_primary.y);
5183               s=newSVpv(color,0);
5184               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5185               continue;
5186             }
5187           if (LocaleCompare(attribute,"rows") == 0)
5188             {
5189               if (image != (Image *) NULL)
5190                 s=newSViv((ssize_t) image->rows);
5191               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5192               continue;
5193             }
5194           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5195             attribute);
5196           break;
5197         }
5198         case 'S':
5199         case 's':
5200         {
5201           if (LocaleCompare(attribute,"sampling-factor") == 0)
5202             {
5203               if (info && info->image_info->sampling_factor)
5204                 s=newSVpv(info->image_info->sampling_factor,0);
5205               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5206               continue;
5207             }
5208           if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5209             {
5210               if (info && info->image_info->server_name)
5211                 s=newSVpv(info->image_info->server_name,0);
5212               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5213               continue;
5214             }
5215           if (LocaleCompare(attribute,"size") == 0)
5216             {
5217               if (info && info->image_info->size)
5218                 s=newSVpv(info->image_info->size,0);
5219               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5220               continue;
5221             }
5222           if (LocaleCompare(attribute,"scene") == 0)
5223             {
5224               if (image != (Image *) NULL)
5225                 s=newSViv((ssize_t) image->scene);
5226               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5227               continue;
5228             }
5229           if (LocaleCompare(attribute,"scenes") == 0)
5230             {
5231               if (image != (Image *) NULL)
5232                 s=newSViv((ssize_t) info->image_info->number_scenes);
5233               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5234               continue;
5235             }
5236           if (LocaleCompare(attribute,"signature") == 0)
5237             {
5238               const char
5239                 *value;
5240
5241               if (image == (Image *) NULL)
5242                 break;
5243               (void) SignatureImage(image,exception);
5244               value=GetImageProperty(image,"Signature");
5245               if (value != (const char *) NULL)
5246                 s=newSVpv(value,0);
5247               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5248               continue;
5249             }
5250           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5251             attribute);
5252           break;
5253         }
5254         case 'T':
5255         case 't':
5256         {
5257           if (LocaleCompare(attribute,"taint") == 0)
5258             {
5259               if (image != (Image *) NULL)
5260                 s=newSViv((ssize_t) IsTaintImage(image));
5261               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5262               continue;
5263             }
5264           if (LocaleCompare(attribute,"texture") == 0)
5265             {
5266               if (info && info->image_info->texture)
5267                 s=newSVpv(info->image_info->texture,0);
5268               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5269               continue;
5270             }
5271           if (LocaleCompare(attribute,"total-ink-density") == 0)
5272             {
5273               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5274               if (image != (Image *) NULL)
5275                 s=newSVnv(GetImageTotalInkDensity(image));
5276               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5277               continue;
5278             }
5279           if (LocaleCompare(attribute,"transparent-color") == 0)
5280             {
5281               if (image == (Image *) NULL)
5282                 break;
5283               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
5284                 QuantumFormat "," QuantumFormat "," QuantumFormat,
5285                 image->transparent_color.red,image->transparent_color.green,
5286                 image->transparent_color.blue,image->transparent_color.alpha);
5287               s=newSVpv(color,0);
5288               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5289               continue;
5290             }
5291           if (LocaleCompare(attribute,"type") == 0)
5292             {
5293               if (image == (Image *) NULL)
5294                 break;
5295               j=(ssize_t) GetImageType(image,&image->exception);
5296               s=newSViv(j);
5297               (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5298               SvIOK_on(s);
5299               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5300               continue;
5301             }
5302           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5303             attribute);
5304           break;
5305         }
5306         case 'U':
5307         case 'u':
5308         {
5309           if (LocaleCompare(attribute,"units") == 0)
5310             {
5311               j=info ? info->image_info->units : image ? image->units :
5312                 UndefinedResolution;
5313               if (info && (info->image_info->units == UndefinedResolution))
5314                 if (image)
5315                   j=image->units;
5316               if (j == UndefinedResolution)
5317                 s=newSVpv("undefined units",0);
5318               else
5319                 if (j == PixelsPerInchResolution)
5320                   s=newSVpv("pixels / inch",0);
5321                 else
5322                   s=newSVpv("pixels / centimeter",0);
5323               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5324               continue;
5325             }
5326           if (LocaleCompare(attribute,"user-time") == 0)
5327             {
5328               if (image != (Image *) NULL)
5329                 s=newSVnv(GetUserTime(&image->timer));
5330               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5331               continue;
5332             }
5333           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5334             attribute);
5335           break;
5336         }
5337         case 'V':
5338         case 'v':
5339         {
5340           if (LocaleCompare(attribute,"verbose") == 0)
5341             {
5342               if (info)
5343                 s=newSViv((ssize_t) info->image_info->verbose);
5344               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5345               continue;
5346             }
5347           if (LocaleCompare(attribute,"version") == 0)
5348             {
5349               s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5350               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5351               continue;
5352             }
5353           if (LocaleCompare(attribute,"view") == 0)
5354             {
5355               if (info && info->image_info->view)
5356                 s=newSVpv(info->image_info->view,0);
5357               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5358               continue;
5359             }
5360           if (LocaleCompare(attribute,"virtual-pixel") == 0)
5361             {
5362               if (image == (Image *) NULL)
5363                 break;
5364               j=(ssize_t) GetImageVirtualPixelMethod(image);
5365               s=newSViv(j);
5366               (void) sv_setpv(s,CommandOptionToMnemonic(
5367                 MagickVirtualPixelOptions,j));
5368               SvIOK_on(s);
5369               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5370               continue;
5371             }
5372           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5373             attribute);
5374           break;
5375         }
5376         case 'W':
5377         case 'w':
5378         {
5379           if (LocaleCompare(attribute,"white-point") == 0)
5380             {
5381               if (image == (Image *) NULL)
5382                 break;
5383               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5384                 image->chromaticity.white_point.x,
5385                 image->chromaticity.white_point.y);
5386               s=newSVpv(color,0);
5387               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5388               continue;
5389             }
5390           if (LocaleCompare(attribute,"width") == 0)
5391             {
5392               if (image != (Image *) NULL)
5393                 s=newSViv((ssize_t) image->columns);
5394               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5395               continue;
5396             }
5397           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5398              attribute);
5399           break;
5400         }
5401         case 'X':
5402         case 'x':
5403         {
5404           if (LocaleCompare(attribute,"x-resolution") == 0)
5405             {
5406               if (image != (Image *) NULL)
5407                 s=newSVnv(image->x_resolution);
5408               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5409               continue;
5410             }
5411           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5412             attribute);
5413           break;
5414         }
5415         case 'Y':
5416         case 'y':
5417         {
5418           if (LocaleCompare(attribute,"y-resolution") == 0)
5419             {
5420               if (image != (Image *) NULL)
5421                 s=newSVnv(image->y_resolution);
5422               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5423               continue;
5424             }
5425           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5426             attribute);
5427           break;
5428         }
5429         default:
5430           break;
5431       }
5432       if (image == (Image *) NULL)
5433         ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5434           attribute)
5435       else
5436         {
5437           value=GetImageProperty(image,attribute);
5438           if (value != (const char *) NULL)
5439             {
5440               s=newSVpv(value,0);
5441               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5442             }
5443           else
5444             if (*attribute != '%')
5445               ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5446                 attribute)
5447             else
5448               {
5449                  char
5450                    *meta;
5451
5452                  meta=InterpretImageProperties(info ? info->image_info :
5453                    (ImageInfo *) NULL,image,attribute,exception);
5454                  s=newSVpv(meta,0);
5455                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5456                  meta=(char *) RelinquishMagickMemory(meta);
5457               }
5458         }
5459     }
5460     exception=DestroyExceptionInfo(exception);
5461     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5462   }
5463 \f
5464 #
5465 ###############################################################################
5466 #                                                                             #
5467 #                                                                             #
5468 #                                                                             #
5469 #   G e t A u t h e n t i c P i x e l s                                       #
5470 #                                                                             #
5471 #                                                                             #
5472 #                                                                             #
5473 ###############################################################################
5474 #
5475 #
5476 void *
5477 GetAuthenticPixels(ref,...)
5478   Image::Magick ref = NO_INIT
5479   ALIAS:
5480     getauthenticpixels = 1
5481     GetImagePixels = 2
5482     getimagepixels = 3
5483   CODE:
5484   {
5485     char
5486       *attribute;
5487
5488     ExceptionInfo
5489       *exception;
5490
5491     Image
5492       *image;
5493
5494     RectangleInfo
5495       region;
5496
5497     ssize_t
5498       i;
5499
5500     struct PackageInfo
5501       *info;
5502
5503     SV
5504       *perl_exception,
5505       *reference;
5506
5507     void
5508       *blob = NULL;
5509
5510     PERL_UNUSED_VAR(ref);
5511     PERL_UNUSED_VAR(ix);
5512     exception=AcquireExceptionInfo();
5513     perl_exception=newSVpv("",0);
5514     if (sv_isobject(ST(0)) == 0)
5515       {
5516         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5517           PackageName);
5518         goto PerlException;
5519       }
5520     reference=SvRV(ST(0));
5521
5522     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5523     if (image == (Image *) NULL)
5524       {
5525         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5526           PackageName);
5527         goto PerlException;
5528       }
5529
5530     region.x=0;
5531     region.y=0;
5532     region.width=image->columns;
5533     region.height=1;
5534     if (items == 1)
5535       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5536     for (i=2; i < items; i+=2)
5537     {
5538       attribute=(char *) SvPV(ST(i-1),na);
5539       switch (*attribute)
5540       {
5541         case 'g':
5542         case 'G':
5543         {
5544           if (LocaleCompare(attribute,"geometry") == 0)
5545             {
5546               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5547               break;
5548             }
5549           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5550             attribute);
5551           break;
5552         }
5553         case 'H':
5554         case 'h':
5555         {
5556           if (LocaleCompare(attribute,"height") == 0)
5557             {
5558               region.height=SvIV(ST(i));
5559               continue;
5560             }
5561           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5562             attribute);
5563           break;
5564         }
5565         case 'X':
5566         case 'x':
5567         {
5568           if (LocaleCompare(attribute,"x") == 0)
5569             {
5570               region.x=SvIV(ST(i));
5571               continue;
5572             }
5573           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5574             attribute);
5575           break;
5576         }
5577         case 'Y':
5578         case 'y':
5579         {
5580           if (LocaleCompare(attribute,"y") == 0)
5581             {
5582               region.y=SvIV(ST(i));
5583               continue;
5584             }
5585           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5586             attribute);
5587           break;
5588         }
5589         case 'W':
5590         case 'w':
5591         {
5592           if (LocaleCompare(attribute,"width") == 0)
5593             {
5594               region.width=SvIV(ST(i));
5595               continue;
5596             }
5597           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5598             attribute);
5599           break;
5600         }
5601       }
5602     }
5603     blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5604       region.height,exception);
5605     if (blob != (void *) NULL)
5606       goto PerlEnd;
5607
5608   PerlException:
5609     InheritPerlException(exception,perl_exception);
5610     exception=DestroyExceptionInfo(exception);
5611     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5612
5613   PerlEnd:
5614     RETVAL = blob;
5615   }
5616   OUTPUT:
5617     RETVAL
5618 \f
5619 #
5620 ###############################################################################
5621 #                                                                             #
5622 #                                                                             #
5623 #                                                                             #
5624 #   G e t V i r t u a l P i x e l s                                           #
5625 #                                                                             #
5626 #                                                                             #
5627 #                                                                             #
5628 ###############################################################################
5629 #
5630 #
5631 void *
5632 GetVirtualPixels(ref,...)
5633   Image::Magick ref = NO_INIT
5634   ALIAS:
5635     getvirtualpixels = 1
5636     AcquireImagePixels = 2
5637     acquireimagepixels = 3
5638   CODE:
5639   {
5640     char
5641       *attribute;
5642
5643     const void
5644       *blob = NULL;
5645
5646     ExceptionInfo
5647       *exception;
5648
5649     Image
5650       *image;
5651
5652     RectangleInfo
5653       region;
5654
5655     ssize_t
5656       i;
5657
5658     struct PackageInfo
5659       *info;
5660
5661     SV
5662       *perl_exception,
5663       *reference;
5664
5665     PERL_UNUSED_VAR(ref);
5666     PERL_UNUSED_VAR(ix);
5667     exception=AcquireExceptionInfo();
5668     perl_exception=newSVpv("",0);
5669     if (sv_isobject(ST(0)) == 0)
5670       {
5671         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5672           PackageName);
5673         goto PerlException;
5674       }
5675     reference=SvRV(ST(0));
5676
5677     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5678     if (image == (Image *) NULL)
5679       {
5680         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5681           PackageName);
5682         goto PerlException;
5683       }
5684
5685     region.x=0;
5686     region.y=0;
5687     region.width=image->columns;
5688     region.height=1;
5689     if (items == 1)
5690       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5691     for (i=2; i < items; i+=2)
5692     {
5693       attribute=(char *) SvPV(ST(i-1),na);
5694       switch (*attribute)
5695       {
5696         case 'g':
5697         case 'G':
5698         {
5699           if (LocaleCompare(attribute,"geometry") == 0)
5700             {
5701               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5702               break;
5703             }
5704           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5705             attribute);
5706           break;
5707         }
5708         case 'H':
5709         case 'h':
5710         {
5711           if (LocaleCompare(attribute,"height") == 0)
5712             {
5713               region.height=SvIV(ST(i));
5714               continue;
5715             }
5716           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5717             attribute);
5718           break;
5719         }
5720         case 'X':
5721         case 'x':
5722         {
5723           if (LocaleCompare(attribute,"x") == 0)
5724             {
5725               region.x=SvIV(ST(i));
5726               continue;
5727             }
5728           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5729             attribute);
5730           break;
5731         }
5732         case 'Y':
5733         case 'y':
5734         {
5735           if (LocaleCompare(attribute,"y") == 0)
5736             {
5737               region.y=SvIV(ST(i));
5738               continue;
5739             }
5740           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5741             attribute);
5742           break;
5743         }
5744         case 'W':
5745         case 'w':
5746         {
5747           if (LocaleCompare(attribute,"width") == 0)
5748             {
5749               region.width=SvIV(ST(i));
5750               continue;
5751             }
5752           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5753             attribute);
5754           break;
5755         }
5756       }
5757     }
5758     blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
5759       region.height,exception);
5760     if (blob != (void *) NULL)
5761       goto PerlEnd;
5762
5763   PerlException:
5764     InheritPerlException(exception,perl_exception);
5765     exception=DestroyExceptionInfo(exception);
5766     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5767
5768   PerlEnd:
5769     RETVAL = (void *) blob;
5770   }
5771   OUTPUT:
5772     RETVAL
5773 \f
5774 #
5775 ###############################################################################
5776 #                                                                             #
5777 #                                                                             #
5778 #                                                                             #
5779 #   G e t A u t h e n t i c M e t a c o n t e n t                             #
5780 #                                                                             #
5781 #                                                                             #
5782 #                                                                             #
5783 ###############################################################################
5784 #
5785 #
5786 void *
5787 GetAuthenticMetacontent(ref,...)
5788   Image::Magick ref = NO_INIT
5789   ALIAS:
5790     getauthenticmetacontent = 1
5791     GetMetacontent = 2
5792     getmetacontent = 3
5793   CODE:
5794   {
5795     ExceptionInfo
5796       *exception;
5797
5798     Image
5799       *image;
5800
5801     struct PackageInfo
5802       *info;
5803
5804     SV
5805       *perl_exception,
5806       *reference;
5807
5808     void
5809       *blob = NULL;
5810
5811     PERL_UNUSED_VAR(ref);
5812     PERL_UNUSED_VAR(ix);
5813     exception=AcquireExceptionInfo();
5814     perl_exception=newSVpv("",0);
5815     if (sv_isobject(ST(0)) == 0)
5816       {
5817         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5818           PackageName);
5819         goto PerlException;
5820       }
5821     reference=SvRV(ST(0));
5822
5823     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5824     if (image == (Image *) NULL)
5825       {
5826         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5827           PackageName);
5828         goto PerlException;
5829       }
5830
5831     blob=(void *) GetAuthenticMetacontent(image);
5832     if (blob != (void *) NULL)
5833       goto PerlEnd;
5834
5835   PerlException:
5836     InheritPerlException(exception,perl_exception);
5837     exception=DestroyExceptionInfo(exception);
5838     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5839
5840   PerlEnd:
5841     RETVAL = blob;
5842   }
5843   OUTPUT:
5844     RETVAL
5845 \f
5846 #
5847 ###############################################################################
5848 #                                                                             #
5849 #                                                                             #
5850 #                                                                             #
5851 #   G e t V i r t u a l M e t a c o n t e n t                                 #
5852 #                                                                             #
5853 #                                                                             #
5854 #                                                                             #
5855 ###############################################################################
5856 #
5857 #
5858 void *
5859 GetVirtualMetacontent(ref,...)
5860   Image::Magick ref = NO_INIT
5861   ALIAS:
5862     getvirtualmetacontent = 1
5863   CODE:
5864   {
5865     ExceptionInfo
5866       *exception;
5867
5868     Image
5869       *image;
5870
5871     struct PackageInfo
5872       *info;
5873
5874     SV
5875       *perl_exception,
5876       *reference;
5877
5878     void
5879       *blob = NULL;
5880
5881     PERL_UNUSED_VAR(ref);
5882     PERL_UNUSED_VAR(ix);
5883     exception=AcquireExceptionInfo();
5884     perl_exception=newSVpv("",0);
5885     if (sv_isobject(ST(0)) == 0)
5886       {
5887         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5888           PackageName);
5889         goto PerlException;
5890       }
5891     reference=SvRV(ST(0));
5892
5893     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5894     if (image == (Image *) NULL)
5895       {
5896         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5897           PackageName);
5898         goto PerlException;
5899       }
5900
5901     blob=(void *) GetVirtualMetacontent(image);
5902     if (blob != (void *) NULL)
5903       goto PerlEnd;
5904
5905   PerlException:
5906     InheritPerlException(exception,perl_exception);
5907     exception=DestroyExceptionInfo(exception);
5908     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5909
5910   PerlEnd:
5911     RETVAL = blob;
5912   }
5913   OUTPUT:
5914     RETVAL
5915 \f
5916 #
5917 ###############################################################################
5918 #                                                                             #
5919 #                                                                             #
5920 #                                                                             #
5921 #   H i s t o g r a m                                                         #
5922 #                                                                             #
5923 #                                                                             #
5924 #                                                                             #
5925 ###############################################################################
5926 #
5927 #
5928 void
5929 Histogram(ref,...)
5930   Image::Magick ref=NO_INIT
5931   ALIAS:
5932     HistogramImage = 1
5933     histogram      = 2
5934     histogramimage = 3
5935   PPCODE:
5936   {
5937     AV
5938       *av;
5939
5940     char
5941       message[MaxTextExtent];
5942
5943     PixelPacket
5944       *histogram;
5945
5946     ExceptionInfo
5947       *exception;
5948
5949     Image
5950       *image;
5951
5952     register ssize_t
5953       i;
5954
5955     ssize_t
5956       count;
5957
5958     struct PackageInfo
5959       *info;
5960
5961     SV
5962       *perl_exception,
5963       *reference;
5964
5965     size_t
5966       number_colors;
5967
5968     PERL_UNUSED_VAR(ref);
5969     PERL_UNUSED_VAR(ix);
5970     exception=AcquireExceptionInfo();
5971     perl_exception=newSVpv("",0);
5972     av=NULL;
5973     if (sv_isobject(ST(0)) == 0)
5974       {
5975         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5976           PackageName);
5977         goto PerlException;
5978       }
5979     reference=SvRV(ST(0));
5980     av=newAV();
5981     SvREFCNT_dec(av);
5982     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5983     if (image == (Image *) NULL)
5984       {
5985         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5986           PackageName);
5987         goto PerlException;
5988       }
5989     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
5990     count=0;
5991     for ( ; image; image=image->next)
5992     {
5993       histogram=GetImageHistogram(image,&number_colors,&image->exception);
5994       if (histogram == (PixelPacket *) NULL)
5995         continue;
5996       count+=(ssize_t) number_colors;
5997       EXTEND(sp,6*count);
5998       for (i=0; i < (ssize_t) number_colors; i++)
5999       {
6000         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
6001           histogram[i].red);
6002         PUSHs(sv_2mortal(newSVpv(message,0)));
6003         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
6004           histogram[i].green);
6005         PUSHs(sv_2mortal(newSVpv(message,0)));
6006         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
6007           histogram[i].blue);
6008         PUSHs(sv_2mortal(newSVpv(message,0)));
6009         if (image->colorspace == CMYKColorspace)
6010           {
6011             (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
6012               histogram[i].black);
6013             PUSHs(sv_2mortal(newSVpv(message,0)));
6014           }
6015         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
6016           histogram[i].alpha);
6017         PUSHs(sv_2mortal(newSVpv(message,0)));
6018         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
6019           histogram[i].count);
6020         PUSHs(sv_2mortal(newSVpv(message,0)));
6021       }
6022       histogram=(PixelPacket *) RelinquishMagickMemory(histogram);
6023     }
6024
6025   PerlException:
6026     InheritPerlException(exception,perl_exception);
6027     exception=DestroyExceptionInfo(exception);
6028     SvREFCNT_dec(perl_exception);
6029   }
6030 \f
6031 #
6032 ###############################################################################
6033 #                                                                             #
6034 #                                                                             #
6035 #                                                                             #
6036 #   G e t P i x e l                                                           #
6037 #                                                                             #
6038 #                                                                             #
6039 #                                                                             #
6040 ###############################################################################
6041 #
6042 #
6043 void
6044 GetPixel(ref,...)
6045   Image::Magick ref=NO_INIT
6046   ALIAS:
6047     getpixel = 1
6048     getPixel = 2
6049   PPCODE:
6050   {
6051     AV
6052       *av;
6053
6054     char
6055       *attribute;
6056
6057     ExceptionInfo
6058       *exception;
6059
6060     Image
6061       *image;
6062
6063     MagickBooleanType
6064       normalize;
6065
6066     RectangleInfo
6067       region;
6068
6069     register const Quantum
6070       *p;
6071
6072     register ssize_t
6073       i;
6074
6075     ssize_t
6076       option;
6077
6078     struct PackageInfo
6079       *info;
6080
6081     SV
6082       *perl_exception,
6083       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6084
6085     PERL_UNUSED_VAR(ref);
6086     PERL_UNUSED_VAR(ix);
6087     exception=AcquireExceptionInfo();
6088     perl_exception=newSVpv("",0);
6089     reference=SvRV(ST(0));
6090     av=(AV *) reference;
6091     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6092       exception);
6093     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6094     if (image == (Image *) NULL)
6095       {
6096         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6097           PackageName);
6098         goto PerlException;
6099       }
6100     normalize=MagickTrue;
6101     region.x=0;
6102     region.y=0;
6103     region.width=image->columns;
6104     region.height=1;
6105     if (items == 1)
6106       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6107     for (i=2; i < items; i+=2)
6108     {
6109       attribute=(char *) SvPV(ST(i-1),na);
6110       switch (*attribute)
6111       {
6112         case 'C':
6113         case 'c':
6114         {
6115           if (LocaleCompare(attribute,"channel") == 0)
6116             {
6117               ssize_t
6118                 option;
6119
6120               option=ParseChannelOption(SvPV(ST(i),na));
6121               if (option < 0)
6122                 {
6123                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6124                     SvPV(ST(i),na));
6125                   return;
6126                 }
6127               SetPixelChannelMap(image,(ChannelType) option);
6128               break;
6129             }
6130           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6131             attribute);
6132           break;
6133         }
6134         case 'g':
6135         case 'G':
6136         {
6137           if (LocaleCompare(attribute,"geometry") == 0)
6138             {
6139               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6140               break;
6141             }
6142           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6143             attribute);
6144           break;
6145         }
6146         case 'N':
6147         case 'n':
6148         {
6149           if (LocaleCompare(attribute,"normalize") == 0)
6150             {
6151               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6152                 SvPV(ST(i),na));
6153               if (option < 0)
6154                 {
6155                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6156                     SvPV(ST(i),na));
6157                   break;
6158                 }
6159              normalize=option != 0 ? MagickTrue : MagickFalse;
6160              break;
6161             }
6162           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6163             attribute);
6164           break;
6165         }
6166         case 'x':
6167         case 'X':
6168         {
6169           if (LocaleCompare(attribute,"x") == 0)
6170             {
6171               region.x=SvIV(ST(i));
6172               break;
6173             }
6174           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6175             attribute);
6176           break;
6177         }
6178         case 'y':
6179         case 'Y':
6180         {
6181           if (LocaleCompare(attribute,"y") == 0)
6182             {
6183               region.y=SvIV(ST(i));
6184               break;
6185             }
6186           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6187             attribute);
6188           break;
6189         }
6190         default:
6191         {
6192           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6193             attribute);
6194           break;
6195         }
6196       }
6197     }
6198     p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6199     if (p == (const Quantum *) NULL)
6200       PUSHs(&sv_undef);
6201     else
6202       {
6203         double
6204           scale;
6205
6206         scale=1.0;
6207         if (normalize != MagickFalse)
6208           scale=1.0/QuantumRange;
6209         if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
6210           PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6211         if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6212           PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6213         if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6214           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6215         if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6216             (image->colorspace == CMYKColorspace))
6217           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6218         if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
6219           PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6220       }
6221
6222   PerlException:
6223     InheritPerlException(exception,perl_exception);
6224     exception=DestroyExceptionInfo(exception);
6225     SvREFCNT_dec(perl_exception);
6226   }
6227 \f
6228 #
6229 ###############################################################################
6230 #                                                                             #
6231 #                                                                             #
6232 #                                                                             #
6233 #   G e t P i x e l s                                                         #
6234 #                                                                             #
6235 #                                                                             #
6236 #                                                                             #
6237 ###############################################################################
6238 #
6239 #
6240 void
6241 GetPixels(ref,...)
6242   Image::Magick ref=NO_INIT
6243   ALIAS:
6244     getpixels = 1
6245     getPixels = 2
6246   PPCODE:
6247   {
6248     AV
6249       *av;
6250
6251     char
6252       *attribute;
6253
6254     const char
6255       *map;
6256
6257     ExceptionInfo
6258       *exception;
6259
6260     Image
6261       *image;
6262
6263     MagickBooleanType
6264       normalize,
6265       status;
6266
6267     RectangleInfo
6268       region;
6269
6270     register ssize_t
6271       i;
6272
6273     ssize_t
6274       option;
6275
6276     struct PackageInfo
6277       *info;
6278
6279     SV
6280       *perl_exception,
6281       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6282
6283     PERL_UNUSED_VAR(ref);
6284     PERL_UNUSED_VAR(ix);
6285     exception=AcquireExceptionInfo();
6286     perl_exception=newSVpv("",0);
6287     reference=SvRV(ST(0));
6288     av=(AV *) reference;
6289     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6290       exception);
6291     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6292     if (image == (Image *) NULL)
6293       {
6294         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6295           PackageName);
6296         goto PerlException;
6297       }
6298     map="RGB";
6299     if (image->matte != MagickFalse)
6300       map="RGBA";
6301     if (image->colorspace == CMYKColorspace)
6302       {
6303         map="CMYK";
6304         if (image->matte != MagickFalse)
6305           map="CMYKA";
6306       }
6307     normalize=MagickFalse;
6308     region.x=0;
6309     region.y=0;
6310     region.width=image->columns;
6311     region.height=1;
6312     if (items == 1)
6313       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6314     for (i=2; i < items; i+=2)
6315     {
6316       attribute=(char *) SvPV(ST(i-1),na);
6317       switch (*attribute)
6318       {
6319         case 'g':
6320         case 'G':
6321         {
6322           if (LocaleCompare(attribute,"geometry") == 0)
6323             {
6324               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6325               break;
6326             }
6327           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6328             attribute);
6329           break;
6330         }
6331         case 'H':
6332         case 'h':
6333         {
6334           if (LocaleCompare(attribute,"height") == 0)
6335             {
6336               region.height=SvIV(ST(i));
6337               break;
6338             }
6339           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6340             attribute);
6341           break;
6342         }
6343         case 'M':
6344         case 'm':
6345         {
6346           if (LocaleCompare(attribute,"map") == 0)
6347             {
6348               map=SvPV(ST(i),na);
6349               break;
6350             }
6351           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6352             attribute);
6353           break;
6354         }
6355         case 'N':
6356         case 'n':
6357         {
6358           if (LocaleCompare(attribute,"normalize") == 0)
6359             {
6360               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6361                 SvPV(ST(i),na));
6362               if (option < 0)
6363                 {
6364                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6365                     SvPV(ST(i),na));
6366                   break;
6367                 }
6368              normalize=option != 0 ? MagickTrue : MagickFalse;
6369              break;
6370             }
6371           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6372             attribute);
6373           break;
6374         }
6375         case 'W':
6376         case 'w':
6377         {
6378           if (LocaleCompare(attribute,"width") == 0)
6379             {
6380               region.width=SvIV(ST(i));
6381               break;
6382             }
6383           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6384             attribute);
6385           break;
6386         }
6387         case 'x':
6388         case 'X':
6389         {
6390           if (LocaleCompare(attribute,"x") == 0)
6391             {
6392               region.x=SvIV(ST(i));
6393               break;
6394             }
6395           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6396             attribute);
6397           break;
6398         }
6399         case 'y':
6400         case 'Y':
6401         {
6402           if (LocaleCompare(attribute,"y") == 0)
6403             {
6404               region.y=SvIV(ST(i));
6405               break;
6406             }
6407           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6408             attribute);
6409           break;
6410         }
6411         default:
6412         {
6413           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6414             attribute);
6415           break;
6416         }
6417       }
6418     }
6419     if (normalize != MagickFalse)
6420       {
6421         float
6422           *pixels;
6423
6424         pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6425           region.height*sizeof(*pixels));
6426         if (pixels == (float *) NULL)
6427           {
6428             ThrowPerlException(exception,ResourceLimitError,
6429               "MemoryAllocationFailed",PackageName);
6430             goto PerlException;
6431           }
6432         status=ExportImagePixels(image,region.x,region.y,region.width,
6433           region.height,map,FloatPixel,pixels,exception);
6434         if (status == MagickFalse)
6435           PUSHs(&sv_undef);
6436         else
6437           {
6438             EXTEND(sp,strlen(map)*region.width*region.height);
6439             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6440               PUSHs(sv_2mortal(newSVnv(pixels[i])));
6441           }
6442         pixels=(float *) RelinquishMagickMemory(pixels);
6443       }
6444     else
6445       {
6446         Quantum
6447           *pixels;
6448
6449         pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6450           region.height*sizeof(*pixels));
6451         if (pixels == (Quantum *) NULL)
6452           {
6453             ThrowPerlException(exception,ResourceLimitError,
6454               "MemoryAllocationFailed",PackageName);
6455             goto PerlException;
6456           }
6457         status=ExportImagePixels(image,region.x,region.y,region.width,
6458           region.height,map,QuantumPixel,pixels,exception);
6459         if (status == MagickFalse)
6460           PUSHs(&sv_undef);
6461         else
6462           {
6463             EXTEND(sp,strlen(map)*region.width*region.height);
6464             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6465               PUSHs(sv_2mortal(newSViv(pixels[i])));
6466           }
6467         pixels=(Quantum *) RelinquishMagickMemory(pixels);
6468       }
6469
6470   PerlException:
6471     InheritPerlException(exception,perl_exception);
6472     exception=DestroyExceptionInfo(exception);
6473     SvREFCNT_dec(perl_exception);
6474   }
6475 \f
6476 #
6477 ###############################################################################
6478 #                                                                             #
6479 #                                                                             #
6480 #                                                                             #
6481 #   I m a g e T o B l o b                                                     #
6482 #                                                                             #
6483 #                                                                             #
6484 #                                                                             #
6485 ###############################################################################
6486 #
6487 #
6488 void
6489 ImageToBlob(ref,...)
6490   Image::Magick ref=NO_INIT
6491   ALIAS:
6492     ImageToBlob  = 1
6493     imagetoblob  = 2
6494     toblob       = 3
6495     blob         = 4
6496   PPCODE:
6497   {
6498     char
6499       filename[MaxTextExtent];
6500
6501     ExceptionInfo
6502       *exception;
6503
6504     Image
6505       *image,
6506       *next;
6507
6508     register ssize_t
6509       i;
6510
6511     struct PackageInfo
6512       *info,
6513       *package_info;
6514
6515     size_t
6516       length;
6517
6518     ssize_t
6519       scene;
6520
6521     SV
6522       *perl_exception,
6523       *reference;
6524
6525     void
6526       *blob;
6527
6528     PERL_UNUSED_VAR(ref);
6529     PERL_UNUSED_VAR(ix);
6530     exception=AcquireExceptionInfo();
6531     perl_exception=newSVpv("",0);
6532     package_info=(struct PackageInfo *) NULL;
6533     if (sv_isobject(ST(0)) == 0)
6534       {
6535         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6536           PackageName);
6537         goto PerlException;
6538       }
6539     reference=SvRV(ST(0));
6540     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6541     if (image == (Image *) NULL)
6542       {
6543         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6544           PackageName);
6545         goto PerlException;
6546       }
6547     package_info=ClonePackageInfo(info,exception);
6548     for (i=2; i < items; i+=2)
6549       SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6550     (void) CopyMagickString(filename,package_info->image_info->filename,
6551       MaxTextExtent);
6552     scene=0;
6553     for (next=image; next; next=next->next)
6554     {
6555       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
6556       next->scene=scene++;
6557     }
6558     SetImageInfo(package_info->image_info,(unsigned int)
6559       GetImageListLength(image),&image->exception);
6560     EXTEND(sp,(ssize_t) GetImageListLength(image));
6561     for ( ; image; image=image->next)
6562     {
6563       length=0;
6564       blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6565       if (blob != (char *) NULL)
6566         {
6567           PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6568           blob=(unsigned char *) RelinquishMagickMemory(blob);
6569         }
6570       if (package_info->image_info->adjoin)
6571         break;
6572     }
6573
6574   PerlException:
6575     if (package_info != (struct PackageInfo *) NULL)
6576       DestroyPackageInfo(package_info);
6577     InheritPerlException(exception,perl_exception);
6578     exception=DestroyExceptionInfo(exception);
6579     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6580   }
6581 \f
6582 #
6583 ###############################################################################
6584 #                                                                             #
6585 #                                                                             #
6586 #                                                                             #
6587 #   L a y e r s                                                               #
6588 #                                                                             #
6589 #                                                                             #
6590 #                                                                             #
6591 ###############################################################################
6592 #
6593 #
6594 void
6595 Layers(ref,...)
6596   Image::Magick ref=NO_INIT
6597   ALIAS:
6598     Layers                = 1
6599     layers           = 2
6600     OptimizeImageLayers   = 3
6601     optimizelayers        = 4
6602     optimizeimagelayers   = 5
6603   PPCODE:
6604   {
6605     AV
6606       *av;
6607
6608     char
6609       *attribute;
6610
6611     CompositeOperator
6612       compose;
6613
6614     ExceptionInfo
6615       *exception;
6616
6617     HV
6618       *hv;
6619
6620     Image
6621       *image,
6622       *layers;
6623
6624     ImageLayerMethod
6625       method;
6626
6627     register ssize_t
6628       i;
6629
6630     ssize_t
6631       option,
6632       sp;
6633
6634     struct PackageInfo
6635       *info;
6636
6637     SV
6638       *av_reference,
6639       *perl_exception,
6640       *reference,
6641       *rv,
6642       *sv;
6643
6644     PERL_UNUSED_VAR(ref);
6645     PERL_UNUSED_VAR(ix);
6646     exception=AcquireExceptionInfo();
6647     perl_exception=newSVpv("",0);
6648     sv=NULL;
6649     if (sv_isobject(ST(0)) == 0)
6650       {
6651         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6652           PackageName);
6653         goto PerlException;
6654       }
6655     reference=SvRV(ST(0));
6656     hv=SvSTASH(reference);
6657     av=newAV();
6658     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
6659     SvREFCNT_dec(av);
6660     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6661     if (image == (Image *) NULL)
6662       {
6663         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6664           PackageName);
6665         goto PerlException;
6666       }
6667     compose=image->compose;
6668     method=OptimizeLayer;
6669     for (i=2; i < items; i+=2)
6670     {
6671       attribute=(char *) SvPV(ST(i-1),na);
6672       switch (*attribute)
6673       {
6674         case 'C':
6675         case 'c':
6676         {
6677           if (LocaleCompare(attribute,"compose") == 0)
6678             {
6679               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
6680                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
6681               if (sp < 0)
6682                 {
6683                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6684                     SvPV(ST(i),na));
6685                   break;
6686                 }
6687               compose=(CompositeOperator) sp;
6688               break;
6689             }
6690           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6691             attribute);
6692           break;
6693         }
6694         case 'M':
6695         case 'm':
6696         {
6697           if (LocaleCompare(attribute,"method") == 0)
6698             {
6699               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
6700                 SvPV(ST(i),na));
6701               if (option < 0)
6702                 {
6703                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6704                     SvPV(ST(i),na));
6705                   break;
6706                 }
6707               method=(ImageLayerMethod) option;
6708               break;
6709             }
6710           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6711             attribute);
6712           break;
6713         }
6714         default:
6715         {
6716           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6717             attribute);
6718           break;
6719         }
6720       }
6721     }
6722     layers=(Image *) NULL;
6723     switch (method)
6724     {
6725       case CompareAnyLayer:
6726       case CompareClearLayer:
6727       case CompareOverlayLayer:
6728       default:
6729       {
6730         layers=CompareImagesLayers(image,method,exception);
6731         break;
6732       }
6733       case MergeLayer:
6734       case FlattenLayer:
6735       case MosaicLayer:
6736       {
6737         layers=MergeImageLayers(image,method,exception);
6738         break;
6739       }
6740       case DisposeLayer:
6741       {
6742         layers=DisposeImages(image,exception);
6743         break;
6744       }
6745       case OptimizeImageLayer:
6746       {
6747         layers=OptimizeImageLayers(image,exception);
6748         break;
6749       }
6750       case OptimizePlusLayer:
6751       {
6752         layers=OptimizePlusImageLayers(image,exception);
6753         break;
6754       }
6755       case OptimizeTransLayer:
6756       {
6757         OptimizeImageTransparency(image,exception);
6758         InheritException(&(image->exception),exception);
6759         break;
6760       }
6761       case RemoveDupsLayer:
6762       {
6763         RemoveDuplicateLayers(&image,exception);
6764         InheritException(&(image->exception),exception);
6765         break;
6766       }
6767       case RemoveZeroLayer:
6768       {
6769         RemoveZeroDelayLayers(&image,exception);
6770         InheritException(&(image->exception),exception);
6771         break;
6772       }
6773       case OptimizeLayer:
6774       {
6775         QuantizeInfo
6776           *quantize_info;
6777
6778         /*
6779           General Purpose, GIF Animation Optimizer.
6780         */
6781         layers=CoalesceImages(image,exception);
6782         if (layers == (Image *) NULL)
6783           break;
6784         InheritException(&(layers->exception),exception);
6785         image=layers;
6786         layers=OptimizeImageLayers(image,exception);
6787         if (layers == (Image *) NULL)
6788           break;
6789         InheritException(&(layers->exception),exception);
6790         image=DestroyImageList(image);
6791         image=layers;
6792         layers=(Image *) NULL;
6793         OptimizeImageTransparency(image,exception);
6794         InheritException(&(image->exception),exception);
6795         quantize_info=AcquireQuantizeInfo(info->image_info);
6796         (void) RemapImages(quantize_info,image,(Image *) NULL,exception);
6797         quantize_info=DestroyQuantizeInfo(quantize_info);
6798         break;
6799       }
6800       case CompositeLayer:
6801       {
6802         Image
6803           *source;
6804
6805         RectangleInfo
6806           geometry;
6807
6808         /*
6809           Split image sequence at the first 'NULL:' image.
6810         */
6811         source=image;
6812         while (source != (Image *) NULL)
6813         {
6814           source=GetNextImageInList(source);
6815           if ((source != (Image *) NULL) &&
6816               (LocaleCompare(source->magick,"NULL") == 0))
6817             break;
6818         }
6819         if (source != (Image *) NULL)
6820           {
6821             if ((GetPreviousImageInList(source) == (Image *) NULL) ||
6822                 (GetNextImageInList(source) == (Image *) NULL))
6823               source=(Image *) NULL;
6824             else
6825               {
6826                 /*
6827                   Separate the two lists, junk the null: image.
6828                 */
6829                 source=SplitImageList(source->previous);
6830                 DeleteImageFromList(&source);
6831               }
6832           }
6833         if (source == (Image *) NULL)
6834           {
6835             (void) ThrowMagickException(exception,GetMagickModule(),
6836               OptionError,"MissingNullSeparator","layers Composite");
6837             break;
6838           }
6839         /*
6840           Adjust offset with gravity and virtual canvas.
6841         */
6842         SetGeometry(image,&geometry);
6843         (void) ParseAbsoluteGeometry(image->geometry,&geometry);
6844         geometry.width=source->page.width != 0 ? source->page.width :
6845           source->columns;
6846         geometry.height=source->page.height != 0 ? source->page.height :
6847           source->rows;
6848         GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
6849           image->columns,image->page.height != 0 ? image->page.height :
6850           image->rows,image->gravity,&geometry);
6851         CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
6852         source=DestroyImageList(source);
6853         InheritException(&(image->exception),exception);
6854         break;
6855       }
6856     }
6857     if (layers != (Image *) NULL)
6858       {
6859         InheritException(&(layers->exception),exception);
6860         image=layers;
6861       }
6862     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
6863       goto PerlException;
6864     for ( ; image; image=image->next)
6865     {
6866       AddImageToRegistry(sv,image);
6867       rv=newRV(sv);
6868       av_push(av,sv_bless(rv,hv));
6869       SvREFCNT_dec(sv);
6870     }
6871     exception=DestroyExceptionInfo(exception);
6872     ST(0)=av_reference;
6873     SvREFCNT_dec(perl_exception);
6874     XSRETURN(1);
6875
6876   PerlException:
6877     InheritPerlException(exception,perl_exception);
6878     exception=DestroyExceptionInfo(exception);
6879     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
6880     SvPOK_on(perl_exception);
6881     ST(0)=sv_2mortal(perl_exception);
6882     XSRETURN(1);
6883   }
6884 \f
6885 #
6886 ###############################################################################
6887 #                                                                             #
6888 #                                                                             #
6889 #                                                                             #
6890 #   M a g i c k T o M i m e                                                   #
6891 #                                                                             #
6892 #                                                                             #
6893 #                                                                             #
6894 ###############################################################################
6895 #
6896 #
6897 SV *
6898 MagickToMime(ref,name)
6899   Image::Magick ref=NO_INIT
6900   char *name
6901   ALIAS:
6902     magicktomime = 1
6903   CODE:
6904   {
6905     char
6906       *mime;
6907
6908     PERL_UNUSED_VAR(ref);
6909     PERL_UNUSED_VAR(ix);
6910     mime=MagickToMime(name);
6911     RETVAL=newSVpv(mime,0);
6912     mime=(char *) RelinquishMagickMemory(mime);
6913   }
6914   OUTPUT:
6915     RETVAL
6916 \f
6917 #
6918 ###############################################################################
6919 #                                                                             #
6920 #                                                                             #
6921 #                                                                             #
6922 #   M o g r i f y                                                             #
6923 #                                                                             #
6924 #                                                                             #
6925 #                                                                             #
6926 ###############################################################################
6927 #
6928 #
6929 void
6930 Mogrify(ref,...)
6931   Image::Magick ref=NO_INIT
6932   ALIAS:
6933     Comment            =   1
6934     CommentImage       =   2
6935     Label              =   3
6936     LabelImage         =   4
6937     AddNoise           =   5
6938     AddNoiseImage      =   6
6939     Colorize           =   7
6940     ColorizeImage      =   8
6941     Border             =   9
6942     BorderImage        =  10
6943     Blur               =  11
6944     BlurImage          =  12
6945     Chop               =  13
6946     ChopImage          =  14
6947     Crop               =  15
6948     CropImage          =  16
6949     Despeckle          =  17
6950     DespeckleImage     =  18
6951     Edge               =  19
6952     EdgeImage          =  20
6953     Emboss             =  21
6954     EmbossImage        =  22
6955     Enhance            =  23
6956     EnhanceImage       =  24
6957     Flip               =  25
6958     FlipImage          =  26
6959     Flop               =  27
6960     FlopImage          =  28
6961     Frame              =  29
6962     FrameImage         =  30
6963     Implode            =  31
6964     ImplodeImage       =  32
6965     Magnify            =  33
6966     MagnifyImage       =  34
6967     MedianFilter       =  35
6968     MedianConvolveImage  =  36
6969     Minify             =  37
6970     MinifyImage        =  38
6971     OilPaint           =  39
6972     OilPaintImage      =  40
6973     ReduceNoise        =  41
6974     ReduceNoiseImage   =  42
6975     Roll               =  43
6976     RollImage          =  44
6977     Rotate             =  45
6978     RotateImage        =  46
6979     Sample             =  47
6980     SampleImage        =  48
6981     Scale              =  49
6982     ScaleImage         =  50
6983     Shade              =  51
6984     ShadeImage         =  52
6985     Sharpen            =  53
6986     SharpenImage       =  54
6987     Shear              =  55
6988     ShearImage         =  56
6989     Spread             =  57
6990     SpreadImage        =  58
6991     Swirl              =  59
6992     SwirlImage         =  60
6993     Resize             =  61
6994     ResizeImage        =  62
6995     Zoom               =  63
6996     ZoomImage          =  64
6997     Annotate           =  65
6998     AnnotateImage      =  66
6999     ColorFloodfill     =  67
7000     ColorFloodfillImage=  68
7001     Composite          =  69
7002     CompositeImage     =  70
7003     Contrast           =  71
7004     ContrastImage      =  72
7005     CycleColormap      =  73
7006     CycleColormapImage =  74
7007     Draw               =  75
7008     DrawImage          =  76
7009     Equalize           =  77
7010     EqualizeImage      =  78
7011     Gamma              =  79
7012     GammaImage         =  80
7013     Map                =  81
7014     MapImage           =  82
7015     MatteFloodfill     =  83
7016     MatteFloodfillImage=  84
7017     Modulate           =  85
7018     ModulateImage      =  86
7019     Negate             =  87
7020     NegateImage        =  88
7021     Normalize          =  89
7022     NormalizeImage     =  90
7023     NumberColors       =  91
7024     NumberColorsImage  =  92
7025     Opaque             =  93
7026     OpaqueImage        =  94
7027     Quantize           =  95
7028     QuantizeImage      =  96
7029     Raise              =  97
7030     RaiseImage         =  98
7031     Segment            =  99
7032     SegmentImage       = 100
7033     Signature          = 101
7034     SignatureImage     = 102
7035     Solarize           = 103
7036     SolarizeImage      = 104
7037     Sync               = 105
7038     SyncImage          = 106
7039     Texture            = 107
7040     TextureImage       = 108
7041     Evaluate           = 109
7042     EvaluateImage      = 110
7043     Transparent        = 111
7044     TransparentImage   = 112
7045     Threshold          = 113
7046     ThresholdImage     = 114
7047     Charcoal           = 115
7048     CharcoalImage      = 116
7049     Trim               = 117
7050     TrimImage          = 118
7051     Wave               = 119
7052     WaveImage          = 120
7053     Separate           = 121
7054     SeparateImage      = 122
7055     Stereo             = 125
7056     StereoImage        = 126
7057     Stegano            = 127
7058     SteganoImage       = 128
7059     Deconstruct        = 129
7060     DeconstructImage   = 130
7061     GaussianBlur       = 131
7062     GaussianBlurImage  = 132
7063     Convolve           = 133
7064     ConvolveImage      = 134
7065     Profile            = 135
7066     ProfileImage       = 136
7067     UnsharpMask        = 137
7068     UnsharpMaskImage   = 138
7069     MotionBlur         = 139
7070     MotionBlurImage    = 140
7071     OrderedDither      = 141
7072     OrderedDitherImage = 142
7073     Shave              = 143
7074     ShaveImage         = 144
7075     Level              = 145
7076     LevelImage         = 146
7077     Clip               = 147
7078     ClipImage          = 148
7079     AffineTransform    = 149
7080     AffineTransformImage = 150
7081     Difference         = 151
7082     DifferenceImage    = 152
7083     AdaptiveThreshold  = 153
7084     AdaptiveThresholdImage = 154
7085     Resample           = 155
7086     ResampleImage      = 156
7087     Describe           = 157
7088     DescribeImage      = 158
7089     BlackThreshold     = 159
7090     BlackThresholdImage= 160
7091     WhiteThreshold     = 161
7092     WhiteThresholdImage= 162
7093     RadialBlur         = 163
7094     RadialBlurImage    = 164
7095     Thumbnail          = 165
7096     ThumbnailImage     = 166
7097     Strip              = 167
7098     StripImage         = 168
7099     Tint               = 169
7100     TintImage          = 170
7101     Channel            = 171
7102     ChannelImage       = 172
7103     Splice             = 173
7104     SpliceImage        = 174
7105     Posterize          = 175
7106     PosterizeImage     = 176
7107     Shadow             = 177
7108     ShadowImage        = 178
7109     Identify           = 179
7110     IdentifyImage      = 180
7111     SepiaTone          = 181
7112     SepiaToneImage     = 182
7113     SigmoidalContrast  = 183
7114     SigmoidalContrastImage = 184
7115     Extent             = 185
7116     ExtentImage        = 186
7117     Vignette           = 187
7118     VignetteImage      = 188
7119     ContrastStretch    = 189
7120     ContrastStretchImage = 190
7121     Sans0              = 191
7122     Sans0Image         = 192
7123     Sans1              = 193
7124     Sans1Image         = 194
7125     AdaptiveSharpen    = 195
7126     AdaptiveSharpenImage = 196
7127     Transpose          = 197
7128     TransposeImage     = 198
7129     Transverse         = 199
7130     TransverseImage    = 200
7131     AutoOrient         = 201
7132     AutoOrientImage    = 202
7133     AdaptiveBlur       = 203
7134     AdaptiveBlurImage  = 204
7135     Sketch             = 205
7136     SketchImage        = 206
7137     UniqueColors       = 207
7138     UniqueColorsImage  = 208
7139     AdaptiveResize     = 209
7140     AdaptiveResizeImage= 210
7141     ClipMask           = 211
7142     ClipMaskImage      = 212
7143     LinearStretch      = 213
7144     LinearStretchImage = 214
7145     RecolorImage       = 215
7146     Recolor            = 216
7147     Mask               = 217
7148     MaskImage          = 218
7149     Polaroid           = 219
7150     PolaroidImage      = 220
7151     FloodfillPaint     = 221
7152     FloodfillPaintImage= 222
7153     Distort            = 223
7154     DistortImage       = 224
7155     Clut               = 225
7156     ClutImage          = 226
7157     LiquidRescale      = 227
7158     LiquidRescaleImage = 228
7159     Encipher           = 229
7160     EncipherImage      = 230
7161     Decipher           = 231
7162     DecipherImage      = 232
7163     Deskew             = 233
7164     DeskewImage        = 234
7165     Remap              = 235
7166     RemapImage         = 236
7167     SparseColor        = 237
7168     SparseColorImage   = 238
7169     Function           = 239
7170     FunctionImage      = 240
7171     SelectiveBlur      = 241
7172     SelectiveBlurImage = 242
7173     HaldClut           = 243
7174     HaldClutImage      = 244
7175     BlueShift          = 245
7176     BlueShiftImage     = 246
7177     ForwardFourierTransform  = 247
7178     ForwardFourierTransformImage = 248
7179     InverseFourierTransform = 249
7180     InverseFourierTransformImage = 250
7181     ColorDecisionList  = 251
7182     ColorDecisionListImage = 252
7183     AutoGamma          = 253
7184     AutoGammaImage     = 254
7185     AutoLevel          = 255
7186     AutoLevelImage     = 256
7187     LevelColors        = 257
7188     LevelImageColors   = 258
7189     Clamp              = 259
7190     ClampImage         = 260
7191     BrightnessContrast = 263
7192     BrightnessContrastImage = 264
7193     Morphology         = 265
7194     MorphologyImage    = 266
7195     ColorMatrix        = 267
7196     ColorMatrixImage   = 268
7197     Color              = 269
7198     ColorImage         = 270
7199     Mode               = 271
7200     ModeImage          = 272
7201     Statistic          = 273
7202     StatisticImage     = 274
7203     MogrifyRegion      = 666
7204   PPCODE:
7205   {
7206     AffineMatrix
7207       affine,
7208       current;
7209
7210     char
7211       attribute_flag[MaxArguments],
7212       message[MaxTextExtent];
7213
7214     ChannelType
7215       channel,
7216       channel_mask;
7217
7218     CompositeOperator
7219       compose;
7220
7221     const char
7222       *attribute,
7223       *value;
7224
7225     double
7226       angle;
7227
7228     ExceptionInfo
7229       *exception;
7230
7231     GeometryInfo
7232       geometry_info;
7233
7234     Image
7235       *image,
7236       *next,
7237       *region_image;
7238
7239     MagickBooleanType
7240       status;
7241
7242     MagickStatusType
7243       flags;
7244
7245     PixelPacket
7246       fill_color;
7247
7248     RectangleInfo
7249       geometry,
7250       region_info;
7251
7252     register ssize_t
7253       i;
7254
7255     ssize_t
7256       base,
7257       j,
7258       number_images;
7259
7260     struct Methods
7261       *rp;
7262
7263     struct PackageInfo
7264       *info;
7265
7266     SV
7267       *perl_exception,
7268       **pv,
7269       *reference,
7270       **reference_vector;
7271
7272     struct ArgumentList
7273       argument_list[MaxArguments];
7274
7275     PERL_UNUSED_VAR(ref);
7276     PERL_UNUSED_VAR(ix);
7277     exception=AcquireExceptionInfo();
7278     perl_exception=newSVpv("",0);
7279     reference_vector=NULL;
7280     region_image=NULL;
7281     number_images=0;
7282     base=2;
7283     if (sv_isobject(ST(0)) == 0)
7284       {
7285         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7286           PackageName);
7287         goto PerlException;
7288       }
7289     reference=SvRV(ST(0));
7290     region_info.width=0;
7291     region_info.height=0;
7292     region_info.x=0;
7293     region_info.y=0;
7294     region_image=(Image *) NULL;
7295     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7296     if (ix && (ix != 666))
7297       {
7298         /*
7299           Called as Method(...)
7300         */
7301         ix=(ix+1)/2;
7302         rp=(&Methods[ix-1]);
7303         attribute=rp->name;
7304       }
7305     else
7306       {
7307         /*
7308           Called as Mogrify("Method",...)
7309         */
7310         attribute=(char *) SvPV(ST(1),na);
7311         if (ix)
7312           {
7313             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7314             attribute=(char *) SvPV(ST(2),na);
7315             base++;
7316           }
7317         for (rp=Methods; ; rp++)
7318         {
7319           if (rp >= EndOf(Methods))
7320             {
7321               ThrowPerlException(exception,OptionError,
7322                 "UnrecognizedPerlMagickMethod",attribute);
7323               goto PerlException;
7324             }
7325           if (strEQcase(attribute,rp->name))
7326             break;
7327         }
7328         ix=rp-Methods+1;
7329         base++;
7330       }
7331     if (image == (Image *) NULL)
7332       {
7333         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7334         goto PerlException;
7335       }
7336     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7337     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7338     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7339     {
7340       Arguments
7341         *pp,
7342         *qq;
7343
7344       ssize_t
7345         ssize_test;
7346
7347       struct ArgumentList
7348         *al;
7349
7350       SV
7351         *sv;
7352
7353       sv=NULL;
7354       ssize_test=0;
7355       pp=(Arguments *) NULL;
7356       qq=rp->arguments;
7357       if (i == items)
7358         {
7359           pp=rp->arguments,
7360           sv=ST(i-1);
7361         }
7362       else
7363         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7364         {
7365           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7366             break;
7367           if (strEQcase(attribute,qq->method) > ssize_test)
7368             {
7369               pp=qq;
7370               ssize_test=strEQcase(attribute,qq->method);
7371             }
7372         }
7373       if (pp == (Arguments *) NULL)
7374         {
7375           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7376             attribute);
7377           goto continue_outer_loop;
7378         }
7379       al=(&argument_list[pp-rp->arguments]);
7380       switch (pp->type)
7381       {
7382         case ArrayReference:
7383         {
7384           if (SvTYPE(sv) != SVt_RV)
7385             {
7386               (void) FormatLocaleString(message,MaxTextExtent,
7387                 "invalid %.60s value",pp->method);
7388               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7389               goto continue_outer_loop;
7390             }
7391           al->array_reference=SvRV(sv);
7392           break;
7393         }
7394         case RealReference:
7395         {
7396           al->real_reference=SvNV(sv);
7397           break;
7398         }
7399         case FileReference:
7400         {
7401           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7402           break;
7403         }
7404         case ImageReference:
7405         {
7406           if (!sv_isobject(sv) ||
7407               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7408                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7409             {
7410               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7411                 PackageName);
7412               goto PerlException;
7413             }
7414           break;
7415         }
7416         case IntegerReference:
7417         {
7418           al->integer_reference=SvIV(sv);
7419           break;
7420         }
7421         case StringReference:
7422         {
7423           al->string_reference=(char *) SvPV(sv,al->length);
7424           if (sv_isobject(sv))
7425             al->image_reference=SetupList(aTHX_ SvRV(sv),
7426               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7427           break;
7428         }
7429         default:
7430         {
7431           /*
7432             Is a string; look up name.
7433           */
7434           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7435             {
7436               al->string_reference=(char *) SvPV(sv,al->length);
7437               al->integer_reference=(-1);
7438               break;
7439             }
7440           al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7441             MagickFalse,SvPV(sv,na));
7442           if (pp->type == MagickChannelOptions)
7443             al->integer_reference=ParseChannelOption(SvPV(sv,na));
7444           if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7445             {
7446               (void) FormatLocaleString(message,MaxTextExtent,
7447                 "invalid %.60s value",pp->method);
7448               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7449               goto continue_outer_loop;
7450             }
7451           break;
7452         }
7453       }
7454       attribute_flag[pp-rp->arguments]++;
7455       continue_outer_loop: ;
7456     }
7457     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7458     pv=reference_vector;
7459     SetGeometryInfo(&geometry_info);
7460     channel=DefaultChannels;
7461     for (next=image; next; next=next->next)
7462     {
7463       image=next;
7464       SetGeometry(image,&geometry);
7465       if ((region_info.width*region_info.height) != 0)
7466         {
7467           region_image=image;
7468           image=CropImage(image,&region_info,exception);
7469         }
7470       switch (ix)
7471       {
7472         default:
7473         {
7474           (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double) ix);
7475           ThrowPerlException(exception,OptionError,
7476             "UnrecognizedPerlMagickMethod",message);
7477           goto PerlException;
7478         }
7479         case 1:  /* Comment */
7480         {
7481           if (attribute_flag[0] == 0)
7482             argument_list[0].string_reference=(char *) NULL;
7483           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7484             info ? info->image_info : (ImageInfo *) NULL,image,
7485             argument_list[0].string_reference,exception));
7486           break;
7487         }
7488         case 2:  /* Label */
7489         {
7490           if (attribute_flag[0] == 0)
7491             argument_list[0].string_reference=(char *) NULL;
7492           (void) SetImageProperty(image,"label",InterpretImageProperties(
7493             info ? info->image_info : (ImageInfo *) NULL,image,
7494             argument_list[0].string_reference,exception));
7495           break;
7496         }
7497         case 3:  /* AddNoise */
7498         {
7499           if (attribute_flag[0] == 0)
7500             argument_list[0].integer_reference=UniformNoise;
7501           if (attribute_flag[1] != 0)
7502             channel=(ChannelType) argument_list[1].integer_reference;
7503           channel_mask=SetPixelChannelMask(image,channel);
7504           image=AddNoiseImage(image,(NoiseType)
7505             argument_list[0].integer_reference,exception);
7506           if (image != (Image *) NULL)
7507             (void) SetPixelChannelMask(image,channel_mask);
7508           break;
7509         }
7510         case 4:  /* Colorize */
7511         {
7512           PixelInfo
7513             target;
7514
7515           Quantum
7516             virtual_pixel[MaxPixelChannels];
7517
7518           GetPixelInfo(image,&target);
7519           (void) GetOneVirtualPixel(image,0,0,virtual_pixel,exception);
7520           target.red=virtual_pixel[RedPixelChannel];
7521           target.green=virtual_pixel[GreenPixelChannel];
7522           target.blue=virtual_pixel[BluePixelChannel];
7523           target.alpha=virtual_pixel[AlphaPixelChannel];
7524           if (attribute_flag[0] != 0)
7525             (void) QueryColorCompliance(argument_list[0].string_reference,
7526               AllCompliance,&target,exception);
7527           if (attribute_flag[1] == 0)
7528             argument_list[1].string_reference="100%";
7529           image=ColorizeImage(image,argument_list[1].string_reference,&target,
7530             exception);
7531           break;
7532         }
7533         case 5:  /* Border */
7534         {
7535           CompositeOperator
7536             compose;
7537
7538           geometry.width=0;
7539           geometry.height=0;
7540           if (attribute_flag[0] != 0)
7541             {
7542               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7543                 &geometry,exception);
7544               if ((flags & HeightValue) == 0)
7545                 geometry.height=geometry.width;
7546             }
7547           if (attribute_flag[1] != 0)
7548             geometry.width=argument_list[1].integer_reference;
7549           if (attribute_flag[2] != 0)
7550             geometry.height=argument_list[2].integer_reference;
7551           if (attribute_flag[3] != 0)
7552             QueryColorCompliance(argument_list[3].string_reference,
7553               AllCompliance,&image->border_color,exception);
7554           if (attribute_flag[4] != 0)
7555             QueryColorCompliance(argument_list[4].string_reference,
7556               AllCompliance,&image->border_color,exception);
7557           if (attribute_flag[5] != 0)
7558             QueryColorCompliance(argument_list[5].string_reference,
7559               AllCompliance,&image->border_color,exception);
7560           compose=image->compose;
7561           if (attribute_flag[6] != 0)
7562             compose=(CompositeOperator) argument_list[6].integer_reference;
7563           image=BorderImage(image,&geometry,compose,exception);
7564           break;
7565         }
7566         case 6:  /* Blur */
7567         {
7568           if (attribute_flag[0] != 0)
7569             {
7570               flags=ParseGeometry(argument_list[0].string_reference,
7571                 &geometry_info);
7572               if ((flags & SigmaValue) == 0)
7573                 geometry_info.sigma=1.0;
7574             }
7575           if (attribute_flag[1] != 0)
7576             geometry_info.rho=argument_list[1].real_reference;
7577           if (attribute_flag[2] != 0)
7578             geometry_info.sigma=argument_list[2].real_reference;
7579           if (attribute_flag[3] != 0)
7580             geometry_info.xi=argument_list[3].real_reference;
7581           if (attribute_flag[4] != 0)
7582             channel=(ChannelType) argument_list[4].integer_reference;
7583           channel_mask=SetPixelChannelMask(image,channel);
7584           image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
7585             geometry_info.xi,exception);
7586           if (image != (Image *) NULL)
7587             (void) SetPixelChannelMask(image,channel_mask);
7588           break;
7589         }
7590         case 7:  /* Chop */
7591         {
7592           if (attribute_flag[0] != 0)
7593             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7594               &geometry,exception);
7595           if (attribute_flag[1] != 0)
7596             geometry.width=argument_list[1].integer_reference;
7597           if (attribute_flag[2] != 0)
7598             geometry.height=argument_list[2].integer_reference;
7599           if (attribute_flag[3] != 0)
7600             geometry.x=argument_list[3].integer_reference;
7601           if (attribute_flag[4] != 0)
7602             geometry.y=argument_list[4].integer_reference;
7603           image=ChopImage(image,&geometry,exception);
7604           break;
7605         }
7606         case 8:  /* Crop */
7607         {
7608           if (attribute_flag[6] != 0)
7609             image->gravity=(GravityType) argument_list[6].integer_reference;
7610           if (attribute_flag[0] != 0)
7611             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7612               &geometry,exception);
7613           if (attribute_flag[1] != 0)
7614             geometry.width=argument_list[1].integer_reference;
7615           if (attribute_flag[2] != 0)
7616             geometry.height=argument_list[2].integer_reference;
7617           if (attribute_flag[3] != 0)
7618             geometry.x=argument_list[3].integer_reference;
7619           if (attribute_flag[4] != 0)
7620             geometry.y=argument_list[4].integer_reference;
7621           if (attribute_flag[5] != 0)
7622             image->fuzz=
7623               SiPrefixToDouble(argument_list[5].string_reference,QuantumRange);
7624           image=CropImage(image,&geometry,exception);
7625           break;
7626         }
7627         case 9:  /* Despeckle */
7628         {
7629           image=DespeckleImage(image,exception);
7630           break;
7631         }
7632         case 10:  /* Edge */
7633         {
7634           if (attribute_flag[0] != 0)
7635             geometry_info.rho=argument_list[0].real_reference;
7636           image=EdgeImage(image,geometry_info.rho,geometry_info.sigma,
7637             exception);
7638           break;
7639         }
7640         case 11:  /* Emboss */
7641         {
7642           if (attribute_flag[0] != 0)
7643             {
7644               flags=ParseGeometry(argument_list[0].string_reference,
7645                 &geometry_info);
7646               if ((flags & SigmaValue) == 0)
7647                 geometry_info.sigma=1.0;
7648             }
7649           if (attribute_flag[1] != 0)
7650             geometry_info.rho=argument_list[1].real_reference;
7651           if (attribute_flag[2] != 0)
7652             geometry_info.sigma=argument_list[2].real_reference;
7653           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
7654             exception);
7655           break;
7656         }
7657         case 12:  /* Enhance */
7658         {
7659           image=EnhanceImage(image,exception);
7660           break;
7661         }
7662         case 13:  /* Flip */
7663         {
7664           image=FlipImage(image,exception);
7665           break;
7666         }
7667         case 14:  /* Flop */
7668         {
7669           image=FlopImage(image,exception);
7670           break;
7671         }
7672         case 15:  /* Frame */
7673         {
7674           CompositeOperator
7675             compose;
7676
7677           FrameInfo
7678             frame_info;
7679
7680           if (attribute_flag[0] != 0)
7681             {
7682               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7683                 &geometry,exception);
7684               if ((flags & HeightValue) == 0)
7685                 geometry.height=geometry.width;
7686               frame_info.width=geometry.width;
7687               frame_info.height=geometry.height;
7688               frame_info.outer_bevel=geometry.x;
7689               frame_info.inner_bevel=geometry.y;
7690             }
7691           if (attribute_flag[1] != 0)
7692             frame_info.width=argument_list[1].integer_reference;
7693           if (attribute_flag[2] != 0)
7694             frame_info.height=argument_list[2].integer_reference;
7695           if (attribute_flag[3] != 0)
7696             frame_info.inner_bevel=argument_list[3].integer_reference;
7697           if (attribute_flag[4] != 0)
7698             frame_info.outer_bevel=argument_list[4].integer_reference;
7699           if (attribute_flag[5] != 0)
7700             QueryColorCompliance(argument_list[5].string_reference,
7701               AllCompliance,&fill_color,exception);
7702           if (attribute_flag[6] != 0)
7703             QueryColorCompliance(argument_list[6].string_reference,
7704               AllCompliance,&fill_color,exception);
7705           frame_info.x=(ssize_t) frame_info.width;
7706           frame_info.y=(ssize_t) frame_info.height;
7707           frame_info.width=image->columns+2*frame_info.x;
7708           frame_info.height=image->rows+2*frame_info.y;
7709           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
7710             image->matte_color=fill_color;
7711           compose=image->compose;
7712           if (attribute_flag[7] != 0)
7713             compose=(CompositeOperator) argument_list[7].integer_reference;
7714           image=FrameImage(image,&frame_info,compose,exception);
7715           break;
7716         }
7717         case 16:  /* Implode */
7718         {
7719           PixelInterpolateMethod
7720             method;
7721
7722           if (attribute_flag[0] == 0)
7723             argument_list[0].real_reference=0.5;
7724           method=UndefinedInterpolatePixel;
7725           if (attribute_flag[1] != 0)
7726             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
7727           image=ImplodeImage(image,argument_list[0].real_reference,
7728             method,exception);
7729           break;
7730         }
7731         case 17:  /* Magnify */
7732         {
7733           image=MagnifyImage(image,exception);
7734           break;
7735         }
7736         case 18:  /* MedianFilter */
7737         {
7738           if (attribute_flag[0] != 0)
7739             {
7740               flags=ParseGeometry(argument_list[0].string_reference,
7741                 &geometry_info);
7742               if ((flags & SigmaValue) == 0)
7743                 geometry_info.sigma=geometry_info.rho;
7744             }
7745           if (attribute_flag[1] != 0)
7746             geometry_info.rho=argument_list[1].real_reference;
7747           if (attribute_flag[2] != 0)
7748             geometry_info.sigma=argument_list[2].real_reference;
7749           if (attribute_flag[3] != 0)
7750             channel=(ChannelType) argument_list[3].integer_reference;
7751           channel_mask=SetPixelChannelMask(image,channel);
7752           image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
7753             (size_t) geometry_info.sigma,exception);
7754           if (image != (Image *) NULL)
7755             (void) SetPixelChannelMask(image,channel_mask);
7756           break;
7757         }
7758         case 19:  /* Minify */
7759         {
7760           image=MinifyImage(image,exception);
7761           break;
7762         }
7763         case 20:  /* OilPaint */
7764         {
7765           if (attribute_flag[0] == 0)
7766             argument_list[0].real_reference=0.0;
7767           if (attribute_flag[1] == 0)
7768             argument_list[1].real_reference=1.0;
7769           image=OilPaintImage(image,argument_list[0].real_reference,
7770             argument_list[1].real_reference,exception);
7771           break;
7772         }
7773         case 21:  /* ReduceNoise */
7774         {
7775           if (attribute_flag[0] != 0)
7776             {
7777               flags=ParseGeometry(argument_list[0].string_reference,
7778                 &geometry_info);
7779               if ((flags & SigmaValue) == 0)
7780                 geometry_info.sigma=1.0;
7781             }
7782           if (attribute_flag[1] != 0)
7783             geometry_info.rho=argument_list[1].real_reference;
7784           if (attribute_flag[2] != 0)
7785             geometry_info.sigma=argument_list[2].real_reference;
7786           if (attribute_flag[3] != 0)
7787             channel=(ChannelType) argument_list[3].integer_reference;
7788           channel_mask=SetPixelChannelMask(image,channel);
7789           image=StatisticImage(image,NonpeakStatistic,(size_t)
7790             geometry_info.rho,(size_t) geometry_info.sigma,exception);
7791           if (image != (Image *) NULL)
7792             (void) SetPixelChannelMask(image,channel_mask);
7793           break;
7794         }
7795         case 22:  /* Roll */
7796         {
7797           if (attribute_flag[0] != 0)
7798             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7799               &geometry,exception);
7800           if (attribute_flag[1] != 0)
7801             geometry.x=argument_list[1].integer_reference;
7802           if (attribute_flag[2] != 0)
7803             geometry.y=argument_list[2].integer_reference;
7804           image=RollImage(image,geometry.x,geometry.y,exception);
7805           break;
7806         }
7807         case 23:  /* Rotate */
7808         {
7809           if (attribute_flag[0] == 0)
7810             argument_list[0].real_reference=90.0;
7811           if (attribute_flag[1] != 0)
7812             QueryColorCompliance(argument_list[1].string_reference,
7813               AllCompliance,&image->background_color,exception);
7814           if (attribute_flag[2] != 0)
7815             QueryColorCompliance(argument_list[2].string_reference,
7816               AllCompliance,&image->background_color,exception);
7817           if (attribute_flag[3] != 0)
7818             QueryColorCompliance(argument_list[3].string_reference,
7819               AllCompliance,&image->background_color,exception);
7820           image=RotateImage(image,argument_list[0].real_reference,exception);
7821           break;
7822         }
7823         case 24:  /* Sample */
7824         {
7825           if (attribute_flag[0] != 0)
7826             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7827               &geometry,exception);
7828           if (attribute_flag[1] != 0)
7829             geometry.width=argument_list[1].integer_reference;
7830           if (attribute_flag[2] != 0)
7831             geometry.height=argument_list[2].integer_reference;
7832           image=SampleImage(image,geometry.width,geometry.height,exception);
7833           break;
7834         }
7835         case 25:  /* Scale */
7836         {
7837           if (attribute_flag[0] != 0)
7838             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7839               &geometry,exception);
7840           if (attribute_flag[1] != 0)
7841             geometry.width=argument_list[1].integer_reference;
7842           if (attribute_flag[2] != 0)
7843             geometry.height=argument_list[2].integer_reference;
7844           image=ScaleImage(image,geometry.width,geometry.height,exception);
7845           break;
7846         }
7847         case 26:  /* Shade */
7848         {
7849           if (attribute_flag[0] != 0)
7850             {
7851               flags=ParseGeometry(argument_list[0].string_reference,
7852                 &geometry_info);
7853               if ((flags & SigmaValue) == 0)
7854                 geometry_info.sigma=0.0;
7855             }
7856           if (attribute_flag[1] != 0)
7857             geometry_info.rho=argument_list[1].real_reference;
7858           if (attribute_flag[2] != 0)
7859             geometry_info.sigma=argument_list[2].real_reference;
7860           image=ShadeImage(image,
7861             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
7862             geometry_info.rho,geometry_info.sigma,exception);
7863           break;
7864         }
7865         case 27:  /* Sharpen */
7866         {
7867           if (attribute_flag[0] != 0)
7868             {
7869               flags=ParseGeometry(argument_list[0].string_reference,
7870                 &geometry_info);
7871               if ((flags & SigmaValue) == 0)
7872                 geometry_info.sigma=1.0;
7873             }
7874           if (attribute_flag[1] != 0)
7875             geometry_info.rho=argument_list[1].real_reference;
7876           if (attribute_flag[2] != 0)
7877             geometry_info.sigma=argument_list[2].real_reference;
7878           if (attribute_flag[3] != 0)
7879             geometry_info.xi=argument_list[3].real_reference;
7880           if (attribute_flag[4] != 0)
7881             channel=(ChannelType) argument_list[4].integer_reference;
7882           channel_mask=SetPixelChannelMask(image,channel);
7883           image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
7884             geometry_info.xi,exception);
7885           if (image != (Image *) NULL)
7886             (void) SetPixelChannelMask(image,channel_mask);
7887           break;
7888         }
7889         case 28:  /* Shear */
7890         {
7891           if (attribute_flag[0] != 0)
7892             {
7893               flags=ParseGeometry(argument_list[0].string_reference,
7894                 &geometry_info);
7895               if ((flags & SigmaValue) == 0)
7896                 geometry_info.sigma=geometry_info.rho;
7897             }
7898           if (attribute_flag[1] != 0)
7899             geometry_info.rho=argument_list[1].real_reference;
7900           if (attribute_flag[2] != 0)
7901             geometry_info.sigma=argument_list[2].real_reference;
7902           if (attribute_flag[3] != 0)
7903             QueryColorCompliance(argument_list[3].string_reference,
7904               AllCompliance,&image->background_color,exception);
7905           if (attribute_flag[4] != 0)
7906             QueryColorCompliance(argument_list[4].string_reference,
7907               AllCompliance,&image->background_color,exception);
7908           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
7909             exception);
7910           break;
7911         }
7912         case 29:  /* Spread */
7913         {
7914           PixelInterpolateMethod
7915             method;
7916
7917           if (attribute_flag[0] == 0)
7918             argument_list[0].real_reference=1.0;
7919           method=UndefinedInterpolatePixel;
7920           if (attribute_flag[1] != 0)
7921             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
7922           image=SpreadImage(image,argument_list[0].real_reference,method,
7923             exception);
7924           break;
7925         }
7926         case 30:  /* Swirl */
7927         {
7928           PixelInterpolateMethod
7929             method;
7930
7931           if (attribute_flag[0] == 0)
7932             argument_list[0].real_reference=50.0;
7933           method=UndefinedInterpolatePixel;
7934           if (attribute_flag[1] != 0)
7935             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
7936           image=SwirlImage(image,argument_list[0].real_reference,
7937             method,exception);
7938           break;
7939         }
7940         case 31:  /* Resize */
7941         case 32:  /* Zoom */
7942         {
7943           if (attribute_flag[0] != 0)
7944             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7945               &geometry,exception);
7946           if (attribute_flag[1] != 0)
7947             geometry.width=argument_list[1].integer_reference;
7948           if (attribute_flag[2] != 0)
7949             geometry.height=argument_list[2].integer_reference;
7950           if (attribute_flag[3] == 0)
7951             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
7952           if (attribute_flag[4] != 0)
7953             SetImageArtifact(image,"filter:support",
7954               argument_list[4].string_reference);
7955           if (attribute_flag[5] == 0)
7956             argument_list[5].real_reference=1.0;
7957           image=ResizeImage(image,geometry.width,geometry.height,
7958             (FilterTypes) argument_list[3].integer_reference,
7959             argument_list[5].real_reference,exception);
7960           break;
7961         }
7962         case 33:  /* Annotate */
7963         {
7964           DrawInfo
7965             *draw_info;
7966
7967           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
7968             (DrawInfo *) NULL);
7969           if (attribute_flag[0] != 0)
7970             {
7971               char
7972                 *text;
7973
7974               text=InterpretImageProperties(info ? info->image_info :
7975                 (ImageInfo *) NULL,image,argument_list[0].string_reference,
7976                 exception);
7977               (void) CloneString(&draw_info->text,text);
7978               text=DestroyString(text);
7979             }
7980           if (attribute_flag[1] != 0)
7981             (void) CloneString(&draw_info->font,
7982               argument_list[1].string_reference);
7983           if (attribute_flag[2] != 0)
7984             draw_info->pointsize=argument_list[2].real_reference;
7985           if (attribute_flag[3] != 0)
7986             (void) CloneString(&draw_info->density,
7987               argument_list[3].string_reference);
7988           if (attribute_flag[4] != 0)
7989             (void) QueryColorCompliance(argument_list[4].string_reference,
7990               AllCompliance,&draw_info->undercolor,exception);
7991           if (attribute_flag[5] != 0)
7992             {
7993               (void) QueryColorCompliance(argument_list[5].string_reference,
7994                 AllCompliance,&draw_info->stroke,exception);
7995               if (argument_list[5].image_reference != (Image *) NULL)
7996                 draw_info->stroke_pattern=CloneImage(
7997                   argument_list[5].image_reference,0,0,MagickTrue,exception);
7998             }
7999           if (attribute_flag[6] != 0)
8000             {
8001               (void) QueryColorCompliance(argument_list[6].string_reference,
8002                 AllCompliance,&draw_info->fill,exception);
8003               if (argument_list[6].image_reference != (Image *) NULL)
8004                 draw_info->fill_pattern=CloneImage(
8005                   argument_list[6].image_reference,0,0,MagickTrue,exception);
8006             }
8007           if (attribute_flag[7] != 0)
8008             {
8009               (void) CloneString(&draw_info->geometry,
8010                 argument_list[7].string_reference);
8011               flags=ParsePageGeometry(image,argument_list[7].string_reference,
8012                 &geometry,exception);
8013               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8014                 geometry_info.sigma=geometry_info.xi;
8015             }
8016           if (attribute_flag[8] != 0)
8017             (void) QueryColorCompliance(argument_list[8].string_reference,
8018               AllCompliance,&draw_info->fill,exception);
8019           if (attribute_flag[11] != 0)
8020             draw_info->gravity=(GravityType)
8021               argument_list[11].integer_reference;
8022           if (attribute_flag[25] != 0)
8023             {
8024               AV
8025                 *av;
8026
8027               av=(AV *) argument_list[25].array_reference;
8028               if ((av_len(av) != 3) && (av_len(av) != 5))
8029                 {
8030                   ThrowPerlException(exception,OptionError,
8031                     "affine matrix must have 4 or 6 elements",PackageName);
8032                   goto PerlException;
8033                 }
8034               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8035               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8036               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8037               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8038               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8039                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8040                 {
8041                   ThrowPerlException(exception,OptionError,
8042                     "affine matrix is singular",PackageName);
8043                    goto PerlException;
8044                 }
8045               if (av_len(av) == 5)
8046                 {
8047                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8048                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8049                 }
8050             }
8051           for (j=12; j < 17; j++)
8052           {
8053             if (attribute_flag[j] == 0)
8054               continue;
8055             value=argument_list[j].string_reference;
8056             angle=argument_list[j].real_reference;
8057             current=draw_info->affine;
8058             GetAffineMatrix(&affine);
8059             switch (j)
8060             {
8061               case 12:
8062               {
8063                 /*
8064                   Translate.
8065                 */
8066                 flags=ParseGeometry(value,&geometry_info);
8067                 affine.tx=geometry_info.xi;
8068                 affine.ty=geometry_info.psi;
8069                 if ((flags & PsiValue) == 0)
8070                   affine.ty=affine.tx;
8071                 break;
8072               }
8073               case 13:
8074               {
8075                 /*
8076                   Scale.
8077                 */
8078                 flags=ParseGeometry(value,&geometry_info);
8079                 affine.sx=geometry_info.rho;
8080                 affine.sy=geometry_info.sigma;
8081                 if ((flags & SigmaValue) == 0)
8082                   affine.sy=affine.sx;
8083                 break;
8084               }
8085               case 14:
8086               {
8087                 /*
8088                   Rotate.
8089                 */
8090                 if (angle == 0.0)
8091                   break;
8092                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8093                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8094                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8095                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8096                 break;
8097               }
8098               case 15:
8099               {
8100                 /*
8101                   SkewX.
8102                 */
8103                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8104                 break;
8105               }
8106               case 16:
8107               {
8108                 /*
8109                   SkewY.
8110                 */
8111                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8112                 break;
8113               }
8114             }
8115             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8116             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8117             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8118             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8119             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8120               current.tx;
8121             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8122               current.ty;
8123           }
8124           if (attribute_flag[9] == 0)
8125             argument_list[9].real_reference=0.0;
8126           if (attribute_flag[10] == 0)
8127             argument_list[10].real_reference=0.0;
8128           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8129             {
8130               char
8131                 geometry[MaxTextExtent];
8132
8133               (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
8134                 (double) argument_list[9].real_reference+draw_info->affine.tx,
8135                 (double) argument_list[10].real_reference+draw_info->affine.ty);
8136               (void) CloneString(&draw_info->geometry,geometry);
8137             }
8138           if (attribute_flag[17] != 0)
8139             draw_info->stroke_width=argument_list[17].real_reference;
8140           if (attribute_flag[18] != 0)
8141             {
8142               draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8143                 MagickTrue : MagickFalse;
8144               draw_info->stroke_antialias=draw_info->text_antialias;
8145             }
8146           if (attribute_flag[19] != 0)
8147             (void) CloneString(&draw_info->family,
8148               argument_list[19].string_reference);
8149           if (attribute_flag[20] != 0)
8150             draw_info->style=(StyleType) argument_list[20].integer_reference;
8151           if (attribute_flag[21] != 0)
8152             draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8153           if (attribute_flag[22] != 0)
8154             draw_info->weight=argument_list[22].integer_reference;
8155           if (attribute_flag[23] != 0)
8156             draw_info->align=(AlignType) argument_list[23].integer_reference;
8157           if (attribute_flag[24] != 0)
8158             (void) CloneString(&draw_info->encoding,
8159               argument_list[24].string_reference);
8160           if (attribute_flag[25] != 0)
8161             draw_info->fill_pattern=CloneImage(
8162               argument_list[25].image_reference,0,0,MagickTrue,exception);
8163           if (attribute_flag[26] != 0)
8164             draw_info->fill_pattern=CloneImage(
8165               argument_list[26].image_reference,0,0,MagickTrue,exception);
8166           if (attribute_flag[27] != 0)
8167             draw_info->stroke_pattern=CloneImage(
8168               argument_list[27].image_reference,0,0,MagickTrue,exception);
8169           if (attribute_flag[29] != 0)
8170             draw_info->kerning=argument_list[29].real_reference;
8171           if (attribute_flag[30] != 0)
8172             draw_info->interline_spacing=argument_list[30].real_reference;
8173           if (attribute_flag[31] != 0)
8174             draw_info->interword_spacing=argument_list[31].real_reference;
8175           if (attribute_flag[32] != 0)
8176             draw_info->direction=(DirectionType)
8177               argument_list[32].integer_reference;
8178           (void) AnnotateImage(image,draw_info,exception);
8179           draw_info=DestroyDrawInfo(draw_info);
8180           break;
8181         }
8182         case 34:  /* ColorFloodfill */
8183         {
8184           DrawInfo
8185             *draw_info;
8186
8187           MagickBooleanType
8188             invert;
8189
8190           PixelInfo
8191             target;
8192
8193           Quantum
8194             virtual_pixel[MaxPixelChannels];
8195
8196           draw_info=CloneDrawInfo(info ? info->image_info :
8197             (ImageInfo *) NULL,(DrawInfo *) NULL);
8198           if (attribute_flag[0] != 0)
8199             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8200               &geometry,exception);
8201           if (attribute_flag[1] != 0)
8202             geometry.x=argument_list[1].integer_reference;
8203           if (attribute_flag[2] != 0)
8204             geometry.y=argument_list[2].integer_reference;
8205           if (attribute_flag[3] != 0)
8206             (void) QueryColorCompliance(argument_list[3].string_reference,
8207               AllCompliance,&draw_info->fill,exception);
8208           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,
8209             virtual_pixel,exception);
8210           target.red=virtual_pixel[RedPixelChannel];
8211           target.green=virtual_pixel[GreenPixelChannel];
8212           target.blue=virtual_pixel[BluePixelChannel];
8213           target.alpha=virtual_pixel[AlphaPixelChannel];
8214           invert=MagickFalse;
8215           if (attribute_flag[4] != 0)
8216             {
8217               QueryMagickColorCompliance(argument_list[4].string_reference,
8218                 AllCompliance,&target,exception);
8219               invert=MagickTrue;
8220             }
8221           if (attribute_flag[5] != 0)
8222             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
8223               QuantumRange);
8224           if (attribute_flag[6] != 0)
8225             invert=(MagickBooleanType) argument_list[6].integer_reference;
8226           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8227             geometry.y,invert,exception);
8228           draw_info=DestroyDrawInfo(draw_info);
8229           break;
8230         }
8231         case 35:  /* Composite */
8232         {
8233           char
8234             composite_geometry[MaxTextExtent];
8235
8236           Image
8237             *composite_image,
8238             *rotate_image;
8239
8240           compose=OverCompositeOp;
8241           if (attribute_flag[0] != 0)
8242             composite_image=argument_list[0].image_reference;
8243           else
8244             {
8245               ThrowPerlException(exception,OptionError,
8246                 "CompositeImageRequired",PackageName);
8247               goto PerlException;
8248             }
8249           /*
8250             Parameter Handling used for BOTH normal and tiled composition.
8251           */
8252           if (attribute_flag[1] != 0) /* compose */
8253             compose=(CompositeOperator) argument_list[1].integer_reference;
8254           if (attribute_flag[6] != 0) /* opacity  */
8255             {
8256               if (compose != DissolveCompositeOp)
8257                 (void) SetImageAlpha(composite_image,(Quantum)
8258                   SiPrefixToDouble(argument_list[6].string_reference,
8259                   QuantumRange));
8260               else
8261                 {
8262                   CacheView
8263                     *composite_view;
8264
8265                   double
8266                     opacity;
8267
8268                   MagickBooleanType
8269                     sync;
8270
8271                   register ssize_t
8272                     x;
8273
8274                   register Quantum
8275                     *q;
8276
8277                   ssize_t
8278                     y;
8279
8280                   /*
8281                     Handle dissolve composite operator (patch by
8282                     Kevin A. McGrail).
8283                   */
8284                   (void) CloneString(&image->geometry,
8285                     argument_list[6].string_reference);
8286                   opacity=(Quantum) SiPrefixToDouble(
8287                     argument_list[6].string_reference,QuantumRange);
8288                   if (composite_image->matte != MagickTrue)
8289                     (void) SetImageAlpha(composite_image,OpaqueAlpha);
8290                   composite_view=AcquireCacheView(composite_image);
8291                   for (y=0; y < (ssize_t) composite_image->rows ; y++)
8292                   {
8293                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8294                       composite_image->columns,1,exception);
8295                     for (x=0; x < (ssize_t) composite_image->columns; x++)
8296                     {
8297                       if (GetPixelAlpha(image,q) == OpaqueAlpha)
8298                         SetPixelAlpha(composite_image,ClampToQuantum(opacity),
8299                           q);
8300                       q+=GetPixelChannels(composite_image);
8301                     }
8302                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8303                     if (sync == MagickFalse)
8304                       break;
8305                   }
8306                   composite_view=DestroyCacheView(composite_view);
8307                 }
8308             }
8309           if (attribute_flag[9] != 0)    /* "color=>" */
8310             QueryColorCompliance(argument_list[9].string_reference,
8311               AllCompliance,&composite_image->background_color,exception);
8312           if (attribute_flag[12] != 0) /* "interpolate=>" */
8313             image->interpolate=(PixelInterpolateMethod)
8314               argument_list[12].integer_reference;
8315           if (attribute_flag[13] != 0)   /* "args=>" */
8316             (void) SetImageArtifact(composite_image,"compose:args",
8317               argument_list[13].string_reference);
8318           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8319             (void) SetImageArtifact(composite_image,"compose:args",
8320               argument_list[14].string_reference);
8321           /*
8322             Tiling Composition (with orthogonal rotate).
8323           */
8324           rotate_image=(Image *) NULL;
8325           if (attribute_flag[8] != 0)   /* "rotate=>" */
8326             {
8327                /*
8328                  Rotate image.
8329                */
8330                rotate_image=RotateImage(composite_image,
8331                  argument_list[8].real_reference,exception);
8332                if (rotate_image == (Image *) NULL)
8333                  break;
8334             }
8335           if (attribute_flag[7] && argument_list[7].integer_reference) /* tile */
8336             {
8337               ssize_t
8338                 x,
8339                 y;
8340
8341               /*
8342                 Tile the composite image.
8343               */
8344              if (attribute_flag[8] != 0)   /* "tile=>" */
8345                (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8346                  "false");
8347              else
8348                (void) SetImageArtifact(composite_image,
8349                  "compose:outside-overlay","false");
8350              for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8351                 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8352                 {
8353                   if (attribute_flag[8] != 0) /* rotate */
8354                     (void) CompositeImage(image,compose,rotate_image,x,y);
8355                   else
8356                     (void) CompositeImage(image,compose,composite_image,x,y);
8357                 }
8358               if (attribute_flag[8] != 0) /* rotate */
8359                 rotate_image=DestroyImage(rotate_image);
8360               break;
8361             }
8362           /*
8363             Parameter Handling used used ONLY for normal composition.
8364           */
8365           if (attribute_flag[5] != 0) /* gravity */
8366             image->gravity=(GravityType) argument_list[5].integer_reference;
8367           if (attribute_flag[2] != 0) /* geometry offset */
8368             {
8369               SetGeometry(image,&geometry);
8370               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8371                 &geometry);
8372               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8373                 &geometry);
8374             }
8375           if (attribute_flag[3] != 0) /* x offset */
8376             geometry.x=argument_list[3].integer_reference;
8377           if (attribute_flag[4] != 0) /* y offset */
8378             geometry.y=argument_list[4].integer_reference;
8379           if (attribute_flag[10] != 0) /* mask */
8380             {
8381               if ((image->compose == DisplaceCompositeOp) ||
8382                   (image->compose == DistortCompositeOp))
8383                 {
8384                   /*
8385                     Merge Y displacement into X displacement image.
8386                   */
8387                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8388                     &image->exception);
8389                   (void) CompositeImage(composite_image,CopyGreenCompositeOp,
8390                     argument_list[10].image_reference,0,0);
8391                 }
8392               else
8393                 {
8394                   /*
8395                     Set a blending mask for the composition.
8396                   */
8397                   image->mask=CloneImage(argument_list[10].image_reference,0,0,
8398                     MagickTrue,&image->exception);
8399                   (void) NegateImage(image->mask,MagickFalse,exception);
8400                 }
8401             }
8402           if (attribute_flag[11] != 0) /* channel */
8403             channel=(ChannelType) argument_list[11].integer_reference;
8404           /*
8405             Composite two images (normal composition).
8406           */
8407           (void) FormatLocaleString(composite_geometry,MaxTextExtent,
8408             "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8409             (double) composite_image->rows,(double) geometry.x,(double)
8410             geometry.y);
8411           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8412             exception);
8413           channel_mask=SetPixelChannelMask(image,channel);
8414           if (attribute_flag[8] == 0) /* no rotate */
8415             CompositeImage(image,compose,composite_image,geometry.x,geometry.y);
8416           else
8417             {
8418               /*
8419                 Position adjust rotated image then composite.
8420               */
8421               geometry.x-=(ssize_t) (rotate_image->columns-
8422                 composite_image->columns)/2;
8423               geometry.y-=(ssize_t) (rotate_image->rows-
8424                 composite_image->rows)/2;
8425               CompositeImage(image,compose,rotate_image,geometry.x,geometry.y);
8426               rotate_image=DestroyImage(rotate_image);
8427             }
8428           if (attribute_flag[10] != 0) /* mask */
8429             {
8430               if ((image->compose == DisplaceCompositeOp) ||
8431                   (image->compose == DistortCompositeOp))
8432                 composite_image=DestroyImage(composite_image);
8433               else
8434                 image->mask=DestroyImage(image->mask);
8435             }
8436           (void) SetPixelChannelMask(image,channel_mask);
8437           break;
8438         }
8439         case 36:  /* Contrast */
8440         {
8441           if (attribute_flag[0] == 0)
8442             argument_list[0].integer_reference=0;
8443           (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8444             MagickTrue : MagickFalse,exception);
8445           break;
8446         }
8447         case 37:  /* CycleColormap */
8448         {
8449           if (attribute_flag[0] == 0)
8450             argument_list[0].integer_reference=6;
8451           (void) CycleColormapImage(image,argument_list[0].integer_reference,
8452             exception);
8453           break;
8454         }
8455         case 38:  /* Draw */
8456         {
8457           DrawInfo
8458             *draw_info;
8459
8460           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8461             (DrawInfo *) NULL);
8462           (void) CloneString(&draw_info->primitive,"point");
8463           if (attribute_flag[0] != 0)
8464             {
8465               if (argument_list[0].integer_reference < 0)
8466                 (void) CloneString(&draw_info->primitive,
8467                   argument_list[0].string_reference);
8468               else
8469                 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8470                   MagickPrimitiveOptions,argument_list[0].integer_reference));
8471             }
8472           if (attribute_flag[1] != 0)
8473             {
8474               if (LocaleCompare(draw_info->primitive,"path") == 0)
8475                 {
8476                   (void) ConcatenateString(&draw_info->primitive," '");
8477                   ConcatenateString(&draw_info->primitive,
8478                     argument_list[1].string_reference);
8479                   (void) ConcatenateString(&draw_info->primitive,"'");
8480                 }
8481               else
8482                 {
8483                   (void) ConcatenateString(&draw_info->primitive," ");
8484                   ConcatenateString(&draw_info->primitive,
8485                     argument_list[1].string_reference);
8486                 }
8487             }
8488           if (attribute_flag[2] != 0)
8489             {
8490               (void) ConcatenateString(&draw_info->primitive," ");
8491               (void) ConcatenateString(&draw_info->primitive,
8492                 CommandOptionToMnemonic(MagickMethodOptions,
8493                 argument_list[2].integer_reference));
8494             }
8495           if (attribute_flag[3] != 0)
8496             {
8497               (void) QueryColorCompliance(argument_list[3].string_reference,
8498                 AllCompliance,&draw_info->stroke,exception);
8499               if (argument_list[3].image_reference != (Image *) NULL)
8500                 draw_info->stroke_pattern=CloneImage(
8501                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8502             }
8503           if (attribute_flag[4] != 0)
8504             {
8505               (void) QueryColorCompliance(argument_list[4].string_reference,
8506                 AllCompliance,&draw_info->fill,exception);
8507               if (argument_list[4].image_reference != (Image *) NULL)
8508                 draw_info->fill_pattern=CloneImage(
8509                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8510             }
8511           if (attribute_flag[5] != 0)
8512             draw_info->stroke_width=argument_list[5].real_reference;
8513           if (attribute_flag[6] != 0)
8514             (void) CloneString(&draw_info->font,
8515               argument_list[6].string_reference);
8516           if (attribute_flag[7] != 0)
8517             (void) QueryColorCompliance(argument_list[7].string_reference,
8518               AllCompliance,&draw_info->border_color,exception);
8519           if (attribute_flag[8] != 0)
8520             draw_info->affine.tx=argument_list[8].real_reference;
8521           if (attribute_flag[9] != 0)
8522             draw_info->affine.ty=argument_list[9].real_reference;
8523           if (attribute_flag[20] != 0)
8524             {
8525               AV
8526                 *av;
8527
8528               av=(AV *) argument_list[20].array_reference;
8529               if ((av_len(av) != 3) && (av_len(av) != 5))
8530                 {
8531                   ThrowPerlException(exception,OptionError,
8532                     "affine matrix must have 4 or 6 elements",PackageName);
8533                   goto PerlException;
8534                 }
8535               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8536               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8537               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8538               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8539               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8540                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8541                 {
8542                   ThrowPerlException(exception,OptionError,
8543                     "affine matrix is singular",PackageName);
8544                    goto PerlException;
8545                 }
8546               if (av_len(av) == 5)
8547                 {
8548                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8549                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8550                 }
8551             }
8552           for (j=10; j < 15; j++)
8553           {
8554             if (attribute_flag[j] == 0)
8555               continue;
8556             value=argument_list[j].string_reference;
8557             angle=argument_list[j].real_reference;
8558             current=draw_info->affine;
8559             GetAffineMatrix(&affine);
8560             switch (j)
8561             {
8562               case 10:
8563               {
8564                 /*
8565                   Translate.
8566                 */
8567                 flags=ParseGeometry(value,&geometry_info);
8568                 affine.tx=geometry_info.xi;
8569                 affine.ty=geometry_info.psi;
8570                 if ((flags & PsiValue) == 0)
8571                   affine.ty=affine.tx;
8572                 break;
8573               }
8574               case 11:
8575               {
8576                 /*
8577                   Scale.
8578                 */
8579                 flags=ParseGeometry(value,&geometry_info);
8580                 affine.sx=geometry_info.rho;
8581                 affine.sy=geometry_info.sigma;
8582                 if ((flags & SigmaValue) == 0)
8583                   affine.sy=affine.sx;
8584                 break;
8585               }
8586               case 12:
8587               {
8588                 /*
8589                   Rotate.
8590                 */
8591                 if (angle == 0.0)
8592                   break;
8593                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8594                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8595                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8596                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8597                 break;
8598               }
8599               case 13:
8600               {
8601                 /*
8602                   SkewX.
8603                 */
8604                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8605                 break;
8606               }
8607               case 14:
8608               {
8609                 /*
8610                   SkewY.
8611                 */
8612                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8613                 break;
8614               }
8615             }
8616             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8617             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8618             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8619             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8620             draw_info->affine.tx=
8621               current.sx*affine.tx+current.ry*affine.ty+current.tx;
8622             draw_info->affine.ty=
8623               current.rx*affine.tx+current.sy*affine.ty+current.ty;
8624           }
8625           if (attribute_flag[15] != 0)
8626             draw_info->fill_pattern=CloneImage(
8627               argument_list[15].image_reference,0,0,MagickTrue,exception);
8628           if (attribute_flag[16] != 0)
8629             draw_info->pointsize=argument_list[16].real_reference;
8630           if (attribute_flag[17] != 0)
8631             {
8632               draw_info->stroke_antialias=argument_list[17].integer_reference != 0
8633                 ? MagickTrue : MagickFalse;
8634               draw_info->text_antialias=draw_info->stroke_antialias;
8635             }
8636           if (attribute_flag[18] != 0)
8637             (void) CloneString(&draw_info->density,
8638               argument_list[18].string_reference);
8639           if (attribute_flag[19] != 0)
8640             draw_info->stroke_width=argument_list[19].real_reference;
8641           if (attribute_flag[21] != 0)
8642             draw_info->dash_offset=argument_list[21].real_reference;
8643           if (attribute_flag[22] != 0)
8644             {
8645               AV
8646                 *av;
8647
8648               av=(AV *) argument_list[22].array_reference;
8649               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
8650                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
8651               if (draw_info->dash_pattern != (double *) NULL)
8652                 {
8653                   for (i=0; i <= av_len(av); i++)
8654                     draw_info->dash_pattern[i]=(double)
8655                       SvNV(*(av_fetch(av,i,0)));
8656                   draw_info->dash_pattern[i]=0.0;
8657                 }
8658             }
8659           if (attribute_flag[23] != 0)
8660             image->interpolate=(PixelInterpolateMethod)
8661               argument_list[23].integer_reference;
8662           if ((attribute_flag[24] != 0) &&
8663               (draw_info->fill_pattern != (Image *) NULL))
8664             flags=ParsePageGeometry(draw_info->fill_pattern,
8665               argument_list[24].string_reference,
8666               &draw_info->fill_pattern->tile_offset,exception);
8667           if (attribute_flag[25] != 0)
8668             {
8669               (void) ConcatenateString(&draw_info->primitive," '");
8670               (void) ConcatenateString(&draw_info->primitive,
8671                 argument_list[25].string_reference);
8672               (void) ConcatenateString(&draw_info->primitive,"'");
8673             }
8674           if (attribute_flag[26] != 0)
8675             draw_info->fill_pattern=CloneImage(
8676               argument_list[26].image_reference,0,0,MagickTrue,exception);
8677           if (attribute_flag[27] != 0)
8678             draw_info->stroke_pattern=CloneImage(
8679               argument_list[27].image_reference,0,0,MagickTrue,exception);
8680           if (attribute_flag[28] != 0)
8681             (void) CloneString(&draw_info->primitive,
8682               argument_list[28].string_reference);
8683           if (attribute_flag[29] != 0)
8684             draw_info->kerning=argument_list[29].real_reference;
8685           if (attribute_flag[30] != 0)
8686             draw_info->interline_spacing=argument_list[30].real_reference;
8687           if (attribute_flag[31] != 0)
8688             draw_info->interword_spacing=argument_list[31].real_reference;
8689           if (attribute_flag[32] != 0)
8690             draw_info->direction=(DirectionType)
8691               argument_list[32].integer_reference;
8692           DrawImage(image,draw_info,exception);
8693           draw_info=DestroyDrawInfo(draw_info);
8694           break;
8695         }
8696         case 39:  /* Equalize */
8697         {
8698           if (attribute_flag[0] != 0)
8699             channel=(ChannelType) argument_list[0].integer_reference;
8700           channel_mask=SetPixelChannelMask(image,channel);
8701           EqualizeImage(image,exception);
8702           (void) SetPixelChannelMask(image,channel_mask);
8703           break;
8704         }
8705         case 40:  /* Gamma */
8706         {
8707           if (attribute_flag[1] != 0)
8708             channel=(ChannelType) argument_list[1].integer_reference;
8709           if (attribute_flag[2] == 0)
8710             argument_list[2].real_reference=1.0;
8711           if (attribute_flag[3] == 0)
8712             argument_list[3].real_reference=1.0;
8713           if (attribute_flag[4] == 0)
8714             argument_list[4].real_reference=1.0;
8715           if (attribute_flag[0] == 0)
8716             {
8717               (void) FormatLocaleString(message,MaxTextExtent,
8718                 "%.15g,%.15g,%.15g",(double) argument_list[2].real_reference,
8719                 (double) argument_list[3].real_reference,
8720                 (double) argument_list[4].real_reference);
8721               argument_list[0].string_reference=message;
8722             }
8723           (void) GammaImage(image,InterpretLocaleValue(
8724             argument_list[0].string_reference,(char **) NULL),exception);
8725           break;
8726         }
8727         case 41:  /* Map */
8728         {
8729           QuantizeInfo
8730             *quantize_info;
8731
8732           if (attribute_flag[0] == 0)
8733             {
8734               ThrowPerlException(exception,OptionError,"MapImageRequired",
8735                 PackageName);
8736               goto PerlException;
8737             }
8738           quantize_info=AcquireQuantizeInfo(info->image_info);
8739           if (attribute_flag[1] != 0)
8740             quantize_info->dither=(MagickBooleanType)
8741               argument_list[1].integer_reference;
8742           if (attribute_flag[2] != 0)
8743             quantize_info->dither_method=(DitherMethod)
8744               argument_list[2].integer_reference;
8745           (void) RemapImages(quantize_info,image,
8746             argument_list[0].image_reference,exception);
8747           quantize_info=DestroyQuantizeInfo(quantize_info);
8748           break;
8749         }
8750         case 42:  /* MatteFloodfill */
8751         {
8752           DrawInfo
8753             *draw_info;
8754
8755           MagickBooleanType
8756             invert;
8757
8758           PixelInfo
8759             target;
8760
8761           Quantum
8762             virtual_pixel[MaxPixelChannels];
8763
8764           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8765             (DrawInfo *) NULL);
8766           if (attribute_flag[0] != 0)
8767             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8768               &geometry,exception);
8769           if (attribute_flag[1] != 0)
8770             geometry.x=argument_list[1].integer_reference;
8771           if (attribute_flag[2] != 0)
8772             geometry.y=argument_list[2].integer_reference;
8773           if (image->matte == MagickFalse)
8774             (void) SetImageAlpha(image,OpaqueAlpha);
8775           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,
8776             virtual_pixel,exception);
8777           target.red=virtual_pixel[RedPixelChannel];
8778           target.green=virtual_pixel[GreenPixelChannel];
8779           target.blue=virtual_pixel[BluePixelChannel];
8780           target.alpha=virtual_pixel[AlphaPixelChannel];
8781           if (attribute_flag[4] != 0)
8782             QueryMagickColorCompliance(argument_list[4].string_reference,
8783               AllCompliance,&target,exception);
8784           if (attribute_flag[3] != 0)
8785             target.alpha=SiPrefixToDouble(argument_list[3].string_reference,
8786               QuantumRange);
8787           if (attribute_flag[5] != 0)
8788             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
8789               QuantumRange);
8790           invert=MagickFalse;
8791           if (attribute_flag[6] != 0)
8792             invert=(MagickBooleanType) argument_list[6].integer_reference;
8793           channel_mask=SetPixelChannelMask(image,AlphaChannel);
8794           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8795             geometry.y,invert,exception);
8796           (void) SetPixelChannelMask(image,channel_mask);
8797           draw_info=DestroyDrawInfo(draw_info);
8798           break;
8799         }
8800         case 43:  /* Modulate */
8801         {
8802           char
8803             modulate[MaxTextExtent];
8804
8805           geometry_info.rho=100.0;
8806           geometry_info.sigma=100.0;
8807           geometry_info.xi=100.0;
8808           if (attribute_flag[0] != 0)
8809             (void)ParseGeometry(argument_list[0].string_reference,
8810               &geometry_info);
8811           if (attribute_flag[1] != 0)
8812             geometry_info.xi=argument_list[1].real_reference;
8813           if (attribute_flag[2] != 0)
8814             geometry_info.sigma=argument_list[2].real_reference;
8815           if (attribute_flag[3] != 0)
8816             {
8817               geometry_info.sigma=argument_list[3].real_reference;
8818               SetImageArtifact(image,"modulate:colorspace","HWB");
8819             }
8820           if (attribute_flag[4] != 0)
8821             {
8822               geometry_info.rho=argument_list[4].real_reference;
8823               SetImageArtifact(image,"modulate:colorspace","HSB");
8824             }
8825           if (attribute_flag[5] != 0)
8826             {
8827               geometry_info.sigma=argument_list[5].real_reference;
8828               SetImageArtifact(image,"modulate:colorspace","HSL");
8829             }
8830           if (attribute_flag[6] != 0)
8831             {
8832               geometry_info.rho=argument_list[6].real_reference;
8833               SetImageArtifact(image,"modulate:colorspace","HWB");
8834             }
8835           (void) FormatLocaleString(modulate,MaxTextExtent,"%.15g,%.15g,%.15g",
8836             geometry_info.rho,geometry_info.sigma,geometry_info.xi);
8837           (void) ModulateImage(image,modulate,exception);
8838           break;
8839         }
8840         case 44:  /* Negate */
8841         {
8842           if (attribute_flag[0] == 0)
8843             argument_list[0].integer_reference=0;
8844           if (attribute_flag[1] != 0)
8845             channel=(ChannelType) argument_list[1].integer_reference;
8846           channel_mask=SetPixelChannelMask(image,channel);
8847           (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
8848             MagickTrue : MagickFalse,exception);
8849           (void) SetPixelChannelMask(image,channel_mask);
8850           break;
8851         }
8852         case 45:  /* Normalize */
8853         {
8854           if (attribute_flag[0] != 0)
8855             channel=(ChannelType) argument_list[0].integer_reference;
8856           channel_mask=SetPixelChannelMask(image,channel);
8857           NormalizeImage(image,exception);
8858           (void) SetPixelChannelMask(image,channel_mask);
8859           break;
8860         }
8861         case 46:  /* NumberColors */
8862           break;
8863         case 47:  /* Opaque */
8864         {
8865           MagickBooleanType
8866             invert;
8867
8868           PixelInfo
8869             fill_color,
8870             target;
8871
8872           (void) QueryMagickColorCompliance("none",AllCompliance,&target,
8873              exception);
8874           (void) QueryMagickColorCompliance("none",AllCompliance,&fill_color,
8875             exception);
8876           if (attribute_flag[0] != 0)
8877             (void) QueryMagickColorCompliance(argument_list[0].string_reference,
8878               AllCompliance,&target,exception);
8879           if (attribute_flag[1] != 0)
8880             (void) QueryMagickColorCompliance(argument_list[1].string_reference,
8881               AllCompliance,&fill_color,exception);
8882           if (attribute_flag[2] != 0)
8883             image->fuzz=SiPrefixToDouble(argument_list[2].string_reference,
8884               QuantumRange);
8885           if (attribute_flag[3] != 0)
8886             channel=(ChannelType) argument_list[3].integer_reference;
8887           invert=MagickFalse;
8888           if (attribute_flag[4] != 0)
8889             invert=(MagickBooleanType) argument_list[4].integer_reference;
8890           channel_mask=SetPixelChannelMask(image,channel);
8891           (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
8892           (void) SetPixelChannelMask(image,channel_mask);
8893           break;
8894         }
8895         case 48:  /* Quantize */
8896         {
8897           QuantizeInfo
8898             *quantize_info;
8899
8900           quantize_info=AcquireQuantizeInfo(info->image_info);
8901           if (attribute_flag[0] != 0)
8902             quantize_info->number_colors=(size_t)
8903               argument_list[0].integer_reference;
8904           if (attribute_flag[1] != 0)
8905             quantize_info->tree_depth=(size_t)
8906               argument_list[1].integer_reference;
8907           if (attribute_flag[2] != 0)
8908             quantize_info->colorspace=(ColorspaceType)
8909               argument_list[2].integer_reference;
8910           if (attribute_flag[3] != 0)
8911             quantize_info->dither=argument_list[3].integer_reference != 0 ?
8912               MagickTrue : MagickFalse;
8913           if (attribute_flag[4] != 0)
8914             quantize_info->measure_error=
8915               argument_list[4].integer_reference != 0 ? MagickTrue :
8916               MagickFalse;
8917           if (attribute_flag[5] != 0)
8918             (void) QueryColorCompliance(argument_list[5].string_reference,
8919               AllCompliance,&image->transparent_color,exception);
8920           if (attribute_flag[5] && argument_list[5].integer_reference)
8921             {
8922               (void) QuantizeImages(quantize_info,image,exception);
8923               goto PerlException;
8924             }
8925           if (attribute_flag[6] != 0)
8926             quantize_info->dither_method=(DitherMethod)
8927               argument_list[6].integer_reference;
8928           if ((image->storage_class == DirectClass) ||
8929               (image->colors > quantize_info->number_colors) ||
8930               (quantize_info->colorspace == GRAYColorspace))
8931             (void) QuantizeImage(quantize_info,image,exception);
8932           else
8933             CompressImageColormap(image,exception);
8934           quantize_info=DestroyQuantizeInfo(quantize_info);
8935           break;
8936         }
8937         case 49:  /* Raise */
8938         {
8939           if (attribute_flag[0] != 0)
8940             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8941               &geometry,exception);
8942           if (attribute_flag[1] != 0)
8943             geometry.width=argument_list[1].integer_reference;
8944           if (attribute_flag[2] != 0)
8945             geometry.height=argument_list[2].integer_reference;
8946           if (attribute_flag[3] == 0)
8947             argument_list[3].integer_reference=1;
8948           (void) RaiseImage(image,&geometry,
8949             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8950             exception);
8951           break;
8952         }
8953         case 50:  /* Segment */
8954         {
8955           ColorspaceType
8956             colorspace;
8957
8958           double
8959             cluster_threshold,
8960             smoothing_threshold;
8961
8962           MagickBooleanType
8963             verbose;
8964
8965           cluster_threshold=1.0;
8966           smoothing_threshold=1.5;
8967           colorspace=RGBColorspace;
8968           verbose=MagickFalse;
8969           if (attribute_flag[0] != 0)
8970             {
8971               flags=ParseGeometry(argument_list[0].string_reference,
8972                 &geometry_info);
8973               cluster_threshold=geometry_info.rho;
8974               if (flags & SigmaValue)
8975                 smoothing_threshold=geometry_info.sigma;
8976             }
8977           if (attribute_flag[1] != 0)
8978             cluster_threshold=argument_list[1].real_reference;
8979           if (attribute_flag[2] != 0)
8980             smoothing_threshold=argument_list[2].real_reference;
8981           if (attribute_flag[3] != 0)
8982             colorspace=(ColorspaceType) argument_list[3].integer_reference;
8983           if (attribute_flag[4] != 0)
8984             verbose=argument_list[4].integer_reference != 0 ?
8985               MagickTrue : MagickFalse;
8986           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
8987             smoothing_threshold,exception);
8988           break;
8989         }
8990         case 51:  /* Signature */
8991         {
8992           (void) SignatureImage(image,exception);
8993           break;
8994         }
8995         case 52:  /* Solarize */
8996         {
8997           geometry_info.rho=QuantumRange/2.0;
8998           if (attribute_flag[0] != 0)
8999             flags=ParseGeometry(argument_list[0].string_reference,
9000               &geometry_info);
9001           if (attribute_flag[1] != 0)
9002             geometry_info.rho=SiPrefixToDouble(
9003              argument_list[1].string_reference,QuantumRange);
9004           (void) SolarizeImage(image,geometry_info.rho,exception);
9005           break;
9006         }
9007         case 53:  /* Sync */
9008         {
9009           (void) SyncImage(image);
9010           break;
9011         }
9012         case 54:  /* Texture */
9013         {
9014           if (attribute_flag[0] == 0)
9015             break;
9016           TextureImage(image,argument_list[0].image_reference);
9017           break;
9018         }
9019         case 55:  /* Evalute */
9020         {
9021           MagickEvaluateOperator
9022             op;
9023
9024           op=SetEvaluateOperator;
9025           if (attribute_flag[0] == MagickFalse)
9026             argument_list[0].real_reference=0.0;
9027           if (attribute_flag[1] != MagickFalse)
9028             op=(MagickEvaluateOperator) argument_list[1].integer_reference;
9029           if (attribute_flag[2] != MagickFalse)
9030             channel=(ChannelType) argument_list[2].integer_reference;
9031           channel_mask=SetPixelChannelMask(image,channel);
9032           (void) EvaluateImage(image,op,argument_list[0].real_reference,
9033             exception);
9034           (void) SetPixelChannelMask(image,channel_mask);
9035           break;
9036         }
9037         case 56:  /* Transparent */
9038         {
9039           double
9040             opacity;
9041
9042           MagickBooleanType
9043             invert;
9044
9045           PixelInfo
9046             target;
9047
9048           (void) QueryMagickColorCompliance("none",AllCompliance,&target,
9049             exception);
9050           if (attribute_flag[0] != 0)
9051             (void) QueryMagickColorCompliance(argument_list[0].string_reference,
9052               AllCompliance,&target,exception);
9053           opacity=TransparentAlpha;
9054           if (attribute_flag[1] != 0)
9055             opacity=SiPrefixToDouble(argument_list[1].string_reference,
9056               QuantumRange);
9057           if (attribute_flag[2] != 0)
9058             image->fuzz=SiPrefixToDouble(argument_list[2].string_reference,
9059               QuantumRange);
9060           if (attribute_flag[3] == 0)
9061             argument_list[3].integer_reference=0;
9062           invert=MagickFalse;
9063           if (attribute_flag[3] != 0)
9064             invert=(MagickBooleanType) argument_list[3].integer_reference;
9065           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9066             invert,exception);
9067           break;
9068         }
9069         case 57:  /* Threshold */
9070         {
9071           double
9072             threshold;
9073
9074           if (attribute_flag[0] == 0)
9075             argument_list[0].string_reference="50%";
9076           if (attribute_flag[1] != 0)
9077             channel=(ChannelType) argument_list[1].integer_reference;
9078           threshold=SiPrefixToDouble(argument_list[0].string_reference,
9079             QuantumRange);
9080           channel_mask=SetPixelChannelMask(image,channel);
9081           (void) BilevelImage(image,threshold);
9082           (void) SetPixelChannelMask(image,channel_mask);
9083           break;
9084         }
9085         case 58:  /* Charcoal */
9086         {
9087           if (attribute_flag[0] != 0)
9088             {
9089               flags=ParseGeometry(argument_list[0].string_reference,
9090                 &geometry_info);
9091               if ((flags & SigmaValue) == 0)
9092                 geometry_info.sigma=1.0;
9093             }
9094           if (attribute_flag[1] != 0)
9095             geometry_info.rho=argument_list[1].real_reference;
9096           if (attribute_flag[2] != 0)
9097             geometry_info.sigma=argument_list[2].real_reference;
9098           if (attribute_flag[3] != 0)
9099             geometry_info.xi=argument_list[3].real_reference;
9100           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9101             geometry_info.xi,exception);
9102           break;
9103         }
9104         case 59:  /* Trim */
9105         {
9106           if (attribute_flag[0] != 0)
9107             image->fuzz=SiPrefixToDouble(argument_list[0].string_reference,
9108               QuantumRange);
9109           image=TrimImage(image,exception);
9110           break;
9111         }
9112         case 60:  /* Wave */
9113         {
9114           PixelInterpolateMethod
9115             method;
9116
9117           if (attribute_flag[0] != 0)
9118             {
9119               flags=ParseGeometry(argument_list[0].string_reference,
9120                 &geometry_info);
9121               if ((flags & SigmaValue) == 0)
9122                 geometry_info.sigma=1.0;
9123             }
9124           if (attribute_flag[1] != 0)
9125             geometry_info.rho=argument_list[1].real_reference;
9126           if (attribute_flag[2] != 0)
9127             geometry_info.sigma=argument_list[2].real_reference;
9128           method=UndefinedInterpolatePixel;
9129           if (attribute_flag[3] != 0)
9130             method=(PixelInterpolateMethod) argument_list[3].integer_reference;
9131           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9132             method,exception);
9133           break;
9134         }
9135         case 61:  /* Separate */
9136         {
9137           if (attribute_flag[0] != 0)
9138             channel=(ChannelType) argument_list[0].integer_reference;
9139           channel_mask=SetPixelChannelMask(image,channel);
9140           (void) SeparateImage(image);
9141           (void) SetPixelChannelMask(image,channel_mask);
9142           break;
9143         }
9144         case 63:  /* Stereo */
9145         {
9146           if (attribute_flag[0] == 0)
9147             {
9148               ThrowPerlException(exception,OptionError,"StereoImageRequired",
9149                 PackageName);
9150               goto PerlException;
9151             }
9152           if (attribute_flag[1] != 0)
9153             geometry.x=argument_list[1].integer_reference;
9154           if (attribute_flag[2] != 0)
9155             geometry.y=argument_list[2].integer_reference;
9156           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9157             geometry.x,geometry.y,exception);
9158           break;
9159         }
9160         case 64:  /* Stegano */
9161         {
9162           if (attribute_flag[0] == 0)
9163             {
9164               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9165                 PackageName);
9166               goto PerlException;
9167             }
9168           if (attribute_flag[1] == 0)
9169             argument_list[1].integer_reference=0;
9170           image->offset=argument_list[1].integer_reference;
9171           image=SteganoImage(image,argument_list[0].image_reference,exception);
9172           break;
9173         }
9174         case 65:  /* Deconstruct */
9175         {
9176           image=CompareImagesLayers(image,CompareAnyLayer,exception);
9177           break;
9178         }
9179         case 66:  /* GaussianBlur */
9180         {
9181           if (attribute_flag[0] != 0)
9182             {
9183               flags=ParseGeometry(argument_list[0].string_reference,
9184                 &geometry_info);
9185               if ((flags & SigmaValue) == 0)
9186                 geometry_info.sigma=1.0;
9187             }
9188           if (attribute_flag[1] != 0)
9189             geometry_info.rho=argument_list[1].real_reference;
9190           if (attribute_flag[2] != 0)
9191             geometry_info.sigma=argument_list[2].real_reference;
9192           if (attribute_flag[3] != 0)
9193             geometry_info.xi=argument_list[3].real_reference;
9194           if (attribute_flag[4] != 0)
9195             channel=(ChannelType) argument_list[4].integer_reference;
9196           channel_mask=SetPixelChannelMask(image,channel);
9197           image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9198             geometry_info.xi,exception);
9199           if (image != (Image *) NULL)
9200             (void) SetPixelChannelMask(image,channel_mask);
9201           break;
9202         }
9203         case 67:  /* Convolve */
9204         {
9205           KernelInfo
9206             *kernel;
9207
9208           kernel=(KernelInfo *) NULL;
9209           if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9210             break;
9211           if (attribute_flag[0] != 0)
9212             {
9213               AV
9214                 *av;
9215
9216               size_t
9217                 order;
9218
9219               kernel=AcquireKernelInfo((const char *) NULL);
9220               if (kernel == (KernelInfo *) NULL)
9221                 break;
9222               av=(AV *) argument_list[0].array_reference;
9223               order=(size_t) sqrt(av_len(av)+1);
9224               kernel->width=order;
9225               kernel->height=order;
9226               kernel->values=(double *) AcquireAlignedMemory(order,order*
9227                 sizeof(*kernel->values));
9228               if (kernel->values == (double *) NULL)
9229                 {
9230                   kernel=DestroyKernelInfo(kernel);
9231                   ThrowPerlException(exception,ResourceLimitFatalError,
9232                     "MemoryAllocationFailed",PackageName);
9233                   goto PerlException;
9234                 }
9235               for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9236                 kernel->values[j]=(double) SvNV(*(av_fetch(av,j,0)));
9237               for ( ; j < (ssize_t) (order*order); j++)
9238                 kernel->values[j]=0.0;
9239             }
9240           if (attribute_flag[1] != 0)
9241             channel=(ChannelType) argument_list[1].integer_reference;
9242           if (attribute_flag[2] != 0)
9243             image->bias=SiPrefixToDouble(argument_list[2].string_reference,
9244               QuantumRange);
9245           if (attribute_flag[3] != 0)
9246             {
9247               kernel=AcquireKernelInfo(argument_list[3].string_reference);
9248               if (kernel == (KernelInfo *) NULL)
9249                 break;
9250             }
9251           channel_mask=SetPixelChannelMask(image,channel);
9252           kernel->bias=image->bias;
9253           image=ConvolveImage(image,kernel,exception);
9254           if (image != (Image *) NULL)
9255             (void) SetPixelChannelMask(image,channel_mask);
9256           kernel=DestroyKernelInfo(kernel);
9257           break;
9258         }
9259         case 68:  /* Profile */
9260         {
9261           const char
9262             *name;
9263
9264           Image
9265             *profile_image;
9266
9267           ImageInfo
9268             *profile_info;
9269
9270           StringInfo
9271             *profile;
9272
9273           name="*";
9274           if (attribute_flag[0] != 0)
9275             name=argument_list[0].string_reference;
9276           if (attribute_flag[2] != 0)
9277             image->rendering_intent=(RenderingIntent)
9278               argument_list[2].integer_reference;
9279           if (attribute_flag[3] != 0)
9280             image->black_point_compensation=
9281               argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9282           if (attribute_flag[1] != 0)
9283             {
9284               if (argument_list[1].length == 0)
9285                 {
9286                   /*
9287                     Remove a profile from the image.
9288                   */
9289                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9290                     MagickTrue);
9291                   break;
9292                 }
9293               /*
9294                 Associate user supplied profile with the image.
9295               */
9296               profile=AcquireStringInfo(argument_list[1].length);
9297               SetStringInfoDatum(profile,(const unsigned char *)
9298                 argument_list[1].string_reference);
9299               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9300                 (size_t) GetStringInfoLength(profile),MagickFalse);
9301               profile=DestroyStringInfo(profile);
9302               break;
9303             }
9304           /*
9305             Associate a profile with the image.
9306           */
9307           profile_info=
9308             CloneImageInfo(info ? info->image_info : (ImageInfo *) NULL);
9309           (void) CopyMagickString(profile_info->filename,name,MaxTextExtent);
9310           profile_image=ReadImages(profile_info,&image->exception);
9311           if (profile_image == (Image *) NULL)
9312             break;
9313           ResetImageProfileIterator(profile_image);
9314           name=GetNextImageProfile(profile_image);
9315           while (name != (const char *) NULL)
9316           {
9317             const StringInfo
9318               *profile;
9319
9320             profile=GetImageProfile(profile_image,name);
9321             if (profile != (const StringInfo *) NULL)
9322               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9323                 (size_t) GetStringInfoLength(profile),MagickFalse);
9324             name=GetNextImageProfile(profile_image);
9325           }
9326           profile_image=DestroyImage(profile_image);
9327           profile_info=DestroyImageInfo(profile_info);
9328           break;
9329         }
9330         case 69:  /* UnsharpMask */
9331         {
9332           if (attribute_flag[0] != 0)
9333             {
9334               flags=ParseGeometry(argument_list[0].string_reference,
9335                 &geometry_info);
9336               if ((flags & SigmaValue) == 0)
9337                 geometry_info.sigma=1.0;
9338               if ((flags & XiValue) == 0)
9339                 geometry_info.xi=1.0;
9340               if ((flags & PsiValue) == 0)
9341                 geometry_info.psi=0.5;
9342             }
9343           if (attribute_flag[1] != 0)
9344             geometry_info.rho=argument_list[1].real_reference;
9345           if (attribute_flag[2] != 0)
9346             geometry_info.sigma=argument_list[2].real_reference;
9347           if (attribute_flag[3] != 0)
9348             geometry_info.xi=argument_list[3].real_reference;
9349           if (attribute_flag[4] != 0)
9350             geometry_info.psi=argument_list[4].real_reference;
9351           if (attribute_flag[5] != 0)
9352             channel=(ChannelType) argument_list[5].integer_reference;
9353           channel_mask=SetPixelChannelMask(image,channel);
9354           image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9355             geometry_info.xi,geometry_info.psi,exception);
9356           if (image != (Image *) NULL)
9357             (void) SetPixelChannelMask(image,channel_mask);
9358           break;
9359         }
9360         case 70:  /* MotionBlur */
9361         {
9362           if (attribute_flag[0] != 0)
9363             {
9364               flags=ParseGeometry(argument_list[0].string_reference,
9365                 &geometry_info);
9366               if ((flags & SigmaValue) == 0)
9367                 geometry_info.sigma=1.0;
9368               if ((flags & XiValue) == 0)
9369                 geometry_info.xi=1.0;
9370             }
9371           if (attribute_flag[1] != 0)
9372             geometry_info.rho=argument_list[1].real_reference;
9373           if (attribute_flag[2] != 0)
9374             geometry_info.sigma=argument_list[2].real_reference;
9375           if (attribute_flag[3] != 0)
9376             geometry_info.xi=argument_list[3].real_reference;
9377           if (attribute_flag[4] != 0)
9378             geometry_info.psi=argument_list[4].real_reference;
9379           if (attribute_flag[5] != 0)
9380             channel=(ChannelType) argument_list[5].integer_reference;
9381           channel_mask=SetPixelChannelMask(image,channel);
9382           image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9383             geometry_info.xi,geometry_info.psi,exception);
9384           if (image != (Image *) NULL)
9385             (void) SetPixelChannelMask(image,channel_mask);
9386           break;
9387         }
9388         case 71:  /* OrderedDither */
9389         {
9390           if (attribute_flag[0] == 0)
9391             argument_list[0].string_reference="o8x8";
9392           if (attribute_flag[1] != 0)
9393             channel=(ChannelType) argument_list[1].integer_reference;
9394           channel_mask=SetPixelChannelMask(image,channel);
9395           (void) OrderedPosterizeImage(image,argument_list[0].string_reference,
9396             exception);
9397           (void) SetPixelChannelMask(image,channel_mask);
9398           break;
9399         }
9400         case 72:  /* Shave */
9401         {
9402           if (attribute_flag[0] != 0)
9403             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9404               &geometry,exception);
9405           if (attribute_flag[1] != 0)
9406             geometry.width=argument_list[1].integer_reference;
9407           if (attribute_flag[2] != 0)
9408             geometry.height=argument_list[2].integer_reference;
9409           image=ShaveImage(image,&geometry,exception);
9410           break;
9411         }
9412         case 73:  /* Level */
9413         {
9414           double
9415             black_point,
9416             gamma,
9417             white_point;
9418
9419           black_point=0.0;
9420           white_point=(MagickRealType) image->columns*image->rows;
9421           gamma=1.0;
9422           if (attribute_flag[0] != 0)
9423             {
9424               flags=ParseGeometry(argument_list[0].string_reference,
9425                 &geometry_info);
9426               black_point=geometry_info.rho;
9427               if ((flags & SigmaValue) != 0)
9428                 white_point=geometry_info.sigma;
9429               if ((flags & XiValue) != 0)
9430                 gamma=geometry_info.xi;
9431               if ((flags & PercentValue) != 0)
9432                 {
9433                   black_point*=(double) (QuantumRange/100.0);
9434                   white_point*=(double) (QuantumRange/100.0);
9435                 }
9436               if ((flags & SigmaValue) == 0)
9437                 white_point=(double) QuantumRange-black_point;
9438             }
9439           if (attribute_flag[1] != 0)
9440             black_point=argument_list[1].real_reference;
9441           if (attribute_flag[2] != 0)
9442             white_point=argument_list[2].real_reference;
9443           if (attribute_flag[3] != 0)
9444             gamma=argument_list[3].real_reference;
9445           if (attribute_flag[4] != 0)
9446             channel=(ChannelType) argument_list[4].integer_reference;
9447           if (attribute_flag[5] != 0)
9448             {
9449               argument_list[0].real_reference=argument_list[5].real_reference;
9450               attribute_flag[0]=attribute_flag[5];
9451             }
9452           channel_mask=SetPixelChannelMask(image,channel);
9453           (void) LevelImage(image,black_point,white_point,gamma,exception);
9454           (void) SetPixelChannelMask(image,channel_mask);
9455           break;
9456         }
9457         case 74:  /* Clip */
9458         {
9459           if (attribute_flag[0] == 0)
9460             argument_list[0].string_reference="#1";
9461           if (attribute_flag[1] == 0)
9462             argument_list[1].integer_reference=MagickTrue;
9463           (void) ClipImagePath(image,argument_list[0].string_reference,
9464             argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse,
9465             exception);
9466           break;
9467         }
9468         case 75:  /* AffineTransform */
9469         {
9470           DrawInfo
9471             *draw_info;
9472
9473           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9474             (DrawInfo *) NULL);
9475           if (attribute_flag[0] != 0)
9476             {
9477               AV
9478                 *av;
9479
9480               av=(AV *) argument_list[0].array_reference;
9481               if ((av_len(av) != 3) && (av_len(av) != 5))
9482                 {
9483                   ThrowPerlException(exception,OptionError,
9484                     "affine matrix must have 4 or 6 elements",PackageName);
9485                   goto PerlException;
9486                 }
9487               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9488               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9489               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9490               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9491               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9492                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9493                 {
9494                   ThrowPerlException(exception,OptionError,
9495                     "affine matrix is singular",PackageName);
9496                    goto PerlException;
9497                 }
9498               if (av_len(av) == 5)
9499                 {
9500                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9501                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9502                 }
9503             }
9504           for (j=1; j < 6; j++)
9505           {
9506             if (attribute_flag[j] == 0)
9507               continue;
9508             value=argument_list[j].string_reference;
9509             angle=argument_list[j].real_reference;
9510             current=draw_info->affine;
9511             GetAffineMatrix(&affine);
9512             switch (j)
9513             {
9514               case 1:
9515               {
9516                 /*
9517                   Translate.
9518                 */
9519                 flags=ParseGeometry(value,&geometry_info);
9520                 affine.tx=geometry_info.xi;
9521                 affine.ty=geometry_info.psi;
9522                 if ((flags & PsiValue) == 0)
9523                   affine.ty=affine.tx;
9524                 break;
9525               }
9526               case 2:
9527               {
9528                 /*
9529                   Scale.
9530                 */
9531                 flags=ParseGeometry(value,&geometry_info);
9532                 affine.sx=geometry_info.rho;
9533                 affine.sy=geometry_info.sigma;
9534                 if ((flags & SigmaValue) == 0)
9535                   affine.sy=affine.sx;
9536                 break;
9537               }
9538               case 3:
9539               {
9540                 /*
9541                   Rotate.
9542                 */
9543                 if (angle == 0.0)
9544                   break;
9545                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9546                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9547                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9548                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9549                 break;
9550               }
9551               case 4:
9552               {
9553                 /*
9554                   SkewX.
9555                 */
9556                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9557                 break;
9558               }
9559               case 5:
9560               {
9561                 /*
9562                   SkewY.
9563                 */
9564                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9565                 break;
9566               }
9567             }
9568             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9569             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9570             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9571             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9572             draw_info->affine.tx=
9573               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9574             draw_info->affine.ty=
9575               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9576           }
9577           if (attribute_flag[6] != 0)
9578             image->interpolate=(PixelInterpolateMethod)
9579               argument_list[6].integer_reference;
9580           if (attribute_flag[7] != 0)
9581             QueryColorCompliance(argument_list[7].string_reference,
9582               AllCompliance,&image->background_color,exception);
9583           image=AffineTransformImage(image,&draw_info->affine,exception);
9584           draw_info=DestroyDrawInfo(draw_info);
9585           break;
9586         }
9587         case 76:  /* Difference */
9588         {
9589           if (attribute_flag[0] == 0)
9590             {
9591               ThrowPerlException(exception,OptionError,
9592                 "ReferenceImageRequired",PackageName);
9593               goto PerlException;
9594             }
9595           if (attribute_flag[1] != 0)
9596             image->fuzz=SiPrefixToDouble(argument_list[1].string_reference,
9597               QuantumRange);
9598           (void) IsImagesEqual(image,argument_list[0].image_reference,
9599             exception);
9600           break;
9601         }
9602         case 77:  /* AdaptiveThreshold */
9603         {
9604           if (attribute_flag[0] != 0)
9605             {
9606               flags=ParseGeometry(argument_list[0].string_reference,
9607                 &geometry_info);
9608               if ((flags & PercentValue) != 0)
9609                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9610             }
9611           if (attribute_flag[1] != 0)
9612             geometry_info.rho=argument_list[1].integer_reference;
9613           if (attribute_flag[2] != 0)
9614             geometry_info.sigma=argument_list[2].integer_reference;
9615           if (attribute_flag[3] != 0)
9616             geometry_info.xi=argument_list[3].integer_reference;;
9617           image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
9618             (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
9619           break;
9620         }
9621         case 78:  /* Resample */
9622         {
9623           size_t
9624             height,
9625             width;
9626
9627           if (attribute_flag[0] != 0)
9628             {
9629               flags=ParseGeometry(argument_list[0].string_reference,
9630                 &geometry_info);
9631               if ((flags & SigmaValue) == 0)
9632                 geometry_info.sigma=geometry_info.rho;
9633             }
9634           if (attribute_flag[1] != 0)
9635             geometry_info.rho=argument_list[1].real_reference;
9636           if (attribute_flag[2] != 0)
9637             geometry_info.sigma=argument_list[2].real_reference;
9638           if (attribute_flag[3] == 0)
9639             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
9640           if (attribute_flag[4] == 0)
9641             SetImageArtifact(image,"filter:support",
9642               argument_list[4].string_reference);
9643           if (attribute_flag[5] != 0)
9644             argument_list[5].real_reference=1.0;
9645           width=(size_t) (geometry_info.rho*image->columns/
9646             (image->x_resolution == 0.0 ? 72.0 : image->x_resolution)+0.5);
9647           height=(size_t) (geometry_info.sigma*image->rows/
9648             (image->y_resolution == 0.0 ? 72.0 : image->y_resolution)+0.5);
9649           image=ResizeImage(image,width,height,(FilterTypes)
9650             argument_list[3].integer_reference,argument_list[5].real_reference,
9651             exception);
9652           if (image != (Image *) NULL)
9653             {
9654               image->x_resolution=geometry_info.rho;
9655               image->y_resolution=geometry_info.sigma;
9656             }
9657           break;
9658         }
9659         case 79:  /* Describe */
9660         {
9661           if (attribute_flag[0] == 0)
9662             argument_list[0].file_reference=(FILE *) NULL;
9663           if (attribute_flag[1] != 0)
9664             (void) SetImageArtifact(image,"identify:features",
9665               argument_list[1].string_reference);
9666           (void) IdentifyImage(image,argument_list[0].file_reference,
9667             MagickTrue,exception);
9668           break;
9669         }
9670         case 80:  /* BlackThreshold */
9671         {
9672           if (attribute_flag[0] == 0)
9673             argument_list[0].string_reference="50%";
9674           if (attribute_flag[2] != 0)
9675             channel=(ChannelType) argument_list[2].integer_reference;
9676           channel_mask=SetPixelChannelMask(image,channel);
9677           BlackThresholdImage(image,argument_list[0].string_reference,
9678             exception);
9679           (void) SetPixelChannelMask(image,channel_mask);
9680           break;
9681         }
9682         case 81:  /* WhiteThreshold */
9683         {
9684           if (attribute_flag[0] == 0)
9685             argument_list[0].string_reference="50%";
9686           if (attribute_flag[2] != 0)
9687             channel=(ChannelType) argument_list[2].integer_reference;
9688           channel_mask=SetPixelChannelMask(image,channel);
9689           WhiteThresholdImage(image,argument_list[0].string_reference,
9690             exception);
9691           (void) SetPixelChannelMask(image,channel_mask);
9692           break;
9693         }
9694         case 82:  /* RadialBlur */
9695         {
9696           if (attribute_flag[0] != 0)
9697             {
9698               flags=ParseGeometry(argument_list[0].string_reference,
9699                 &geometry_info);
9700             }
9701           if (attribute_flag[1] != 0)
9702             geometry_info.rho=argument_list[1].real_reference;
9703           if (attribute_flag[2] != 0)
9704             geometry_info.sigma=argument_list[2].real_reference;
9705           if (attribute_flag[3] != 0)
9706             channel=(ChannelType) argument_list[3].integer_reference;
9707           channel_mask=SetPixelChannelMask(image,channel);
9708           image=RadialBlurImage(image,geometry_info.rho,geometry_info.sigma,
9709             exception);
9710           if (image != (Image *) NULL)
9711             (void) SetPixelChannelMask(image,channel_mask);
9712           break;
9713         }
9714         case 83:  /* Thumbnail */
9715         {
9716           if (attribute_flag[0] != 0)
9717             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
9718               &geometry,exception);
9719           if (attribute_flag[1] != 0)
9720             geometry.width=argument_list[1].integer_reference;
9721           if (attribute_flag[2] != 0)
9722             geometry.height=argument_list[2].integer_reference;
9723           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
9724           break;
9725         }
9726         case 84:  /* Strip */
9727         {
9728           (void) StripImage(image);
9729           break;
9730         }
9731         case 85:  /* Tint */
9732         {
9733           PixelInfo
9734             tint;
9735
9736           GetPixelInfo(image,&tint);
9737           if (attribute_flag[0] != 0)
9738             (void) QueryMagickColorCompliance(argument_list[0].string_reference,
9739               AllCompliance,&tint,exception);
9740           if (attribute_flag[1] == 0)
9741             argument_list[1].string_reference="100";
9742           image=TintImage(image,argument_list[1].string_reference,&tint,
9743             exception);
9744           break;
9745         }
9746         case 86:  /* Channel */
9747         {
9748           if (attribute_flag[0] != 0)
9749             channel=(ChannelType) argument_list[0].integer_reference;
9750           channel_mask=SetPixelChannelMask(image,channel);
9751           (void) SeparateImage(image);
9752           (void) SetPixelChannelMask(image,channel_mask);
9753           break;
9754         }
9755         case 87:  /* Splice */
9756         {
9757           if (attribute_flag[0] != 0)
9758             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
9759               &geometry,exception);
9760           if (attribute_flag[1] != 0)
9761             geometry.width=argument_list[1].integer_reference;
9762           if (attribute_flag[2] != 0)
9763             geometry.height=argument_list[2].integer_reference;
9764           if (attribute_flag[3] != 0)
9765             geometry.x=argument_list[3].integer_reference;
9766           if (attribute_flag[4] != 0)
9767             geometry.y=argument_list[4].integer_reference;
9768           if (attribute_flag[5] != 0)
9769             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
9770               QuantumRange);
9771           if (attribute_flag[6] != 0)
9772             (void) QueryColorCompliance(argument_list[6].string_reference,
9773               AllCompliance,&image->background_color,exception);
9774           if (attribute_flag[7] != 0)
9775             image->gravity=(GravityType) argument_list[7].integer_reference;
9776           image=SpliceImage(image,&geometry,exception);
9777           break;
9778         }
9779         case 88:  /* Posterize */
9780         {
9781           if (attribute_flag[0] == 0)
9782             argument_list[0].integer_reference=3;
9783           if (attribute_flag[1] == 0)
9784             argument_list[1].integer_reference=0;
9785           (void) PosterizeImage(image,argument_list[0].integer_reference,
9786             argument_list[1].integer_reference ? MagickTrue : MagickFalse,
9787             exception);
9788           break;
9789         }
9790         case 89:  /* Shadow */
9791         {
9792           if (attribute_flag[0] != 0)
9793             {
9794               flags=ParseGeometry(argument_list[0].string_reference,
9795                 &geometry_info);
9796               if ((flags & SigmaValue) == 0)
9797                 geometry_info.sigma=1.0;
9798               if ((flags & XiValue) == 0)
9799                 geometry_info.xi=4.0;
9800               if ((flags & PsiValue) == 0)
9801                 geometry_info.psi=4.0;
9802             }
9803           if (attribute_flag[1] != 0)
9804             geometry_info.rho=argument_list[1].real_reference;
9805           if (attribute_flag[2] != 0)
9806             geometry_info.sigma=argument_list[2].real_reference;
9807           if (attribute_flag[3] != 0)
9808             geometry_info.xi=argument_list[3].integer_reference;
9809           if (attribute_flag[4] != 0)
9810             geometry_info.psi=argument_list[4].integer_reference;
9811           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
9812             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-
9813             0.5),exception);
9814           break;
9815         }
9816         case 90:  /* Identify */
9817         {
9818           if (attribute_flag[0] == 0)
9819             argument_list[0].file_reference=(FILE *) NULL;
9820           if (attribute_flag[1] != 0)
9821             (void) SetImageArtifact(image,"identify:features",
9822               argument_list[1].string_reference);
9823           if ((attribute_flag[2] != 0) &&
9824               (argument_list[2].integer_reference != 0))
9825             (void) SetImageArtifact(image,"identify:unique","true");
9826           (void) IdentifyImage(image,argument_list[0].file_reference,
9827             MagickTrue,exception);
9828           break;
9829         }
9830         case 91:  /* SepiaTone */
9831         {
9832           if (attribute_flag[0] == 0)
9833             argument_list[0].real_reference=80.0*QuantumRange/100.0;
9834           image=SepiaToneImage(image,argument_list[0].real_reference,
9835             exception);
9836           break;
9837         }
9838         case 92:  /* SigmoidalContrast */
9839         {
9840           MagickBooleanType
9841             sharpen;
9842
9843           if (attribute_flag[0] != 0)
9844             {
9845               flags=ParseGeometry(argument_list[0].string_reference,
9846                 &geometry_info);
9847               if ((flags & SigmaValue) == 0)
9848                 geometry_info.sigma=QuantumRange/2.0;
9849               if ((flags & PercentValue) != 0)
9850                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
9851             }
9852           if (attribute_flag[1] != 0)
9853             geometry_info.rho=argument_list[1].real_reference;
9854           if (attribute_flag[2] != 0)
9855             geometry_info.sigma=argument_list[2].real_reference;
9856           if (attribute_flag[3] != 0)
9857             channel=(ChannelType) argument_list[3].integer_reference;
9858           sharpen=MagickTrue;
9859           if (attribute_flag[4] != 0)
9860             sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
9861               MagickFalse;
9862           channel_mask=SetPixelChannelMask(image,channel);
9863           (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
9864             geometry_info.sigma,exception);
9865           (void) SetPixelChannelMask(image,channel_mask);
9866           break;
9867         }
9868         case 93:  /* Extent */
9869         {
9870           if (attribute_flag[7] != 0)
9871             image->gravity=(GravityType) argument_list[7].integer_reference;
9872           if (attribute_flag[0] != 0)
9873             {
9874               int
9875                 flags;
9876
9877               flags=ParseGravityGeometry(image,
9878                 argument_list[0].string_reference,&geometry,exception);
9879               (void) flags;
9880               if (geometry.width == 0)
9881                 geometry.width=image->columns;
9882               if (geometry.height == 0)
9883                 geometry.height=image->rows;
9884             }
9885           if (attribute_flag[1] != 0)
9886             geometry.width=argument_list[1].integer_reference;
9887           if (attribute_flag[2] != 0)
9888             geometry.height=argument_list[2].integer_reference;
9889           if (attribute_flag[3] != 0)
9890             geometry.x=argument_list[3].integer_reference;
9891           if (attribute_flag[4] != 0)
9892             geometry.y=argument_list[4].integer_reference;
9893           if (attribute_flag[5] != 0)
9894             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
9895               QuantumRange);
9896           if (attribute_flag[6] != 0)
9897             (void) QueryColorCompliance(argument_list[6].string_reference,
9898               AllCompliance,&image->background_color,exception);
9899           image=ExtentImage(image,&geometry,exception);
9900           break;
9901         }
9902         case 94:  /* Vignette */
9903         {
9904           if (attribute_flag[0] != 0)
9905             {
9906               flags=ParseGeometry(argument_list[0].string_reference,
9907                 &geometry_info);
9908               if ((flags & SigmaValue) == 0)
9909                 geometry_info.sigma=1.0;
9910               if ((flags & XiValue) == 0)
9911                 geometry_info.xi=0.1*image->columns;
9912               if ((flags & PsiValue) == 0)
9913                 geometry_info.psi=0.1*image->rows;
9914             }
9915           if (attribute_flag[1] != 0)
9916             geometry_info.rho=argument_list[1].real_reference;
9917           if (attribute_flag[2] != 0)
9918             geometry_info.sigma=argument_list[2].real_reference;
9919           if (attribute_flag[3] != 0)
9920             geometry_info.xi=argument_list[3].integer_reference;
9921           if (attribute_flag[4] != 0)
9922             geometry_info.psi=argument_list[4].integer_reference;
9923           if (attribute_flag[5] != 0)
9924             (void) QueryColorCompliance(argument_list[5].string_reference,
9925               AllCompliance,&image->background_color,exception);
9926           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
9927             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-
9928             0.5),exception);
9929           break;
9930         }
9931         case 95:  /* ContrastStretch */
9932         {
9933           double
9934             black_point,
9935             white_point;
9936
9937           black_point=0.0;
9938           white_point=(MagickRealType) image->columns*image->rows;
9939           if (attribute_flag[0] != 0)
9940             {
9941               flags=ParseGeometry(argument_list[0].string_reference,
9942                 &geometry_info);
9943               black_point=geometry_info.rho;
9944               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
9945                 black_point;
9946               if ((flags & PercentValue) != 0)
9947                 {
9948                   black_point*=(double) image->columns*image->rows/100.0;
9949                   white_point*=(double) image->columns*image->rows/100.0;
9950                 }
9951               white_point=(MagickRealType) image->columns*image->rows-
9952                 white_point;
9953             }
9954           if (attribute_flag[1] != 0)
9955             black_point=argument_list[1].real_reference;
9956           if (attribute_flag[2] != 0)
9957             white_point=argument_list[2].real_reference;
9958           if (attribute_flag[4] != 0)
9959             channel=(ChannelType) argument_list[4].integer_reference;
9960           channel_mask=SetPixelChannelMask(image,channel);
9961           (void) ContrastStretchImage(image,black_point,white_point,exception);
9962           (void) SetPixelChannelMask(image,channel_mask);
9963           break;
9964         }
9965         case 96:  /* Sans0 */
9966         {
9967           break;
9968         }
9969         case 97:  /* Sans1 */
9970         {
9971           break;
9972         }
9973         case 98:  /* AdaptiveSharpen */
9974         {
9975           if (attribute_flag[0] != 0)
9976             {
9977               flags=ParseGeometry(argument_list[0].string_reference,
9978                 &geometry_info);
9979               if ((flags & SigmaValue) == 0)
9980                 geometry_info.sigma=1.0;
9981               if ((flags & XiValue) == 0)
9982                 geometry_info.xi=0.0;
9983             }
9984           if (attribute_flag[1] != 0)
9985             geometry_info.rho=argument_list[1].real_reference;
9986           if (attribute_flag[2] != 0)
9987             geometry_info.sigma=argument_list[2].real_reference;
9988           if (attribute_flag[3] != 0)
9989             geometry_info.xi=argument_list[3].real_reference;
9990           if (attribute_flag[4] != 0)
9991             channel=(ChannelType) argument_list[4].integer_reference;
9992           channel_mask=SetPixelChannelMask(image,channel);
9993           image=AdaptiveSharpenImage(image,geometry_info.rho,
9994             geometry_info.sigma,geometry_info.xi,exception);
9995           if (image != (Image *) NULL)
9996             (void) SetPixelChannelMask(image,channel_mask);
9997           break;
9998         }
9999         case 99:  /* Transpose */
10000         {
10001           image=TransposeImage(image,exception);
10002           break;
10003         }
10004         case 100:  /* Tranverse */
10005         {
10006           image=TransverseImage(image,exception);
10007           break;
10008         }
10009         case 101:  /* AutoOrient */
10010         {
10011           switch (image->orientation)
10012           {
10013             case TopRightOrientation:
10014             {
10015               image=FlopImage(image,exception);
10016               break;
10017             }
10018             case BottomRightOrientation:
10019             {
10020               image=RotateImage(image,180.0,exception);
10021               break;
10022             }
10023             case BottomLeftOrientation:
10024             {
10025               image=FlipImage(image,exception);
10026               break;
10027             }
10028             case LeftTopOrientation:
10029             {
10030               image=TransposeImage(image,exception);
10031               break;
10032             }
10033             case RightTopOrientation:
10034             {
10035               image=RotateImage(image,90.0,exception);
10036               break;
10037             }
10038             case RightBottomOrientation:
10039             {
10040               image=TransverseImage(image,exception);
10041               break;
10042             }
10043             case LeftBottomOrientation:
10044             {
10045               image=RotateImage(image,270.0,exception);
10046               break;
10047             }
10048             default:
10049               break;
10050           }
10051           break;
10052         }
10053         case 102:  /* AdaptiveBlur */
10054         {
10055           if (attribute_flag[0] != 0)
10056             {
10057               flags=ParseGeometry(argument_list[0].string_reference,
10058                 &geometry_info);
10059               if ((flags & SigmaValue) == 0)
10060                 geometry_info.sigma=1.0;
10061               if ((flags & XiValue) == 0)
10062                 geometry_info.xi=0.0;
10063             }
10064           if (attribute_flag[1] != 0)
10065             geometry_info.rho=argument_list[1].real_reference;
10066           if (attribute_flag[2] != 0)
10067             geometry_info.sigma=argument_list[2].real_reference;
10068           if (attribute_flag[3] != 0)
10069             geometry_info.xi=argument_list[3].real_reference;
10070           if (attribute_flag[4] != 0)
10071             channel=(ChannelType) argument_list[4].integer_reference;
10072           channel_mask=SetPixelChannelMask(image,channel);
10073           image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10074             geometry_info.xi,exception);
10075           if (image != (Image *) NULL)
10076             (void) SetPixelChannelMask(image,channel_mask);
10077           break;
10078         }
10079         case 103:  /* Sketch */
10080         {
10081           if (attribute_flag[0] != 0)
10082             {
10083               flags=ParseGeometry(argument_list[0].string_reference,
10084                 &geometry_info);
10085               if ((flags & SigmaValue) == 0)
10086                 geometry_info.sigma=1.0;
10087               if ((flags & XiValue) == 0)
10088                 geometry_info.xi=1.0;
10089             }
10090           if (attribute_flag[1] != 0)
10091             geometry_info.rho=argument_list[1].real_reference;
10092           if (attribute_flag[2] != 0)
10093             geometry_info.sigma=argument_list[2].real_reference;
10094           if (attribute_flag[3] != 0)
10095             geometry_info.xi=argument_list[3].real_reference;
10096           if (attribute_flag[4] != 0)
10097             geometry_info.psi=argument_list[4].real_reference;
10098           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10099             geometry_info.xi,geometry_info.psi,exception);
10100           break;
10101         }
10102         case 104:  /* UniqueColors */
10103         {
10104           image=UniqueImageColors(image,exception);
10105           break;
10106         }
10107         case 105:  /* AdaptiveResize */
10108         {
10109           PixelInterpolateMethod
10110             method;
10111
10112           if (attribute_flag[0] != 0)
10113             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10114               &geometry,exception);
10115           if (attribute_flag[1] != 0)
10116             geometry.width=argument_list[1].integer_reference;
10117           if (attribute_flag[2] != 0)
10118             geometry.height=argument_list[2].integer_reference;
10119           if (attribute_flag[3] != 0)
10120             image->filter=(FilterTypes) argument_list[4].integer_reference;
10121           if (attribute_flag[4] != 0)
10122             SetImageArtifact(image,"filter:support",
10123               argument_list[4].string_reference);
10124           if (attribute_flag[5] != 0)
10125             image->blur=argument_list[5].real_reference;
10126           method=UndefinedInterpolatePixel;
10127           if (attribute_flag[6] != 0)
10128             method=(PixelInterpolateMethod) argument_list[6].integer_reference;
10129           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10130             method,exception);
10131           break;
10132         }
10133         case 106:  /* ClipMask */
10134         {
10135           if (attribute_flag[0] == 0)
10136             {
10137               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10138                 PackageName);
10139               goto PerlException;
10140             }
10141           image->clip_mask=CloneImage(argument_list[0].image_reference,0,0,
10142             MagickTrue,exception);
10143           (void) NegateImage(image->clip_mask,MagickFalse,exception);
10144           break;
10145         }
10146         case 107:  /* LinearStretch */
10147         {
10148            double
10149              black_point,
10150              white_point;
10151
10152            black_point=0.0;
10153            white_point=(MagickRealType) image->columns*image->rows;
10154            if (attribute_flag[0] != 0)
10155              {
10156                flags=ParseGeometry(argument_list[0].string_reference,
10157                  &geometry_info);
10158                if ((flags & SigmaValue) != 0)
10159                   white_point=geometry_info.sigma;
10160                if ((flags & PercentValue) != 0)
10161                  {
10162                    black_point*=(double) image->columns*image->rows/100.0;
10163                    white_point*=(double) image->columns*image->rows/100.0;
10164                  }
10165                if ((flags & SigmaValue) == 0)
10166                  white_point=(double) image->columns*image->rows-black_point;
10167              }
10168           if (attribute_flag[1] != 0)
10169             black_point=argument_list[1].real_reference;
10170           if (attribute_flag[2] != 0)
10171             white_point=argument_list[2].real_reference;
10172           (void) LinearStretchImage(image,black_point,white_point,exception);
10173           break;
10174         }
10175         case 109:  /* Mask */
10176         {
10177           if (attribute_flag[0] == 0)
10178             {
10179               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10180                 PackageName);
10181               goto PerlException;
10182             }
10183           image->mask=CloneImage(argument_list[0].image_reference,0,0,
10184             MagickTrue,exception);
10185           (void) NegateImage(image->mask,MagickFalse,exception);
10186           break;
10187         }
10188         case 110:  /* Polaroid */
10189         {
10190           DrawInfo
10191             *draw_info;
10192
10193           double
10194             angle;
10195
10196           PixelInterpolateMethod
10197             method;
10198
10199           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10200             (DrawInfo *) NULL);
10201           if (attribute_flag[0] != 0)
10202             (void) SetImageProperty(image,"caption",InterpretImageProperties(
10203               info ? info->image_info : (ImageInfo *) NULL,image,
10204               argument_list[0].string_reference,exception));
10205           angle=0.0;
10206           if (attribute_flag[1] != 0)
10207             angle=argument_list[1].real_reference;
10208           if (attribute_flag[2] != 0)
10209             (void) CloneString(&draw_info->font,
10210               argument_list[2].string_reference);
10211           if (attribute_flag[3] != 0)
10212             (void) QueryColorCompliance(argument_list[3].string_reference,
10213               AllCompliance,&draw_info->stroke,exception);
10214           if (attribute_flag[4] != 0)
10215             (void) QueryColorCompliance(argument_list[4].string_reference,
10216               AllCompliance,&draw_info->fill,exception);
10217           if (attribute_flag[5] != 0)
10218             draw_info->stroke_width=argument_list[5].real_reference;
10219           if (attribute_flag[6] != 0)
10220             draw_info->pointsize=argument_list[6].real_reference;
10221           if (attribute_flag[7] != 0)
10222             draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10223           if (attribute_flag[8] != 0)
10224             (void) QueryColorCompliance(argument_list[8].string_reference,
10225               AllCompliance,&image->background_color,exception);
10226           method=UndefinedInterpolatePixel;
10227           if (attribute_flag[9] != 0)
10228             method=(PixelInterpolateMethod) argument_list[9].integer_reference;
10229           image=PolaroidImage(image,draw_info,angle,method,exception);
10230           draw_info=DestroyDrawInfo(draw_info);
10231           break;
10232         }
10233         case 111:  /* FloodfillPaint */
10234         {
10235           DrawInfo
10236             *draw_info;
10237
10238           MagickBooleanType
10239             invert;
10240
10241           PixelInfo
10242             target;
10243
10244           Quantum
10245             virtual_pixel[MaxPixelChannels];
10246
10247           draw_info=CloneDrawInfo(info ? info->image_info :
10248             (ImageInfo *) NULL,(DrawInfo *) NULL);
10249           if (attribute_flag[0] != 0)
10250             flags=ParsePageGeometry(image,argument_list[0].string_reference,
10251               &geometry,exception);
10252           if (attribute_flag[1] != 0)
10253             geometry.x=argument_list[1].integer_reference;
10254           if (attribute_flag[2] != 0)
10255             geometry.y=argument_list[2].integer_reference;
10256           if (attribute_flag[3] != 0)
10257             (void) QueryColorCompliance(argument_list[3].string_reference,
10258               AllCompliance,&draw_info->fill,exception);
10259           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,
10260             virtual_pixel,exception);
10261           target.red=virtual_pixel[RedPixelChannel];
10262           target.green=virtual_pixel[GreenPixelChannel];
10263           target.blue=virtual_pixel[BluePixelChannel];
10264           target.alpha=virtual_pixel[AlphaPixelChannel];
10265           if (attribute_flag[4] != 0)
10266             QueryMagickColorCompliance(argument_list[4].string_reference,
10267               AllCompliance,&target,exception);
10268           if (attribute_flag[5] != 0)
10269             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
10270               QuantumRange);
10271           if (attribute_flag[6] != 0)
10272             channel=(ChannelType) argument_list[6].integer_reference;
10273           invert=MagickFalse;
10274           if (attribute_flag[7] != 0)
10275             invert=(MagickBooleanType) argument_list[7].integer_reference;
10276           channel_mask=SetPixelChannelMask(image,channel);
10277           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10278             geometry.y,invert,exception);
10279           (void) SetPixelChannelMask(image,channel_mask);
10280           draw_info=DestroyDrawInfo(draw_info);
10281           break;
10282         }
10283         case 112:  /* Distort */
10284         {
10285           AV
10286             *av;
10287
10288           double
10289             *coordinates;
10290
10291           DistortImageMethod
10292             method;
10293
10294           size_t
10295             number_coordinates;
10296
10297           VirtualPixelMethod
10298             virtual_pixel;
10299
10300           if (attribute_flag[0] == 0)
10301             break;
10302           method=UndefinedDistortion;
10303           if (attribute_flag[1] != 0)
10304             method=(DistortImageMethod) argument_list[1].integer_reference;
10305           av=(AV *) argument_list[0].array_reference;
10306           number_coordinates=(size_t) av_len(av)+1;
10307           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10308             sizeof(*coordinates));
10309           if (coordinates == (double *) NULL)
10310             {
10311               ThrowPerlException(exception,ResourceLimitFatalError,
10312                 "MemoryAllocationFailed",PackageName);
10313               goto PerlException;
10314             }
10315           for (j=0; j < (ssize_t) number_coordinates; j++)
10316             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10317           virtual_pixel=UndefinedVirtualPixelMethod;
10318           if (attribute_flag[2] != 0)
10319             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10320               argument_list[2].integer_reference);
10321           image=DistortImage(image,method,number_coordinates,coordinates,
10322             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10323             exception);
10324           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10325             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10326           coordinates=(double *) RelinquishMagickMemory(coordinates);
10327           break;
10328         }
10329         case 113:  /* Clut */
10330         {
10331           PixelInterpolateMethod
10332             method;
10333
10334           if (attribute_flag[0] == 0)
10335             {
10336               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10337                 PackageName);
10338               goto PerlException;
10339             }
10340           method=UndefinedInterpolatePixel;
10341           if (attribute_flag[1] != 0)
10342             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
10343           if (attribute_flag[2] != 0)
10344             channel=(ChannelType) argument_list[2].integer_reference;
10345           channel_mask=SetPixelChannelMask(image,channel);
10346           (void) ClutImage(image,argument_list[0].image_reference,method,
10347             exception);
10348           (void) SetPixelChannelMask(image,channel_mask);
10349           break;
10350         }
10351         case 114:  /* LiquidRescale */
10352         {
10353           if (attribute_flag[0] != 0)
10354             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10355               &geometry,exception);
10356           if (attribute_flag[1] != 0)
10357             geometry.width=argument_list[1].integer_reference;
10358           if (attribute_flag[2] != 0)
10359             geometry.height=argument_list[2].integer_reference;
10360           if (attribute_flag[3] == 0)
10361             argument_list[3].real_reference=1.0;
10362           if (attribute_flag[4] == 0)
10363             argument_list[4].real_reference=0.0;
10364           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10365             argument_list[3].real_reference,argument_list[4].real_reference,
10366             exception);
10367           break;
10368         }
10369         case 115:  /* EncipherImage */
10370         {
10371           (void) EncipherImage(image,argument_list[0].string_reference,
10372             exception);
10373           break;
10374         }
10375         case 116:  /* DecipherImage */
10376         {
10377           (void) DecipherImage(image,argument_list[0].string_reference,
10378             exception);
10379           break;
10380         }
10381         case 117:  /* Deskew */
10382         {
10383           geometry_info.rho=QuantumRange/2.0;
10384           if (attribute_flag[0] != 0)
10385             flags=ParseGeometry(argument_list[0].string_reference,
10386               &geometry_info);
10387           if (attribute_flag[1] != 0)
10388             geometry_info.rho=SiPrefixToDouble(
10389               argument_list[1].string_reference,QuantumRange);
10390           image=DeskewImage(image,geometry_info.rho,exception);
10391           break;
10392         }
10393         case 118:  /* Remap */
10394         {
10395           QuantizeInfo
10396             *quantize_info;
10397
10398           if (attribute_flag[0] == 0)
10399             {
10400               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10401                 PackageName);
10402               goto PerlException;
10403             }
10404           quantize_info=AcquireQuantizeInfo(info->image_info);
10405           if (attribute_flag[1] != 0)
10406             quantize_info->dither=(MagickBooleanType)
10407               argument_list[1].integer_reference;
10408           if (attribute_flag[2] != 0)
10409             quantize_info->dither_method=(DitherMethod)
10410               argument_list[2].integer_reference;
10411           (void) RemapImages(quantize_info,image,
10412             argument_list[0].image_reference,exception);
10413           quantize_info=DestroyQuantizeInfo(quantize_info);
10414           break;
10415         }
10416         case 119:  /* SparseColor */
10417         {
10418           AV
10419             *av;
10420
10421           double
10422             *coordinates;
10423
10424           SparseColorMethod
10425             method;
10426
10427           size_t
10428             number_coordinates;
10429
10430           VirtualPixelMethod
10431             virtual_pixel;
10432
10433           if (attribute_flag[0] == 0)
10434             break;
10435           method=UndefinedColorInterpolate;
10436           if (attribute_flag[1] != 0)
10437             method=(SparseColorMethod) argument_list[1].integer_reference;
10438           av=(AV *) argument_list[0].array_reference;
10439           number_coordinates=(size_t) av_len(av)+1;
10440           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10441             sizeof(*coordinates));
10442           if (coordinates == (double *) NULL)
10443             {
10444               ThrowPerlException(exception,ResourceLimitFatalError,
10445                 "MemoryAllocationFailed",PackageName);
10446               goto PerlException;
10447             }
10448           for (j=0; j < (ssize_t) number_coordinates; j++)
10449             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10450           virtual_pixel=UndefinedVirtualPixelMethod;
10451           if (attribute_flag[2] != 0)
10452             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10453               argument_list[2].integer_reference);
10454           if (attribute_flag[3] != 0)
10455             channel=(ChannelType) argument_list[3].integer_reference;
10456           channel_mask=SetPixelChannelMask(image,channel);
10457           image=SparseColorImage(image,method,number_coordinates,coordinates,
10458             exception);
10459           if (image != (Image *) NULL)
10460             (void) SetPixelChannelMask(image,channel_mask);
10461           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10462             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10463           coordinates=(double *) RelinquishMagickMemory(coordinates);
10464           break;
10465         }
10466         case 120:  /* Function */
10467         {
10468           AV
10469             *av;
10470
10471           double
10472             *parameters;
10473
10474           MagickFunction
10475             function;
10476
10477           size_t
10478             number_parameters;
10479
10480           VirtualPixelMethod
10481             virtual_pixel;
10482
10483           if (attribute_flag[0] == 0)
10484             break;
10485           function=UndefinedFunction;
10486           if (attribute_flag[1] != 0)
10487             function=(MagickFunction) argument_list[1].integer_reference;
10488           av=(AV *) argument_list[0].array_reference;
10489           number_parameters=(size_t) av_len(av)+1;
10490           parameters=(double *) AcquireQuantumMemory(number_parameters,
10491             sizeof(*parameters));
10492           if (parameters == (double *) NULL)
10493             {
10494               ThrowPerlException(exception,ResourceLimitFatalError,
10495                 "MemoryAllocationFailed",PackageName);
10496               goto PerlException;
10497             }
10498           for (j=0; j < (ssize_t) number_parameters; j++)
10499             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10500           virtual_pixel=UndefinedVirtualPixelMethod;
10501           if (attribute_flag[2] != 0)
10502             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10503               argument_list[2].integer_reference);
10504           (void) FunctionImage(image,function,number_parameters,parameters,
10505             exception);
10506           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10507             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10508           parameters=(double *) RelinquishMagickMemory(parameters);
10509           break;
10510         }
10511         case 121:  /* SelectiveBlur */
10512         {
10513           if (attribute_flag[0] != 0)
10514             {
10515               flags=ParseGeometry(argument_list[0].string_reference,
10516                 &geometry_info);
10517               if ((flags & SigmaValue) == 0)
10518                 geometry_info.sigma=1.0;
10519               if ((flags & PercentValue) != 0)
10520                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10521             }
10522           if (attribute_flag[1] != 0)
10523             geometry_info.rho=argument_list[1].real_reference;
10524           if (attribute_flag[2] != 0)
10525             geometry_info.sigma=argument_list[2].real_reference;
10526           if (attribute_flag[3] != 0)
10527             geometry_info.xi=argument_list[3].integer_reference;;
10528           if (attribute_flag[4] != 0)
10529             geometry_info.psi=argument_list[4].integer_reference;;
10530           if (attribute_flag[5] != 0)
10531             channel=(ChannelType) argument_list[5].integer_reference;
10532           channel_mask=SetPixelChannelMask(image,channel);
10533           image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10534             geometry_info.xi,geometry_info.psi,exception);
10535           if (image != (Image *) NULL)
10536             (void) SetPixelChannelMask(image,channel_mask);
10537           break;
10538         }
10539         case 122:  /* HaldClut */
10540         {
10541           if (attribute_flag[0] == 0)
10542             {
10543               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10544                 PackageName);
10545               goto PerlException;
10546             }
10547           if (attribute_flag[1] != 0)
10548             channel=(ChannelType) argument_list[1].integer_reference;
10549           channel_mask=SetPixelChannelMask(image,channel);
10550           (void) HaldClutImage(image,argument_list[0].image_reference,
10551             exception);
10552           (void) SetPixelChannelMask(image,channel_mask);
10553           break;
10554         }
10555         case 123:  /* BlueShift */
10556         {
10557           if (attribute_flag[0] != 0)
10558             (void) ParseGeometry(argument_list[0].string_reference,
10559               &geometry_info);
10560           image=BlueShiftImage(image,geometry_info.rho,exception);
10561           break;
10562         }
10563         case 124:  /* ForwardFourierTransformImage */
10564         {
10565           image=ForwardFourierTransformImage(image,
10566             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10567             exception);
10568           break;
10569         }
10570         case 125:  /* InverseFourierTransformImage */
10571         {
10572           image=InverseFourierTransformImage(image,image->next,
10573             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10574             exception);
10575           break;
10576         }
10577         case 126:  /* ColorDecisionList */
10578         {
10579           if (attribute_flag[0] == 0)
10580             argument_list[0].string_reference=(char *) NULL;
10581           (void) ColorDecisionListImage(image,
10582             argument_list[0].string_reference,exception);
10583           break;
10584         }
10585         case 127:  /* AutoGamma */
10586         {
10587           if (attribute_flag[0] != 0)
10588             channel=(ChannelType) argument_list[0].integer_reference;
10589           channel_mask=SetPixelChannelMask(image,channel);
10590           (void) AutoGammaImage(image,exception);
10591           (void) SetPixelChannelMask(image,channel_mask);
10592           break;
10593         }
10594         case 128:  /* AutoLevel */
10595         {
10596           if (attribute_flag[0] != 0)
10597             channel=(ChannelType) argument_list[0].integer_reference;
10598           channel_mask=SetPixelChannelMask(image,channel);
10599           (void) AutoLevelImage(image,exception);
10600           (void) SetPixelChannelMask(image,channel_mask);
10601           break;
10602         }
10603         case 129:  /* LevelColors */
10604         {
10605           PixelInfo
10606             black_point,
10607             white_point;
10608
10609           (void) QueryMagickColorCompliance("#000000",AllCompliance,
10610             &black_point,exception);
10611           (void) QueryMagickColorCompliance("#ffffff",AllCompliance,
10612             &white_point,exception);
10613           if (attribute_flag[1] != 0)
10614              (void) QueryMagickColorCompliance(
10615                argument_list[1].string_reference,AllCompliance,&black_point,
10616                exception);
10617           if (attribute_flag[2] != 0)
10618              (void) QueryMagickColorCompliance(
10619                argument_list[2].string_reference,AllCompliance,&white_point,
10620                exception);
10621           if (attribute_flag[3] != 0)
10622             channel=(ChannelType) argument_list[3].integer_reference;
10623           channel_mask=SetPixelChannelMask(image,channel);
10624           (void) LevelImageColors(image,&black_point,&white_point,
10625             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10626             exception);
10627           (void) SetPixelChannelMask(image,channel_mask);
10628           break;
10629         }
10630         case 130:  /* Clamp */
10631         {
10632           if (attribute_flag[0] != 0)
10633             channel=(ChannelType) argument_list[0].integer_reference;
10634           channel_mask=SetPixelChannelMask(image,channel);
10635           (void) ClampImage(image);
10636           (void) SetPixelChannelMask(image,channel_mask);
10637           break;
10638         }
10639         case 132:  /* BrightnessContrast */
10640         {
10641           double
10642             brightness,
10643             contrast;
10644
10645           brightness=0.0;
10646           contrast=0.0;
10647           if (attribute_flag[0] != 0)
10648             {
10649               flags=ParseGeometry(argument_list[0].string_reference,
10650                 &geometry_info);
10651               brightness=geometry_info.rho;
10652               if ((flags & SigmaValue) == 0)
10653                 contrast=geometry_info.sigma;
10654             }
10655           if (attribute_flag[1] != 0)
10656             brightness=argument_list[1].real_reference;
10657           if (attribute_flag[2] != 0)
10658             contrast=argument_list[2].real_reference;
10659           if (attribute_flag[4] != 0)
10660             channel=(ChannelType) argument_list[4].integer_reference;
10661           channel_mask=SetPixelChannelMask(image,channel);
10662           (void) BrightnessContrastImage(image,brightness,contrast,exception);
10663           (void) SetPixelChannelMask(image,channel_mask);
10664           break;
10665         }
10666         case 133:  /* Morphology */
10667         {
10668           KernelInfo
10669             *kernel;
10670
10671           MorphologyMethod
10672             method;
10673
10674           ssize_t
10675             iterations;
10676
10677           if (attribute_flag[0] == 0)
10678             break;
10679           kernel=AcquireKernelInfo(argument_list[0].string_reference);
10680           if (kernel == (KernelInfo *) NULL)
10681             break;
10682           if (attribute_flag[1] != 0)
10683             channel=(ChannelType) argument_list[1].integer_reference;
10684           method=UndefinedMorphology;
10685           if (attribute_flag[2] != 0)
10686             method=argument_list[2].integer_reference;
10687           iterations=1;
10688           if (attribute_flag[3] != 0)
10689             iterations=argument_list[4].integer_reference;
10690           channel_mask=SetPixelChannelMask(image,channel);
10691           image=MorphologyImage(image,method,iterations,kernel,exception);
10692           if (image != (Image *) NULL)
10693             (void) SetPixelChannelMask(image,channel_mask);
10694           kernel=DestroyKernelInfo(kernel);
10695           break;
10696         }
10697         case 108:  /* Recolor */
10698         case 134:  /* ColorMatrix */
10699         {
10700           AV
10701             *av;
10702
10703           double
10704             *color_matrix;
10705
10706           KernelInfo
10707             *kernel_info;
10708
10709           size_t
10710             order;
10711
10712           if (attribute_flag[0] == 0)
10713             break;
10714           av=(AV *) argument_list[0].array_reference;
10715           if (av == (AV *) NULL)
10716             break;
10717           order=(size_t) sqrt(av_len(av)+1);
10718           color_matrix=(double *) AcquireQuantumMemory(order,order*
10719             sizeof(*color_matrix));
10720           if (color_matrix == (double *) NULL)
10721             {
10722               ThrowPerlException(exception,ResourceLimitFatalError,
10723                 "MemoryAllocationFailed",PackageName);
10724               goto PerlException;
10725            }
10726           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10727             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10728           for ( ; j < (ssize_t) (order*order); j++)
10729             color_matrix[j]=0.0;
10730           kernel_info=AcquireKernelInfo((const char *) NULL);
10731           if (kernel_info == (KernelInfo *) NULL)
10732             break;
10733           kernel_info->width=order;
10734           kernel_info->height=order;
10735           kernel_info->values=color_matrix;
10736           image=ColorMatrixImage(image,kernel_info,exception);
10737           kernel_info->values=(double *) NULL;
10738           kernel_info=DestroyKernelInfo(kernel_info);
10739           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10740           break;
10741         }
10742         case 135:  /* Color */
10743         {
10744           PixelInfo
10745             color;
10746
10747           (void) QueryMagickColorCompliance("none",AllCompliance,&color,
10748             exception);
10749           if (attribute_flag[0] != 0)
10750             (void) QueryMagickColorCompliance(argument_list[0].string_reference,
10751               AllCompliance,&color,exception);
10752           (void) SetImageColor(image,&color);
10753           break;
10754         }
10755         case 136:  /* Mode */
10756         {
10757           if (attribute_flag[0] != 0)
10758             {
10759               flags=ParseGeometry(argument_list[0].string_reference,
10760                 &geometry_info);
10761               if ((flags & SigmaValue) == 0)
10762                 geometry_info.sigma=1.0;
10763             }
10764           if (attribute_flag[1] != 0)
10765             geometry_info.rho=argument_list[1].real_reference;
10766           if (attribute_flag[2] != 0)
10767             geometry_info.sigma=argument_list[2].real_reference;
10768           if (attribute_flag[3] != 0)
10769             channel=(ChannelType) argument_list[3].integer_reference;
10770           channel_mask=SetPixelChannelMask(image,channel);
10771           image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
10772             (size_t) geometry_info.sigma,exception);
10773           if (image != (Image *) NULL)
10774             (void) SetPixelChannelMask(image,channel_mask);
10775           break;
10776         }
10777         case 137:  /* Statistic */
10778         {
10779           StatisticType
10780             statistic;
10781
10782           statistic=UndefinedStatistic;
10783           if (attribute_flag[0] != 0)
10784             {
10785               flags=ParseGeometry(argument_list[0].string_reference,
10786                 &geometry_info);
10787               if ((flags & SigmaValue) == 0)
10788                 geometry_info.sigma=1.0;
10789             }
10790           if (attribute_flag[1] != 0)
10791             geometry_info.rho=argument_list[1].real_reference;
10792           if (attribute_flag[2] != 0)
10793             geometry_info.sigma=argument_list[2].real_reference;
10794           if (attribute_flag[3] != 0)
10795             channel=(ChannelType) argument_list[3].integer_reference;
10796           if (attribute_flag[4] != 0)
10797             statistic=(StatisticType) argument_list[4].integer_reference;
10798           channel_mask=SetPixelChannelMask(image,channel);
10799           image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
10800             (size_t) geometry_info.sigma,exception);
10801           if (image != (Image *) NULL)
10802             (void) SetPixelChannelMask(image,channel_mask);
10803           break;
10804         }
10805       }
10806       if (next != (Image *) NULL)
10807         (void) CatchImageException(next);
10808       if (region_image != (Image *) NULL)
10809         {
10810           /*
10811             Composite region.
10812           */ 
10813           status=CompositeImage(region_image,CopyCompositeOp,image,
10814             region_info.x,region_info.y);
10815           (void) status;
10816           (void) CatchImageException(region_image);
10817           image=DestroyImage(image);
10818           image=region_image;
10819         }
10820       if (image != (Image *) NULL)
10821         {
10822           number_images++;
10823           if (next && (next != image))
10824             {
10825               image->next=next->next;
10826               if (image->next != (Image *) NULL)
10827                 image->next->previous=image;
10828               DeleteImageFromRegistry(*pv,next);
10829             }
10830           sv_setiv(*pv,(IV) image);
10831           next=image;
10832         }
10833       if (*pv)
10834         pv++;
10835     }
10836
10837   PerlException:
10838     if (reference_vector)
10839       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
10840     InheritPerlException(exception,perl_exception);
10841     exception=DestroyExceptionInfo(exception);
10842     sv_setiv(perl_exception,(IV) number_images);
10843     SvPOK_on(perl_exception);
10844     ST(0)=sv_2mortal(perl_exception);
10845     XSRETURN(1);
10846   }
10847 \f
10848 #
10849 ###############################################################################
10850 #                                                                             #
10851 #                                                                             #
10852 #                                                                             #
10853 #   M o n t a g e                                                             #
10854 #                                                                             #
10855 #                                                                             #
10856 #                                                                             #
10857 ###############################################################################
10858 #
10859 #
10860 void
10861 Montage(ref,...)
10862   Image::Magick ref=NO_INIT
10863   ALIAS:
10864     MontageImage  = 1
10865     montage       = 2
10866     montageimage  = 3
10867   PPCODE:
10868   {
10869     AV
10870       *av;
10871
10872     char
10873       *attribute;
10874
10875     ExceptionInfo
10876       *exception;
10877
10878     HV
10879       *hv;
10880
10881     Image
10882       *image,
10883       *next;
10884
10885     PixelInfo
10886       transparent_color;
10887
10888     MontageInfo
10889       *montage_info;
10890
10891     register ssize_t
10892       i;
10893
10894     ssize_t
10895       sp;
10896
10897     struct PackageInfo
10898       *info;
10899
10900     SV
10901       *av_reference,
10902       *perl_exception,
10903       *reference,
10904       *rv,
10905       *sv;
10906
10907     PERL_UNUSED_VAR(ref);
10908     PERL_UNUSED_VAR(ix);
10909     exception=AcquireExceptionInfo();
10910     perl_exception=newSVpv("",0);
10911     sv=NULL;
10912     attribute=NULL;
10913     if (sv_isobject(ST(0)) == 0)
10914       {
10915         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
10916           PackageName);
10917         goto PerlException;
10918       }
10919     reference=SvRV(ST(0));
10920     hv=SvSTASH(reference);
10921     av=newAV();
10922     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
10923     SvREFCNT_dec(av);
10924     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
10925     if (image == (Image *) NULL)
10926       {
10927         ThrowPerlException(exception,OptionError,"NoImagesDefined",
10928           PackageName);
10929         goto PerlException;
10930       }
10931     /*
10932       Get options.
10933     */
10934     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
10935     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
10936     (void) QueryMagickColorCompliance("none",AllCompliance,&transparent_color,
10937       exception);
10938     for (i=2; i < items; i+=2)
10939     {
10940       attribute=(char *) SvPV(ST(i-1),na);
10941       switch (*attribute)
10942       {
10943         case 'B':
10944         case 'b':
10945         {
10946           if (LocaleCompare(attribute,"background") == 0)
10947             {
10948               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
10949                 &montage_info->background_color,exception);
10950               for (next=image; next; next=next->next)
10951                 next->background_color=montage_info->background_color;
10952               break;
10953             }
10954           if (LocaleCompare(attribute,"border") == 0)
10955             {
10956               montage_info->border_width=SvIV(ST(i));
10957               break;
10958             }
10959           if (LocaleCompare(attribute,"bordercolor") == 0)
10960             {
10961               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
10962                 &montage_info->border_color,exception);
10963               for (next=image; next; next=next->next)
10964                 next->border_color=montage_info->border_color;
10965               break;
10966             }
10967           if (LocaleCompare(attribute,"borderwidth") == 0)
10968             {
10969               montage_info->border_width=SvIV(ST(i));
10970               break;
10971             }
10972           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10973             attribute);
10974           break;
10975         }
10976         case 'C':
10977         case 'c':
10978         {
10979           if (LocaleCompare(attribute,"compose") == 0)
10980             {
10981               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
10982                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
10983               if (sp < 0)
10984                 {
10985                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
10986                     SvPV(ST(i),na));
10987                   break;
10988                 }
10989               for (next=image; next; next=next->next)
10990                 next->compose=(CompositeOperator) sp;
10991               break;
10992             }
10993           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10994             attribute);
10995           break;
10996         }
10997         case 'F':
10998         case 'f':
10999         {
11000           if (LocaleCompare(attribute,"fill") == 0)
11001             {
11002               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11003                 &montage_info->fill,exception);
11004               break;
11005             }
11006           if (LocaleCompare(attribute,"font") == 0)
11007             {
11008               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
11009               break;
11010             }
11011           if (LocaleCompare(attribute,"frame") == 0)
11012             {
11013               char
11014                 *p;
11015
11016               p=SvPV(ST(i),na);
11017               if (IsGeometry(p) == MagickFalse)
11018                 {
11019                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11020                     p);
11021                   break;
11022                 }
11023               (void) CloneString(&montage_info->frame,p);
11024               if (*p == '\0')
11025                 montage_info->frame=(char *) NULL;
11026               break;
11027             }
11028           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11029             attribute);
11030           break;
11031         }
11032         case 'G':
11033         case 'g':
11034         {
11035           if (LocaleCompare(attribute,"geometry") == 0)
11036             {
11037               char
11038                 *p;
11039
11040               p=SvPV(ST(i),na);
11041               if (IsGeometry(p) == MagickFalse)
11042                 {
11043                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11044                     p);
11045                   break;
11046                 }
11047              (void) CloneString(&montage_info->geometry,p);
11048              if (*p == '\0')
11049                montage_info->geometry=(char *) NULL;
11050              break;
11051            }
11052          if (LocaleCompare(attribute,"gravity") == 0)
11053            {
11054              ssize_t
11055                in;
11056
11057              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11058                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11059              if (in < 0)
11060                {
11061                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
11062                    SvPV(ST(i),na));
11063                  return;
11064                }
11065              montage_info->gravity=(GravityType) in;
11066              for (next=image; next; next=next->next)
11067                next->gravity=(GravityType) in;
11068              break;
11069            }
11070           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11071             attribute);
11072           break;
11073         }
11074         case 'L':
11075         case 'l':
11076         {
11077           if (LocaleCompare(attribute,"label") == 0)
11078             {
11079               for (next=image; next; next=next->next)
11080                 (void) SetImageProperty(next,"label",InterpretImageProperties(
11081                   info ? info->image_info : (ImageInfo *) NULL,next,
11082                   SvPV(ST(i),na),exception));
11083               break;
11084             }
11085           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11086             attribute);
11087           break;
11088         }
11089         case 'M':
11090         case 'm':
11091         {
11092           if (LocaleCompare(attribute,"mattecolor") == 0)
11093             {
11094               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11095                 &montage_info->matte_color,exception);
11096               for (next=image; next; next=next->next)
11097                 next->matte_color=montage_info->matte_color;
11098               break;
11099             }
11100           if (LocaleCompare(attribute,"mode") == 0)
11101             {
11102               ssize_t
11103                 in;
11104
11105               in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11106                 MagickModeOptions,MagickFalse,SvPV(ST(i),na));
11107               switch (in)
11108               {
11109                 default:
11110                 {
11111                   ThrowPerlException(exception,OptionError,
11112                     "UnrecognizedModeType",SvPV(ST(i),na));
11113                   break;
11114                 }
11115                 case FrameMode:
11116                 {
11117                   (void) CloneString(&montage_info->frame,"15x15+3+3");
11118                   montage_info->shadow=MagickTrue;
11119                   break;
11120                 }
11121                 case UnframeMode:
11122                 {
11123                   montage_info->frame=(char *) NULL;
11124                   montage_info->shadow=MagickFalse;
11125                   montage_info->border_width=0;
11126                   break;
11127                 }
11128                 case ConcatenateMode:
11129                 {
11130                   montage_info->frame=(char *) NULL;
11131                   montage_info->shadow=MagickFalse;
11132                   (void) CloneString(&montage_info->geometry,"+0+0");
11133                   montage_info->border_width=0;
11134                 }
11135               }
11136               break;
11137             }
11138           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11139             attribute);
11140           break;
11141         }
11142         case 'P':
11143         case 'p':
11144         {
11145           if (LocaleCompare(attribute,"pointsize") == 0)
11146             {
11147               montage_info->pointsize=SvIV(ST(i));
11148               break;
11149             }
11150           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11151             attribute);
11152           break;
11153         }
11154         case 'S':
11155         case 's':
11156         {
11157           if (LocaleCompare(attribute,"shadow") == 0)
11158             {
11159               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11160                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11161               if (sp < 0)
11162                 {
11163                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11164                     SvPV(ST(i),na));
11165                   break;
11166                 }
11167              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11168              break;
11169             }
11170           if (LocaleCompare(attribute,"stroke") == 0)
11171             {
11172               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11173                 &montage_info->stroke,exception);
11174               break;
11175             }
11176           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11177             attribute);
11178           break;
11179         }
11180         case 'T':
11181         case 't':
11182         {
11183           if (LocaleCompare(attribute,"texture") == 0)
11184             {
11185               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11186               break;
11187             }
11188           if (LocaleCompare(attribute,"tile") == 0)
11189             {
11190               char *p=SvPV(ST(i),na);
11191               if (IsGeometry(p) == MagickFalse)
11192                 {
11193                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11194                     p);
11195                   break;
11196                 }
11197               (void) CloneString(&montage_info->tile,p);
11198               if (*p == '\0')
11199                 montage_info->tile=(char *) NULL;
11200               break;
11201             }
11202           if (LocaleCompare(attribute,"title") == 0)
11203             {
11204               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11205               break;
11206             }
11207           if (LocaleCompare(attribute,"transparent") == 0)
11208             {
11209               PixelInfo
11210                 transparent_color;
11211
11212               QueryMagickColorCompliance(SvPV(ST(i),na),AllCompliance,
11213                 &transparent_color,exception);
11214               for (next=image; next; next=next->next)
11215                 (void) TransparentPaintImage(next,&transparent_color,
11216                   TransparentAlpha,MagickFalse,exception);
11217               break;
11218             }
11219           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11220             attribute);
11221           break;
11222         }
11223         default:
11224         {
11225           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11226             attribute);
11227           break;
11228         }
11229       }
11230     }
11231     image=MontageImageList(info->image_info,montage_info,image,exception);
11232     montage_info=DestroyMontageInfo(montage_info);
11233     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11234       goto PerlException;
11235     if (transparent_color.alpha != TransparentAlpha)
11236       for (next=image; next; next=next->next)
11237         (void) TransparentPaintImage(next,&transparent_color,
11238           TransparentAlpha,MagickFalse,exception);
11239     for (  ; image; image=image->next)
11240     {
11241       AddImageToRegistry(sv,image);
11242       rv=newRV(sv);
11243       av_push(av,sv_bless(rv,hv));
11244       SvREFCNT_dec(sv);
11245     }
11246     exception=DestroyExceptionInfo(exception);
11247     ST(0)=av_reference;
11248     SvREFCNT_dec(perl_exception);
11249     XSRETURN(1);
11250
11251   PerlException:
11252     InheritPerlException(exception,perl_exception);
11253     exception=DestroyExceptionInfo(exception);
11254     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11255     SvPOK_on(perl_exception);
11256     ST(0)=sv_2mortal(perl_exception);
11257     XSRETURN(1);
11258   }
11259 \f
11260 #
11261 ###############################################################################
11262 #                                                                             #
11263 #                                                                             #
11264 #                                                                             #
11265 #   M o r p h                                                                 #
11266 #                                                                             #
11267 #                                                                             #
11268 #                                                                             #
11269 ###############################################################################
11270 #
11271 #
11272 void
11273 Morph(ref,...)
11274   Image::Magick ref=NO_INIT
11275   ALIAS:
11276     MorphImage  = 1
11277     morph       = 2
11278     morphimage  = 3
11279   PPCODE:
11280   {
11281     AV
11282       *av;
11283
11284     char
11285       *attribute;
11286
11287     ExceptionInfo
11288       *exception;
11289
11290     HV
11291       *hv;
11292
11293     Image
11294       *image;
11295
11296     register ssize_t
11297       i;
11298
11299     ssize_t
11300       number_frames;
11301
11302     struct PackageInfo
11303       *info;
11304
11305     SV
11306       *av_reference,
11307       *perl_exception,
11308       *reference,
11309       *rv,
11310       *sv;
11311
11312     PERL_UNUSED_VAR(ref);
11313     PERL_UNUSED_VAR(ix);
11314     exception=AcquireExceptionInfo();
11315     perl_exception=newSVpv("",0);
11316     sv=NULL;
11317     av=NULL;
11318     attribute=NULL;
11319     if (sv_isobject(ST(0)) == 0)
11320       {
11321         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11322           PackageName);
11323         goto PerlException;
11324       }
11325     reference=SvRV(ST(0));
11326     hv=SvSTASH(reference);
11327     av=newAV();
11328     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11329     SvREFCNT_dec(av);
11330     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11331     if (image == (Image *) NULL)
11332       {
11333         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11334           PackageName);
11335         goto PerlException;
11336       }
11337     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11338     /*
11339       Get attribute.
11340     */
11341     number_frames=30;
11342     for (i=2; i < items; i+=2)
11343     {
11344       attribute=(char *) SvPV(ST(i-1),na);
11345       switch (*attribute)
11346       {
11347         case 'F':
11348         case 'f':
11349         {
11350           if (LocaleCompare(attribute,"frames") == 0)
11351             {
11352               number_frames=SvIV(ST(i));
11353               break;
11354             }
11355           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11356             attribute);
11357           break;
11358         }
11359         default:
11360         {
11361           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11362             attribute);
11363           break;
11364         }
11365       }
11366     }
11367     image=MorphImages(image,number_frames,exception);
11368     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11369       goto PerlException;
11370     for ( ; image; image=image->next)
11371     {
11372       AddImageToRegistry(sv,image);
11373       rv=newRV(sv);
11374       av_push(av,sv_bless(rv,hv));
11375       SvREFCNT_dec(sv);
11376     }
11377     exception=DestroyExceptionInfo(exception);
11378     ST(0)=av_reference;
11379     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11380     XSRETURN(1);
11381
11382   PerlException:
11383     InheritPerlException(exception,perl_exception);
11384     exception=DestroyExceptionInfo(exception);
11385     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11386     SvPOK_on(perl_exception);
11387     ST(0)=sv_2mortal(perl_exception);
11388     XSRETURN(1);
11389   }
11390 \f
11391 #
11392 ###############################################################################
11393 #                                                                             #
11394 #                                                                             #
11395 #                                                                             #
11396 #   M o s a i c                                                               #
11397 #                                                                             #
11398 #                                                                             #
11399 #                                                                             #
11400 ###############################################################################
11401 #
11402 #
11403 void
11404 Mosaic(ref)
11405   Image::Magick ref=NO_INIT
11406   ALIAS:
11407     MosaicImage   = 1
11408     mosaic        = 2
11409     mosaicimage   = 3
11410   PPCODE:
11411   {
11412     AV
11413       *av;
11414
11415     ExceptionInfo
11416       *exception;
11417
11418     HV
11419       *hv;
11420
11421     Image
11422       *image;
11423
11424     struct PackageInfo
11425       *info;
11426
11427     SV
11428       *perl_exception,
11429       *reference,
11430       *rv,
11431       *sv;
11432
11433     PERL_UNUSED_VAR(ref);
11434     PERL_UNUSED_VAR(ix);
11435     exception=AcquireExceptionInfo();
11436     perl_exception=newSVpv("",0);
11437     sv=NULL;
11438     if (sv_isobject(ST(0)) == 0)
11439       {
11440         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11441           PackageName);
11442         goto PerlException;
11443       }
11444     reference=SvRV(ST(0));
11445     hv=SvSTASH(reference);
11446     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11447     if (image == (Image *) NULL)
11448       {
11449         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11450           PackageName);
11451         goto PerlException;
11452       }
11453     image=MergeImageLayers(image,MosaicLayer,exception);
11454     /*
11455       Create blessed Perl array for the returned image.
11456     */
11457     av=newAV();
11458     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11459     SvREFCNT_dec(av);
11460     AddImageToRegistry(sv,image);
11461     rv=newRV(sv);
11462     av_push(av,sv_bless(rv,hv));
11463     SvREFCNT_dec(sv);
11464     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11465     (void) CopyMagickString(info->image_info->filename,image->filename,
11466       MaxTextExtent);
11467     SetImageInfo(info->image_info,0,&image->exception);
11468     exception=DestroyExceptionInfo(exception);
11469     SvREFCNT_dec(perl_exception);
11470     XSRETURN(1);
11471
11472   PerlException:
11473     InheritPerlException(exception,perl_exception);
11474     exception=DestroyExceptionInfo(exception);
11475     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11476     SvPOK_on(perl_exception);  /* return messages in string context */
11477     ST(0)=sv_2mortal(perl_exception);
11478     XSRETURN(1);
11479   }
11480 \f
11481 #
11482 ###############################################################################
11483 #                                                                             #
11484 #                                                                             #
11485 #                                                                             #
11486 #   P i n g                                                                   #
11487 #                                                                             #
11488 #                                                                             #
11489 #                                                                             #
11490 ###############################################################################
11491 #
11492 #
11493 void
11494 Ping(ref,...)
11495   Image::Magick ref=NO_INIT
11496   ALIAS:
11497     PingImage  = 1
11498     ping       = 2
11499     pingimage  = 3
11500   PPCODE:
11501   {
11502     AV
11503       *av;
11504
11505     char
11506       **keep,
11507       **list;
11508
11509     ExceptionInfo
11510       *exception;
11511
11512     Image
11513       *image,
11514       *next;
11515
11516     int
11517       n;
11518
11519     MagickBooleanType
11520       status;
11521
11522     register char
11523       **p;
11524
11525     register ssize_t
11526       i;
11527
11528     ssize_t
11529       ac;
11530
11531     STRLEN
11532       *length;
11533
11534     struct PackageInfo
11535       *info,
11536       *package_info;
11537
11538     SV
11539       *perl_exception,
11540       *reference;
11541
11542     size_t
11543       count;
11544
11545     PERL_UNUSED_VAR(ref);
11546     PERL_UNUSED_VAR(ix);
11547     exception=AcquireExceptionInfo();
11548     perl_exception=newSVpv("",0);
11549     package_info=(struct PackageInfo *) NULL;
11550     ac=(items < 2) ? 1 : items-1;
11551     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
11552     keep=list;
11553     length=(STRLEN *) NULL;
11554     if (list == (char **) NULL)
11555       {
11556         ThrowPerlException(exception,ResourceLimitError,
11557           "MemoryAllocationFailed",PackageName);
11558         goto PerlException;
11559       }
11560     keep=list;
11561     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
11562     if (length == (STRLEN *) NULL)
11563       {
11564         ThrowPerlException(exception,ResourceLimitError,
11565           "MemoryAllocationFailed",PackageName);
11566         goto PerlException;
11567       }
11568     if (sv_isobject(ST(0)) == 0)
11569       {
11570         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11571           PackageName);
11572         goto PerlException;
11573       }
11574     reference=SvRV(ST(0));
11575     if (SvTYPE(reference) != SVt_PVAV)
11576       {
11577         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11578           PackageName);
11579         goto PerlException;
11580       }
11581     av=(AV *) reference;
11582     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11583       exception);
11584     package_info=ClonePackageInfo(info,exception);
11585     n=1;
11586     if (items <= 1)
11587       *list=(char *) (*package_info->image_info->filename ?
11588         package_info->image_info->filename : "XC:black");
11589     else
11590       for (n=0, i=0; i < ac; i++)
11591       {
11592         list[n]=(char *) SvPV(ST(i+1),length[n]);
11593         if ((items >= 3) && strEQcase(list[n],"blob"))
11594           {
11595             void
11596               *blob;
11597
11598             i++;
11599             blob=(void *) (SvPV(ST(i+1),length[n]));
11600             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
11601           }
11602         if ((items >= 3) && strEQcase(list[n],"filename"))
11603           continue;
11604         if ((items >= 3) && strEQcase(list[n],"file"))
11605           {
11606             FILE
11607               *file;
11608
11609             PerlIO
11610               *io_info;
11611
11612             i++;
11613             io_info=IoIFP(sv_2io(ST(i+1)));
11614             if (io_info == (PerlIO *) NULL)
11615               {
11616                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11617                   PackageName);
11618                 continue;
11619               }
11620             file=PerlIO_findFILE(io_info);
11621             if (file == (FILE *) NULL)
11622               {
11623                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11624                   PackageName);
11625                 continue;
11626               }
11627             SetImageInfoFile(package_info->image_info,file);
11628           }
11629         if ((items >= 3) && strEQcase(list[n],"magick"))
11630           continue;
11631         n++;
11632       }
11633     list[n]=(char *) NULL;
11634     keep=list;
11635     status=ExpandFilenames(&n,&list);
11636     if (status == MagickFalse)
11637       {
11638         ThrowPerlException(exception,ResourceLimitError,
11639           "MemoryAllocationFailed",PackageName);
11640         goto PerlException;
11641       }
11642     count=0;
11643     for (i=0; i < n; i++)
11644     {
11645       (void) CopyMagickString(package_info->image_info->filename,list[i],
11646         MaxTextExtent);
11647       image=PingImage(package_info->image_info,exception);
11648       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11649         break;
11650       if ((package_info->image_info->file != (FILE *) NULL) ||
11651           (package_info->image_info->blob != (void *) NULL))
11652         DisassociateImageStream(image);
11653       count+=GetImageListLength(image);
11654       EXTEND(sp,4*count);
11655       for (next=image; next; next=next->next)
11656       {
11657         PUSHs(sv_2mortal(newSViv(next->columns)));
11658         PUSHs(sv_2mortal(newSViv(next->rows)));
11659         PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
11660         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
11661       }
11662       image=DestroyImageList(image);
11663     }
11664     /*
11665       Free resources.
11666     */
11667     for (i=0; i < n; i++)
11668       if (list[i] != (char *) NULL)
11669         for (p=keep; list[i] != *p++; )
11670           if (*p == NULL)
11671             {
11672               list[i]=(char *) RelinquishMagickMemory(list[i]);
11673               break;
11674             }
11675
11676   PerlException:
11677     if (package_info != (struct PackageInfo *) NULL)
11678       DestroyPackageInfo(package_info);
11679     if (list && (list != keep))
11680       list=(char **) RelinquishMagickMemory(list);
11681     if (keep)
11682       keep=(char **) RelinquishMagickMemory(keep);
11683     if (length)
11684       length=(STRLEN *) RelinquishMagickMemory(length);
11685     InheritPerlException(exception,perl_exception);
11686     exception=DestroyExceptionInfo(exception);
11687     SvREFCNT_dec(perl_exception);  /* throw away all errors */
11688   }
11689 \f
11690 #
11691 ###############################################################################
11692 #                                                                             #
11693 #                                                                             #
11694 #                                                                             #
11695 #   P r e v i e w                                                             #
11696 #                                                                             #
11697 #                                                                             #
11698 #                                                                             #
11699 ###############################################################################
11700 #
11701 #
11702 void
11703 Preview(ref,...)
11704   Image::Magick ref=NO_INIT
11705   ALIAS:
11706     PreviewImage = 1
11707     preview      = 2
11708     previewimage = 3
11709   PPCODE:
11710   {
11711     AV
11712       *av;
11713
11714     ExceptionInfo
11715       *exception;
11716
11717     HV
11718       *hv;
11719
11720     Image
11721       *image,
11722       *preview_image;
11723
11724     PreviewType
11725       preview_type;
11726
11727     struct PackageInfo
11728       *info;
11729
11730     SV
11731       *av_reference,
11732       *perl_exception,
11733       *reference,
11734       *rv,
11735       *sv;
11736
11737     PERL_UNUSED_VAR(ref);
11738     PERL_UNUSED_VAR(ix);
11739     exception=AcquireExceptionInfo();
11740     perl_exception=newSVpv("",0);
11741     sv=NULL;
11742     av=NULL;
11743     if (sv_isobject(ST(0)) == 0)
11744       {
11745         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11746           PackageName);
11747         goto PerlException;
11748       }
11749     reference=SvRV(ST(0));
11750     hv=SvSTASH(reference);
11751     av=newAV();
11752     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11753     SvREFCNT_dec(av);
11754     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11755     if (image == (Image *) NULL)
11756       {
11757         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11758           PackageName);
11759         goto PerlException;
11760       }
11761     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11762     preview_type=GammaPreview;
11763     if (items > 1)
11764       preview_type=(PreviewType)
11765         ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
11766     for ( ; image; image=image->next)
11767     {
11768       preview_image=PreviewImage(image,preview_type,exception);
11769       if (preview_image == (Image *) NULL)
11770         goto PerlException;
11771       AddImageToRegistry(sv,preview_image);
11772       rv=newRV(sv);
11773       av_push(av,sv_bless(rv,hv));
11774       SvREFCNT_dec(sv);
11775     }
11776     exception=DestroyExceptionInfo(exception);
11777     ST(0)=av_reference;
11778     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11779     XSRETURN(1);
11780
11781   PerlException:
11782     InheritPerlException(exception,perl_exception);
11783     exception=DestroyExceptionInfo(exception);
11784     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11785     SvPOK_on(perl_exception);
11786     ST(0)=sv_2mortal(perl_exception);
11787     XSRETURN(1);
11788   }
11789 \f
11790 #
11791 ###############################################################################
11792 #                                                                             #
11793 #                                                                             #
11794 #                                                                             #
11795 #   Q u e r y C o l o r                                                       #
11796 #                                                                             #
11797 #                                                                             #
11798 #                                                                             #
11799 ###############################################################################
11800 #
11801 #
11802 void
11803 QueryColor(ref,...)
11804   Image::Magick ref=NO_INIT
11805   ALIAS:
11806     querycolor = 1
11807   PPCODE:
11808   {
11809     char
11810       *name;
11811
11812     ExceptionInfo
11813       *exception;
11814
11815     PixelInfo
11816       color;
11817
11818     register ssize_t
11819       i;
11820
11821     SV
11822       *perl_exception;
11823
11824     PERL_UNUSED_VAR(ref);
11825     PERL_UNUSED_VAR(ix);
11826     exception=AcquireExceptionInfo();
11827     perl_exception=newSVpv("",0);
11828     if (items == 1)
11829       {
11830         const ColorInfo
11831           **colorlist;
11832
11833         size_t
11834           colors;
11835
11836         colorlist=GetColorInfoList("*",&colors,exception);
11837         EXTEND(sp,colors);
11838         for (i=0; i < (ssize_t) colors; i++)
11839         {
11840           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
11841         }
11842         colorlist=(const ColorInfo **)
11843           RelinquishMagickMemory((ColorInfo **) colorlist);
11844         goto PerlException;
11845       }
11846     EXTEND(sp,5*items);
11847     for (i=1; i < items; i++)
11848     {
11849       name=(char *) SvPV(ST(i),na);
11850       if (QueryMagickColorCompliance(name,AllCompliance,&color,exception) == MagickFalse)
11851         {
11852           PUSHs(&sv_undef);
11853           continue;
11854         }
11855       PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
11856       PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
11857       PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
11858       if (color.colorspace == CMYKColorspace)
11859         PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
11860       if (color.matte != MagickFalse)
11861         PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
11862     }
11863
11864   PerlException:
11865     InheritPerlException(exception,perl_exception);
11866     exception=DestroyExceptionInfo(exception);
11867     SvREFCNT_dec(perl_exception);
11868   }
11869 \f
11870 #
11871 ###############################################################################
11872 #                                                                             #
11873 #                                                                             #
11874 #                                                                             #
11875 #   Q u e r y C o l o r N a m e                                               #
11876 #                                                                             #
11877 #                                                                             #
11878 #                                                                             #
11879 ###############################################################################
11880 #
11881 #
11882 void
11883 QueryColorname(ref,...)
11884   Image::Magick ref=NO_INIT
11885   ALIAS:
11886     querycolorname = 1
11887   PPCODE:
11888   {
11889     AV
11890       *av;
11891
11892     char
11893       message[MaxTextExtent];
11894
11895     ExceptionInfo
11896       *exception;
11897
11898     Image
11899       *image;
11900
11901     PixelPacket
11902       target_color;
11903
11904     register ssize_t
11905       i;
11906
11907     struct PackageInfo
11908       *info;
11909
11910     SV
11911       *perl_exception,
11912       *reference;  /* reference is the SV* of ref=SvIV(reference) */
11913
11914     PERL_UNUSED_VAR(ref);
11915     PERL_UNUSED_VAR(ix);
11916     exception=AcquireExceptionInfo();
11917     perl_exception=newSVpv("",0);
11918     reference=SvRV(ST(0));
11919     av=(AV *) reference;
11920     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11921       exception);
11922     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11923     if (image == (Image *) NULL)
11924       {
11925         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11926           PackageName);
11927         goto PerlException;
11928       }
11929     EXTEND(sp,items);
11930     for (i=1; i < items; i++)
11931     {
11932       (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,&target_color,
11933         exception);
11934       (void) QueryColorname(image,&target_color,SVGCompliance,message,
11935         exception);
11936       PUSHs(sv_2mortal(newSVpv(message,0)));
11937     }
11938
11939   PerlException:
11940     InheritPerlException(exception,perl_exception);
11941     exception=DestroyExceptionInfo(exception);
11942     SvREFCNT_dec(perl_exception);
11943   }
11944 \f
11945 #
11946 ###############################################################################
11947 #                                                                             #
11948 #                                                                             #
11949 #                                                                             #
11950 #   Q u e r y F o n t                                                         #
11951 #                                                                             #
11952 #                                                                             #
11953 #                                                                             #
11954 ###############################################################################
11955 #
11956 #
11957 void
11958 QueryFont(ref,...)
11959   Image::Magick ref=NO_INIT
11960   ALIAS:
11961     queryfont = 1
11962   PPCODE:
11963   {
11964     char
11965       *name,
11966       message[MaxTextExtent];
11967
11968     ExceptionInfo
11969       *exception;
11970
11971     register ssize_t
11972       i;
11973
11974     SV
11975       *perl_exception;
11976
11977     volatile const TypeInfo
11978       *type_info;
11979
11980     PERL_UNUSED_VAR(ref);
11981     PERL_UNUSED_VAR(ix);
11982     exception=AcquireExceptionInfo();
11983     perl_exception=newSVpv("",0);
11984     if (items == 1)
11985       {
11986         const TypeInfo
11987           **typelist;
11988
11989         size_t
11990           types;
11991
11992         typelist=GetTypeInfoList("*",&types,exception);
11993         EXTEND(sp,types);
11994         for (i=0; i < (ssize_t) types; i++)
11995         {
11996           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
11997         }
11998         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
11999           typelist);
12000         goto PerlException;
12001       }
12002     EXTEND(sp,10*items);
12003     for (i=1; i < items; i++)
12004     {
12005       name=(char *) SvPV(ST(i),na);
12006       type_info=GetTypeInfo(name,exception);
12007       if (type_info == (TypeInfo *) NULL)
12008         {
12009           PUSHs(&sv_undef);
12010           continue;
12011         }
12012       if (type_info->name == (char *) NULL)
12013         PUSHs(&sv_undef);
12014       else
12015         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
12016       if (type_info->description == (char *) NULL)
12017         PUSHs(&sv_undef);
12018       else
12019         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
12020       if (type_info->family == (char *) NULL)
12021         PUSHs(&sv_undef);
12022       else
12023         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
12024       if (type_info->style == UndefinedStyle)
12025         PUSHs(&sv_undef);
12026       else
12027         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
12028           type_info->style),0)));
12029       if (type_info->stretch == UndefinedStretch)
12030         PUSHs(&sv_undef);
12031       else
12032         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
12033           type_info->stretch),0)));
12034       (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
12035         type_info->weight);
12036       PUSHs(sv_2mortal(newSVpv(message,0)));
12037       if (type_info->encoding == (char *) NULL)
12038         PUSHs(&sv_undef);
12039       else
12040         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
12041       if (type_info->foundry == (char *) NULL)
12042         PUSHs(&sv_undef);
12043       else
12044         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
12045       if (type_info->format == (char *) NULL)
12046         PUSHs(&sv_undef);
12047       else
12048         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
12049       if (type_info->metrics == (char *) NULL)
12050         PUSHs(&sv_undef);
12051       else
12052         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
12053       if (type_info->glyphs == (char *) NULL)
12054         PUSHs(&sv_undef);
12055       else
12056         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
12057     }
12058
12059   PerlException:
12060     InheritPerlException(exception,perl_exception);
12061     exception=DestroyExceptionInfo(exception);
12062     SvREFCNT_dec(perl_exception);
12063   }
12064 \f
12065 #
12066 ###############################################################################
12067 #                                                                             #
12068 #                                                                             #
12069 #                                                                             #
12070 #   Q u e r y F o n t M e t r i c s                                           #
12071 #                                                                             #
12072 #                                                                             #
12073 #                                                                             #
12074 ###############################################################################
12075 #
12076 #
12077 void
12078 QueryFontMetrics(ref,...)
12079   Image::Magick ref=NO_INIT
12080   ALIAS:
12081     queryfontmetrics = 1
12082   PPCODE:
12083   {
12084     AffineMatrix
12085       affine,
12086       current;
12087
12088     AV
12089       *av;
12090
12091     char
12092       *attribute;
12093
12094     double
12095       x,
12096       y;
12097
12098     DrawInfo
12099       *draw_info;
12100
12101     ExceptionInfo
12102       *exception;
12103
12104     GeometryInfo
12105       geometry_info;
12106
12107     Image
12108       *image;
12109
12110     MagickBooleanType
12111       status;
12112
12113     MagickStatusType
12114       flags;
12115
12116     register ssize_t
12117       i;
12118
12119     ssize_t
12120       type;
12121
12122     struct PackageInfo
12123       *info,
12124       *package_info;
12125
12126     SV
12127       *perl_exception,
12128       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12129
12130     TypeMetric
12131       metrics;
12132
12133     PERL_UNUSED_VAR(ref);
12134     PERL_UNUSED_VAR(ix);
12135     exception=AcquireExceptionInfo();
12136     package_info=(struct PackageInfo *) NULL;
12137     perl_exception=newSVpv("",0);
12138     reference=SvRV(ST(0));
12139     av=(AV *) reference;
12140     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12141       exception);
12142     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12143     if (image == (Image *) NULL)
12144       {
12145         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12146           PackageName);
12147         goto PerlException;
12148       }
12149     package_info=ClonePackageInfo(info,exception);
12150     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12151     CloneString(&draw_info->text,"");
12152     current=draw_info->affine;
12153     GetAffineMatrix(&affine);
12154     x=0.0;
12155     y=0.0;
12156     EXTEND(sp,7*items);
12157     for (i=2; i < items; i+=2)
12158     {
12159       attribute=(char *) SvPV(ST(i-1),na);
12160       switch (*attribute)
12161       {
12162         case 'A':
12163         case 'a':
12164         {
12165           if (LocaleCompare(attribute,"antialias") == 0)
12166             {
12167               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12168                 SvPV(ST(i),na));
12169               if (type < 0)
12170                 {
12171                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12172                     SvPV(ST(i),na));
12173                   break;
12174                 }
12175               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12176               break;
12177             }
12178           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12179             attribute);
12180           break;
12181         }
12182         case 'd':
12183         case 'D':
12184         {
12185           if (LocaleCompare(attribute,"density") == 0)
12186             {
12187               CloneString(&draw_info->density,SvPV(ST(i),na));
12188               break;
12189             }
12190           if (LocaleCompare(attribute,"direction") == 0)
12191             {
12192               draw_info->direction=(DirectionType) ParseCommandOption(
12193                 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12194               break;
12195             }
12196           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12197             attribute);
12198           break;
12199         }
12200         case 'e':
12201         case 'E':
12202         {
12203           if (LocaleCompare(attribute,"encoding") == 0)
12204             {
12205               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12206               break;
12207             }
12208           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12209             attribute);
12210           break;
12211         }
12212         case 'f':
12213         case 'F':
12214         {
12215           if (LocaleCompare(attribute,"family") == 0)
12216             {
12217               CloneString(&draw_info->family,SvPV(ST(i),na));
12218               break;
12219             }
12220           if (LocaleCompare(attribute,"fill") == 0)
12221             {
12222               if (info)
12223                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12224                   &draw_info->fill,&image->exception);
12225               break;
12226             }
12227           if (LocaleCompare(attribute,"font") == 0)
12228             {
12229               CloneString(&draw_info->font,SvPV(ST(i),na));
12230               break;
12231             }
12232           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12233             attribute);
12234           break;
12235         }
12236         case 'g':
12237         case 'G':
12238         {
12239           if (LocaleCompare(attribute,"geometry") == 0)
12240             {
12241               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12242               break;
12243             }
12244           if (LocaleCompare(attribute,"gravity") == 0)
12245             {
12246               draw_info->gravity=(GravityType) ParseCommandOption(
12247                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12248               break;
12249             }
12250           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12251             attribute);
12252           break;
12253         }
12254         case 'i':
12255         case 'I':
12256         {
12257           if (LocaleCompare(attribute,"interline-spacing") == 0)
12258             {
12259               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12260               draw_info->interline_spacing=geometry_info.rho;
12261               break;
12262             }
12263           if (LocaleCompare(attribute,"interword-spacing") == 0)
12264             {
12265               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12266               draw_info->interword_spacing=geometry_info.rho;
12267               break;
12268             }
12269           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12270             attribute);
12271           break;
12272         }
12273         case 'k':
12274         case 'K':
12275         {
12276           if (LocaleCompare(attribute,"kerning") == 0)
12277             {
12278               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12279               draw_info->kerning=geometry_info.rho;
12280               break;
12281             }
12282           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12283             attribute);
12284           break;
12285         }
12286         case 'p':
12287         case 'P':
12288         {
12289           if (LocaleCompare(attribute,"pointsize") == 0)
12290             {
12291               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12292               draw_info->pointsize=geometry_info.rho;
12293               break;
12294             }
12295           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12296             attribute);
12297           break;
12298         }
12299         case 'r':
12300         case 'R':
12301         {
12302           if (LocaleCompare(attribute,"rotate") == 0)
12303             {
12304               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12305               affine.rx=geometry_info.rho;
12306               affine.ry=geometry_info.sigma;
12307               if ((flags & SigmaValue) == 0)
12308                 affine.ry=affine.rx;
12309               break;
12310             }
12311           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12312             attribute);
12313           break;
12314         }
12315         case 's':
12316         case 'S':
12317         {
12318           if (LocaleCompare(attribute,"scale") == 0)
12319             {
12320               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12321               affine.sx=geometry_info.rho;
12322               affine.sy=geometry_info.sigma;
12323               if ((flags & SigmaValue) == 0)
12324                 affine.sy=affine.sx;
12325               break;
12326             }
12327           if (LocaleCompare(attribute,"skew") == 0)
12328             {
12329               double
12330                 x_angle,
12331                 y_angle;
12332
12333               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12334               x_angle=geometry_info.rho;
12335               y_angle=geometry_info.sigma;
12336               if ((flags & SigmaValue) == 0)
12337                 y_angle=x_angle;
12338               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12339               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12340               break;
12341             }
12342           if (LocaleCompare(attribute,"stroke") == 0)
12343             {
12344               if (info)
12345                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12346                   &draw_info->stroke,&image->exception);
12347               break;
12348             }
12349           if (LocaleCompare(attribute,"style") == 0)
12350             {
12351               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12352                 SvPV(ST(i),na));
12353               if (type < 0)
12354                 {
12355                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12356                     SvPV(ST(i),na));
12357                   break;
12358                 }
12359               draw_info->style=(StyleType) type;
12360               break;
12361             }
12362           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12363             attribute);
12364           break;
12365         }
12366         case 't':
12367         case 'T':
12368         {
12369           if (LocaleCompare(attribute,"text") == 0)
12370             {
12371               CloneString(&draw_info->text,SvPV(ST(i),na));
12372               break;
12373             }
12374           if (LocaleCompare(attribute,"translate") == 0)
12375             {
12376               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12377               affine.tx=geometry_info.rho;
12378               affine.ty=geometry_info.sigma;
12379               if ((flags & SigmaValue) == 0)
12380                 affine.ty=affine.tx;
12381               break;
12382             }
12383           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12384             attribute);
12385           break;
12386         }
12387         case 'w':
12388         case 'W':
12389         {
12390           if (LocaleCompare(attribute,"weight") == 0)
12391             {
12392               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12393               draw_info->weight=(size_t) geometry_info.rho;
12394               break;
12395             }
12396           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12397             attribute);
12398           break;
12399         }
12400         case 'x':
12401         case 'X':
12402         {
12403           if (LocaleCompare(attribute,"x") == 0)
12404             {
12405               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12406               x=geometry_info.rho;
12407               break;
12408             }
12409           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12410             attribute);
12411           break;
12412         }
12413         case 'y':
12414         case 'Y':
12415         {
12416           if (LocaleCompare(attribute,"y") == 0)
12417             {
12418               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12419               y=geometry_info.rho;
12420               break;
12421             }
12422           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12423             attribute);
12424           break;
12425         }
12426         default:
12427         {
12428           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12429             attribute);
12430           break;
12431         }
12432       }
12433     }
12434     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12435     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12436     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12437     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12438     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12439     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12440     if (draw_info->geometry == (char *) NULL)
12441       {
12442         draw_info->geometry=AcquireString((char *) NULL);
12443         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12444           "%.15g,%.15g",x,y);
12445       }
12446     status=GetTypeMetrics(image,draw_info,&metrics,exception);
12447     (void) CatchImageException(image);
12448     if (status == MagickFalse)
12449       PUSHs(&sv_undef);
12450     else
12451       {
12452         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12453         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12454         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12455         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12456         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12457         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12458         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12459         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12460         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12461         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12462         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12463         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12464         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12465       }
12466     draw_info=DestroyDrawInfo(draw_info);
12467
12468   PerlException:
12469     if (package_info != (struct PackageInfo *) NULL)
12470       DestroyPackageInfo(package_info);
12471     InheritPerlException(exception,perl_exception);
12472     exception=DestroyExceptionInfo(exception);
12473     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12474   }
12475 \f
12476 #
12477 ###############################################################################
12478 #                                                                             #
12479 #                                                                             #
12480 #                                                                             #
12481 #   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                         #
12482 #                                                                             #
12483 #                                                                             #
12484 #                                                                             #
12485 ###############################################################################
12486 #
12487 #
12488 void
12489 QueryMultilineFontMetrics(ref,...)
12490   Image::Magick ref=NO_INIT
12491   ALIAS:
12492     querymultilinefontmetrics = 1
12493   PPCODE:
12494   {
12495     AffineMatrix
12496       affine,
12497       current;
12498
12499     AV
12500       *av;
12501
12502     char
12503       *attribute;
12504
12505     double
12506       x,
12507       y;
12508
12509     DrawInfo
12510       *draw_info;
12511
12512     ExceptionInfo
12513       *exception;
12514
12515     GeometryInfo
12516       geometry_info;
12517
12518     Image
12519       *image;
12520
12521     MagickBooleanType
12522       status;
12523
12524     MagickStatusType
12525       flags;
12526
12527     register ssize_t
12528       i;
12529
12530     ssize_t
12531       type;
12532
12533     struct PackageInfo
12534       *info,
12535       *package_info;
12536
12537     SV
12538       *perl_exception,
12539       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12540
12541     TypeMetric
12542       metrics;
12543
12544     PERL_UNUSED_VAR(ref);
12545     PERL_UNUSED_VAR(ix);
12546     exception=AcquireExceptionInfo();
12547     package_info=(struct PackageInfo *) NULL;
12548     perl_exception=newSVpv("",0);
12549     reference=SvRV(ST(0));
12550     av=(AV *) reference;
12551     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12552       exception);
12553     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12554     if (image == (Image *) NULL)
12555       {
12556         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12557           PackageName);
12558         goto PerlException;
12559       }
12560     package_info=ClonePackageInfo(info,exception);
12561     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12562     CloneString(&draw_info->text,"");
12563     current=draw_info->affine;
12564     GetAffineMatrix(&affine);
12565     x=0.0;
12566     y=0.0;
12567     EXTEND(sp,7*items);
12568     for (i=2; i < items; i+=2)
12569     {
12570       attribute=(char *) SvPV(ST(i-1),na);
12571       switch (*attribute)
12572       {
12573         case 'A':
12574         case 'a':
12575         {
12576           if (LocaleCompare(attribute,"antialias") == 0)
12577             {
12578               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12579                 SvPV(ST(i),na));
12580               if (type < 0)
12581                 {
12582                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12583                     SvPV(ST(i),na));
12584                   break;
12585                 }
12586               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12587               break;
12588             }
12589           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12590             attribute);
12591           break;
12592         }
12593         case 'd':
12594         case 'D':
12595         {
12596           if (LocaleCompare(attribute,"density") == 0)
12597             {
12598               CloneString(&draw_info->density,SvPV(ST(i),na));
12599               break;
12600             }
12601           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12602             attribute);
12603           break;
12604         }
12605         case 'e':
12606         case 'E':
12607         {
12608           if (LocaleCompare(attribute,"encoding") == 0)
12609             {
12610               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12611               break;
12612             }
12613           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12614             attribute);
12615           break;
12616         }
12617         case 'f':
12618         case 'F':
12619         {
12620           if (LocaleCompare(attribute,"family") == 0)
12621             {
12622               CloneString(&draw_info->family,SvPV(ST(i),na));
12623               break;
12624             }
12625           if (LocaleCompare(attribute,"fill") == 0)
12626             {
12627               if (info)
12628                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12629                   &draw_info->fill,&image->exception);
12630               break;
12631             }
12632           if (LocaleCompare(attribute,"font") == 0)
12633             {
12634               CloneString(&draw_info->font,SvPV(ST(i),na));
12635               break;
12636             }
12637           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12638             attribute);
12639           break;
12640         }
12641         case 'g':
12642         case 'G':
12643         {
12644           if (LocaleCompare(attribute,"geometry") == 0)
12645             {
12646               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12647               break;
12648             }
12649           if (LocaleCompare(attribute,"gravity") == 0)
12650             {
12651               draw_info->gravity=(GravityType) ParseCommandOption(
12652                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12653               break;
12654             }
12655           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12656             attribute);
12657           break;
12658         }
12659         case 'p':
12660         case 'P':
12661         {
12662           if (LocaleCompare(attribute,"pointsize") == 0)
12663             {
12664               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12665               draw_info->pointsize=geometry_info.rho;
12666               break;
12667             }
12668           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12669             attribute);
12670           break;
12671         }
12672         case 'r':
12673         case 'R':
12674         {
12675           if (LocaleCompare(attribute,"rotate") == 0)
12676             {
12677               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12678               affine.rx=geometry_info.rho;
12679               affine.ry=geometry_info.sigma;
12680               if ((flags & SigmaValue) == 0)
12681                 affine.ry=affine.rx;
12682               break;
12683             }
12684           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12685             attribute);
12686           break;
12687         }
12688         case 's':
12689         case 'S':
12690         {
12691           if (LocaleCompare(attribute,"scale") == 0)
12692             {
12693               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12694               affine.sx=geometry_info.rho;
12695               affine.sy=geometry_info.sigma;
12696               if ((flags & SigmaValue) == 0)
12697                 affine.sy=affine.sx;
12698               break;
12699             }
12700           if (LocaleCompare(attribute,"skew") == 0)
12701             {
12702               double
12703                 x_angle,
12704                 y_angle;
12705
12706               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12707               x_angle=geometry_info.rho;
12708               y_angle=geometry_info.sigma;
12709               if ((flags & SigmaValue) == 0)
12710                 y_angle=x_angle;
12711               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12712               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12713               break;
12714             }
12715           if (LocaleCompare(attribute,"stroke") == 0)
12716             {
12717               if (info)
12718                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12719                   &draw_info->stroke,&image->exception);
12720               break;
12721             }
12722           if (LocaleCompare(attribute,"style") == 0)
12723             {
12724               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12725                 SvPV(ST(i),na));
12726               if (type < 0)
12727                 {
12728                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12729                     SvPV(ST(i),na));
12730                   break;
12731                 }
12732               draw_info->style=(StyleType) type;
12733               break;
12734             }
12735           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12736             attribute);
12737           break;
12738         }
12739         case 't':
12740         case 'T':
12741         {
12742           if (LocaleCompare(attribute,"text") == 0)
12743             {
12744               CloneString(&draw_info->text,SvPV(ST(i),na));
12745               break;
12746             }
12747           if (LocaleCompare(attribute,"translate") == 0)
12748             {
12749               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12750               affine.tx=geometry_info.rho;
12751               affine.ty=geometry_info.sigma;
12752               if ((flags & SigmaValue) == 0)
12753                 affine.ty=affine.tx;
12754               break;
12755             }
12756           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12757             attribute);
12758           break;
12759         }
12760         case 'w':
12761         case 'W':
12762         {
12763           if (LocaleCompare(attribute,"weight") == 0)
12764             {
12765               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12766               draw_info->weight=(size_t) geometry_info.rho;
12767               break;
12768             }
12769           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12770             attribute);
12771           break;
12772         }
12773         case 'x':
12774         case 'X':
12775         {
12776           if (LocaleCompare(attribute,"x") == 0)
12777             {
12778               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12779               x=geometry_info.rho;
12780               break;
12781             }
12782           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12783             attribute);
12784           break;
12785         }
12786         case 'y':
12787         case 'Y':
12788         {
12789           if (LocaleCompare(attribute,"y") == 0)
12790             {
12791               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12792               y=geometry_info.rho;
12793               break;
12794             }
12795           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12796             attribute);
12797           break;
12798         }
12799         default:
12800         {
12801           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12802             attribute);
12803           break;
12804         }
12805       }
12806     }
12807     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12808     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12809     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12810     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12811     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12812     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12813     if (draw_info->geometry == (char *) NULL)
12814       {
12815         draw_info->geometry=AcquireString((char *) NULL);
12816         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12817           "%.15g,%.15g",x,y);
12818       }
12819     status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
12820     (void) CatchException(exception);
12821     if (status == MagickFalse)
12822       PUSHs(&sv_undef);
12823     else
12824       {
12825         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12826         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12827         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12828         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12829         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12830         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12831         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12832         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12833         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12834         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12835         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12836         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12837         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12838       }
12839     draw_info=DestroyDrawInfo(draw_info);
12840
12841   PerlException:
12842     if (package_info != (struct PackageInfo *) NULL)
12843       DestroyPackageInfo(package_info);
12844     InheritPerlException(exception,perl_exception);
12845     exception=DestroyExceptionInfo(exception);
12846     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12847   }
12848 \f
12849 #
12850 ###############################################################################
12851 #                                                                             #
12852 #                                                                             #
12853 #                                                                             #
12854 #   Q u e r y F o r m a t                                                     #
12855 #                                                                             #
12856 #                                                                             #
12857 #                                                                             #
12858 ###############################################################################
12859 #
12860 #
12861 void
12862 QueryFormat(ref,...)
12863   Image::Magick ref=NO_INIT
12864   ALIAS:
12865     queryformat = 1
12866   PPCODE:
12867   {
12868     char
12869       *name;
12870
12871     ExceptionInfo
12872       *exception;
12873
12874     register ssize_t
12875       i;
12876
12877     SV
12878       *perl_exception;
12879
12880     volatile const MagickInfo
12881       *magick_info;
12882
12883     PERL_UNUSED_VAR(ref);
12884     PERL_UNUSED_VAR(ix);
12885     exception=AcquireExceptionInfo();
12886     perl_exception=newSVpv("",0);
12887     if (items == 1)
12888       {
12889         char
12890           format[MaxTextExtent];
12891
12892         const MagickInfo
12893           **format_list;
12894
12895         size_t
12896           types;
12897
12898         format_list=GetMagickInfoList("*",&types,exception);
12899         EXTEND(sp,types);
12900         for (i=0; i < (ssize_t) types; i++)
12901         {
12902           (void) CopyMagickString(format,format_list[i]->name,MaxTextExtent);
12903           LocaleLower(format);
12904           PUSHs(sv_2mortal(newSVpv(format,0)));
12905         }
12906         format_list=(const MagickInfo **)
12907           RelinquishMagickMemory((MagickInfo *) format_list);
12908         goto PerlException;
12909       }
12910     EXTEND(sp,8*items);
12911     for (i=1; i < items; i++)
12912     {
12913       name=(char *) SvPV(ST(i),na);
12914       magick_info=GetMagickInfo(name,exception);
12915       if (magick_info == (const MagickInfo *) NULL)
12916         {
12917           PUSHs(&sv_undef);
12918           continue;
12919         }
12920       PUSHs(sv_2mortal(newSViv(magick_info->adjoin)));
12921       PUSHs(sv_2mortal(newSViv(magick_info->blob_support)));
12922       PUSHs(sv_2mortal(newSViv(magick_info->raw)));
12923       PUSHs(sv_2mortal(newSViv((long) magick_info->decoder)));
12924       PUSHs(sv_2mortal(newSViv((long) magick_info->encoder)));
12925       if (magick_info->description == (char *) NULL)
12926         PUSHs(&sv_undef);
12927       else
12928         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
12929       if (magick_info->module == (char *) NULL)
12930         PUSHs(&sv_undef);
12931       else
12932         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
12933     }
12934
12935   PerlException:
12936     InheritPerlException(exception,perl_exception);
12937     exception=DestroyExceptionInfo(exception);
12938     SvREFCNT_dec(perl_exception);
12939   }
12940 \f
12941 #
12942 ###############################################################################
12943 #                                                                             #
12944 #                                                                             #
12945 #                                                                             #
12946 #   Q u e r y O p t i o n                                                     #
12947 #                                                                             #
12948 #                                                                             #
12949 #                                                                             #
12950 ###############################################################################
12951 #
12952 #
12953 void
12954 QueryOption(ref,...)
12955   Image::Magick ref=NO_INIT
12956   ALIAS:
12957     queryoption = 1
12958   PPCODE:
12959   {
12960     char
12961       **options;
12962
12963     ExceptionInfo
12964       *exception;
12965
12966     register ssize_t
12967       i;
12968
12969     ssize_t
12970       j,
12971       option;
12972
12973     SV
12974       *perl_exception;
12975
12976     PERL_UNUSED_VAR(ref);
12977     PERL_UNUSED_VAR(ix);
12978     exception=AcquireExceptionInfo();
12979     perl_exception=newSVpv("",0);
12980     EXTEND(sp,8*items);
12981     for (i=1; i < items; i++)
12982     {
12983       option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
12984         SvPV(ST(i),na));
12985       options=GetCommandOptions((CommandOption) option);
12986       if (options == (char **) NULL)
12987         PUSHs(&sv_undef);
12988       else
12989         {
12990           for (j=0; options[j] != (char *) NULL; j++)
12991             PUSHs(sv_2mortal(newSVpv(options[j],0)));
12992           options=DestroyStringList(options);
12993         }
12994     }
12995
12996     InheritPerlException(exception,perl_exception);
12997     exception=DestroyExceptionInfo(exception);
12998     SvREFCNT_dec(perl_exception);
12999   }
13000 \f
13001 #
13002 ###############################################################################
13003 #                                                                             #
13004 #                                                                             #
13005 #                                                                             #
13006 #   R e a d                                                                   #
13007 #                                                                             #
13008 #                                                                             #
13009 #                                                                             #
13010 ###############################################################################
13011 #
13012 #
13013 void
13014 Read(ref,...)
13015   Image::Magick ref=NO_INIT
13016   ALIAS:
13017     ReadImage  = 1
13018     read       = 2
13019     readimage  = 3
13020   PPCODE:
13021   {
13022     AV
13023       *av;
13024
13025     char
13026       **keep,
13027       **list;
13028
13029     ExceptionInfo
13030       *exception;
13031
13032     HV
13033       *hv;
13034
13035     Image
13036       *image;
13037
13038     int
13039       n;
13040
13041     MagickBooleanType
13042       status;
13043
13044     register char
13045       **p;
13046
13047     register ssize_t
13048       i;
13049
13050     ssize_t
13051       ac,
13052       number_images;
13053
13054     STRLEN
13055       *length;
13056
13057     struct PackageInfo
13058       *info,
13059       *package_info;
13060
13061     SV
13062       *perl_exception,  /* Perl variable for storing messages */
13063       *reference,
13064       *rv,
13065       *sv;
13066
13067     PERL_UNUSED_VAR(ref);
13068     PERL_UNUSED_VAR(ix);
13069     exception=AcquireExceptionInfo();
13070     perl_exception=newSVpv("",0);
13071     sv=NULL;
13072     package_info=(struct PackageInfo *) NULL;
13073     number_images=0;
13074     ac=(items < 2) ? 1 : items-1;
13075     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
13076     keep=list;
13077     length=(STRLEN *) NULL;
13078     if (list == (char **) NULL)
13079       {
13080         ThrowPerlException(exception,ResourceLimitError,
13081           "MemoryAllocationFailed",PackageName);
13082         goto PerlException;
13083       }
13084     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
13085     if (length == (STRLEN *) NULL)
13086       {
13087         ThrowPerlException(exception,ResourceLimitError,
13088           "MemoryAllocationFailed",PackageName);
13089         goto PerlException;
13090       }
13091     if (sv_isobject(ST(0)) == 0)
13092       {
13093         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13094           PackageName);
13095         goto PerlException;
13096       }
13097     reference=SvRV(ST(0));
13098     hv=SvSTASH(reference);
13099     if (SvTYPE(reference) != SVt_PVAV)
13100       {
13101         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13102           PackageName);
13103         goto PerlException;
13104       }
13105     av=(AV *) reference;
13106     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13107       exception);
13108     package_info=ClonePackageInfo(info,exception);
13109     n=1;
13110     if (items <= 1)
13111       *list=(char *) (*package_info->image_info->filename ?
13112         package_info->image_info->filename : "XC:black");
13113     else
13114       for (n=0, i=0; i < ac; i++)
13115       {
13116         list[n]=(char *) SvPV(ST(i+1),length[n]);
13117         if ((items >= 3) && strEQcase(list[n],"blob"))
13118           {
13119             void
13120               *blob;
13121
13122             i++;
13123             blob=(void *) (SvPV(ST(i+1),length[n]));
13124             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13125           }
13126         if ((items >= 3) && strEQcase(list[n],"filename"))
13127           continue;
13128         if ((items >= 3) && strEQcase(list[n],"file"))
13129           {
13130             FILE
13131               *file;
13132
13133             PerlIO
13134               *io_info;
13135
13136             i++;
13137             io_info=IoIFP(sv_2io(ST(i+1)));
13138             if (io_info == (PerlIO *) NULL)
13139               {
13140                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13141                   PackageName);
13142                 continue;
13143               }
13144             file=PerlIO_findFILE(io_info);
13145             if (file == (FILE *) NULL)
13146               {
13147                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13148                   PackageName);
13149                 continue;
13150               }
13151             SetImageInfoFile(package_info->image_info,file);
13152           }
13153         if ((items >= 3) && strEQcase(list[n],"magick"))
13154           continue;
13155         n++;
13156       }
13157     list[n]=(char *) NULL;
13158     keep=list;
13159     status=ExpandFilenames(&n,&list);
13160     if (status == MagickFalse)
13161       {
13162         ThrowPerlException(exception,ResourceLimitError,
13163           "MemoryAllocationFailed",PackageName);
13164         goto PerlException;
13165       }
13166     number_images=0;
13167     for (i=0; i < n; i++)
13168     {
13169       if ((package_info->image_info->file != (FILE *) NULL) ||
13170           (package_info->image_info->blob != (void *) NULL))
13171         {
13172           image=ReadImages(package_info->image_info,exception);
13173           if (image != (Image *) NULL)
13174             DisassociateImageStream(image);
13175         }
13176       else
13177         {
13178           (void) CopyMagickString(package_info->image_info->filename,list[i],
13179             MaxTextExtent);
13180           image=ReadImages(package_info->image_info,exception);
13181         }
13182       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
13183         break;
13184       for ( ; image; image=image->next)
13185       {
13186         AddImageToRegistry(sv,image);
13187         rv=newRV(sv);
13188         av_push(av,sv_bless(rv,hv));
13189         SvREFCNT_dec(sv);
13190         number_images++;
13191       }
13192     }
13193     /*
13194       Free resources.
13195     */
13196     for (i=0; i < n; i++)
13197       if (list[i] != (char *) NULL)
13198         for (p=keep; list[i] != *p++; )
13199           if (*p == (char *) NULL)
13200             {
13201               list[i]=(char *) RelinquishMagickMemory(list[i]);
13202               break;
13203             }
13204
13205   PerlException:
13206     if (package_info != (struct PackageInfo *) NULL)
13207       DestroyPackageInfo(package_info);
13208     if (list && (list != keep))
13209       list=(char **) RelinquishMagickMemory(list);
13210     if (keep)
13211       keep=(char **) RelinquishMagickMemory(keep);
13212     if (length)
13213       length=(STRLEN *) RelinquishMagickMemory(length);
13214     InheritPerlException(exception,perl_exception);
13215     exception=DestroyExceptionInfo(exception);
13216     sv_setiv(perl_exception,(IV) number_images);
13217     SvPOK_on(perl_exception);
13218     ST(0)=sv_2mortal(perl_exception);
13219     XSRETURN(1);
13220   }
13221 \f
13222 #
13223 ###############################################################################
13224 #                                                                             #
13225 #                                                                             #
13226 #                                                                             #
13227 #   R e m o t e                                                               #
13228 #                                                                             #
13229 #                                                                             #
13230 #                                                                             #
13231 ###############################################################################
13232 #
13233 #
13234 void
13235 Remote(ref,...)
13236   Image::Magick ref=NO_INIT
13237   ALIAS:
13238     RemoteCommand  = 1
13239     remote         = 2
13240     remoteCommand  = 3
13241   PPCODE:
13242   {
13243     AV
13244       *av;
13245
13246     ExceptionInfo
13247       *exception;
13248
13249     register ssize_t
13250       i;
13251
13252     SV
13253       *perl_exception,
13254       *reference;
13255
13256     struct PackageInfo
13257       *info;
13258
13259     PERL_UNUSED_VAR(ref);
13260     PERL_UNUSED_VAR(ix);
13261     exception=AcquireExceptionInfo();
13262     perl_exception=newSVpv("",0);
13263     reference=SvRV(ST(0));
13264     av=(AV *) reference;
13265     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13266       exception);
13267     for (i=1; i < items; i++)
13268       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13269         SvPV(ST(i),na),exception);
13270     InheritPerlException(exception,perl_exception);
13271     exception=DestroyExceptionInfo(exception);
13272     SvREFCNT_dec(perl_exception);    /* throw away all errors */
13273   }
13274 \f
13275 #
13276 ###############################################################################
13277 #                                                                             #
13278 #                                                                             #
13279 #                                                                             #
13280 #   S e t                                                                     #
13281 #                                                                             #
13282 #                                                                             #
13283 #                                                                             #
13284 ###############################################################################
13285 #
13286 #
13287 void
13288 Set(ref,...)
13289   Image::Magick ref=NO_INIT
13290   ALIAS:
13291     SetAttributes  = 1
13292     SetAttribute   = 2
13293     set            = 3
13294     setattributes  = 4
13295     setattribute   = 5
13296   PPCODE:
13297   {
13298     ExceptionInfo
13299       *exception;
13300
13301     Image
13302       *image;
13303
13304     register ssize_t
13305       i;
13306
13307     struct PackageInfo
13308       *info;
13309
13310     SV
13311       *perl_exception,
13312       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13313
13314     PERL_UNUSED_VAR(ref);
13315     PERL_UNUSED_VAR(ix);
13316     exception=AcquireExceptionInfo();
13317     perl_exception=newSVpv("",0);
13318     if (sv_isobject(ST(0)) == 0)
13319       {
13320         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13321           PackageName);
13322         goto PerlException;
13323       }
13324     reference=SvRV(ST(0));
13325     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13326     if (items == 2)
13327       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13328     else
13329       for (i=2; i < items; i+=2)
13330         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13331
13332   PerlException:
13333     InheritPerlException(exception,perl_exception);
13334     exception=DestroyExceptionInfo(exception);
13335     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13336     SvPOK_on(perl_exception);
13337     ST(0)=sv_2mortal(perl_exception);
13338     XSRETURN(1);
13339   }
13340 \f
13341 #
13342 ###############################################################################
13343 #                                                                             #
13344 #                                                                             #
13345 #                                                                             #
13346 #   S e t P i x e l                                                           #
13347 #                                                                             #
13348 #                                                                             #
13349 #                                                                             #
13350 ###############################################################################
13351 #
13352 #
13353 void
13354 SetPixel(ref,...)
13355   Image::Magick ref=NO_INIT
13356   ALIAS:
13357     setpixel = 1
13358     setPixel = 2
13359   PPCODE:
13360   {
13361     AV
13362       *av;
13363
13364     char
13365       *attribute;
13366
13367     ChannelType
13368       channel,
13369       channel_mask;
13370
13371     ExceptionInfo
13372       *exception;
13373
13374     Image
13375       *image;
13376
13377     MagickBooleanType
13378       normalize;
13379
13380     RectangleInfo
13381       region;
13382
13383     register ssize_t
13384       i;
13385
13386     register Quantum
13387       *q;
13388
13389     ssize_t
13390       option;
13391
13392     struct PackageInfo
13393       *info;
13394
13395     SV
13396       *perl_exception,
13397       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13398
13399     PERL_UNUSED_VAR(ref);
13400     PERL_UNUSED_VAR(ix);
13401     exception=AcquireExceptionInfo();
13402     perl_exception=newSVpv("",0);
13403     reference=SvRV(ST(0));
13404     av=(AV *) reference;
13405     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13406       exception);
13407     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13408     if (image == (Image *) NULL)
13409       {
13410         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13411           PackageName);
13412         goto PerlException;
13413       }
13414     av=(AV *) NULL;
13415     normalize=MagickTrue;
13416     region.x=0;
13417     region.y=0;
13418     region.width=image->columns;
13419     region.height=1;
13420     if (items == 1)
13421       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13422     channel=DefaultChannels;
13423     for (i=2; i < items; i+=2)
13424     {
13425       attribute=(char *) SvPV(ST(i-1),na);
13426       switch (*attribute)
13427       {
13428         case 'C':
13429         case 'c':
13430         {
13431           if (LocaleCompare(attribute,"channel") == 0)
13432             {
13433               ssize_t
13434                 option;
13435
13436               option=ParseChannelOption(SvPV(ST(i),na));
13437               if (option < 0)
13438                 {
13439                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13440                     SvPV(ST(i),na));
13441                   return;
13442                 }
13443               channel=(ChannelType) option;
13444               break;
13445             }
13446           if (LocaleCompare(attribute,"color") == 0)
13447             {
13448               if (SvTYPE(ST(i)) != SVt_RV)
13449                 {
13450                   char
13451                     message[MaxTextExtent];
13452
13453                   (void) FormatLocaleString(message,MaxTextExtent,
13454                     "invalid %.60s value",attribute);
13455                   ThrowPerlException(exception,OptionError,message,
13456                     SvPV(ST(i),na));
13457                 }
13458               av=(AV *) SvRV(ST(i));
13459               break;
13460             }
13461           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13462             attribute);
13463           break;
13464         }
13465         case 'g':
13466         case 'G':
13467         {
13468           if (LocaleCompare(attribute,"geometry") == 0)
13469             {
13470               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
13471               break;
13472             }
13473           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13474             attribute);
13475           break;
13476         }
13477         case 'N':
13478         case 'n':
13479         {
13480           if (LocaleCompare(attribute,"normalize") == 0)
13481             {
13482               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13483                 SvPV(ST(i),na));
13484               if (option < 0)
13485                 {
13486                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13487                     SvPV(ST(i),na));
13488                   break;
13489                 }
13490              normalize=option != 0 ? MagickTrue : MagickFalse;
13491              break;
13492             }
13493           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13494             attribute);
13495           break;
13496         }
13497         case 'x':
13498         case 'X':
13499         {
13500           if (LocaleCompare(attribute,"x") == 0)
13501             {
13502               region.x=SvIV(ST(i));
13503               break;
13504             }
13505           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13506             attribute);
13507           break;
13508         }
13509         case 'y':
13510         case 'Y':
13511         {
13512           if (LocaleCompare(attribute,"y") == 0)
13513             {
13514               region.y=SvIV(ST(i));
13515               break;
13516             }
13517           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13518             attribute);
13519           break;
13520         }
13521         default:
13522         {
13523           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13524             attribute);
13525           break;
13526         }
13527       }
13528     }
13529     (void) SetImageStorageClass(image,DirectClass,exception);
13530     channel_mask=SetPixelChannelMask(image,channel);
13531     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
13532     if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
13533         (SvTYPE(av) != SVt_PVAV))
13534       PUSHs(&sv_undef);
13535     else
13536       {
13537         double
13538           scale;
13539
13540         register ssize_t
13541           i;
13542
13543         i=0;
13544         scale=1.0;
13545         if (normalize != MagickFalse)
13546           scale=QuantumRange;
13547         if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
13548             (i <= av_len(av)))
13549           {
13550             SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
13551               av_fetch(av,i,0)))),q);
13552             i++;
13553           }
13554         if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
13555             (i <= av_len(av)))
13556           {
13557             SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
13558               av_fetch(av,i,0)))),q);
13559             i++;
13560           }
13561         if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
13562             (i <= av_len(av)))
13563           {
13564             SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
13565               av_fetch(av,i,0)))),q);
13566             i++;
13567           }
13568         if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
13569             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
13570           {
13571             SetPixelBlack(image,ClampToQuantum(scale*
13572               SvNV(*(av_fetch(av,i,0)))),q);
13573             i++;
13574           }
13575         if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
13576             (i <= av_len(av)))
13577           {
13578             SetPixelAlpha(image,ClampToQuantum(scale*
13579               SvNV(*(av_fetch(av,i,0)))),q);
13580             i++;
13581           }
13582         (void) SyncAuthenticPixels(image,exception);
13583       }
13584     (void) SetPixelChannelMask(image,channel_mask);
13585
13586   PerlException:
13587     InheritPerlException(exception,perl_exception);
13588     exception=DestroyExceptionInfo(exception);
13589     SvREFCNT_dec(perl_exception);
13590   }
13591 \f
13592 #
13593 ###############################################################################
13594 #                                                                             #
13595 #                                                                             #
13596 #                                                                             #
13597 #   S m u s h                                                                 #
13598 #                                                                             #
13599 #                                                                             #
13600 #                                                                             #
13601 ###############################################################################
13602 #
13603 #
13604 void
13605 Smush(ref,...)
13606   Image::Magick ref=NO_INIT
13607   ALIAS:
13608     SmushImage  = 1
13609     smush       = 2
13610     smushimage  = 3
13611   PPCODE:
13612   {
13613     AV
13614       *av;
13615
13616     char
13617       *attribute;
13618
13619     ExceptionInfo
13620       *exception;
13621
13622     HV
13623       *hv;
13624
13625     Image
13626       *image;
13627
13628     register ssize_t
13629       i;
13630
13631     ssize_t
13632       offset,
13633       stack;
13634
13635     struct PackageInfo
13636       *info;
13637
13638     SV
13639       *av_reference,
13640       *perl_exception,
13641       *reference,
13642       *rv,
13643       *sv;
13644
13645     PERL_UNUSED_VAR(ref);
13646     PERL_UNUSED_VAR(ix);
13647     exception=AcquireExceptionInfo();
13648     perl_exception=newSVpv("",0);
13649     sv=NULL;
13650     attribute=NULL;
13651     av=NULL;
13652     if (sv_isobject(ST(0)) == 0)
13653       {
13654         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13655           PackageName);
13656         goto PerlException;
13657       }
13658     reference=SvRV(ST(0));
13659     hv=SvSTASH(reference);
13660     av=newAV();
13661     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13662     SvREFCNT_dec(av);
13663     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13664     if (image == (Image *) NULL)
13665       {
13666         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13667           PackageName);
13668         goto PerlException;
13669       }
13670     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13671     /*
13672       Get options.
13673     */
13674     offset=0;
13675     stack=MagickTrue;
13676     for (i=2; i < items; i+=2)
13677     {
13678       attribute=(char *) SvPV(ST(i-1),na);
13679       switch (*attribute)
13680       {
13681         case 'O':
13682         case 'o':
13683         {
13684           if (LocaleCompare(attribute,"offset") == 0)
13685             {
13686               offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
13687               break;
13688             }
13689           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13690             attribute);
13691           break;
13692         }
13693         case 'S':
13694         case 's':
13695         {
13696           if (LocaleCompare(attribute,"stack") == 0)
13697             {
13698               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13699                 SvPV(ST(i),na));
13700               if (stack < 0)
13701                 {
13702                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13703                     SvPV(ST(i),na));
13704                   return;
13705                 }
13706               break;
13707             }
13708           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13709             attribute);
13710           break;
13711         }
13712         default:
13713         {
13714           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13715             attribute);
13716           break;
13717         }
13718       }
13719     }
13720     image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
13721       exception);
13722     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
13723       goto PerlException;
13724     for ( ; image; image=image->next)
13725     {
13726       AddImageToRegistry(sv,image);
13727       rv=newRV(sv);
13728       av_push(av,sv_bless(rv,hv));
13729       SvREFCNT_dec(sv);
13730     }
13731     exception=DestroyExceptionInfo(exception);
13732     ST(0)=av_reference;
13733     SvREFCNT_dec(perl_exception);
13734     XSRETURN(1);
13735
13736   PerlException:
13737     InheritPerlException(exception,perl_exception);
13738     exception=DestroyExceptionInfo(exception);
13739     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
13740     SvPOK_on(perl_exception);
13741     ST(0)=sv_2mortal(perl_exception);
13742     XSRETURN(1);
13743   }
13744 \f
13745 #
13746 ###############################################################################
13747 #                                                                             #
13748 #                                                                             #
13749 #                                                                             #
13750 #   S t a t i s t i c s                                                       #
13751 #                                                                             #
13752 #                                                                             #
13753 #                                                                             #
13754 ###############################################################################
13755 #
13756 #
13757 void
13758 Statistics(ref,...)
13759   Image::Magick ref=NO_INIT
13760   ALIAS:
13761     StatisticsImage = 1
13762     statistics      = 2
13763     statisticsimage = 3
13764   PPCODE:
13765   {
13766 #define ChannelStatistics(channel) \
13767 { \
13768   (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
13769     (double) channel_statistics[channel].depth); \
13770   PUSHs(sv_2mortal(newSVpv(message,0))); \
13771   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13772     channel_statistics[channel].minima/scale); \
13773   PUSHs(sv_2mortal(newSVpv(message,0))); \
13774   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13775     channel_statistics[channel].maxima/scale); \
13776   PUSHs(sv_2mortal(newSVpv(message,0))); \
13777   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13778     channel_statistics[channel].mean/scale); \
13779   PUSHs(sv_2mortal(newSVpv(message,0))); \
13780   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13781     channel_statistics[channel].standard_deviation/scale); \
13782   PUSHs(sv_2mortal(newSVpv(message,0))); \
13783   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13784     channel_statistics[channel].kurtosis); \
13785   PUSHs(sv_2mortal(newSVpv(message,0))); \
13786   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13787     channel_statistics[channel].skewness); \
13788   PUSHs(sv_2mortal(newSVpv(message,0))); \
13789 }
13790
13791     AV
13792       *av;
13793
13794     char
13795       message[MaxTextExtent];
13796
13797     ChannelStatistics
13798       *channel_statistics;
13799
13800     double
13801       scale;
13802
13803     ExceptionInfo
13804       *exception;
13805
13806     Image
13807       *image;
13808
13809     ssize_t
13810       count;
13811
13812     struct PackageInfo
13813       *info;
13814
13815     SV
13816       *perl_exception,
13817       *reference;
13818
13819     PERL_UNUSED_VAR(ref);
13820     PERL_UNUSED_VAR(ix);
13821     exception=AcquireExceptionInfo();
13822     perl_exception=newSVpv("",0);
13823     av=NULL;
13824     if (sv_isobject(ST(0)) == 0)
13825       {
13826         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13827           PackageName);
13828         goto PerlException;
13829       }
13830     reference=SvRV(ST(0));
13831     av=newAV();
13832     SvREFCNT_dec(av);
13833     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13834     if (image == (Image *) NULL)
13835       {
13836         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13837           PackageName);
13838         goto PerlException;
13839       }
13840     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13841     count=0;
13842     for ( ; image; image=image->next)
13843     {
13844       channel_statistics=GetImageStatistics(image,&image->exception);
13845       if (channel_statistics == (ChannelStatistics *) NULL)
13846         continue;
13847       count++;
13848       EXTEND(sp,35*count);
13849       scale=(double) QuantumRange;
13850       ChannelStatistics(RedChannel);
13851       ChannelStatistics(GreenChannel);
13852       ChannelStatistics(BlueChannel);
13853       if (image->colorspace == CMYKColorspace)
13854         ChannelStatistics(BlackChannel);
13855       if (image->matte != MagickFalse)
13856         ChannelStatistics(AlphaChannel);
13857       channel_statistics=(ChannelStatistics *)
13858         RelinquishMagickMemory(channel_statistics);
13859     }
13860
13861   PerlException:
13862     InheritPerlException(exception,perl_exception);
13863     exception=DestroyExceptionInfo(exception);
13864     SvREFCNT_dec(perl_exception);
13865   }
13866 \f
13867 #
13868 ###############################################################################
13869 #                                                                             #
13870 #                                                                             #
13871 #                                                                             #
13872 #   S y n c A u t h e n t i c P i x e l s                                     #
13873 #                                                                             #
13874 #                                                                             #
13875 #                                                                             #
13876 ###############################################################################
13877 #
13878 #
13879 void
13880 SyncAuthenticPixels(ref,...)
13881   Image::Magick ref = NO_INIT
13882   ALIAS:
13883     Syncauthenticpixels = 1
13884     SyncImagePixels = 2
13885     syncimagepixels = 3
13886   CODE:
13887   {
13888     ExceptionInfo
13889       *exception;
13890
13891     Image
13892       *image;
13893
13894     MagickBooleanType
13895       status;
13896
13897     struct PackageInfo
13898       *info;
13899
13900     SV
13901       *perl_exception,
13902       *reference;
13903
13904     PERL_UNUSED_VAR(ref);
13905     PERL_UNUSED_VAR(ix);
13906     exception=AcquireExceptionInfo();
13907     perl_exception=newSVpv("",0);
13908     if (sv_isobject(ST(0)) == 0)
13909       {
13910         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13911           PackageName);
13912         goto PerlException;
13913       }
13914
13915     reference=SvRV(ST(0));
13916     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13917     if (image == (Image *) NULL)
13918       {
13919         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13920           PackageName);
13921         goto PerlException;
13922       }
13923
13924     status=SyncAuthenticPixels(image,exception);
13925     if (status != MagickFalse)
13926       return;
13927     InheritException(exception,&image->exception);
13928
13929   PerlException:
13930     InheritPerlException(exception,perl_exception);
13931     exception=DestroyExceptionInfo(exception);
13932     SvREFCNT_dec(perl_exception);  /* throw away all errors */
13933   }
13934 \f
13935 #
13936 ###############################################################################
13937 #                                                                             #
13938 #                                                                             #
13939 #                                                                             #
13940 #   T r a n s f o r m                                                         #
13941 #                                                                             #
13942 #                                                                             #
13943 #                                                                             #
13944 ###############################################################################
13945 #
13946 #
13947 void
13948 Transform(ref,...)
13949   Image::Magick ref=NO_INIT
13950   ALIAS:
13951     TransformImage = 1
13952     transform      = 2
13953     transformimage = 3
13954   PPCODE:
13955   {
13956     AV
13957       *av;
13958
13959     char
13960       *attribute,
13961       *crop_geometry,
13962       *geometry;
13963
13964     ExceptionInfo
13965       *exception;
13966
13967     HV
13968       *hv;
13969
13970     Image
13971       *clone,
13972       *image;
13973
13974     register ssize_t
13975       i;
13976
13977     struct PackageInfo
13978       *info;
13979
13980     SV
13981       *av_reference,
13982       *perl_exception,
13983       *reference,
13984       *rv,
13985       *sv;
13986
13987     PERL_UNUSED_VAR(ref);
13988     PERL_UNUSED_VAR(ix);
13989     exception=AcquireExceptionInfo();
13990     perl_exception=newSVpv("",0);
13991     sv=NULL;
13992     av=NULL;
13993     attribute=NULL;
13994     if (sv_isobject(ST(0)) == 0)
13995       {
13996         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13997           PackageName);
13998         goto PerlException;
13999       }
14000     reference=SvRV(ST(0));
14001     hv=SvSTASH(reference);
14002     av=newAV();
14003     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14004     SvREFCNT_dec(av);
14005     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14006     if (image == (Image *) NULL)
14007       {
14008         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14009           PackageName);
14010         goto PerlException;
14011       }
14012     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14013     /*
14014       Get attribute.
14015     */
14016     crop_geometry=(char *) NULL;
14017     geometry=(char *) NULL;
14018     for (i=2; i < items; i+=2)
14019     {
14020       attribute=(char *) SvPV(ST(i-1),na);
14021       switch (*attribute)
14022       {
14023         case 'c':
14024         case 'C':
14025         {
14026           if (LocaleCompare(attribute,"crop") == 0)
14027             {
14028               crop_geometry=SvPV(ST(i),na);
14029               break;
14030             }
14031           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14032             attribute);
14033           break;
14034         }
14035         case 'g':
14036         case 'G':
14037         {
14038           if (LocaleCompare(attribute,"geometry") == 0)
14039             {
14040               geometry=SvPV(ST(i),na);
14041               break;
14042             }
14043          if (LocaleCompare(attribute,"gravity") == 0)
14044            {
14045              Image
14046                *next;
14047
14048              ssize_t
14049                in;
14050
14051              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
14052                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
14053              if (in < 0)
14054                {
14055                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
14056                    SvPV(ST(i),na));
14057                  return;
14058                }
14059              for (next=image; next; next=next->next)
14060                next->gravity=(GravityType) in;
14061              break;
14062            }
14063           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14064             attribute);
14065           break;
14066         }
14067         default:
14068         {
14069           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14070             attribute);
14071           break;
14072         }
14073       }
14074     }
14075     for ( ; image; image=image->next)
14076     {
14077       clone=CloneImage(image,0,0,MagickTrue,exception);
14078       if ((clone == (Image *) NULL) || (exception->severity >= ErrorException))
14079         goto PerlException;
14080       TransformImage(&clone,crop_geometry,geometry);
14081       for ( ; clone; clone=clone->next)
14082       {
14083         AddImageToRegistry(sv,clone);
14084         rv=newRV(sv);
14085         av_push(av,sv_bless(rv,hv));
14086         SvREFCNT_dec(sv);
14087       }
14088     }
14089     exception=DestroyExceptionInfo(exception);
14090     ST(0)=av_reference;
14091     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
14092     XSRETURN(1);
14093
14094   PerlException:
14095     InheritPerlException(exception,perl_exception);
14096     exception=DestroyExceptionInfo(exception);
14097     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14098     SvPOK_on(perl_exception);
14099     ST(0)=sv_2mortal(perl_exception);
14100     XSRETURN(1);
14101   }
14102 \f
14103 #
14104 ###############################################################################
14105 #                                                                             #
14106 #                                                                             #
14107 #                                                                             #
14108 #   W r i t e                                                                 #
14109 #                                                                             #
14110 #                                                                             #
14111 #                                                                             #
14112 ###############################################################################
14113 #
14114 #
14115 void
14116 Write(ref,...)
14117   Image::Magick ref=NO_INIT
14118   ALIAS:
14119     WriteImage    = 1
14120     write         = 2
14121     writeimage    = 3
14122   PPCODE:
14123   {
14124     char
14125       filename[MaxTextExtent];
14126
14127     ExceptionInfo
14128       *exception;
14129
14130     Image
14131       *image,
14132       *next;
14133
14134     register ssize_t
14135       i;
14136
14137     ssize_t
14138       number_images,
14139       scene;
14140
14141     struct PackageInfo
14142       *info,
14143       *package_info;
14144
14145     SV
14146       *perl_exception,
14147       *reference;
14148
14149     PERL_UNUSED_VAR(ref);
14150     PERL_UNUSED_VAR(ix);
14151     exception=AcquireExceptionInfo();
14152     perl_exception=newSVpv("",0);
14153     number_images=0;
14154     package_info=(struct PackageInfo *) NULL;
14155     if (sv_isobject(ST(0)) == 0)
14156       {
14157         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14158           PackageName);
14159         goto PerlException;
14160       }
14161     reference=SvRV(ST(0));
14162     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14163     if (image == (Image *) NULL)
14164       {
14165         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14166           PackageName);
14167         goto PerlException;
14168       }
14169     package_info=ClonePackageInfo(info,exception);
14170     if (items == 2)
14171       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14172     else
14173       if (items > 2)
14174         for (i=2; i < items; i+=2)
14175           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14176             exception);
14177     (void) CopyMagickString(filename,package_info->image_info->filename,
14178       MaxTextExtent);
14179     scene=0;
14180     for (next=image; next; next=next->next)
14181     {
14182       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
14183       next->scene=scene++;
14184     }
14185     SetImageInfo(package_info->image_info,(unsigned int)
14186       GetImageListLength(image),&image->exception);
14187     for (next=image; next; next=next->next)
14188     {
14189       (void) WriteImage(package_info->image_info,next,exception);
14190       number_images++;
14191       if (package_info->image_info->adjoin)
14192         break;
14193     }
14194
14195   PerlException:
14196     if (package_info != (struct PackageInfo *) NULL)
14197       DestroyPackageInfo(package_info);
14198     InheritPerlException(exception,perl_exception);
14199     exception=DestroyExceptionInfo(exception);
14200     sv_setiv(perl_exception,(IV) number_images);
14201     SvPOK_on(perl_exception);
14202     ST(0)=sv_2mortal(perl_exception);
14203     XSRETURN(1);
14204   }