]> 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}, {"attenuate", RealReference},
210       {"channel", MagickChannelOptions} } },
211     { "Colorize", { {"fill", StringReference}, {"blend", StringReference} } },
212     { "Border", { {"geometry", StringReference}, {"width", IntegerReference},
213       {"height", IntegerReference}, {"fill", StringReference},
214       {"bordercolor", StringReference}, {"color", StringReference},
215       {"compose", MagickComposeOptions} } },
216     { "Blur", { {"geometry", StringReference}, {"radius", RealReference},
217       {"sigma", RealReference}, {"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   PixelInfo
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             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1154           break;
1155         }
1156       if (info)
1157         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1158       for ( ; image; image=image->next)
1159         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1160       break;
1161     }
1162     case 'B':
1163     case 'b':
1164     {
1165       if (LocaleCompare(attribute,"background") == 0)
1166         {
1167           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1168             exception);
1169           if (info)
1170             info->image_info->background_color=target_color;
1171           for ( ; image; image=image->next)
1172             image->background_color=target_color;
1173           break;
1174         }
1175       if (LocaleCompare(attribute,"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),exception);
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),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),exception);
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),exception);
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),exception);
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),exception);
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),exception);
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),exception);
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),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),exception);
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),exception);
1738       break;
1739     }
1740     case 'O':
1741     case 'o':
1742     {
1743       if (LocaleCompare(attribute,"option") == 0)
1744         {
1745           if (info)
1746             DefineImageOption(info->image_info,SvPV(sval,na));
1747           break;
1748         }
1749       if (LocaleCompare(attribute,"orientation") == 0)
1750         {
1751           sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1752             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1753           if (sp < 0)
1754             {
1755               ThrowPerlException(exception,OptionError,
1756                 "UnrecognizedOrientationType",SvPV(sval,na));
1757               break;
1758             }
1759           if (info)
1760             info->image_info->orientation=(OrientationType) sp;
1761           for ( ; image; image=image->next)
1762             image->orientation=(OrientationType) sp;
1763           break;
1764         }
1765       if (info)
1766         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1767       for ( ; image; image=image->next)
1768         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1769       break;
1770     }
1771     case 'P':
1772     case 'p':
1773     {
1774       if (LocaleCompare(attribute,"page") == 0)
1775         {
1776           char
1777             *geometry;
1778
1779           geometry=GetPageGeometry(SvPV(sval,na));
1780           if (info)
1781             (void) CloneString(&info->image_info->page,geometry);
1782           for ( ; image; image=image->next)
1783             (void) ParsePageGeometry(image,geometry,&image->page,exception);
1784           geometry=(char *) RelinquishMagickMemory(geometry);
1785           break;
1786         }
1787       if (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                   QueryColorCompliance(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),exception);
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),exception);
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),exception);
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),exception);
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),exception);
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),exception);
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),exception);
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),exception);
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),exception);
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     PixelInfo
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,exception);
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                 {
4296                   const char
4297                     *option;
4298
4299                   option=GetImageOption(info->image_info,attribute);
4300                   if (option != (const char *) NULL)
4301                     s=newSVpv(option,0);
4302                 }
4303               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4304               continue;
4305             }
4306           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4307             attribute);
4308           break;
4309         }
4310         case 'B':
4311         case 'b':
4312         {
4313           if (LocaleCompare(attribute,"background") == 0)
4314             {
4315               if (image == (Image *) NULL)
4316                 break;
4317               (void) FormatLocaleString(color,MaxTextExtent,
4318                 "%.20g,%.20g,%.20g,%.20g",image->background_color.red,
4319                 image->background_color.green,image->background_color.blue,
4320                 image->background_color.alpha);
4321               s=newSVpv(color,0);
4322               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4323               continue;
4324             }
4325           if (LocaleCompare(attribute,"base-columns") == 0)
4326             {
4327               if (image != (Image *) NULL)
4328                 s=newSViv((ssize_t) image->magick_columns);
4329               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4330               continue;
4331             }
4332           if (LocaleCompare(attribute,"base-filename") == 0)
4333             {
4334               if (image != (Image *) NULL)
4335                 s=newSVpv(image->magick_filename,0);
4336               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4337               continue;
4338             }
4339           if (LocaleCompare(attribute,"base-height") == 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-rows") == 0)
4347             {
4348               if (image != (Image *) NULL)
4349                 s=newSViv((ssize_t) image->magick_rows);
4350               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4351               continue;
4352             }
4353           if (LocaleCompare(attribute,"base-width") == 0)
4354             {
4355               if (image != (Image *) NULL)
4356                 s=newSViv((ssize_t) image->magick_columns);
4357               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4358               continue;
4359             }
4360           if (LocaleCompare(attribute,"bias") == 0)
4361             {
4362               if (image != (Image *) NULL)
4363                 s=newSVnv(image->bias);
4364               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4365               continue;
4366             }
4367           if (LocaleCompare(attribute,"blue-primary") == 0)
4368             {
4369               if (image == (Image *) NULL)
4370                 break;
4371               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4372                 image->chromaticity.blue_primary.x,
4373                 image->chromaticity.blue_primary.y);
4374               s=newSVpv(color,0);
4375               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4376               continue;
4377             }
4378           if (LocaleCompare(attribute,"bordercolor") == 0)
4379             {
4380               if (image == (Image *) NULL)
4381                 break;
4382               (void) FormatLocaleString(color,MaxTextExtent,
4383                 "%.20g,%.20g,%.20g,%.20g",image->border_color.red,
4384                 image->border_color.green,image->border_color.blue,
4385                 image->border_color.alpha);
4386               s=newSVpv(color,0);
4387               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4388               continue;
4389             }
4390           if (LocaleCompare(attribute,"bounding-box") == 0)
4391             {
4392               char
4393                 geometry[MaxTextExtent];
4394
4395               RectangleInfo
4396                 page;
4397
4398               if (image == (Image *) NULL)
4399                 break;
4400               page=GetImageBoundingBox(image,&image->exception);
4401               (void) FormatLocaleString(geometry,MaxTextExtent,
4402                 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4403                 page.height,(double) page.x,(double) page.y);
4404               s=newSVpv(geometry,0);
4405               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4406               continue;
4407             }
4408           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4409             attribute);
4410           break;
4411         }
4412         case 'C':
4413         case 'c':
4414         {
4415           if (LocaleCompare(attribute,"class") == 0)
4416             {
4417               if (image == (Image *) NULL)
4418                 break;
4419               s=newSViv(image->storage_class);
4420               (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4421                 image->storage_class));
4422               SvIOK_on(s);
4423               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4424               continue;
4425             }
4426           if (LocaleCompare(attribute,"clip-mask") == 0)
4427             {
4428               if (image != (Image *) NULL)
4429                 {
4430                   SV
4431                     *sv;
4432
4433                   sv=NULL;
4434                   if (image->mask == (Image *) NULL)
4435                     ClipImage(image,exception);
4436                   if (image->mask != (Image *) NULL)
4437                     {
4438                       AddImageToRegistry(sv,image->mask);
4439                       s=sv_bless(newRV(sv),SvSTASH(reference));
4440                     }
4441                 }
4442               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4443               continue;
4444             }
4445           if (LocaleCompare(attribute,"clip-path") == 0)
4446             {
4447               if (image != (Image *) NULL)
4448                 {
4449                   SV
4450                     *sv;
4451
4452                   sv=NULL;
4453                   if (image->clip_mask == (Image *) NULL)
4454                     ClipImage(image,exception);
4455                   if (image->clip_mask != (Image *) NULL)
4456                     {
4457                       AddImageToRegistry(sv,image->clip_mask);
4458                       s=sv_bless(newRV(sv),SvSTASH(reference));
4459                     }
4460                 }
4461               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4462               continue;
4463             }
4464           if (LocaleCompare(attribute,"compression") == 0)
4465             {
4466               j=info ? info->image_info->compression : image ?
4467                 image->compression : UndefinedCompression;
4468               if (info)
4469                 if (info->image_info->compression == UndefinedCompression)
4470                   j=image->compression;
4471               s=newSViv(j);
4472               (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4473                 j));
4474               SvIOK_on(s);
4475               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4476               continue;
4477             }
4478           if (LocaleCompare(attribute,"colorspace") == 0)
4479             {
4480               j=image ? image->colorspace : RGBColorspace;
4481               s=newSViv(j);
4482               (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4483                 j));
4484               SvIOK_on(s);
4485               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4486               continue;
4487             }
4488           if (LocaleCompare(attribute,"colors") == 0)
4489             {
4490               if (image != (Image *) NULL)
4491                 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4492                   &image->exception));
4493               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4494               continue;
4495             }
4496           if (LocaleNCompare(attribute,"colormap",8) == 0)
4497             {
4498               int
4499                 items;
4500
4501               if (image == (Image *) NULL || !image->colormap)
4502                 break;
4503               j=0;
4504               items=sscanf(attribute,"%*[^[][%ld",&j);
4505               (void) items;
4506               if (j > (ssize_t) image->colors)
4507                 j%=image->colors;
4508               (void) FormatLocaleString(color,MaxTextExtent,
4509                 "%.20g,%.20g,%.20g,%.20g",image->colormap[j].red,
4510                 image->colormap[j].green,image->colormap[j].blue,
4511                 image->colormap[j].alpha);
4512               s=newSVpv(color,0);
4513               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4514               continue;
4515             }
4516           if (LocaleCompare(attribute,"columns") == 0)
4517             {
4518               if (image != (Image *) NULL)
4519                 s=newSViv((ssize_t) image->columns);
4520               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4521               continue;
4522             }
4523           if (LocaleCompare(attribute,"comment") == 0)
4524             {
4525               const char
4526                 *value;
4527
4528               value=GetImageProperty(image,attribute,exception);
4529               if (value != (const char *) NULL)
4530                 s=newSVpv(value,0);
4531               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4532               continue;
4533             }
4534           if (LocaleCompare(attribute,"copyright") == 0)
4535             {
4536               s=newSVpv(GetMagickCopyright(),0);
4537               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4538               continue;
4539             }
4540           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4541             attribute);
4542           break;
4543         }
4544         case 'D':
4545         case 'd':
4546         {
4547           if (LocaleCompare(attribute,"density") == 0)
4548             {
4549               char
4550                 geometry[MaxTextExtent];
4551
4552               if (image == (Image *) NULL)
4553                 break;
4554               (void) FormatLocaleString(geometry,MaxTextExtent,"%.15gx%.15g",
4555                 image->x_resolution,image->y_resolution);
4556               s=newSVpv(geometry,0);
4557               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4558               continue;
4559             }
4560           if (LocaleCompare(attribute,"delay") == 0)
4561             {
4562               if (image != (Image *) NULL)
4563                 s=newSViv((ssize_t) image->delay);
4564               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4565               continue;
4566             }
4567           if (LocaleCompare(attribute,"depth") == 0)
4568             {
4569               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4570               if (image != (Image *) NULL)
4571                 s=newSViv((ssize_t) GetImageDepth(image,&image->exception));
4572               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4573               continue;
4574             }
4575           if (LocaleCompare(attribute,"directory") == 0)
4576             {
4577               if (image && image->directory)
4578                 s=newSVpv(image->directory,0);
4579               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4580               continue;
4581             }
4582           if (LocaleCompare(attribute,"dispose") == 0)
4583             {
4584               if (image == (Image *) NULL)
4585                 break;
4586
4587               s=newSViv(image->dispose);
4588               (void) sv_setpv(s,
4589                 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
4590               SvIOK_on(s);
4591               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4592               continue;
4593             }
4594           if (LocaleCompare(attribute,"disk") == 0)
4595             {
4596               s=newSViv(GetMagickResource(DiskResource));
4597               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4598               continue;
4599             }
4600           if (LocaleCompare(attribute,"dither") == 0)
4601             {
4602               if (info)
4603                 s=newSViv((ssize_t) info->image_info->dither);
4604               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4605               continue;
4606             }
4607           if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4608             {
4609               if (info && info->image_info->server_name)
4610                 s=newSVpv(info->image_info->server_name,0);
4611               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4612               continue;
4613             }
4614           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4615             attribute);
4616           break;
4617         }
4618         case 'E':
4619         case 'e':
4620         {
4621           if (LocaleCompare(attribute,"elapsed-time") == 0)
4622             {
4623               if (image != (Image *) NULL)
4624                 s=newSVnv(GetElapsedTime(&image->timer));
4625               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4626               continue;
4627             }
4628           if (LocaleCompare(attribute,"endian") == 0)
4629             {
4630               j=info ? info->image_info->endian : image ? image->endian :
4631                 UndefinedEndian;
4632               s=newSViv(j);
4633               (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
4634               SvIOK_on(s);
4635               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4636               continue;
4637             }
4638           if (LocaleCompare(attribute,"error") == 0)
4639             {
4640               if (image != (Image *) NULL)
4641                 s=newSVnv(image->error.mean_error_per_pixel);
4642               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4643               continue;
4644             }
4645           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4646             attribute);
4647           break;
4648         }
4649         case 'F':
4650         case 'f':
4651         {
4652           if (LocaleCompare(attribute,"filesize") == 0)
4653             {
4654               if (image != (Image *) NULL)
4655                 s=newSViv((ssize_t) GetBlobSize(image));
4656               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4657               continue;
4658             }
4659           if (LocaleCompare(attribute,"filename") == 0)
4660             {
4661               if (info && info->image_info->filename &&
4662                   *info->image_info->filename)
4663                 s=newSVpv(info->image_info->filename,0);
4664               if (image != (Image *) NULL)
4665                 s=newSVpv(image->filename,0);
4666               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4667               continue;
4668             }
4669           if (LocaleCompare(attribute,"filter") == 0)
4670             {
4671               s=image ? newSViv(image->filter) : newSViv(0);
4672               (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
4673                 image->filter));
4674               SvIOK_on(s);
4675               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4676               continue;
4677             }
4678           if (LocaleCompare(attribute,"font") == 0)
4679             {
4680               if (info && info->image_info->font)
4681                 s=newSVpv(info->image_info->font,0);
4682               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4683               continue;
4684             }
4685           if (LocaleCompare(attribute,"foreground") == 0)
4686             continue;
4687           if (LocaleCompare(attribute,"format") == 0)
4688             {
4689               const MagickInfo
4690                 *magick_info;
4691
4692               magick_info=(const MagickInfo *) NULL;
4693               if (info && (*info->image_info->magick != '\0'))
4694                 magick_info=GetMagickInfo(info->image_info->magick,exception);
4695               if (image != (Image *) NULL)
4696                 magick_info=GetMagickInfo(image->magick,&image->exception);
4697               if ((magick_info != (const MagickInfo *) NULL) &&
4698                   (*magick_info->description != '\0'))
4699                 s=newSVpv((char *) magick_info->description,0);
4700               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4701               continue;
4702             }
4703           if (LocaleCompare(attribute,"fuzz") == 0)
4704             {
4705               if (info)
4706                 s=newSVnv(info->image_info->fuzz);
4707               if (image != (Image *) NULL)
4708                 s=newSVnv(image->fuzz);
4709               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4710               continue;
4711             }
4712           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4713             attribute);
4714           break;
4715         }
4716         case 'G':
4717         case 'g':
4718         {
4719           if (LocaleCompare(attribute,"gamma") == 0)
4720             {
4721               if (image != (Image *) NULL)
4722                 s=newSVnv(image->gamma);
4723               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4724               continue;
4725             }
4726           if (LocaleCompare(attribute,"geometry") == 0)
4727             {
4728               if (image && image->geometry)
4729                 s=newSVpv(image->geometry,0);
4730               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4731               continue;
4732             }
4733           if (LocaleCompare(attribute,"gravity") == 0)
4734             {
4735               s=image ? newSViv(image->gravity) : newSViv(0);
4736               (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
4737                 image->gravity));
4738               SvIOK_on(s);
4739               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4740               continue;
4741             }
4742           if (LocaleCompare(attribute,"green-primary") == 0)
4743             {
4744               if (image == (Image *) NULL)
4745                 break;
4746               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4747                 image->chromaticity.green_primary.x,
4748                 image->chromaticity.green_primary.y);
4749               s=newSVpv(color,0);
4750               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4751               continue;
4752             }
4753           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4754             attribute);
4755           break;
4756         }
4757         case 'H':
4758         case 'h':
4759         {
4760           if (LocaleCompare(attribute,"height") == 0)
4761             {
4762               if (image != (Image *) NULL)
4763                 s=newSViv((ssize_t) image->rows);
4764               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4765               continue;
4766             }
4767           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4768             attribute);
4769           break;
4770         }
4771         case 'I':
4772         case 'i':
4773         {
4774           if (LocaleCompare(attribute,"icc") == 0)
4775             {
4776               if (image != (Image *) NULL)
4777                 {
4778                   const StringInfo
4779                     *profile;
4780
4781                   profile=GetImageProfile(image,"icc");
4782                   if (profile != (StringInfo *) NULL)
4783                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4784                       GetStringInfoLength(profile));
4785                 }
4786               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4787               continue;
4788             }
4789           if (LocaleCompare(attribute,"icm") == 0)
4790             {
4791               if (image != (Image *) NULL)
4792                 {
4793                   const StringInfo
4794                     *profile;
4795
4796                   profile=GetImageProfile(image,"icm");
4797                   if (profile != (const StringInfo *) NULL)
4798                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4799                       GetStringInfoLength(profile));
4800                 }
4801               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4802               continue;
4803             }
4804           if (LocaleCompare(attribute,"id") == 0)
4805             {
4806               if (image != (Image *) NULL)
4807                 {
4808                   char
4809                     key[MaxTextExtent];
4810
4811                   MagickBooleanType
4812                     status;
4813
4814                   static ssize_t
4815                     id = 0;
4816
4817                   (void) FormatLocaleString(key,MaxTextExtent,"%.20g\n",(double)
4818                     id);
4819                   status=SetImageRegistry(ImageRegistryType,key,image,
4820                     &image->exception);
4821                   (void) status;
4822                   s=newSViv(id++);
4823                 }
4824               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4825               continue;
4826             }
4827           if (LocaleNCompare(attribute,"index",5) == 0)
4828             {
4829               char
4830                 name[MaxTextExtent];
4831
4832               int
4833                 items;
4834
4835               long
4836                 x,
4837                 y;
4838
4839               register const Quantum
4840                 *p;
4841
4842               CacheView
4843                 *image_view;
4844
4845               if (image == (Image *) NULL)
4846                 break;
4847               if (image->storage_class != PseudoClass)
4848                 break;
4849               x=0;
4850               y=0;
4851               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
4852               (void) items;
4853               image_view=AcquireCacheView(image);
4854               p=GetCacheViewVirtualPixels(image_view,x,y,1,1,&image->exception);
4855               if (p != (const Quantum *) NULL)
4856                 {
4857                   (void) FormatLocaleString(name,MaxTextExtent,QuantumFormat,
4858                     GetPixelIndex(image,p));
4859                   s=newSVpv(name,0);
4860                   PUSHs(s ? sv_2mortal(s) : &sv_undef);
4861                 }
4862               image_view=DestroyCacheView(image_view);
4863               continue;
4864             }
4865           if (LocaleCompare(attribute,"iptc") == 0)
4866             {
4867               if (image != (Image *) NULL)
4868                 {
4869                   const StringInfo
4870                     *profile;
4871
4872                   profile=GetImageProfile(image,"iptc");
4873                   if (profile != (const StringInfo *) NULL)
4874                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4875                       GetStringInfoLength(profile));
4876                 }
4877               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4878               continue;
4879             }
4880           if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
4881             {
4882               if (image != (Image *) NULL)
4883                 s=newSViv((ssize_t) image->iterations);
4884               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4885               continue;
4886             }
4887           if (LocaleCompare(attribute,"interlace") == 0)
4888             {
4889               j=info ? info->image_info->interlace : image ? image->interlace :
4890                 UndefinedInterlace;
4891               s=newSViv(j);
4892               (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
4893                 j));
4894               SvIOK_on(s);
4895               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4896               continue;
4897             }
4898           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4899             attribute);
4900           break;
4901         }
4902         case 'L':
4903         case 'l':
4904         {
4905           if (LocaleCompare(attribute,"label") == 0)
4906             {
4907               const char
4908                 *value;
4909
4910               if (image == (Image *) NULL)
4911                 break;
4912               value=GetImageProperty(image,"Label",exception);
4913               if (value != (const char *) NULL)
4914                 s=newSVpv(value,0);
4915               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4916               continue;
4917             }
4918           if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
4919             {
4920               if (image != (Image *) NULL)
4921                 s=newSViv((ssize_t) image->iterations);
4922               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4923               continue;
4924             }
4925           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4926             attribute);
4927           break;
4928         }
4929         case 'M':
4930         case 'm':
4931         {
4932           if (LocaleCompare(attribute,"magick") == 0)
4933             {
4934               if (info && *info->image_info->magick)
4935                 s=newSVpv(info->image_info->magick,0);
4936               if (image != (Image *) NULL)
4937                 s=newSVpv(image->magick,0);
4938               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4939               continue;
4940             }
4941           if (LocaleCompare(attribute,"map") == 0)
4942             {
4943               s=newSViv(GetMagickResource(MapResource));
4944               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4945               continue;
4946             }
4947           if (LocaleCompare(attribute,"maximum-error") == 0)
4948             {
4949               if (image != (Image *) NULL)
4950                 s=newSVnv(image->error.normalized_maximum_error);
4951               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4952               continue;
4953             }
4954           if (LocaleCompare(attribute,"memory") == 0)
4955             {
4956               s=newSViv(GetMagickResource(MemoryResource));
4957               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4958               continue;
4959             }
4960           if (LocaleCompare(attribute,"mean-error") == 0)
4961             {
4962               if (image != (Image *) NULL)
4963                 s=newSVnv(image->error.normalized_mean_error);
4964               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4965               continue;
4966             }
4967           if (LocaleCompare(attribute,"mime") == 0)
4968             {
4969               if (info && *info->image_info->magick)
4970                 s=newSVpv(MagickToMime(info->image_info->magick),0);
4971               if (image != (Image *) NULL)
4972                 s=newSVpv(MagickToMime(image->magick),0);
4973               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4974               continue;
4975             }
4976           if (LocaleCompare(attribute,"mattecolor") == 0)
4977             {
4978               if (image == (Image *) NULL)
4979                 break;
4980               (void) FormatLocaleString(color,MaxTextExtent,
4981                 "%.20g,%.20g,%.20g,%.20g",image->matte_color.red,
4982                 image->matte_color.green,image->matte_color.blue,
4983                 image->matte_color.alpha);
4984               s=newSVpv(color,0);
4985               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4986               continue;
4987             }
4988           if (LocaleCompare(attribute,"matte") == 0)
4989             {
4990               if (image != (Image *) NULL)
4991                 s=newSViv((ssize_t) image->matte);
4992               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4993               continue;
4994             }
4995           if (LocaleCompare(attribute,"mime") == 0)
4996             {
4997               const char
4998                 *magick;
4999
5000               magick=NULL;
5001               if (info && *info->image_info->magick)
5002                 magick=info->image_info->magick;
5003               if (image != (Image *) NULL)
5004                 magick=image->magick;
5005               if (magick)
5006                 {
5007                   char
5008                     *mime;
5009
5010                   mime=MagickToMime(magick);
5011                   s=newSVpv(mime,0);
5012                   mime=(char *) RelinquishMagickMemory(mime);
5013                 }
5014               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5015               continue;
5016             }
5017           if (LocaleCompare(attribute,"monochrome") == 0)
5018             {
5019               if (image == (Image *) NULL)
5020                 continue;
5021               j=info ? info->image_info->monochrome :
5022                 IsImageMonochrome(image,&image->exception);
5023               s=newSViv(j);
5024               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5025               continue;
5026             }
5027           if (LocaleCompare(attribute,"montage") == 0)
5028             {
5029               if (image && image->montage)
5030                 s=newSVpv(image->montage,0);
5031               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5032               continue;
5033             }
5034           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5035             attribute);
5036           break;
5037         }
5038         case 'O':
5039         case 'o':
5040         {
5041           if (LocaleCompare(attribute,"orientation") == 0)
5042             {
5043               j=info ? info->image_info->orientation : image ?
5044                 image->orientation : UndefinedOrientation;
5045               s=newSViv(j);
5046               (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5047                 j));
5048               SvIOK_on(s);
5049               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5050               continue;
5051             }
5052           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5053             attribute);
5054           break;
5055         }
5056         case 'P':
5057         case 'p':
5058         {
5059           if (LocaleCompare(attribute,"page") == 0)
5060             {
5061               if (info && info->image_info->page)
5062                 s=newSVpv(info->image_info->page,0);
5063               if (image != (Image *) NULL)
5064                 {
5065                   char
5066                     geometry[MaxTextExtent];
5067
5068                   (void) FormatLocaleString(geometry,MaxTextExtent,
5069                     "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5070                     (double) image->page.height,(double) image->page.x,(double)
5071                     image->page.y);
5072                   s=newSVpv(geometry,0);
5073                 }
5074               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5075               continue;
5076             }
5077           if (LocaleCompare(attribute,"page.x") == 0)
5078             {
5079               if (image != (Image *) NULL)
5080                 s=newSViv((ssize_t) image->page.x);
5081               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5082               continue;
5083             }
5084           if (LocaleCompare(attribute,"page.y") == 0)
5085             {
5086               if (image != (Image *) NULL)
5087                 s=newSViv((ssize_t) image->page.y);
5088               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5089               continue;
5090             }
5091           if (LocaleNCompare(attribute,"pixel",5) == 0)
5092             {
5093               char
5094                 tuple[MaxTextExtent];
5095
5096               int
5097                 items;
5098
5099               long
5100                 x,
5101                 y;
5102
5103               register const Quantum
5104                 *p;
5105
5106               if (image == (Image *) NULL)
5107                 break;
5108               x=0;
5109               y=0;
5110               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5111               (void) items;
5112               p=GetVirtualPixels(image,x,y,1,1,exception);
5113               if (image->colorspace != CMYKColorspace)
5114                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5115                   QuantumFormat "," QuantumFormat "," QuantumFormat,
5116                   GetPixelRed(image,p),GetPixelGreen(image,p),
5117                   GetPixelBlue(image,p),GetPixelAlpha(image,p));
5118               else
5119                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5120                   QuantumFormat "," QuantumFormat "," QuantumFormat ","
5121                   QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5122                   GetPixelBlue(image,p),GetPixelBlack(image,p),
5123                   GetPixelAlpha(image,p));
5124               s=newSVpv(tuple,0);
5125               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5126               continue;
5127             }
5128           if (LocaleCompare(attribute,"pointsize") == 0)
5129             {
5130               if (info)
5131                 s=newSViv((ssize_t) info->image_info->pointsize);
5132               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5133               continue;
5134             }
5135           if (LocaleCompare(attribute,"preview") == 0)
5136             {
5137               s=newSViv(info->image_info->preview_type);
5138               (void) sv_setpv(s,CommandOptionToMnemonic(MagickPreviewOptions,
5139                 info->image_info->preview_type));
5140               SvIOK_on(s);
5141               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5142               continue;
5143             }
5144           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5145             attribute);
5146           break;
5147         }
5148         case 'Q':
5149         case 'q':
5150         {
5151           if (LocaleCompare(attribute,"quality") == 0)
5152             {
5153               if (info)
5154                 s=newSViv((ssize_t) info->image_info->quality);
5155               if (image != (Image *) NULL)
5156                 s=newSViv((ssize_t) image->quality);
5157               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5158               continue;
5159             }
5160           if (LocaleCompare(attribute,"quantum") == 0)
5161             {
5162               if (info)
5163                 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5164               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5165               continue;
5166             }
5167           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5168             attribute);
5169           break;
5170         }
5171         case 'R':
5172         case 'r':
5173         {
5174           if (LocaleCompare(attribute,"rendering-intent") == 0)
5175             {
5176               s=newSViv(image->rendering_intent);
5177               (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5178                 image->rendering_intent));
5179               SvIOK_on(s);
5180               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5181               continue;
5182             }
5183           if (LocaleCompare(attribute,"red-primary") == 0)
5184             {
5185               if (image == (Image *) NULL)
5186                 break;
5187               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5188                 image->chromaticity.red_primary.x,
5189                 image->chromaticity.red_primary.y);
5190               s=newSVpv(color,0);
5191               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5192               continue;
5193             }
5194           if (LocaleCompare(attribute,"rows") == 0)
5195             {
5196               if (image != (Image *) NULL)
5197                 s=newSViv((ssize_t) image->rows);
5198               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5199               continue;
5200             }
5201           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5202             attribute);
5203           break;
5204         }
5205         case 'S':
5206         case 's':
5207         {
5208           if (LocaleCompare(attribute,"sampling-factor") == 0)
5209             {
5210               if (info && info->image_info->sampling_factor)
5211                 s=newSVpv(info->image_info->sampling_factor,0);
5212               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5213               continue;
5214             }
5215           if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5216             {
5217               if (info && info->image_info->server_name)
5218                 s=newSVpv(info->image_info->server_name,0);
5219               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5220               continue;
5221             }
5222           if (LocaleCompare(attribute,"size") == 0)
5223             {
5224               if (info && info->image_info->size)
5225                 s=newSVpv(info->image_info->size,0);
5226               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5227               continue;
5228             }
5229           if (LocaleCompare(attribute,"scene") == 0)
5230             {
5231               if (image != (Image *) NULL)
5232                 s=newSViv((ssize_t) image->scene);
5233               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5234               continue;
5235             }
5236           if (LocaleCompare(attribute,"scenes") == 0)
5237             {
5238               if (image != (Image *) NULL)
5239                 s=newSViv((ssize_t) info->image_info->number_scenes);
5240               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5241               continue;
5242             }
5243           if (LocaleCompare(attribute,"signature") == 0)
5244             {
5245               const char
5246                 *value;
5247
5248               if (image == (Image *) NULL)
5249                 break;
5250               (void) SignatureImage(image,exception);
5251               value=GetImageProperty(image,"Signature",exception);
5252               if (value != (const char *) NULL)
5253                 s=newSVpv(value,0);
5254               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5255               continue;
5256             }
5257           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5258             attribute);
5259           break;
5260         }
5261         case 'T':
5262         case 't':
5263         {
5264           if (LocaleCompare(attribute,"taint") == 0)
5265             {
5266               if (image != (Image *) NULL)
5267                 s=newSViv((ssize_t) IsTaintImage(image));
5268               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5269               continue;
5270             }
5271           if (LocaleCompare(attribute,"texture") == 0)
5272             {
5273               if (info && info->image_info->texture)
5274                 s=newSVpv(info->image_info->texture,0);
5275               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5276               continue;
5277             }
5278           if (LocaleCompare(attribute,"total-ink-density") == 0)
5279             {
5280               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5281               if (image != (Image *) NULL)
5282                 s=newSVnv(GetImageTotalInkDensity(image));
5283               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5284               continue;
5285             }
5286           if (LocaleCompare(attribute,"transparent-color") == 0)
5287             {
5288               if (image == (Image *) NULL)
5289                 break;
5290               (void) FormatLocaleString(color,MaxTextExtent,
5291                 "%.20g,%.20g,%.20g,%.20g",image->transparent_color.red,
5292                 image->transparent_color.green,image->transparent_color.blue,
5293                 image->transparent_color.alpha);
5294               s=newSVpv(color,0);
5295               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5296               continue;
5297             }
5298           if (LocaleCompare(attribute,"type") == 0)
5299             {
5300               if (image == (Image *) NULL)
5301                 break;
5302               j=(ssize_t) GetImageType(image,&image->exception);
5303               s=newSViv(j);
5304               (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5305               SvIOK_on(s);
5306               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5307               continue;
5308             }
5309           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5310             attribute);
5311           break;
5312         }
5313         case 'U':
5314         case 'u':
5315         {
5316           if (LocaleCompare(attribute,"units") == 0)
5317             {
5318               j=info ? info->image_info->units : image ? image->units :
5319                 UndefinedResolution;
5320               if (info && (info->image_info->units == UndefinedResolution))
5321                 if (image)
5322                   j=image->units;
5323               if (j == UndefinedResolution)
5324                 s=newSVpv("undefined units",0);
5325               else
5326                 if (j == PixelsPerInchResolution)
5327                   s=newSVpv("pixels / inch",0);
5328                 else
5329                   s=newSVpv("pixels / centimeter",0);
5330               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5331               continue;
5332             }
5333           if (LocaleCompare(attribute,"user-time") == 0)
5334             {
5335               if (image != (Image *) NULL)
5336                 s=newSVnv(GetUserTime(&image->timer));
5337               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5338               continue;
5339             }
5340           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5341             attribute);
5342           break;
5343         }
5344         case 'V':
5345         case 'v':
5346         {
5347           if (LocaleCompare(attribute,"verbose") == 0)
5348             {
5349               if (info)
5350                 s=newSViv((ssize_t) info->image_info->verbose);
5351               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5352               continue;
5353             }
5354           if (LocaleCompare(attribute,"version") == 0)
5355             {
5356               s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5357               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5358               continue;
5359             }
5360           if (LocaleCompare(attribute,"view") == 0)
5361             {
5362               if (info && info->image_info->view)
5363                 s=newSVpv(info->image_info->view,0);
5364               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5365               continue;
5366             }
5367           if (LocaleCompare(attribute,"virtual-pixel") == 0)
5368             {
5369               if (image == (Image *) NULL)
5370                 break;
5371               j=(ssize_t) GetImageVirtualPixelMethod(image);
5372               s=newSViv(j);
5373               (void) sv_setpv(s,CommandOptionToMnemonic(
5374                 MagickVirtualPixelOptions,j));
5375               SvIOK_on(s);
5376               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5377               continue;
5378             }
5379           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5380             attribute);
5381           break;
5382         }
5383         case 'W':
5384         case 'w':
5385         {
5386           if (LocaleCompare(attribute,"white-point") == 0)
5387             {
5388               if (image == (Image *) NULL)
5389                 break;
5390               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5391                 image->chromaticity.white_point.x,
5392                 image->chromaticity.white_point.y);
5393               s=newSVpv(color,0);
5394               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5395               continue;
5396             }
5397           if (LocaleCompare(attribute,"width") == 0)
5398             {
5399               if (image != (Image *) NULL)
5400                 s=newSViv((ssize_t) image->columns);
5401               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5402               continue;
5403             }
5404           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5405              attribute);
5406           break;
5407         }
5408         case 'X':
5409         case 'x':
5410         {
5411           if (LocaleCompare(attribute,"x-resolution") == 0)
5412             {
5413               if (image != (Image *) NULL)
5414                 s=newSVnv(image->x_resolution);
5415               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5416               continue;
5417             }
5418           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5419             attribute);
5420           break;
5421         }
5422         case 'Y':
5423         case 'y':
5424         {
5425           if (LocaleCompare(attribute,"y-resolution") == 0)
5426             {
5427               if (image != (Image *) NULL)
5428                 s=newSVnv(image->y_resolution);
5429               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5430               continue;
5431             }
5432           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5433             attribute);
5434           break;
5435         }
5436         default:
5437           break;
5438       }
5439       if (image == (Image *) NULL)
5440         ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5441           attribute)
5442       else
5443         {
5444           value=GetImageProperty(image,attribute,exception);
5445           if (value != (const char *) NULL)
5446             {
5447               s=newSVpv(value,0);
5448               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5449             }
5450           else
5451             if (*attribute != '%')
5452               ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5453                 attribute)
5454             else
5455               {
5456                  char
5457                    *meta;
5458
5459                  meta=InterpretImageProperties(info ? info->image_info :
5460                    (ImageInfo *) NULL,image,attribute,exception);
5461                  s=newSVpv(meta,0);
5462                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5463                  meta=(char *) RelinquishMagickMemory(meta);
5464               }
5465         }
5466     }
5467     exception=DestroyExceptionInfo(exception);
5468     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5469   }
5470 \f
5471 #
5472 ###############################################################################
5473 #                                                                             #
5474 #                                                                             #
5475 #                                                                             #
5476 #   G e t A u t h e n t i c P i x e l s                                       #
5477 #                                                                             #
5478 #                                                                             #
5479 #                                                                             #
5480 ###############################################################################
5481 #
5482 #
5483 void *
5484 GetAuthenticPixels(ref,...)
5485   Image::Magick ref = NO_INIT
5486   ALIAS:
5487     getauthenticpixels = 1
5488     GetImagePixels = 2
5489     getimagepixels = 3
5490   CODE:
5491   {
5492     char
5493       *attribute;
5494
5495     ExceptionInfo
5496       *exception;
5497
5498     Image
5499       *image;
5500
5501     RectangleInfo
5502       region;
5503
5504     ssize_t
5505       i;
5506
5507     struct PackageInfo
5508       *info;
5509
5510     SV
5511       *perl_exception,
5512       *reference;
5513
5514     void
5515       *blob = NULL;
5516
5517     PERL_UNUSED_VAR(ref);
5518     PERL_UNUSED_VAR(ix);
5519     exception=AcquireExceptionInfo();
5520     perl_exception=newSVpv("",0);
5521     if (sv_isobject(ST(0)) == 0)
5522       {
5523         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5524           PackageName);
5525         goto PerlException;
5526       }
5527     reference=SvRV(ST(0));
5528
5529     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5530     if (image == (Image *) NULL)
5531       {
5532         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5533           PackageName);
5534         goto PerlException;
5535       }
5536
5537     region.x=0;
5538     region.y=0;
5539     region.width=image->columns;
5540     region.height=1;
5541     if (items == 1)
5542       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5543     for (i=2; i < items; i+=2)
5544     {
5545       attribute=(char *) SvPV(ST(i-1),na);
5546       switch (*attribute)
5547       {
5548         case 'g':
5549         case 'G':
5550         {
5551           if (LocaleCompare(attribute,"geometry") == 0)
5552             {
5553               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5554               break;
5555             }
5556           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5557             attribute);
5558           break;
5559         }
5560         case 'H':
5561         case 'h':
5562         {
5563           if (LocaleCompare(attribute,"height") == 0)
5564             {
5565               region.height=SvIV(ST(i));
5566               continue;
5567             }
5568           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5569             attribute);
5570           break;
5571         }
5572         case 'X':
5573         case 'x':
5574         {
5575           if (LocaleCompare(attribute,"x") == 0)
5576             {
5577               region.x=SvIV(ST(i));
5578               continue;
5579             }
5580           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5581             attribute);
5582           break;
5583         }
5584         case 'Y':
5585         case 'y':
5586         {
5587           if (LocaleCompare(attribute,"y") == 0)
5588             {
5589               region.y=SvIV(ST(i));
5590               continue;
5591             }
5592           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5593             attribute);
5594           break;
5595         }
5596         case 'W':
5597         case 'w':
5598         {
5599           if (LocaleCompare(attribute,"width") == 0)
5600             {
5601               region.width=SvIV(ST(i));
5602               continue;
5603             }
5604           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5605             attribute);
5606           break;
5607         }
5608       }
5609     }
5610     blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5611       region.height,exception);
5612     if (blob != (void *) NULL)
5613       goto PerlEnd;
5614
5615   PerlException:
5616     InheritPerlException(exception,perl_exception);
5617     exception=DestroyExceptionInfo(exception);
5618     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5619
5620   PerlEnd:
5621     RETVAL = blob;
5622   }
5623   OUTPUT:
5624     RETVAL
5625 \f
5626 #
5627 ###############################################################################
5628 #                                                                             #
5629 #                                                                             #
5630 #                                                                             #
5631 #   G e t V i r t u a l P i x e l s                                           #
5632 #                                                                             #
5633 #                                                                             #
5634 #                                                                             #
5635 ###############################################################################
5636 #
5637 #
5638 void *
5639 GetVirtualPixels(ref,...)
5640   Image::Magick ref = NO_INIT
5641   ALIAS:
5642     getvirtualpixels = 1
5643     AcquireImagePixels = 2
5644     acquireimagepixels = 3
5645   CODE:
5646   {
5647     char
5648       *attribute;
5649
5650     const void
5651       *blob = NULL;
5652
5653     ExceptionInfo
5654       *exception;
5655
5656     Image
5657       *image;
5658
5659     RectangleInfo
5660       region;
5661
5662     ssize_t
5663       i;
5664
5665     struct PackageInfo
5666       *info;
5667
5668     SV
5669       *perl_exception,
5670       *reference;
5671
5672     PERL_UNUSED_VAR(ref);
5673     PERL_UNUSED_VAR(ix);
5674     exception=AcquireExceptionInfo();
5675     perl_exception=newSVpv("",0);
5676     if (sv_isobject(ST(0)) == 0)
5677       {
5678         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5679           PackageName);
5680         goto PerlException;
5681       }
5682     reference=SvRV(ST(0));
5683
5684     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5685     if (image == (Image *) NULL)
5686       {
5687         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5688           PackageName);
5689         goto PerlException;
5690       }
5691
5692     region.x=0;
5693     region.y=0;
5694     region.width=image->columns;
5695     region.height=1;
5696     if (items == 1)
5697       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5698     for (i=2; i < items; i+=2)
5699     {
5700       attribute=(char *) SvPV(ST(i-1),na);
5701       switch (*attribute)
5702       {
5703         case 'g':
5704         case 'G':
5705         {
5706           if (LocaleCompare(attribute,"geometry") == 0)
5707             {
5708               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5709               break;
5710             }
5711           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5712             attribute);
5713           break;
5714         }
5715         case 'H':
5716         case 'h':
5717         {
5718           if (LocaleCompare(attribute,"height") == 0)
5719             {
5720               region.height=SvIV(ST(i));
5721               continue;
5722             }
5723           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5724             attribute);
5725           break;
5726         }
5727         case 'X':
5728         case 'x':
5729         {
5730           if (LocaleCompare(attribute,"x") == 0)
5731             {
5732               region.x=SvIV(ST(i));
5733               continue;
5734             }
5735           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5736             attribute);
5737           break;
5738         }
5739         case 'Y':
5740         case 'y':
5741         {
5742           if (LocaleCompare(attribute,"y") == 0)
5743             {
5744               region.y=SvIV(ST(i));
5745               continue;
5746             }
5747           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5748             attribute);
5749           break;
5750         }
5751         case 'W':
5752         case 'w':
5753         {
5754           if (LocaleCompare(attribute,"width") == 0)
5755             {
5756               region.width=SvIV(ST(i));
5757               continue;
5758             }
5759           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5760             attribute);
5761           break;
5762         }
5763       }
5764     }
5765     blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
5766       region.height,exception);
5767     if (blob != (void *) NULL)
5768       goto PerlEnd;
5769
5770   PerlException:
5771     InheritPerlException(exception,perl_exception);
5772     exception=DestroyExceptionInfo(exception);
5773     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5774
5775   PerlEnd:
5776     RETVAL = (void *) blob;
5777   }
5778   OUTPUT:
5779     RETVAL
5780 \f
5781 #
5782 ###############################################################################
5783 #                                                                             #
5784 #                                                                             #
5785 #                                                                             #
5786 #   G e t A u t h e n t i c M e t a c o n t e n t                             #
5787 #                                                                             #
5788 #                                                                             #
5789 #                                                                             #
5790 ###############################################################################
5791 #
5792 #
5793 void *
5794 GetAuthenticMetacontent(ref,...)
5795   Image::Magick ref = NO_INIT
5796   ALIAS:
5797     getauthenticmetacontent = 1
5798     GetMetacontent = 2
5799     getmetacontent = 3
5800   CODE:
5801   {
5802     ExceptionInfo
5803       *exception;
5804
5805     Image
5806       *image;
5807
5808     struct PackageInfo
5809       *info;
5810
5811     SV
5812       *perl_exception,
5813       *reference;
5814
5815     void
5816       *blob = NULL;
5817
5818     PERL_UNUSED_VAR(ref);
5819     PERL_UNUSED_VAR(ix);
5820     exception=AcquireExceptionInfo();
5821     perl_exception=newSVpv("",0);
5822     if (sv_isobject(ST(0)) == 0)
5823       {
5824         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5825           PackageName);
5826         goto PerlException;
5827       }
5828     reference=SvRV(ST(0));
5829
5830     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5831     if (image == (Image *) NULL)
5832       {
5833         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5834           PackageName);
5835         goto PerlException;
5836       }
5837
5838     blob=(void *) GetAuthenticMetacontent(image);
5839     if (blob != (void *) NULL)
5840       goto PerlEnd;
5841
5842   PerlException:
5843     InheritPerlException(exception,perl_exception);
5844     exception=DestroyExceptionInfo(exception);
5845     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5846
5847   PerlEnd:
5848     RETVAL = blob;
5849   }
5850   OUTPUT:
5851     RETVAL
5852 \f
5853 #
5854 ###############################################################################
5855 #                                                                             #
5856 #                                                                             #
5857 #                                                                             #
5858 #   G e t V i r t u a l M e t a c o n t e n t                                 #
5859 #                                                                             #
5860 #                                                                             #
5861 #                                                                             #
5862 ###############################################################################
5863 #
5864 #
5865 void *
5866 GetVirtualMetacontent(ref,...)
5867   Image::Magick ref = NO_INIT
5868   ALIAS:
5869     getvirtualmetacontent = 1
5870   CODE:
5871   {
5872     ExceptionInfo
5873       *exception;
5874
5875     Image
5876       *image;
5877
5878     struct PackageInfo
5879       *info;
5880
5881     SV
5882       *perl_exception,
5883       *reference;
5884
5885     void
5886       *blob = NULL;
5887
5888     PERL_UNUSED_VAR(ref);
5889     PERL_UNUSED_VAR(ix);
5890     exception=AcquireExceptionInfo();
5891     perl_exception=newSVpv("",0);
5892     if (sv_isobject(ST(0)) == 0)
5893       {
5894         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5895           PackageName);
5896         goto PerlException;
5897       }
5898     reference=SvRV(ST(0));
5899
5900     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5901     if (image == (Image *) NULL)
5902       {
5903         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5904           PackageName);
5905         goto PerlException;
5906       }
5907
5908     blob=(void *) GetVirtualMetacontent(image);
5909     if (blob != (void *) NULL)
5910       goto PerlEnd;
5911
5912   PerlException:
5913     InheritPerlException(exception,perl_exception);
5914     exception=DestroyExceptionInfo(exception);
5915     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5916
5917   PerlEnd:
5918     RETVAL = blob;
5919   }
5920   OUTPUT:
5921     RETVAL
5922 \f
5923 #
5924 ###############################################################################
5925 #                                                                             #
5926 #                                                                             #
5927 #                                                                             #
5928 #   H i s t o g r a m                                                         #
5929 #                                                                             #
5930 #                                                                             #
5931 #                                                                             #
5932 ###############################################################################
5933 #
5934 #
5935 void
5936 Histogram(ref,...)
5937   Image::Magick ref=NO_INIT
5938   ALIAS:
5939     HistogramImage = 1
5940     histogram      = 2
5941     histogramimage = 3
5942   PPCODE:
5943   {
5944     AV
5945       *av;
5946
5947     char
5948       message[MaxTextExtent];
5949
5950     PixelInfo
5951       *histogram;
5952
5953     ExceptionInfo
5954       *exception;
5955
5956     Image
5957       *image;
5958
5959     register ssize_t
5960       i;
5961
5962     ssize_t
5963       count;
5964
5965     struct PackageInfo
5966       *info;
5967
5968     SV
5969       *perl_exception,
5970       *reference;
5971
5972     size_t
5973       number_colors;
5974
5975     PERL_UNUSED_VAR(ref);
5976     PERL_UNUSED_VAR(ix);
5977     exception=AcquireExceptionInfo();
5978     perl_exception=newSVpv("",0);
5979     av=NULL;
5980     if (sv_isobject(ST(0)) == 0)
5981       {
5982         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5983           PackageName);
5984         goto PerlException;
5985       }
5986     reference=SvRV(ST(0));
5987     av=newAV();
5988     SvREFCNT_dec(av);
5989     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5990     if (image == (Image *) NULL)
5991       {
5992         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5993           PackageName);
5994         goto PerlException;
5995       }
5996     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
5997     count=0;
5998     for ( ; image; image=image->next)
5999     {
6000       histogram=GetImageHistogram(image,&number_colors,&image->exception);
6001       if (histogram == (PixelInfo *) NULL)
6002         continue;
6003       count+=(ssize_t) number_colors;
6004       EXTEND(sp,6*count);
6005       for (i=0; i < (ssize_t) number_colors; i++)
6006       {
6007         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6008           histogram[i].red);
6009         PUSHs(sv_2mortal(newSVpv(message,0)));
6010         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6011           histogram[i].green);
6012         PUSHs(sv_2mortal(newSVpv(message,0)));
6013         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6014           histogram[i].blue);
6015         PUSHs(sv_2mortal(newSVpv(message,0)));
6016         if (image->colorspace == CMYKColorspace)
6017           {
6018             (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6019               histogram[i].black);
6020             PUSHs(sv_2mortal(newSVpv(message,0)));
6021           }
6022         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6023           histogram[i].alpha);
6024         PUSHs(sv_2mortal(newSVpv(message,0)));
6025         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
6026           histogram[i].count);
6027         PUSHs(sv_2mortal(newSVpv(message,0)));
6028       }
6029       histogram=(PixelInfo *) RelinquishMagickMemory(histogram);
6030     }
6031
6032   PerlException:
6033     InheritPerlException(exception,perl_exception);
6034     exception=DestroyExceptionInfo(exception);
6035     SvREFCNT_dec(perl_exception);
6036   }
6037 \f
6038 #
6039 ###############################################################################
6040 #                                                                             #
6041 #                                                                             #
6042 #                                                                             #
6043 #   G e t P i x e l                                                           #
6044 #                                                                             #
6045 #                                                                             #
6046 #                                                                             #
6047 ###############################################################################
6048 #
6049 #
6050 void
6051 GetPixel(ref,...)
6052   Image::Magick ref=NO_INIT
6053   ALIAS:
6054     getpixel = 1
6055     getPixel = 2
6056   PPCODE:
6057   {
6058     AV
6059       *av;
6060
6061     char
6062       *attribute;
6063
6064     ExceptionInfo
6065       *exception;
6066
6067     Image
6068       *image;
6069
6070     MagickBooleanType
6071       normalize;
6072
6073     RectangleInfo
6074       region;
6075
6076     register const Quantum
6077       *p;
6078
6079     register ssize_t
6080       i;
6081
6082     ssize_t
6083       option;
6084
6085     struct PackageInfo
6086       *info;
6087
6088     SV
6089       *perl_exception,
6090       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6091
6092     PERL_UNUSED_VAR(ref);
6093     PERL_UNUSED_VAR(ix);
6094     exception=AcquireExceptionInfo();
6095     perl_exception=newSVpv("",0);
6096     reference=SvRV(ST(0));
6097     av=(AV *) reference;
6098     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6099       exception);
6100     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6101     if (image == (Image *) NULL)
6102       {
6103         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6104           PackageName);
6105         goto PerlException;
6106       }
6107     normalize=MagickTrue;
6108     region.x=0;
6109     region.y=0;
6110     region.width=image->columns;
6111     region.height=1;
6112     if (items == 1)
6113       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6114     for (i=2; i < items; i+=2)
6115     {
6116       attribute=(char *) SvPV(ST(i-1),na);
6117       switch (*attribute)
6118       {
6119         case 'C':
6120         case 'c':
6121         {
6122           if (LocaleCompare(attribute,"channel") == 0)
6123             {
6124               ssize_t
6125                 option;
6126
6127               option=ParseChannelOption(SvPV(ST(i),na));
6128               if (option < 0)
6129                 {
6130                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6131                     SvPV(ST(i),na));
6132                   return;
6133                 }
6134               SetPixelChannelMap(image,(ChannelType) option);
6135               break;
6136             }
6137           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6138             attribute);
6139           break;
6140         }
6141         case 'g':
6142         case 'G':
6143         {
6144           if (LocaleCompare(attribute,"geometry") == 0)
6145             {
6146               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6147               break;
6148             }
6149           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6150             attribute);
6151           break;
6152         }
6153         case 'N':
6154         case 'n':
6155         {
6156           if (LocaleCompare(attribute,"normalize") == 0)
6157             {
6158               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6159                 SvPV(ST(i),na));
6160               if (option < 0)
6161                 {
6162                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6163                     SvPV(ST(i),na));
6164                   break;
6165                 }
6166              normalize=option != 0 ? MagickTrue : MagickFalse;
6167              break;
6168             }
6169           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6170             attribute);
6171           break;
6172         }
6173         case 'x':
6174         case 'X':
6175         {
6176           if (LocaleCompare(attribute,"x") == 0)
6177             {
6178               region.x=SvIV(ST(i));
6179               break;
6180             }
6181           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6182             attribute);
6183           break;
6184         }
6185         case 'y':
6186         case 'Y':
6187         {
6188           if (LocaleCompare(attribute,"y") == 0)
6189             {
6190               region.y=SvIV(ST(i));
6191               break;
6192             }
6193           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6194             attribute);
6195           break;
6196         }
6197         default:
6198         {
6199           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6200             attribute);
6201           break;
6202         }
6203       }
6204     }
6205     p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6206     if (p == (const Quantum *) NULL)
6207       PUSHs(&sv_undef);
6208     else
6209       {
6210         double
6211           scale;
6212
6213         scale=1.0;
6214         if (normalize != MagickFalse)
6215           scale=1.0/QuantumRange;
6216         if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
6217           PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6218         if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6219           PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6220         if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6221           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6222         if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6223             (image->colorspace == CMYKColorspace))
6224           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6225         if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
6226           PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6227       }
6228
6229   PerlException:
6230     InheritPerlException(exception,perl_exception);
6231     exception=DestroyExceptionInfo(exception);
6232     SvREFCNT_dec(perl_exception);
6233   }
6234 \f
6235 #
6236 ###############################################################################
6237 #                                                                             #
6238 #                                                                             #
6239 #                                                                             #
6240 #   G e t P i x e l s                                                         #
6241 #                                                                             #
6242 #                                                                             #
6243 #                                                                             #
6244 ###############################################################################
6245 #
6246 #
6247 void
6248 GetPixels(ref,...)
6249   Image::Magick ref=NO_INIT
6250   ALIAS:
6251     getpixels = 1
6252     getPixels = 2
6253   PPCODE:
6254   {
6255     AV
6256       *av;
6257
6258     char
6259       *attribute;
6260
6261     const char
6262       *map;
6263
6264     ExceptionInfo
6265       *exception;
6266
6267     Image
6268       *image;
6269
6270     MagickBooleanType
6271       normalize,
6272       status;
6273
6274     RectangleInfo
6275       region;
6276
6277     register ssize_t
6278       i;
6279
6280     ssize_t
6281       option;
6282
6283     struct PackageInfo
6284       *info;
6285
6286     SV
6287       *perl_exception,
6288       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6289
6290     PERL_UNUSED_VAR(ref);
6291     PERL_UNUSED_VAR(ix);
6292     exception=AcquireExceptionInfo();
6293     perl_exception=newSVpv("",0);
6294     reference=SvRV(ST(0));
6295     av=(AV *) reference;
6296     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6297       exception);
6298     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6299     if (image == (Image *) NULL)
6300       {
6301         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6302           PackageName);
6303         goto PerlException;
6304       }
6305     map="RGB";
6306     if (image->matte != MagickFalse)
6307       map="RGBA";
6308     if (image->colorspace == CMYKColorspace)
6309       {
6310         map="CMYK";
6311         if (image->matte != MagickFalse)
6312           map="CMYKA";
6313       }
6314     normalize=MagickFalse;
6315     region.x=0;
6316     region.y=0;
6317     region.width=image->columns;
6318     region.height=1;
6319     if (items == 1)
6320       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6321     for (i=2; i < items; i+=2)
6322     {
6323       attribute=(char *) SvPV(ST(i-1),na);
6324       switch (*attribute)
6325       {
6326         case 'g':
6327         case 'G':
6328         {
6329           if (LocaleCompare(attribute,"geometry") == 0)
6330             {
6331               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6332               break;
6333             }
6334           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6335             attribute);
6336           break;
6337         }
6338         case 'H':
6339         case 'h':
6340         {
6341           if (LocaleCompare(attribute,"height") == 0)
6342             {
6343               region.height=SvIV(ST(i));
6344               break;
6345             }
6346           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6347             attribute);
6348           break;
6349         }
6350         case 'M':
6351         case 'm':
6352         {
6353           if (LocaleCompare(attribute,"map") == 0)
6354             {
6355               map=SvPV(ST(i),na);
6356               break;
6357             }
6358           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6359             attribute);
6360           break;
6361         }
6362         case 'N':
6363         case 'n':
6364         {
6365           if (LocaleCompare(attribute,"normalize") == 0)
6366             {
6367               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6368                 SvPV(ST(i),na));
6369               if (option < 0)
6370                 {
6371                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6372                     SvPV(ST(i),na));
6373                   break;
6374                 }
6375              normalize=option != 0 ? MagickTrue : MagickFalse;
6376              break;
6377             }
6378           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6379             attribute);
6380           break;
6381         }
6382         case 'W':
6383         case 'w':
6384         {
6385           if (LocaleCompare(attribute,"width") == 0)
6386             {
6387               region.width=SvIV(ST(i));
6388               break;
6389             }
6390           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6391             attribute);
6392           break;
6393         }
6394         case 'x':
6395         case 'X':
6396         {
6397           if (LocaleCompare(attribute,"x") == 0)
6398             {
6399               region.x=SvIV(ST(i));
6400               break;
6401             }
6402           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6403             attribute);
6404           break;
6405         }
6406         case 'y':
6407         case 'Y':
6408         {
6409           if (LocaleCompare(attribute,"y") == 0)
6410             {
6411               region.y=SvIV(ST(i));
6412               break;
6413             }
6414           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6415             attribute);
6416           break;
6417         }
6418         default:
6419         {
6420           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6421             attribute);
6422           break;
6423         }
6424       }
6425     }
6426     if (normalize != MagickFalse)
6427       {
6428         float
6429           *pixels;
6430
6431         pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6432           region.height*sizeof(*pixels));
6433         if (pixels == (float *) NULL)
6434           {
6435             ThrowPerlException(exception,ResourceLimitError,
6436               "MemoryAllocationFailed",PackageName);
6437             goto PerlException;
6438           }
6439         status=ExportImagePixels(image,region.x,region.y,region.width,
6440           region.height,map,FloatPixel,pixels,exception);
6441         if (status == MagickFalse)
6442           PUSHs(&sv_undef);
6443         else
6444           {
6445             EXTEND(sp,strlen(map)*region.width*region.height);
6446             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6447               PUSHs(sv_2mortal(newSVnv(pixels[i])));
6448           }
6449         pixels=(float *) RelinquishMagickMemory(pixels);
6450       }
6451     else
6452       {
6453         Quantum
6454           *pixels;
6455
6456         pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6457           region.height*sizeof(*pixels));
6458         if (pixels == (Quantum *) NULL)
6459           {
6460             ThrowPerlException(exception,ResourceLimitError,
6461               "MemoryAllocationFailed",PackageName);
6462             goto PerlException;
6463           }
6464         status=ExportImagePixels(image,region.x,region.y,region.width,
6465           region.height,map,QuantumPixel,pixels,exception);
6466         if (status == MagickFalse)
6467           PUSHs(&sv_undef);
6468         else
6469           {
6470             EXTEND(sp,strlen(map)*region.width*region.height);
6471             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6472               PUSHs(sv_2mortal(newSViv(pixels[i])));
6473           }
6474         pixels=(Quantum *) RelinquishMagickMemory(pixels);
6475       }
6476
6477   PerlException:
6478     InheritPerlException(exception,perl_exception);
6479     exception=DestroyExceptionInfo(exception);
6480     SvREFCNT_dec(perl_exception);
6481   }
6482 \f
6483 #
6484 ###############################################################################
6485 #                                                                             #
6486 #                                                                             #
6487 #                                                                             #
6488 #   I m a g e T o B l o b                                                     #
6489 #                                                                             #
6490 #                                                                             #
6491 #                                                                             #
6492 ###############################################################################
6493 #
6494 #
6495 void
6496 ImageToBlob(ref,...)
6497   Image::Magick ref=NO_INIT
6498   ALIAS:
6499     ImageToBlob  = 1
6500     imagetoblob  = 2
6501     toblob       = 3
6502     blob         = 4
6503   PPCODE:
6504   {
6505     char
6506       filename[MaxTextExtent];
6507
6508     ExceptionInfo
6509       *exception;
6510
6511     Image
6512       *image,
6513       *next;
6514
6515     register ssize_t
6516       i;
6517
6518     struct PackageInfo
6519       *info,
6520       *package_info;
6521
6522     size_t
6523       length;
6524
6525     ssize_t
6526       scene;
6527
6528     SV
6529       *perl_exception,
6530       *reference;
6531
6532     void
6533       *blob;
6534
6535     PERL_UNUSED_VAR(ref);
6536     PERL_UNUSED_VAR(ix);
6537     exception=AcquireExceptionInfo();
6538     perl_exception=newSVpv("",0);
6539     package_info=(struct PackageInfo *) NULL;
6540     if (sv_isobject(ST(0)) == 0)
6541       {
6542         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6543           PackageName);
6544         goto PerlException;
6545       }
6546     reference=SvRV(ST(0));
6547     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6548     if (image == (Image *) NULL)
6549       {
6550         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6551           PackageName);
6552         goto PerlException;
6553       }
6554     package_info=ClonePackageInfo(info,exception);
6555     for (i=2; i < items; i+=2)
6556       SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6557     (void) CopyMagickString(filename,package_info->image_info->filename,
6558       MaxTextExtent);
6559     scene=0;
6560     for (next=image; next; next=next->next)
6561     {
6562       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
6563       next->scene=scene++;
6564     }
6565     SetImageInfo(package_info->image_info,(unsigned int)
6566       GetImageListLength(image),&image->exception);
6567     EXTEND(sp,(ssize_t) GetImageListLength(image));
6568     for ( ; image; image=image->next)
6569     {
6570       length=0;
6571       blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6572       if (blob != (char *) NULL)
6573         {
6574           PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6575           blob=(unsigned char *) RelinquishMagickMemory(blob);
6576         }
6577       if (package_info->image_info->adjoin)
6578         break;
6579     }
6580
6581   PerlException:
6582     if (package_info != (struct PackageInfo *) NULL)
6583       DestroyPackageInfo(package_info);
6584     InheritPerlException(exception,perl_exception);
6585     exception=DestroyExceptionInfo(exception);
6586     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6587   }
6588 \f
6589 #
6590 ###############################################################################
6591 #                                                                             #
6592 #                                                                             #
6593 #                                                                             #
6594 #   L a y e r s                                                               #
6595 #                                                                             #
6596 #                                                                             #
6597 #                                                                             #
6598 ###############################################################################
6599 #
6600 #
6601 void
6602 Layers(ref,...)
6603   Image::Magick ref=NO_INIT
6604   ALIAS:
6605     Layers                = 1
6606     layers           = 2
6607     OptimizeImageLayers   = 3
6608     optimizelayers        = 4
6609     optimizeimagelayers   = 5
6610   PPCODE:
6611   {
6612     AV
6613       *av;
6614
6615     char
6616       *attribute;
6617
6618     CompositeOperator
6619       compose;
6620
6621     ExceptionInfo
6622       *exception;
6623
6624     HV
6625       *hv;
6626
6627     Image
6628       *image,
6629       *layers;
6630
6631     ImageLayerMethod
6632       method;
6633
6634     register ssize_t
6635       i;
6636
6637     ssize_t
6638       option,
6639       sp;
6640
6641     struct PackageInfo
6642       *info;
6643
6644     SV
6645       *av_reference,
6646       *perl_exception,
6647       *reference,
6648       *rv,
6649       *sv;
6650
6651     PERL_UNUSED_VAR(ref);
6652     PERL_UNUSED_VAR(ix);
6653     exception=AcquireExceptionInfo();
6654     perl_exception=newSVpv("",0);
6655     sv=NULL;
6656     if (sv_isobject(ST(0)) == 0)
6657       {
6658         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6659           PackageName);
6660         goto PerlException;
6661       }
6662     reference=SvRV(ST(0));
6663     hv=SvSTASH(reference);
6664     av=newAV();
6665     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
6666     SvREFCNT_dec(av);
6667     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6668     if (image == (Image *) NULL)
6669       {
6670         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6671           PackageName);
6672         goto PerlException;
6673       }
6674     compose=image->compose;
6675     method=OptimizeLayer;
6676     for (i=2; i < items; i+=2)
6677     {
6678       attribute=(char *) SvPV(ST(i-1),na);
6679       switch (*attribute)
6680       {
6681         case 'C':
6682         case 'c':
6683         {
6684           if (LocaleCompare(attribute,"compose") == 0)
6685             {
6686               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
6687                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
6688               if (sp < 0)
6689                 {
6690                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6691                     SvPV(ST(i),na));
6692                   break;
6693                 }
6694               compose=(CompositeOperator) sp;
6695               break;
6696             }
6697           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6698             attribute);
6699           break;
6700         }
6701         case 'M':
6702         case 'm':
6703         {
6704           if (LocaleCompare(attribute,"method") == 0)
6705             {
6706               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
6707                 SvPV(ST(i),na));
6708               if (option < 0)
6709                 {
6710                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6711                     SvPV(ST(i),na));
6712                   break;
6713                 }
6714               method=(ImageLayerMethod) option;
6715               break;
6716             }
6717           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6718             attribute);
6719           break;
6720         }
6721         default:
6722         {
6723           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6724             attribute);
6725           break;
6726         }
6727       }
6728     }
6729     layers=(Image *) NULL;
6730     switch (method)
6731     {
6732       case CompareAnyLayer:
6733       case CompareClearLayer:
6734       case CompareOverlayLayer:
6735       default:
6736       {
6737         layers=CompareImagesLayers(image,method,exception);
6738         break;
6739       }
6740       case MergeLayer:
6741       case FlattenLayer:
6742       case MosaicLayer:
6743       {
6744         layers=MergeImageLayers(image,method,exception);
6745         break;
6746       }
6747       case DisposeLayer:
6748       {
6749         layers=DisposeImages(image,exception);
6750         break;
6751       }
6752       case OptimizeImageLayer:
6753       {
6754         layers=OptimizeImageLayers(image,exception);
6755         break;
6756       }
6757       case OptimizePlusLayer:
6758       {
6759         layers=OptimizePlusImageLayers(image,exception);
6760         break;
6761       }
6762       case OptimizeTransLayer:
6763       {
6764         OptimizeImageTransparency(image,exception);
6765         InheritException(&(image->exception),exception);
6766         break;
6767       }
6768       case RemoveDupsLayer:
6769       {
6770         RemoveDuplicateLayers(&image,exception);
6771         InheritException(&(image->exception),exception);
6772         break;
6773       }
6774       case RemoveZeroLayer:
6775       {
6776         RemoveZeroDelayLayers(&image,exception);
6777         InheritException(&(image->exception),exception);
6778         break;
6779       }
6780       case OptimizeLayer:
6781       {
6782         QuantizeInfo
6783           *quantize_info;
6784
6785         /*
6786           General Purpose, GIF Animation Optimizer.
6787         */
6788         layers=CoalesceImages(image,exception);
6789         if (layers == (Image *) NULL)
6790           break;
6791         InheritException(&(layers->exception),exception);
6792         image=layers;
6793         layers=OptimizeImageLayers(image,exception);
6794         if (layers == (Image *) NULL)
6795           break;
6796         InheritException(&(layers->exception),exception);
6797         image=DestroyImageList(image);
6798         image=layers;
6799         layers=(Image *) NULL;
6800         OptimizeImageTransparency(image,exception);
6801         InheritException(&(image->exception),exception);
6802         quantize_info=AcquireQuantizeInfo(info->image_info);
6803         (void) RemapImages(quantize_info,image,(Image *) NULL,exception);
6804         quantize_info=DestroyQuantizeInfo(quantize_info);
6805         break;
6806       }
6807       case CompositeLayer:
6808       {
6809         Image
6810           *source;
6811
6812         RectangleInfo
6813           geometry;
6814
6815         /*
6816           Split image sequence at the first 'NULL:' image.
6817         */
6818         source=image;
6819         while (source != (Image *) NULL)
6820         {
6821           source=GetNextImageInList(source);
6822           if ((source != (Image *) NULL) &&
6823               (LocaleCompare(source->magick,"NULL") == 0))
6824             break;
6825         }
6826         if (source != (Image *) NULL)
6827           {
6828             if ((GetPreviousImageInList(source) == (Image *) NULL) ||
6829                 (GetNextImageInList(source) == (Image *) NULL))
6830               source=(Image *) NULL;
6831             else
6832               {
6833                 /*
6834                   Separate the two lists, junk the null: image.
6835                 */
6836                 source=SplitImageList(source->previous);
6837                 DeleteImageFromList(&source);
6838               }
6839           }
6840         if (source == (Image *) NULL)
6841           {
6842             (void) ThrowMagickException(exception,GetMagickModule(),
6843               OptionError,"MissingNullSeparator","layers Composite");
6844             break;
6845           }
6846         /*
6847           Adjust offset with gravity and virtual canvas.
6848         */
6849         SetGeometry(image,&geometry);
6850         (void) ParseAbsoluteGeometry(image->geometry,&geometry);
6851         geometry.width=source->page.width != 0 ? source->page.width :
6852           source->columns;
6853         geometry.height=source->page.height != 0 ? source->page.height :
6854           source->rows;
6855         GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
6856           image->columns,image->page.height != 0 ? image->page.height :
6857           image->rows,image->gravity,&geometry);
6858         CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
6859         source=DestroyImageList(source);
6860         InheritException(&(image->exception),exception);
6861         break;
6862       }
6863     }
6864     if (layers != (Image *) NULL)
6865       {
6866         InheritException(&(layers->exception),exception);
6867         image=layers;
6868       }
6869     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
6870       goto PerlException;
6871     for ( ; image; image=image->next)
6872     {
6873       AddImageToRegistry(sv,image);
6874       rv=newRV(sv);
6875       av_push(av,sv_bless(rv,hv));
6876       SvREFCNT_dec(sv);
6877     }
6878     exception=DestroyExceptionInfo(exception);
6879     ST(0)=av_reference;
6880     SvREFCNT_dec(perl_exception);
6881     XSRETURN(1);
6882
6883   PerlException:
6884     InheritPerlException(exception,perl_exception);
6885     exception=DestroyExceptionInfo(exception);
6886     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
6887     SvPOK_on(perl_exception);
6888     ST(0)=sv_2mortal(perl_exception);
6889     XSRETURN(1);
6890   }
6891 \f
6892 #
6893 ###############################################################################
6894 #                                                                             #
6895 #                                                                             #
6896 #                                                                             #
6897 #   M a g i c k T o M i m e                                                   #
6898 #                                                                             #
6899 #                                                                             #
6900 #                                                                             #
6901 ###############################################################################
6902 #
6903 #
6904 SV *
6905 MagickToMime(ref,name)
6906   Image::Magick ref=NO_INIT
6907   char *name
6908   ALIAS:
6909     magicktomime = 1
6910   CODE:
6911   {
6912     char
6913       *mime;
6914
6915     PERL_UNUSED_VAR(ref);
6916     PERL_UNUSED_VAR(ix);
6917     mime=MagickToMime(name);
6918     RETVAL=newSVpv(mime,0);
6919     mime=(char *) RelinquishMagickMemory(mime);
6920   }
6921   OUTPUT:
6922     RETVAL
6923 \f
6924 #
6925 ###############################################################################
6926 #                                                                             #
6927 #                                                                             #
6928 #                                                                             #
6929 #   M o g r i f y                                                             #
6930 #                                                                             #
6931 #                                                                             #
6932 #                                                                             #
6933 ###############################################################################
6934 #
6935 #
6936 void
6937 Mogrify(ref,...)
6938   Image::Magick ref=NO_INIT
6939   ALIAS:
6940     Comment            =   1
6941     CommentImage       =   2
6942     Label              =   3
6943     LabelImage         =   4
6944     AddNoise           =   5
6945     AddNoiseImage      =   6
6946     Colorize           =   7
6947     ColorizeImage      =   8
6948     Border             =   9
6949     BorderImage        =  10
6950     Blur               =  11
6951     BlurImage          =  12
6952     Chop               =  13
6953     ChopImage          =  14
6954     Crop               =  15
6955     CropImage          =  16
6956     Despeckle          =  17
6957     DespeckleImage     =  18
6958     Edge               =  19
6959     EdgeImage          =  20
6960     Emboss             =  21
6961     EmbossImage        =  22
6962     Enhance            =  23
6963     EnhanceImage       =  24
6964     Flip               =  25
6965     FlipImage          =  26
6966     Flop               =  27
6967     FlopImage          =  28
6968     Frame              =  29
6969     FrameImage         =  30
6970     Implode            =  31
6971     ImplodeImage       =  32
6972     Magnify            =  33
6973     MagnifyImage       =  34
6974     MedianFilter       =  35
6975     MedianConvolveImage  =  36
6976     Minify             =  37
6977     MinifyImage        =  38
6978     OilPaint           =  39
6979     OilPaintImage      =  40
6980     ReduceNoise        =  41
6981     ReduceNoiseImage   =  42
6982     Roll               =  43
6983     RollImage          =  44
6984     Rotate             =  45
6985     RotateImage        =  46
6986     Sample             =  47
6987     SampleImage        =  48
6988     Scale              =  49
6989     ScaleImage         =  50
6990     Shade              =  51
6991     ShadeImage         =  52
6992     Sharpen            =  53
6993     SharpenImage       =  54
6994     Shear              =  55
6995     ShearImage         =  56
6996     Spread             =  57
6997     SpreadImage        =  58
6998     Swirl              =  59
6999     SwirlImage         =  60
7000     Resize             =  61
7001     ResizeImage        =  62
7002     Zoom               =  63
7003     ZoomImage          =  64
7004     Annotate           =  65
7005     AnnotateImage      =  66
7006     ColorFloodfill     =  67
7007     ColorFloodfillImage=  68
7008     Composite          =  69
7009     CompositeImage     =  70
7010     Contrast           =  71
7011     ContrastImage      =  72
7012     CycleColormap      =  73
7013     CycleColormapImage =  74
7014     Draw               =  75
7015     DrawImage          =  76
7016     Equalize           =  77
7017     EqualizeImage      =  78
7018     Gamma              =  79
7019     GammaImage         =  80
7020     Map                =  81
7021     MapImage           =  82
7022     MatteFloodfill     =  83
7023     MatteFloodfillImage=  84
7024     Modulate           =  85
7025     ModulateImage      =  86
7026     Negate             =  87
7027     NegateImage        =  88
7028     Normalize          =  89
7029     NormalizeImage     =  90
7030     NumberColors       =  91
7031     NumberColorsImage  =  92
7032     Opaque             =  93
7033     OpaqueImage        =  94
7034     Quantize           =  95
7035     QuantizeImage      =  96
7036     Raise              =  97
7037     RaiseImage         =  98
7038     Segment            =  99
7039     SegmentImage       = 100
7040     Signature          = 101
7041     SignatureImage     = 102
7042     Solarize           = 103
7043     SolarizeImage      = 104
7044     Sync               = 105
7045     SyncImage          = 106
7046     Texture            = 107
7047     TextureImage       = 108
7048     Evaluate           = 109
7049     EvaluateImage      = 110
7050     Transparent        = 111
7051     TransparentImage   = 112
7052     Threshold          = 113
7053     ThresholdImage     = 114
7054     Charcoal           = 115
7055     CharcoalImage      = 116
7056     Trim               = 117
7057     TrimImage          = 118
7058     Wave               = 119
7059     WaveImage          = 120
7060     Separate           = 121
7061     SeparateImage      = 122
7062     Stereo             = 125
7063     StereoImage        = 126
7064     Stegano            = 127
7065     SteganoImage       = 128
7066     Deconstruct        = 129
7067     DeconstructImage   = 130
7068     GaussianBlur       = 131
7069     GaussianBlurImage  = 132
7070     Convolve           = 133
7071     ConvolveImage      = 134
7072     Profile            = 135
7073     ProfileImage       = 136
7074     UnsharpMask        = 137
7075     UnsharpMaskImage   = 138
7076     MotionBlur         = 139
7077     MotionBlurImage    = 140
7078     OrderedDither      = 141
7079     OrderedDitherImage = 142
7080     Shave              = 143
7081     ShaveImage         = 144
7082     Level              = 145
7083     LevelImage         = 146
7084     Clip               = 147
7085     ClipImage          = 148
7086     AffineTransform    = 149
7087     AffineTransformImage = 150
7088     Difference         = 151
7089     DifferenceImage    = 152
7090     AdaptiveThreshold  = 153
7091     AdaptiveThresholdImage = 154
7092     Resample           = 155
7093     ResampleImage      = 156
7094     Describe           = 157
7095     DescribeImage      = 158
7096     BlackThreshold     = 159
7097     BlackThresholdImage= 160
7098     WhiteThreshold     = 161
7099     WhiteThresholdImage= 162
7100     RadialBlur         = 163
7101     RadialBlurImage    = 164
7102     Thumbnail          = 165
7103     ThumbnailImage     = 166
7104     Strip              = 167
7105     StripImage         = 168
7106     Tint               = 169
7107     TintImage          = 170
7108     Channel            = 171
7109     ChannelImage       = 172
7110     Splice             = 173
7111     SpliceImage        = 174
7112     Posterize          = 175
7113     PosterizeImage     = 176
7114     Shadow             = 177
7115     ShadowImage        = 178
7116     Identify           = 179
7117     IdentifyImage      = 180
7118     SepiaTone          = 181
7119     SepiaToneImage     = 182
7120     SigmoidalContrast  = 183
7121     SigmoidalContrastImage = 184
7122     Extent             = 185
7123     ExtentImage        = 186
7124     Vignette           = 187
7125     VignetteImage      = 188
7126     ContrastStretch    = 189
7127     ContrastStretchImage = 190
7128     Sans0              = 191
7129     Sans0Image         = 192
7130     Sans1              = 193
7131     Sans1Image         = 194
7132     AdaptiveSharpen    = 195
7133     AdaptiveSharpenImage = 196
7134     Transpose          = 197
7135     TransposeImage     = 198
7136     Transverse         = 199
7137     TransverseImage    = 200
7138     AutoOrient         = 201
7139     AutoOrientImage    = 202
7140     AdaptiveBlur       = 203
7141     AdaptiveBlurImage  = 204
7142     Sketch             = 205
7143     SketchImage        = 206
7144     UniqueColors       = 207
7145     UniqueColorsImage  = 208
7146     AdaptiveResize     = 209
7147     AdaptiveResizeImage= 210
7148     ClipMask           = 211
7149     ClipMaskImage      = 212
7150     LinearStretch      = 213
7151     LinearStretchImage = 214
7152     RecolorImage       = 215
7153     Recolor            = 216
7154     Mask               = 217
7155     MaskImage          = 218
7156     Polaroid           = 219
7157     PolaroidImage      = 220
7158     FloodfillPaint     = 221
7159     FloodfillPaintImage= 222
7160     Distort            = 223
7161     DistortImage       = 224
7162     Clut               = 225
7163     ClutImage          = 226
7164     LiquidRescale      = 227
7165     LiquidRescaleImage = 228
7166     Encipher           = 229
7167     EncipherImage      = 230
7168     Decipher           = 231
7169     DecipherImage      = 232
7170     Deskew             = 233
7171     DeskewImage        = 234
7172     Remap              = 235
7173     RemapImage         = 236
7174     SparseColor        = 237
7175     SparseColorImage   = 238
7176     Function           = 239
7177     FunctionImage      = 240
7178     SelectiveBlur      = 241
7179     SelectiveBlurImage = 242
7180     HaldClut           = 243
7181     HaldClutImage      = 244
7182     BlueShift          = 245
7183     BlueShiftImage     = 246
7184     ForwardFourierTransform  = 247
7185     ForwardFourierTransformImage = 248
7186     InverseFourierTransform = 249
7187     InverseFourierTransformImage = 250
7188     ColorDecisionList  = 251
7189     ColorDecisionListImage = 252
7190     AutoGamma          = 253
7191     AutoGammaImage     = 254
7192     AutoLevel          = 255
7193     AutoLevelImage     = 256
7194     LevelColors        = 257
7195     LevelImageColors   = 258
7196     Clamp              = 259
7197     ClampImage         = 260
7198     BrightnessContrast = 263
7199     BrightnessContrastImage = 264
7200     Morphology         = 265
7201     MorphologyImage    = 266
7202     ColorMatrix        = 267
7203     ColorMatrixImage   = 268
7204     Color              = 269
7205     ColorImage         = 270
7206     Mode               = 271
7207     ModeImage          = 272
7208     Statistic          = 273
7209     StatisticImage     = 274
7210     MogrifyRegion      = 666
7211   PPCODE:
7212   {
7213     AffineMatrix
7214       affine,
7215       current;
7216
7217     char
7218       attribute_flag[MaxArguments],
7219       message[MaxTextExtent];
7220
7221     ChannelType
7222       channel,
7223       channel_mask;
7224
7225     CompositeOperator
7226       compose;
7227
7228     const char
7229       *attribute,
7230       *value;
7231
7232     double
7233       angle;
7234
7235     ExceptionInfo
7236       *exception;
7237
7238     GeometryInfo
7239       geometry_info;
7240
7241     Image
7242       *image,
7243       *next,
7244       *region_image;
7245
7246     MagickBooleanType
7247       status;
7248
7249     MagickStatusType
7250       flags;
7251
7252     PixelInfo
7253       fill_color;
7254
7255     RectangleInfo
7256       geometry,
7257       region_info;
7258
7259     register ssize_t
7260       i;
7261
7262     ssize_t
7263       base,
7264       j,
7265       number_images;
7266
7267     struct Methods
7268       *rp;
7269
7270     struct PackageInfo
7271       *info;
7272
7273     SV
7274       *perl_exception,
7275       **pv,
7276       *reference,
7277       **reference_vector;
7278
7279     struct ArgumentList
7280       argument_list[MaxArguments];
7281
7282     PERL_UNUSED_VAR(ref);
7283     PERL_UNUSED_VAR(ix);
7284     exception=AcquireExceptionInfo();
7285     perl_exception=newSVpv("",0);
7286     reference_vector=NULL;
7287     region_image=NULL;
7288     number_images=0;
7289     base=2;
7290     if (sv_isobject(ST(0)) == 0)
7291       {
7292         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7293           PackageName);
7294         goto PerlException;
7295       }
7296     reference=SvRV(ST(0));
7297     region_info.width=0;
7298     region_info.height=0;
7299     region_info.x=0;
7300     region_info.y=0;
7301     region_image=(Image *) NULL;
7302     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7303     if (ix && (ix != 666))
7304       {
7305         /*
7306           Called as Method(...)
7307         */
7308         ix=(ix+1)/2;
7309         rp=(&Methods[ix-1]);
7310         attribute=rp->name;
7311       }
7312     else
7313       {
7314         /*
7315           Called as Mogrify("Method",...)
7316         */
7317         attribute=(char *) SvPV(ST(1),na);
7318         if (ix)
7319           {
7320             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7321             attribute=(char *) SvPV(ST(2),na);
7322             base++;
7323           }
7324         for (rp=Methods; ; rp++)
7325         {
7326           if (rp >= EndOf(Methods))
7327             {
7328               ThrowPerlException(exception,OptionError,
7329                 "UnrecognizedPerlMagickMethod",attribute);
7330               goto PerlException;
7331             }
7332           if (strEQcase(attribute,rp->name))
7333             break;
7334         }
7335         ix=rp-Methods+1;
7336         base++;
7337       }
7338     if (image == (Image *) NULL)
7339       {
7340         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7341         goto PerlException;
7342       }
7343     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7344     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7345     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7346     {
7347       Arguments
7348         *pp,
7349         *qq;
7350
7351       ssize_t
7352         ssize_test;
7353
7354       struct ArgumentList
7355         *al;
7356
7357       SV
7358         *sv;
7359
7360       sv=NULL;
7361       ssize_test=0;
7362       pp=(Arguments *) NULL;
7363       qq=rp->arguments;
7364       if (i == items)
7365         {
7366           pp=rp->arguments,
7367           sv=ST(i-1);
7368         }
7369       else
7370         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7371         {
7372           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7373             break;
7374           if (strEQcase(attribute,qq->method) > ssize_test)
7375             {
7376               pp=qq;
7377               ssize_test=strEQcase(attribute,qq->method);
7378             }
7379         }
7380       if (pp == (Arguments *) NULL)
7381         {
7382           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7383             attribute);
7384           goto continue_outer_loop;
7385         }
7386       al=(&argument_list[pp-rp->arguments]);
7387       switch (pp->type)
7388       {
7389         case ArrayReference:
7390         {
7391           if (SvTYPE(sv) != SVt_RV)
7392             {
7393               (void) FormatLocaleString(message,MaxTextExtent,
7394                 "invalid %.60s value",pp->method);
7395               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7396               goto continue_outer_loop;
7397             }
7398           al->array_reference=SvRV(sv);
7399           break;
7400         }
7401         case RealReference:
7402         {
7403           al->real_reference=SvNV(sv);
7404           break;
7405         }
7406         case FileReference:
7407         {
7408           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7409           break;
7410         }
7411         case ImageReference:
7412         {
7413           if (!sv_isobject(sv) ||
7414               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7415                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7416             {
7417               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7418                 PackageName);
7419               goto PerlException;
7420             }
7421           break;
7422         }
7423         case IntegerReference:
7424         {
7425           al->integer_reference=SvIV(sv);
7426           break;
7427         }
7428         case StringReference:
7429         {
7430           al->string_reference=(char *) SvPV(sv,al->length);
7431           if (sv_isobject(sv))
7432             al->image_reference=SetupList(aTHX_ SvRV(sv),
7433               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7434           break;
7435         }
7436         default:
7437         {
7438           /*
7439             Is a string; look up name.
7440           */
7441           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7442             {
7443               al->string_reference=(char *) SvPV(sv,al->length);
7444               al->integer_reference=(-1);
7445               break;
7446             }
7447           al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7448             MagickFalse,SvPV(sv,na));
7449           if (pp->type == MagickChannelOptions)
7450             al->integer_reference=ParseChannelOption(SvPV(sv,na));
7451           if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7452             {
7453               (void) FormatLocaleString(message,MaxTextExtent,
7454                 "invalid %.60s value",pp->method);
7455               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7456               goto continue_outer_loop;
7457             }
7458           break;
7459         }
7460       }
7461       attribute_flag[pp-rp->arguments]++;
7462       continue_outer_loop: ;
7463     }
7464     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7465     pv=reference_vector;
7466     SetGeometryInfo(&geometry_info);
7467     channel=DefaultChannels;
7468     for (next=image; next; next=next->next)
7469     {
7470       image=next;
7471       SetGeometry(image,&geometry);
7472       if ((region_info.width*region_info.height) != 0)
7473         {
7474           region_image=image;
7475           image=CropImage(image,&region_info,exception);
7476         }
7477       switch (ix)
7478       {
7479         default:
7480         {
7481           (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double) ix);
7482           ThrowPerlException(exception,OptionError,
7483             "UnrecognizedPerlMagickMethod",message);
7484           goto PerlException;
7485         }
7486         case 1:  /* Comment */
7487         {
7488           if (attribute_flag[0] == 0)
7489             argument_list[0].string_reference=(char *) NULL;
7490           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7491             info ? info->image_info : (ImageInfo *) NULL,image,
7492             argument_list[0].string_reference,exception),exception);
7493           break;
7494         }
7495         case 2:  /* Label */
7496         {
7497           if (attribute_flag[0] == 0)
7498             argument_list[0].string_reference=(char *) NULL;
7499           (void) SetImageProperty(image,"label",InterpretImageProperties(
7500             info ? info->image_info : (ImageInfo *) NULL,image,
7501             argument_list[0].string_reference,exception),exception);
7502           break;
7503         }
7504         case 3:  /* AddNoise */
7505         {
7506           double
7507             attenuate;
7508
7509           if (attribute_flag[0] == 0)
7510             argument_list[0].integer_reference=UniformNoise;
7511           attenuate=1.0;
7512           if (attribute_flag[1] != 0)
7513             attenuate=argument_list[1].real_reference;
7514           if (attribute_flag[2] != 0)
7515             channel=(ChannelType) argument_list[2].integer_reference;
7516           channel_mask=SetPixelChannelMask(image,channel);
7517           image=AddNoiseImage(image,(NoiseType)
7518             argument_list[0].integer_reference,attenuate,exception);
7519           if (image != (Image *) NULL)
7520             (void) SetPixelChannelMask(image,channel_mask);
7521           break;
7522         }
7523         case 4:  /* Colorize */
7524         {
7525           PixelInfo
7526             target;
7527
7528           Quantum
7529             virtual_pixel[MaxPixelChannels];
7530
7531           GetPixelInfo(image,&target);
7532           (void) GetOneVirtualPixel(image,0,0,virtual_pixel,exception);
7533           target.red=virtual_pixel[RedPixelChannel];
7534           target.green=virtual_pixel[GreenPixelChannel];
7535           target.blue=virtual_pixel[BluePixelChannel];
7536           target.alpha=virtual_pixel[AlphaPixelChannel];
7537           if (attribute_flag[0] != 0)
7538             (void) QueryColorCompliance(argument_list[0].string_reference,
7539               AllCompliance,&target,exception);
7540           if (attribute_flag[1] == 0)
7541             argument_list[1].string_reference="100%";
7542           image=ColorizeImage(image,argument_list[1].string_reference,&target,
7543             exception);
7544           break;
7545         }
7546         case 5:  /* Border */
7547         {
7548           CompositeOperator
7549             compose;
7550
7551           geometry.width=0;
7552           geometry.height=0;
7553           if (attribute_flag[0] != 0)
7554             {
7555               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7556                 &geometry,exception);
7557               if ((flags & HeightValue) == 0)
7558                 geometry.height=geometry.width;
7559             }
7560           if (attribute_flag[1] != 0)
7561             geometry.width=argument_list[1].integer_reference;
7562           if (attribute_flag[2] != 0)
7563             geometry.height=argument_list[2].integer_reference;
7564           if (attribute_flag[3] != 0)
7565             QueryColorCompliance(argument_list[3].string_reference,
7566               AllCompliance,&image->border_color,exception);
7567           if (attribute_flag[4] != 0)
7568             QueryColorCompliance(argument_list[4].string_reference,
7569               AllCompliance,&image->border_color,exception);
7570           if (attribute_flag[5] != 0)
7571             QueryColorCompliance(argument_list[5].string_reference,
7572               AllCompliance,&image->border_color,exception);
7573           compose=image->compose;
7574           if (attribute_flag[6] != 0)
7575             compose=(CompositeOperator) argument_list[6].integer_reference;
7576           image=BorderImage(image,&geometry,compose,exception);
7577           break;
7578         }
7579         case 6:  /* Blur */
7580         {
7581           if (attribute_flag[0] != 0)
7582             {
7583               flags=ParseGeometry(argument_list[0].string_reference,
7584                 &geometry_info);
7585               if ((flags & SigmaValue) == 0)
7586                 geometry_info.sigma=1.0;
7587             }
7588           if (attribute_flag[1] != 0)
7589             geometry_info.rho=argument_list[1].real_reference;
7590           if (attribute_flag[2] != 0)
7591             geometry_info.sigma=argument_list[2].real_reference;
7592           if (attribute_flag[3] != 0)
7593             geometry_info.xi=argument_list[3].real_reference;
7594           if (attribute_flag[4] != 0)
7595             channel=(ChannelType) argument_list[4].integer_reference;
7596           channel_mask=SetPixelChannelMask(image,channel);
7597           image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
7598             geometry_info.xi,exception);
7599           if (image != (Image *) NULL)
7600             (void) SetPixelChannelMask(image,channel_mask);
7601           break;
7602         }
7603         case 7:  /* Chop */
7604         {
7605           if (attribute_flag[0] != 0)
7606             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7607               &geometry,exception);
7608           if (attribute_flag[1] != 0)
7609             geometry.width=argument_list[1].integer_reference;
7610           if (attribute_flag[2] != 0)
7611             geometry.height=argument_list[2].integer_reference;
7612           if (attribute_flag[3] != 0)
7613             geometry.x=argument_list[3].integer_reference;
7614           if (attribute_flag[4] != 0)
7615             geometry.y=argument_list[4].integer_reference;
7616           image=ChopImage(image,&geometry,exception);
7617           break;
7618         }
7619         case 8:  /* Crop */
7620         {
7621           if (attribute_flag[6] != 0)
7622             image->gravity=(GravityType) argument_list[6].integer_reference;
7623           if (attribute_flag[0] != 0)
7624             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7625               &geometry,exception);
7626           if (attribute_flag[1] != 0)
7627             geometry.width=argument_list[1].integer_reference;
7628           if (attribute_flag[2] != 0)
7629             geometry.height=argument_list[2].integer_reference;
7630           if (attribute_flag[3] != 0)
7631             geometry.x=argument_list[3].integer_reference;
7632           if (attribute_flag[4] != 0)
7633             geometry.y=argument_list[4].integer_reference;
7634           if (attribute_flag[5] != 0)
7635             image->fuzz=
7636               SiPrefixToDouble(argument_list[5].string_reference,QuantumRange);
7637           image=CropImage(image,&geometry,exception);
7638           break;
7639         }
7640         case 9:  /* Despeckle */
7641         {
7642           image=DespeckleImage(image,exception);
7643           break;
7644         }
7645         case 10:  /* Edge */
7646         {
7647           if (attribute_flag[0] != 0)
7648             geometry_info.rho=argument_list[0].real_reference;
7649           image=EdgeImage(image,geometry_info.rho,geometry_info.sigma,
7650             exception);
7651           break;
7652         }
7653         case 11:  /* Emboss */
7654         {
7655           if (attribute_flag[0] != 0)
7656             {
7657               flags=ParseGeometry(argument_list[0].string_reference,
7658                 &geometry_info);
7659               if ((flags & SigmaValue) == 0)
7660                 geometry_info.sigma=1.0;
7661             }
7662           if (attribute_flag[1] != 0)
7663             geometry_info.rho=argument_list[1].real_reference;
7664           if (attribute_flag[2] != 0)
7665             geometry_info.sigma=argument_list[2].real_reference;
7666           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
7667             exception);
7668           break;
7669         }
7670         case 12:  /* Enhance */
7671         {
7672           image=EnhanceImage(image,exception);
7673           break;
7674         }
7675         case 13:  /* Flip */
7676         {
7677           image=FlipImage(image,exception);
7678           break;
7679         }
7680         case 14:  /* Flop */
7681         {
7682           image=FlopImage(image,exception);
7683           break;
7684         }
7685         case 15:  /* Frame */
7686         {
7687           CompositeOperator
7688             compose;
7689
7690           FrameInfo
7691             frame_info;
7692
7693           if (attribute_flag[0] != 0)
7694             {
7695               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7696                 &geometry,exception);
7697               if ((flags & HeightValue) == 0)
7698                 geometry.height=geometry.width;
7699               frame_info.width=geometry.width;
7700               frame_info.height=geometry.height;
7701               frame_info.outer_bevel=geometry.x;
7702               frame_info.inner_bevel=geometry.y;
7703             }
7704           if (attribute_flag[1] != 0)
7705             frame_info.width=argument_list[1].integer_reference;
7706           if (attribute_flag[2] != 0)
7707             frame_info.height=argument_list[2].integer_reference;
7708           if (attribute_flag[3] != 0)
7709             frame_info.inner_bevel=argument_list[3].integer_reference;
7710           if (attribute_flag[4] != 0)
7711             frame_info.outer_bevel=argument_list[4].integer_reference;
7712           if (attribute_flag[5] != 0)
7713             QueryColorCompliance(argument_list[5].string_reference,
7714               AllCompliance,&fill_color,exception);
7715           if (attribute_flag[6] != 0)
7716             QueryColorCompliance(argument_list[6].string_reference,
7717               AllCompliance,&fill_color,exception);
7718           frame_info.x=(ssize_t) frame_info.width;
7719           frame_info.y=(ssize_t) frame_info.height;
7720           frame_info.width=image->columns+2*frame_info.x;
7721           frame_info.height=image->rows+2*frame_info.y;
7722           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
7723             image->matte_color=fill_color;
7724           compose=image->compose;
7725           if (attribute_flag[7] != 0)
7726             compose=(CompositeOperator) argument_list[7].integer_reference;
7727           image=FrameImage(image,&frame_info,compose,exception);
7728           break;
7729         }
7730         case 16:  /* Implode */
7731         {
7732           PixelInterpolateMethod
7733             method;
7734
7735           if (attribute_flag[0] == 0)
7736             argument_list[0].real_reference=0.5;
7737           method=UndefinedInterpolatePixel;
7738           if (attribute_flag[1] != 0)
7739             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
7740           image=ImplodeImage(image,argument_list[0].real_reference,
7741             method,exception);
7742           break;
7743         }
7744         case 17:  /* Magnify */
7745         {
7746           image=MagnifyImage(image,exception);
7747           break;
7748         }
7749         case 18:  /* MedianFilter */
7750         {
7751           if (attribute_flag[0] != 0)
7752             {
7753               flags=ParseGeometry(argument_list[0].string_reference,
7754                 &geometry_info);
7755               if ((flags & SigmaValue) == 0)
7756                 geometry_info.sigma=geometry_info.rho;
7757             }
7758           if (attribute_flag[1] != 0)
7759             geometry_info.rho=argument_list[1].real_reference;
7760           if (attribute_flag[2] != 0)
7761             geometry_info.sigma=argument_list[2].real_reference;
7762           if (attribute_flag[3] != 0)
7763             channel=(ChannelType) argument_list[3].integer_reference;
7764           channel_mask=SetPixelChannelMask(image,channel);
7765           image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
7766             (size_t) geometry_info.sigma,exception);
7767           if (image != (Image *) NULL)
7768             (void) SetPixelChannelMask(image,channel_mask);
7769           break;
7770         }
7771         case 19:  /* Minify */
7772         {
7773           image=MinifyImage(image,exception);
7774           break;
7775         }
7776         case 20:  /* OilPaint */
7777         {
7778           if (attribute_flag[0] == 0)
7779             argument_list[0].real_reference=0.0;
7780           if (attribute_flag[1] == 0)
7781             argument_list[1].real_reference=1.0;
7782           image=OilPaintImage(image,argument_list[0].real_reference,
7783             argument_list[1].real_reference,exception);
7784           break;
7785         }
7786         case 21:  /* ReduceNoise */
7787         {
7788           if (attribute_flag[0] != 0)
7789             {
7790               flags=ParseGeometry(argument_list[0].string_reference,
7791                 &geometry_info);
7792               if ((flags & SigmaValue) == 0)
7793                 geometry_info.sigma=1.0;
7794             }
7795           if (attribute_flag[1] != 0)
7796             geometry_info.rho=argument_list[1].real_reference;
7797           if (attribute_flag[2] != 0)
7798             geometry_info.sigma=argument_list[2].real_reference;
7799           if (attribute_flag[3] != 0)
7800             channel=(ChannelType) argument_list[3].integer_reference;
7801           channel_mask=SetPixelChannelMask(image,channel);
7802           image=StatisticImage(image,NonpeakStatistic,(size_t)
7803             geometry_info.rho,(size_t) geometry_info.sigma,exception);
7804           if (image != (Image *) NULL)
7805             (void) SetPixelChannelMask(image,channel_mask);
7806           break;
7807         }
7808         case 22:  /* Roll */
7809         {
7810           if (attribute_flag[0] != 0)
7811             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7812               &geometry,exception);
7813           if (attribute_flag[1] != 0)
7814             geometry.x=argument_list[1].integer_reference;
7815           if (attribute_flag[2] != 0)
7816             geometry.y=argument_list[2].integer_reference;
7817           image=RollImage(image,geometry.x,geometry.y,exception);
7818           break;
7819         }
7820         case 23:  /* Rotate */
7821         {
7822           if (attribute_flag[0] == 0)
7823             argument_list[0].real_reference=90.0;
7824           if (attribute_flag[1] != 0)
7825             QueryColorCompliance(argument_list[1].string_reference,
7826               AllCompliance,&image->background_color,exception);
7827           if (attribute_flag[2] != 0)
7828             QueryColorCompliance(argument_list[2].string_reference,
7829               AllCompliance,&image->background_color,exception);
7830           if (attribute_flag[3] != 0)
7831             QueryColorCompliance(argument_list[3].string_reference,
7832               AllCompliance,&image->background_color,exception);
7833           image=RotateImage(image,argument_list[0].real_reference,exception);
7834           break;
7835         }
7836         case 24:  /* Sample */
7837         {
7838           if (attribute_flag[0] != 0)
7839             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7840               &geometry,exception);
7841           if (attribute_flag[1] != 0)
7842             geometry.width=argument_list[1].integer_reference;
7843           if (attribute_flag[2] != 0)
7844             geometry.height=argument_list[2].integer_reference;
7845           image=SampleImage(image,geometry.width,geometry.height,exception);
7846           break;
7847         }
7848         case 25:  /* Scale */
7849         {
7850           if (attribute_flag[0] != 0)
7851             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7852               &geometry,exception);
7853           if (attribute_flag[1] != 0)
7854             geometry.width=argument_list[1].integer_reference;
7855           if (attribute_flag[2] != 0)
7856             geometry.height=argument_list[2].integer_reference;
7857           image=ScaleImage(image,geometry.width,geometry.height,exception);
7858           break;
7859         }
7860         case 26:  /* Shade */
7861         {
7862           if (attribute_flag[0] != 0)
7863             {
7864               flags=ParseGeometry(argument_list[0].string_reference,
7865                 &geometry_info);
7866               if ((flags & SigmaValue) == 0)
7867                 geometry_info.sigma=0.0;
7868             }
7869           if (attribute_flag[1] != 0)
7870             geometry_info.rho=argument_list[1].real_reference;
7871           if (attribute_flag[2] != 0)
7872             geometry_info.sigma=argument_list[2].real_reference;
7873           image=ShadeImage(image,
7874             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
7875             geometry_info.rho,geometry_info.sigma,exception);
7876           break;
7877         }
7878         case 27:  /* Sharpen */
7879         {
7880           if (attribute_flag[0] != 0)
7881             {
7882               flags=ParseGeometry(argument_list[0].string_reference,
7883                 &geometry_info);
7884               if ((flags & SigmaValue) == 0)
7885                 geometry_info.sigma=1.0;
7886             }
7887           if (attribute_flag[1] != 0)
7888             geometry_info.rho=argument_list[1].real_reference;
7889           if (attribute_flag[2] != 0)
7890             geometry_info.sigma=argument_list[2].real_reference;
7891           if (attribute_flag[3] != 0)
7892             geometry_info.xi=argument_list[3].real_reference;
7893           if (attribute_flag[4] != 0)
7894             channel=(ChannelType) argument_list[4].integer_reference;
7895           channel_mask=SetPixelChannelMask(image,channel);
7896           image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
7897             geometry_info.xi,exception);
7898           if (image != (Image *) NULL)
7899             (void) SetPixelChannelMask(image,channel_mask);
7900           break;
7901         }
7902         case 28:  /* Shear */
7903         {
7904           if (attribute_flag[0] != 0)
7905             {
7906               flags=ParseGeometry(argument_list[0].string_reference,
7907                 &geometry_info);
7908               if ((flags & SigmaValue) == 0)
7909                 geometry_info.sigma=geometry_info.rho;
7910             }
7911           if (attribute_flag[1] != 0)
7912             geometry_info.rho=argument_list[1].real_reference;
7913           if (attribute_flag[2] != 0)
7914             geometry_info.sigma=argument_list[2].real_reference;
7915           if (attribute_flag[3] != 0)
7916             QueryColorCompliance(argument_list[3].string_reference,
7917               AllCompliance,&image->background_color,exception);
7918           if (attribute_flag[4] != 0)
7919             QueryColorCompliance(argument_list[4].string_reference,
7920               AllCompliance,&image->background_color,exception);
7921           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
7922             exception);
7923           break;
7924         }
7925         case 29:  /* Spread */
7926         {
7927           PixelInterpolateMethod
7928             method;
7929
7930           if (attribute_flag[0] == 0)
7931             argument_list[0].real_reference=1.0;
7932           method=UndefinedInterpolatePixel;
7933           if (attribute_flag[1] != 0)
7934             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
7935           image=SpreadImage(image,argument_list[0].real_reference,method,
7936             exception);
7937           break;
7938         }
7939         case 30:  /* Swirl */
7940         {
7941           PixelInterpolateMethod
7942             method;
7943
7944           if (attribute_flag[0] == 0)
7945             argument_list[0].real_reference=50.0;
7946           method=UndefinedInterpolatePixel;
7947           if (attribute_flag[1] != 0)
7948             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
7949           image=SwirlImage(image,argument_list[0].real_reference,
7950             method,exception);
7951           break;
7952         }
7953         case 31:  /* Resize */
7954         case 32:  /* Zoom */
7955         {
7956           if (attribute_flag[0] != 0)
7957             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7958               &geometry,exception);
7959           if (attribute_flag[1] != 0)
7960             geometry.width=argument_list[1].integer_reference;
7961           if (attribute_flag[2] != 0)
7962             geometry.height=argument_list[2].integer_reference;
7963           if (attribute_flag[3] == 0)
7964             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
7965           if (attribute_flag[4] != 0)
7966             SetImageArtifact(image,"filter:support",
7967               argument_list[4].string_reference);
7968           if (attribute_flag[5] == 0)
7969             argument_list[5].real_reference=1.0;
7970           image=ResizeImage(image,geometry.width,geometry.height,
7971             (FilterTypes) argument_list[3].integer_reference,
7972             argument_list[5].real_reference,exception);
7973           break;
7974         }
7975         case 33:  /* Annotate */
7976         {
7977           DrawInfo
7978             *draw_info;
7979
7980           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
7981             (DrawInfo *) NULL);
7982           if (attribute_flag[0] != 0)
7983             {
7984               char
7985                 *text;
7986
7987               text=InterpretImageProperties(info ? info->image_info :
7988                 (ImageInfo *) NULL,image,argument_list[0].string_reference,
7989                 exception);
7990               (void) CloneString(&draw_info->text,text);
7991               text=DestroyString(text);
7992             }
7993           if (attribute_flag[1] != 0)
7994             (void) CloneString(&draw_info->font,
7995               argument_list[1].string_reference);
7996           if (attribute_flag[2] != 0)
7997             draw_info->pointsize=argument_list[2].real_reference;
7998           if (attribute_flag[3] != 0)
7999             (void) CloneString(&draw_info->density,
8000               argument_list[3].string_reference);
8001           if (attribute_flag[4] != 0)
8002             (void) QueryColorCompliance(argument_list[4].string_reference,
8003               AllCompliance,&draw_info->undercolor,exception);
8004           if (attribute_flag[5] != 0)
8005             {
8006               (void) QueryColorCompliance(argument_list[5].string_reference,
8007                 AllCompliance,&draw_info->stroke,exception);
8008               if (argument_list[5].image_reference != (Image *) NULL)
8009                 draw_info->stroke_pattern=CloneImage(
8010                   argument_list[5].image_reference,0,0,MagickTrue,exception);
8011             }
8012           if (attribute_flag[6] != 0)
8013             {
8014               (void) QueryColorCompliance(argument_list[6].string_reference,
8015                 AllCompliance,&draw_info->fill,exception);
8016               if (argument_list[6].image_reference != (Image *) NULL)
8017                 draw_info->fill_pattern=CloneImage(
8018                   argument_list[6].image_reference,0,0,MagickTrue,exception);
8019             }
8020           if (attribute_flag[7] != 0)
8021             {
8022               (void) CloneString(&draw_info->geometry,
8023                 argument_list[7].string_reference);
8024               flags=ParsePageGeometry(image,argument_list[7].string_reference,
8025                 &geometry,exception);
8026               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8027                 geometry_info.sigma=geometry_info.xi;
8028             }
8029           if (attribute_flag[8] != 0)
8030             (void) QueryColorCompliance(argument_list[8].string_reference,
8031               AllCompliance,&draw_info->fill,exception);
8032           if (attribute_flag[11] != 0)
8033             draw_info->gravity=(GravityType)
8034               argument_list[11].integer_reference;
8035           if (attribute_flag[25] != 0)
8036             {
8037               AV
8038                 *av;
8039
8040               av=(AV *) argument_list[25].array_reference;
8041               if ((av_len(av) != 3) && (av_len(av) != 5))
8042                 {
8043                   ThrowPerlException(exception,OptionError,
8044                     "affine matrix must have 4 or 6 elements",PackageName);
8045                   goto PerlException;
8046                 }
8047               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8048               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8049               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8050               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8051               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8052                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8053                 {
8054                   ThrowPerlException(exception,OptionError,
8055                     "affine matrix is singular",PackageName);
8056                    goto PerlException;
8057                 }
8058               if (av_len(av) == 5)
8059                 {
8060                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8061                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8062                 }
8063             }
8064           for (j=12; j < 17; j++)
8065           {
8066             if (attribute_flag[j] == 0)
8067               continue;
8068             value=argument_list[j].string_reference;
8069             angle=argument_list[j].real_reference;
8070             current=draw_info->affine;
8071             GetAffineMatrix(&affine);
8072             switch (j)
8073             {
8074               case 12:
8075               {
8076                 /*
8077                   Translate.
8078                 */
8079                 flags=ParseGeometry(value,&geometry_info);
8080                 affine.tx=geometry_info.xi;
8081                 affine.ty=geometry_info.psi;
8082                 if ((flags & PsiValue) == 0)
8083                   affine.ty=affine.tx;
8084                 break;
8085               }
8086               case 13:
8087               {
8088                 /*
8089                   Scale.
8090                 */
8091                 flags=ParseGeometry(value,&geometry_info);
8092                 affine.sx=geometry_info.rho;
8093                 affine.sy=geometry_info.sigma;
8094                 if ((flags & SigmaValue) == 0)
8095                   affine.sy=affine.sx;
8096                 break;
8097               }
8098               case 14:
8099               {
8100                 /*
8101                   Rotate.
8102                 */
8103                 if (angle == 0.0)
8104                   break;
8105                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8106                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8107                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8108                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8109                 break;
8110               }
8111               case 15:
8112               {
8113                 /*
8114                   SkewX.
8115                 */
8116                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8117                 break;
8118               }
8119               case 16:
8120               {
8121                 /*
8122                   SkewY.
8123                 */
8124                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8125                 break;
8126               }
8127             }
8128             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8129             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8130             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8131             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8132             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8133               current.tx;
8134             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8135               current.ty;
8136           }
8137           if (attribute_flag[9] == 0)
8138             argument_list[9].real_reference=0.0;
8139           if (attribute_flag[10] == 0)
8140             argument_list[10].real_reference=0.0;
8141           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8142             {
8143               char
8144                 geometry[MaxTextExtent];
8145
8146               (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
8147                 (double) argument_list[9].real_reference+draw_info->affine.tx,
8148                 (double) argument_list[10].real_reference+draw_info->affine.ty);
8149               (void) CloneString(&draw_info->geometry,geometry);
8150             }
8151           if (attribute_flag[17] != 0)
8152             draw_info->stroke_width=argument_list[17].real_reference;
8153           if (attribute_flag[18] != 0)
8154             {
8155               draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8156                 MagickTrue : MagickFalse;
8157               draw_info->stroke_antialias=draw_info->text_antialias;
8158             }
8159           if (attribute_flag[19] != 0)
8160             (void) CloneString(&draw_info->family,
8161               argument_list[19].string_reference);
8162           if (attribute_flag[20] != 0)
8163             draw_info->style=(StyleType) argument_list[20].integer_reference;
8164           if (attribute_flag[21] != 0)
8165             draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8166           if (attribute_flag[22] != 0)
8167             draw_info->weight=argument_list[22].integer_reference;
8168           if (attribute_flag[23] != 0)
8169             draw_info->align=(AlignType) argument_list[23].integer_reference;
8170           if (attribute_flag[24] != 0)
8171             (void) CloneString(&draw_info->encoding,
8172               argument_list[24].string_reference);
8173           if (attribute_flag[25] != 0)
8174             draw_info->fill_pattern=CloneImage(
8175               argument_list[25].image_reference,0,0,MagickTrue,exception);
8176           if (attribute_flag[26] != 0)
8177             draw_info->fill_pattern=CloneImage(
8178               argument_list[26].image_reference,0,0,MagickTrue,exception);
8179           if (attribute_flag[27] != 0)
8180             draw_info->stroke_pattern=CloneImage(
8181               argument_list[27].image_reference,0,0,MagickTrue,exception);
8182           if (attribute_flag[29] != 0)
8183             draw_info->kerning=argument_list[29].real_reference;
8184           if (attribute_flag[30] != 0)
8185             draw_info->interline_spacing=argument_list[30].real_reference;
8186           if (attribute_flag[31] != 0)
8187             draw_info->interword_spacing=argument_list[31].real_reference;
8188           if (attribute_flag[32] != 0)
8189             draw_info->direction=(DirectionType)
8190               argument_list[32].integer_reference;
8191           (void) AnnotateImage(image,draw_info,exception);
8192           draw_info=DestroyDrawInfo(draw_info);
8193           break;
8194         }
8195         case 34:  /* ColorFloodfill */
8196         {
8197           DrawInfo
8198             *draw_info;
8199
8200           MagickBooleanType
8201             invert;
8202
8203           PixelInfo
8204             target;
8205
8206           Quantum
8207             virtual_pixel[MaxPixelChannels];
8208
8209           draw_info=CloneDrawInfo(info ? info->image_info :
8210             (ImageInfo *) NULL,(DrawInfo *) NULL);
8211           if (attribute_flag[0] != 0)
8212             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8213               &geometry,exception);
8214           if (attribute_flag[1] != 0)
8215             geometry.x=argument_list[1].integer_reference;
8216           if (attribute_flag[2] != 0)
8217             geometry.y=argument_list[2].integer_reference;
8218           if (attribute_flag[3] != 0)
8219             (void) QueryColorCompliance(argument_list[3].string_reference,
8220               AllCompliance,&draw_info->fill,exception);
8221           (void) GetOneVirtualPixel(image,geometry.x,geometry.y,virtual_pixel,
8222             exception);
8223           target.red=virtual_pixel[RedPixelChannel];
8224           target.green=virtual_pixel[GreenPixelChannel];
8225           target.blue=virtual_pixel[BluePixelChannel];
8226           target.alpha=virtual_pixel[AlphaPixelChannel];
8227           invert=MagickFalse;
8228           if (attribute_flag[4] != 0)
8229             {
8230               QueryColorCompliance(argument_list[4].string_reference,
8231                 AllCompliance,&target,exception);
8232               invert=MagickTrue;
8233             }
8234           if (attribute_flag[5] != 0)
8235             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
8236               QuantumRange);
8237           if (attribute_flag[6] != 0)
8238             invert=(MagickBooleanType) argument_list[6].integer_reference;
8239           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8240             geometry.y,invert,exception);
8241           draw_info=DestroyDrawInfo(draw_info);
8242           break;
8243         }
8244         case 35:  /* Composite */
8245         {
8246           char
8247             composite_geometry[MaxTextExtent];
8248
8249           Image
8250             *composite_image,
8251             *rotate_image;
8252
8253           compose=OverCompositeOp;
8254           if (attribute_flag[0] != 0)
8255             composite_image=argument_list[0].image_reference;
8256           else
8257             {
8258               ThrowPerlException(exception,OptionError,
8259                 "CompositeImageRequired",PackageName);
8260               goto PerlException;
8261             }
8262           /*
8263             Parameter Handling used for BOTH normal and tiled composition.
8264           */
8265           if (attribute_flag[1] != 0) /* compose */
8266             compose=(CompositeOperator) argument_list[1].integer_reference;
8267           if (attribute_flag[6] != 0) /* opacity  */
8268             {
8269               if (compose != DissolveCompositeOp)
8270                 (void) SetImageAlpha(composite_image,(Quantum)
8271                   SiPrefixToDouble(argument_list[6].string_reference,
8272                   QuantumRange));
8273               else
8274                 {
8275                   CacheView
8276                     *composite_view;
8277
8278                   double
8279                     opacity;
8280
8281                   MagickBooleanType
8282                     sync;
8283
8284                   register ssize_t
8285                     x;
8286
8287                   register Quantum
8288                     *q;
8289
8290                   ssize_t
8291                     y;
8292
8293                   /*
8294                     Handle dissolve composite operator (patch by
8295                     Kevin A. McGrail).
8296                   */
8297                   (void) CloneString(&image->geometry,
8298                     argument_list[6].string_reference);
8299                   opacity=(Quantum) SiPrefixToDouble(
8300                     argument_list[6].string_reference,QuantumRange);
8301                   if (composite_image->matte != MagickTrue)
8302                     (void) SetImageAlpha(composite_image,OpaqueAlpha);
8303                   composite_view=AcquireCacheView(composite_image);
8304                   for (y=0; y < (ssize_t) composite_image->rows ; y++)
8305                   {
8306                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8307                       composite_image->columns,1,exception);
8308                     for (x=0; x < (ssize_t) composite_image->columns; x++)
8309                     {
8310                       if (GetPixelAlpha(image,q) == OpaqueAlpha)
8311                         SetPixelAlpha(composite_image,ClampToQuantum(opacity),
8312                           q);
8313                       q+=GetPixelChannels(composite_image);
8314                     }
8315                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8316                     if (sync == MagickFalse)
8317                       break;
8318                   }
8319                   composite_view=DestroyCacheView(composite_view);
8320                 }
8321             }
8322           if (attribute_flag[9] != 0)    /* "color=>" */
8323             QueryColorCompliance(argument_list[9].string_reference,
8324               AllCompliance,&composite_image->background_color,exception);
8325           if (attribute_flag[12] != 0) /* "interpolate=>" */
8326             image->interpolate=(PixelInterpolateMethod)
8327               argument_list[12].integer_reference;
8328           if (attribute_flag[13] != 0)   /* "args=>" */
8329             (void) SetImageArtifact(composite_image,"compose:args",
8330               argument_list[13].string_reference);
8331           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8332             (void) SetImageArtifact(composite_image,"compose:args",
8333               argument_list[14].string_reference);
8334           /*
8335             Tiling Composition (with orthogonal rotate).
8336           */
8337           rotate_image=(Image *) NULL;
8338           if (attribute_flag[8] != 0)   /* "rotate=>" */
8339             {
8340                /*
8341                  Rotate image.
8342                */
8343                rotate_image=RotateImage(composite_image,
8344                  argument_list[8].real_reference,exception);
8345                if (rotate_image == (Image *) NULL)
8346                  break;
8347             }
8348           if (attribute_flag[7] && argument_list[7].integer_reference) /* tile */
8349             {
8350               ssize_t
8351                 x,
8352                 y;
8353
8354               /*
8355                 Tile the composite image.
8356               */
8357              if (attribute_flag[8] != 0)   /* "tile=>" */
8358                (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8359                  "false");
8360              else
8361                (void) SetImageArtifact(composite_image,
8362                  "compose:outside-overlay","false");
8363              for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8364                 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8365                 {
8366                   if (attribute_flag[8] != 0) /* rotate */
8367                     (void) CompositeImage(image,compose,rotate_image,x,y);
8368                   else
8369                     (void) CompositeImage(image,compose,composite_image,x,y);
8370                 }
8371               if (attribute_flag[8] != 0) /* rotate */
8372                 rotate_image=DestroyImage(rotate_image);
8373               break;
8374             }
8375           /*
8376             Parameter Handling used used ONLY for normal composition.
8377           */
8378           if (attribute_flag[5] != 0) /* gravity */
8379             image->gravity=(GravityType) argument_list[5].integer_reference;
8380           if (attribute_flag[2] != 0) /* geometry offset */
8381             {
8382               SetGeometry(image,&geometry);
8383               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8384                 &geometry);
8385               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8386                 &geometry);
8387             }
8388           if (attribute_flag[3] != 0) /* x offset */
8389             geometry.x=argument_list[3].integer_reference;
8390           if (attribute_flag[4] != 0) /* y offset */
8391             geometry.y=argument_list[4].integer_reference;
8392           if (attribute_flag[10] != 0) /* mask */
8393             {
8394               if ((image->compose == DisplaceCompositeOp) ||
8395                   (image->compose == DistortCompositeOp))
8396                 {
8397                   /*
8398                     Merge Y displacement into X displacement image.
8399                   */
8400                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8401                     &image->exception);
8402                   (void) CompositeImage(composite_image,CopyGreenCompositeOp,
8403                     argument_list[10].image_reference,0,0);
8404                 }
8405               else
8406                 {
8407                   /*
8408                     Set a blending mask for the composition.
8409                   */
8410                   image->mask=CloneImage(argument_list[10].image_reference,0,0,
8411                     MagickTrue,&image->exception);
8412                   (void) NegateImage(image->mask,MagickFalse,exception);
8413                 }
8414             }
8415           if (attribute_flag[11] != 0) /* channel */
8416             channel=(ChannelType) argument_list[11].integer_reference;
8417           /*
8418             Composite two images (normal composition).
8419           */
8420           (void) FormatLocaleString(composite_geometry,MaxTextExtent,
8421             "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8422             (double) composite_image->rows,(double) geometry.x,(double)
8423             geometry.y);
8424           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8425             exception);
8426           channel_mask=SetPixelChannelMask(image,channel);
8427           if (attribute_flag[8] == 0) /* no rotate */
8428             CompositeImage(image,compose,composite_image,geometry.x,geometry.y);
8429           else
8430             {
8431               /*
8432                 Position adjust rotated image then composite.
8433               */
8434               geometry.x-=(ssize_t) (rotate_image->columns-
8435                 composite_image->columns)/2;
8436               geometry.y-=(ssize_t) (rotate_image->rows-
8437                 composite_image->rows)/2;
8438               CompositeImage(image,compose,rotate_image,geometry.x,geometry.y);
8439               rotate_image=DestroyImage(rotate_image);
8440             }
8441           if (attribute_flag[10] != 0) /* mask */
8442             {
8443               if ((image->compose == DisplaceCompositeOp) ||
8444                   (image->compose == DistortCompositeOp))
8445                 composite_image=DestroyImage(composite_image);
8446               else
8447                 image->mask=DestroyImage(image->mask);
8448             }
8449           (void) SetPixelChannelMask(image,channel_mask);
8450           break;
8451         }
8452         case 36:  /* Contrast */
8453         {
8454           if (attribute_flag[0] == 0)
8455             argument_list[0].integer_reference=0;
8456           (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8457             MagickTrue : MagickFalse,exception);
8458           break;
8459         }
8460         case 37:  /* CycleColormap */
8461         {
8462           if (attribute_flag[0] == 0)
8463             argument_list[0].integer_reference=6;
8464           (void) CycleColormapImage(image,argument_list[0].integer_reference,
8465             exception);
8466           break;
8467         }
8468         case 38:  /* Draw */
8469         {
8470           DrawInfo
8471             *draw_info;
8472
8473           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8474             (DrawInfo *) NULL);
8475           (void) CloneString(&draw_info->primitive,"point");
8476           if (attribute_flag[0] != 0)
8477             {
8478               if (argument_list[0].integer_reference < 0)
8479                 (void) CloneString(&draw_info->primitive,
8480                   argument_list[0].string_reference);
8481               else
8482                 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8483                   MagickPrimitiveOptions,argument_list[0].integer_reference));
8484             }
8485           if (attribute_flag[1] != 0)
8486             {
8487               if (LocaleCompare(draw_info->primitive,"path") == 0)
8488                 {
8489                   (void) ConcatenateString(&draw_info->primitive," '");
8490                   ConcatenateString(&draw_info->primitive,
8491                     argument_list[1].string_reference);
8492                   (void) ConcatenateString(&draw_info->primitive,"'");
8493                 }
8494               else
8495                 {
8496                   (void) ConcatenateString(&draw_info->primitive," ");
8497                   ConcatenateString(&draw_info->primitive,
8498                     argument_list[1].string_reference);
8499                 }
8500             }
8501           if (attribute_flag[2] != 0)
8502             {
8503               (void) ConcatenateString(&draw_info->primitive," ");
8504               (void) ConcatenateString(&draw_info->primitive,
8505                 CommandOptionToMnemonic(MagickMethodOptions,
8506                 argument_list[2].integer_reference));
8507             }
8508           if (attribute_flag[3] != 0)
8509             {
8510               (void) QueryColorCompliance(argument_list[3].string_reference,
8511                 AllCompliance,&draw_info->stroke,exception);
8512               if (argument_list[3].image_reference != (Image *) NULL)
8513                 draw_info->stroke_pattern=CloneImage(
8514                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8515             }
8516           if (attribute_flag[4] != 0)
8517             {
8518               (void) QueryColorCompliance(argument_list[4].string_reference,
8519                 AllCompliance,&draw_info->fill,exception);
8520               if (argument_list[4].image_reference != (Image *) NULL)
8521                 draw_info->fill_pattern=CloneImage(
8522                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8523             }
8524           if (attribute_flag[5] != 0)
8525             draw_info->stroke_width=argument_list[5].real_reference;
8526           if (attribute_flag[6] != 0)
8527             (void) CloneString(&draw_info->font,
8528               argument_list[6].string_reference);
8529           if (attribute_flag[7] != 0)
8530             (void) QueryColorCompliance(argument_list[7].string_reference,
8531               AllCompliance,&draw_info->border_color,exception);
8532           if (attribute_flag[8] != 0)
8533             draw_info->affine.tx=argument_list[8].real_reference;
8534           if (attribute_flag[9] != 0)
8535             draw_info->affine.ty=argument_list[9].real_reference;
8536           if (attribute_flag[20] != 0)
8537             {
8538               AV
8539                 *av;
8540
8541               av=(AV *) argument_list[20].array_reference;
8542               if ((av_len(av) != 3) && (av_len(av) != 5))
8543                 {
8544                   ThrowPerlException(exception,OptionError,
8545                     "affine matrix must have 4 or 6 elements",PackageName);
8546                   goto PerlException;
8547                 }
8548               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8549               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8550               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8551               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8552               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8553                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8554                 {
8555                   ThrowPerlException(exception,OptionError,
8556                     "affine matrix is singular",PackageName);
8557                    goto PerlException;
8558                 }
8559               if (av_len(av) == 5)
8560                 {
8561                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8562                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8563                 }
8564             }
8565           for (j=10; j < 15; j++)
8566           {
8567             if (attribute_flag[j] == 0)
8568               continue;
8569             value=argument_list[j].string_reference;
8570             angle=argument_list[j].real_reference;
8571             current=draw_info->affine;
8572             GetAffineMatrix(&affine);
8573             switch (j)
8574             {
8575               case 10:
8576               {
8577                 /*
8578                   Translate.
8579                 */
8580                 flags=ParseGeometry(value,&geometry_info);
8581                 affine.tx=geometry_info.xi;
8582                 affine.ty=geometry_info.psi;
8583                 if ((flags & PsiValue) == 0)
8584                   affine.ty=affine.tx;
8585                 break;
8586               }
8587               case 11:
8588               {
8589                 /*
8590                   Scale.
8591                 */
8592                 flags=ParseGeometry(value,&geometry_info);
8593                 affine.sx=geometry_info.rho;
8594                 affine.sy=geometry_info.sigma;
8595                 if ((flags & SigmaValue) == 0)
8596                   affine.sy=affine.sx;
8597                 break;
8598               }
8599               case 12:
8600               {
8601                 /*
8602                   Rotate.
8603                 */
8604                 if (angle == 0.0)
8605                   break;
8606                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8607                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8608                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8609                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8610                 break;
8611               }
8612               case 13:
8613               {
8614                 /*
8615                   SkewX.
8616                 */
8617                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8618                 break;
8619               }
8620               case 14:
8621               {
8622                 /*
8623                   SkewY.
8624                 */
8625                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8626                 break;
8627               }
8628             }
8629             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8630             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8631             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8632             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8633             draw_info->affine.tx=
8634               current.sx*affine.tx+current.ry*affine.ty+current.tx;
8635             draw_info->affine.ty=
8636               current.rx*affine.tx+current.sy*affine.ty+current.ty;
8637           }
8638           if (attribute_flag[15] != 0)
8639             draw_info->fill_pattern=CloneImage(
8640               argument_list[15].image_reference,0,0,MagickTrue,exception);
8641           if (attribute_flag[16] != 0)
8642             draw_info->pointsize=argument_list[16].real_reference;
8643           if (attribute_flag[17] != 0)
8644             {
8645               draw_info->stroke_antialias=argument_list[17].integer_reference != 0
8646                 ? MagickTrue : MagickFalse;
8647               draw_info->text_antialias=draw_info->stroke_antialias;
8648             }
8649           if (attribute_flag[18] != 0)
8650             (void) CloneString(&draw_info->density,
8651               argument_list[18].string_reference);
8652           if (attribute_flag[19] != 0)
8653             draw_info->stroke_width=argument_list[19].real_reference;
8654           if (attribute_flag[21] != 0)
8655             draw_info->dash_offset=argument_list[21].real_reference;
8656           if (attribute_flag[22] != 0)
8657             {
8658               AV
8659                 *av;
8660
8661               av=(AV *) argument_list[22].array_reference;
8662               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
8663                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
8664               if (draw_info->dash_pattern != (double *) NULL)
8665                 {
8666                   for (i=0; i <= av_len(av); i++)
8667                     draw_info->dash_pattern[i]=(double)
8668                       SvNV(*(av_fetch(av,i,0)));
8669                   draw_info->dash_pattern[i]=0.0;
8670                 }
8671             }
8672           if (attribute_flag[23] != 0)
8673             image->interpolate=(PixelInterpolateMethod)
8674               argument_list[23].integer_reference;
8675           if ((attribute_flag[24] != 0) &&
8676               (draw_info->fill_pattern != (Image *) NULL))
8677             flags=ParsePageGeometry(draw_info->fill_pattern,
8678               argument_list[24].string_reference,
8679               &draw_info->fill_pattern->tile_offset,exception);
8680           if (attribute_flag[25] != 0)
8681             {
8682               (void) ConcatenateString(&draw_info->primitive," '");
8683               (void) ConcatenateString(&draw_info->primitive,
8684                 argument_list[25].string_reference);
8685               (void) ConcatenateString(&draw_info->primitive,"'");
8686             }
8687           if (attribute_flag[26] != 0)
8688             draw_info->fill_pattern=CloneImage(
8689               argument_list[26].image_reference,0,0,MagickTrue,exception);
8690           if (attribute_flag[27] != 0)
8691             draw_info->stroke_pattern=CloneImage(
8692               argument_list[27].image_reference,0,0,MagickTrue,exception);
8693           if (attribute_flag[28] != 0)
8694             (void) CloneString(&draw_info->primitive,
8695               argument_list[28].string_reference);
8696           if (attribute_flag[29] != 0)
8697             draw_info->kerning=argument_list[29].real_reference;
8698           if (attribute_flag[30] != 0)
8699             draw_info->interline_spacing=argument_list[30].real_reference;
8700           if (attribute_flag[31] != 0)
8701             draw_info->interword_spacing=argument_list[31].real_reference;
8702           if (attribute_flag[32] != 0)
8703             draw_info->direction=(DirectionType)
8704               argument_list[32].integer_reference;
8705           DrawImage(image,draw_info,exception);
8706           draw_info=DestroyDrawInfo(draw_info);
8707           break;
8708         }
8709         case 39:  /* Equalize */
8710         {
8711           if (attribute_flag[0] != 0)
8712             channel=(ChannelType) argument_list[0].integer_reference;
8713           channel_mask=SetPixelChannelMask(image,channel);
8714           EqualizeImage(image,exception);
8715           (void) SetPixelChannelMask(image,channel_mask);
8716           break;
8717         }
8718         case 40:  /* Gamma */
8719         {
8720           if (attribute_flag[1] != 0)
8721             channel=(ChannelType) argument_list[1].integer_reference;
8722           if (attribute_flag[2] == 0)
8723             argument_list[2].real_reference=1.0;
8724           if (attribute_flag[3] == 0)
8725             argument_list[3].real_reference=1.0;
8726           if (attribute_flag[4] == 0)
8727             argument_list[4].real_reference=1.0;
8728           if (attribute_flag[0] == 0)
8729             {
8730               (void) FormatLocaleString(message,MaxTextExtent,
8731                 "%.15g,%.15g,%.15g",(double) argument_list[2].real_reference,
8732                 (double) argument_list[3].real_reference,
8733                 (double) argument_list[4].real_reference);
8734               argument_list[0].string_reference=message;
8735             }
8736           (void) GammaImage(image,InterpretLocaleValue(
8737             argument_list[0].string_reference,(char **) NULL),exception);
8738           break;
8739         }
8740         case 41:  /* Map */
8741         {
8742           QuantizeInfo
8743             *quantize_info;
8744
8745           if (attribute_flag[0] == 0)
8746             {
8747               ThrowPerlException(exception,OptionError,"MapImageRequired",
8748                 PackageName);
8749               goto PerlException;
8750             }
8751           quantize_info=AcquireQuantizeInfo(info->image_info);
8752           if (attribute_flag[1] != 0)
8753             quantize_info->dither=(MagickBooleanType)
8754               argument_list[1].integer_reference;
8755           if (attribute_flag[2] != 0)
8756             quantize_info->dither_method=(DitherMethod)
8757               argument_list[2].integer_reference;
8758           (void) RemapImages(quantize_info,image,
8759             argument_list[0].image_reference,exception);
8760           quantize_info=DestroyQuantizeInfo(quantize_info);
8761           break;
8762         }
8763         case 42:  /* MatteFloodfill */
8764         {
8765           DrawInfo
8766             *draw_info;
8767
8768           MagickBooleanType
8769             invert;
8770
8771           PixelInfo
8772             target;
8773
8774           Quantum
8775             virtual_pixel[MaxPixelChannels];
8776
8777           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8778             (DrawInfo *) NULL);
8779           if (attribute_flag[0] != 0)
8780             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8781               &geometry,exception);
8782           if (attribute_flag[1] != 0)
8783             geometry.x=argument_list[1].integer_reference;
8784           if (attribute_flag[2] != 0)
8785             geometry.y=argument_list[2].integer_reference;
8786           if (image->matte == MagickFalse)
8787             (void) SetImageAlpha(image,OpaqueAlpha);
8788           (void) GetOneVirtualPixel(image,geometry.x,geometry.y,virtual_pixel,
8789             exception);
8790           target.red=virtual_pixel[RedPixelChannel];
8791           target.green=virtual_pixel[GreenPixelChannel];
8792           target.blue=virtual_pixel[BluePixelChannel];
8793           target.alpha=virtual_pixel[AlphaPixelChannel];
8794           if (attribute_flag[4] != 0)
8795             QueryColorCompliance(argument_list[4].string_reference,
8796               AllCompliance,&target,exception);
8797           if (attribute_flag[3] != 0)
8798             target.alpha=SiPrefixToDouble(argument_list[3].string_reference,
8799               QuantumRange);
8800           if (attribute_flag[5] != 0)
8801             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
8802               QuantumRange);
8803           invert=MagickFalse;
8804           if (attribute_flag[6] != 0)
8805             invert=(MagickBooleanType) argument_list[6].integer_reference;
8806           channel_mask=SetPixelChannelMask(image,AlphaChannel);
8807           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8808             geometry.y,invert,exception);
8809           (void) SetPixelChannelMask(image,channel_mask);
8810           draw_info=DestroyDrawInfo(draw_info);
8811           break;
8812         }
8813         case 43:  /* Modulate */
8814         {
8815           char
8816             modulate[MaxTextExtent];
8817
8818           geometry_info.rho=100.0;
8819           geometry_info.sigma=100.0;
8820           geometry_info.xi=100.0;
8821           if (attribute_flag[0] != 0)
8822             (void)ParseGeometry(argument_list[0].string_reference,
8823               &geometry_info);
8824           if (attribute_flag[1] != 0)
8825             geometry_info.xi=argument_list[1].real_reference;
8826           if (attribute_flag[2] != 0)
8827             geometry_info.sigma=argument_list[2].real_reference;
8828           if (attribute_flag[3] != 0)
8829             {
8830               geometry_info.sigma=argument_list[3].real_reference;
8831               SetImageArtifact(image,"modulate:colorspace","HWB");
8832             }
8833           if (attribute_flag[4] != 0)
8834             {
8835               geometry_info.rho=argument_list[4].real_reference;
8836               SetImageArtifact(image,"modulate:colorspace","HSB");
8837             }
8838           if (attribute_flag[5] != 0)
8839             {
8840               geometry_info.sigma=argument_list[5].real_reference;
8841               SetImageArtifact(image,"modulate:colorspace","HSL");
8842             }
8843           if (attribute_flag[6] != 0)
8844             {
8845               geometry_info.rho=argument_list[6].real_reference;
8846               SetImageArtifact(image,"modulate:colorspace","HWB");
8847             }
8848           (void) FormatLocaleString(modulate,MaxTextExtent,"%.15g,%.15g,%.15g",
8849             geometry_info.rho,geometry_info.sigma,geometry_info.xi);
8850           (void) ModulateImage(image,modulate,exception);
8851           break;
8852         }
8853         case 44:  /* Negate */
8854         {
8855           if (attribute_flag[0] == 0)
8856             argument_list[0].integer_reference=0;
8857           if (attribute_flag[1] != 0)
8858             channel=(ChannelType) argument_list[1].integer_reference;
8859           channel_mask=SetPixelChannelMask(image,channel);
8860           (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
8861             MagickTrue : MagickFalse,exception);
8862           (void) SetPixelChannelMask(image,channel_mask);
8863           break;
8864         }
8865         case 45:  /* Normalize */
8866         {
8867           if (attribute_flag[0] != 0)
8868             channel=(ChannelType) argument_list[0].integer_reference;
8869           channel_mask=SetPixelChannelMask(image,channel);
8870           NormalizeImage(image,exception);
8871           (void) SetPixelChannelMask(image,channel_mask);
8872           break;
8873         }
8874         case 46:  /* NumberColors */
8875           break;
8876         case 47:  /* Opaque */
8877         {
8878           MagickBooleanType
8879             invert;
8880
8881           PixelInfo
8882             fill_color,
8883             target;
8884
8885           (void) QueryColorCompliance("none",AllCompliance,&target,
8886              exception);
8887           (void) QueryColorCompliance("none",AllCompliance,&fill_color,
8888             exception);
8889           if (attribute_flag[0] != 0)
8890             (void) QueryColorCompliance(argument_list[0].string_reference,
8891               AllCompliance,&target,exception);
8892           if (attribute_flag[1] != 0)
8893             (void) QueryColorCompliance(argument_list[1].string_reference,
8894               AllCompliance,&fill_color,exception);
8895           if (attribute_flag[2] != 0)
8896             image->fuzz=SiPrefixToDouble(argument_list[2].string_reference,
8897               QuantumRange);
8898           if (attribute_flag[3] != 0)
8899             channel=(ChannelType) argument_list[3].integer_reference;
8900           invert=MagickFalse;
8901           if (attribute_flag[4] != 0)
8902             invert=(MagickBooleanType) argument_list[4].integer_reference;
8903           channel_mask=SetPixelChannelMask(image,channel);
8904           (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
8905           (void) SetPixelChannelMask(image,channel_mask);
8906           break;
8907         }
8908         case 48:  /* Quantize */
8909         {
8910           QuantizeInfo
8911             *quantize_info;
8912
8913           quantize_info=AcquireQuantizeInfo(info->image_info);
8914           if (attribute_flag[0] != 0)
8915             quantize_info->number_colors=(size_t)
8916               argument_list[0].integer_reference;
8917           if (attribute_flag[1] != 0)
8918             quantize_info->tree_depth=(size_t)
8919               argument_list[1].integer_reference;
8920           if (attribute_flag[2] != 0)
8921             quantize_info->colorspace=(ColorspaceType)
8922               argument_list[2].integer_reference;
8923           if (attribute_flag[3] != 0)
8924             quantize_info->dither=argument_list[3].integer_reference != 0 ?
8925               MagickTrue : MagickFalse;
8926           if (attribute_flag[4] != 0)
8927             quantize_info->measure_error=
8928               argument_list[4].integer_reference != 0 ? MagickTrue :
8929               MagickFalse;
8930           if (attribute_flag[5] != 0)
8931             (void) QueryColorCompliance(argument_list[5].string_reference,
8932               AllCompliance,&image->transparent_color,exception);
8933           if (attribute_flag[5] && argument_list[5].integer_reference)
8934             {
8935               (void) QuantizeImages(quantize_info,image,exception);
8936               goto PerlException;
8937             }
8938           if (attribute_flag[6] != 0)
8939             quantize_info->dither_method=(DitherMethod)
8940               argument_list[6].integer_reference;
8941           if ((image->storage_class == DirectClass) ||
8942               (image->colors > quantize_info->number_colors) ||
8943               (quantize_info->colorspace == GRAYColorspace))
8944             (void) QuantizeImage(quantize_info,image,exception);
8945           else
8946             CompressImageColormap(image,exception);
8947           quantize_info=DestroyQuantizeInfo(quantize_info);
8948           break;
8949         }
8950         case 49:  /* Raise */
8951         {
8952           if (attribute_flag[0] != 0)
8953             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8954               &geometry,exception);
8955           if (attribute_flag[1] != 0)
8956             geometry.width=argument_list[1].integer_reference;
8957           if (attribute_flag[2] != 0)
8958             geometry.height=argument_list[2].integer_reference;
8959           if (attribute_flag[3] == 0)
8960             argument_list[3].integer_reference=1;
8961           (void) RaiseImage(image,&geometry,
8962             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8963             exception);
8964           break;
8965         }
8966         case 50:  /* Segment */
8967         {
8968           ColorspaceType
8969             colorspace;
8970
8971           double
8972             cluster_threshold,
8973             smoothing_threshold;
8974
8975           MagickBooleanType
8976             verbose;
8977
8978           cluster_threshold=1.0;
8979           smoothing_threshold=1.5;
8980           colorspace=RGBColorspace;
8981           verbose=MagickFalse;
8982           if (attribute_flag[0] != 0)
8983             {
8984               flags=ParseGeometry(argument_list[0].string_reference,
8985                 &geometry_info);
8986               cluster_threshold=geometry_info.rho;
8987               if (flags & SigmaValue)
8988                 smoothing_threshold=geometry_info.sigma;
8989             }
8990           if (attribute_flag[1] != 0)
8991             cluster_threshold=argument_list[1].real_reference;
8992           if (attribute_flag[2] != 0)
8993             smoothing_threshold=argument_list[2].real_reference;
8994           if (attribute_flag[3] != 0)
8995             colorspace=(ColorspaceType) argument_list[3].integer_reference;
8996           if (attribute_flag[4] != 0)
8997             verbose=argument_list[4].integer_reference != 0 ?
8998               MagickTrue : MagickFalse;
8999           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
9000             smoothing_threshold,exception);
9001           break;
9002         }
9003         case 51:  /* Signature */
9004         {
9005           (void) SignatureImage(image,exception);
9006           break;
9007         }
9008         case 52:  /* Solarize */
9009         {
9010           geometry_info.rho=QuantumRange/2.0;
9011           if (attribute_flag[0] != 0)
9012             flags=ParseGeometry(argument_list[0].string_reference,
9013               &geometry_info);
9014           if (attribute_flag[1] != 0)
9015             geometry_info.rho=SiPrefixToDouble(
9016              argument_list[1].string_reference,QuantumRange);
9017           (void) SolarizeImage(image,geometry_info.rho,exception);
9018           break;
9019         }
9020         case 53:  /* Sync */
9021         {
9022           (void) SyncImage(image);
9023           break;
9024         }
9025         case 54:  /* Texture */
9026         {
9027           if (attribute_flag[0] == 0)
9028             break;
9029           TextureImage(image,argument_list[0].image_reference);
9030           break;
9031         }
9032         case 55:  /* Evalute */
9033         {
9034           MagickEvaluateOperator
9035             op;
9036
9037           op=SetEvaluateOperator;
9038           if (attribute_flag[0] == MagickFalse)
9039             argument_list[0].real_reference=0.0;
9040           if (attribute_flag[1] != MagickFalse)
9041             op=(MagickEvaluateOperator) argument_list[1].integer_reference;
9042           if (attribute_flag[2] != MagickFalse)
9043             channel=(ChannelType) argument_list[2].integer_reference;
9044           channel_mask=SetPixelChannelMask(image,channel);
9045           (void) EvaluateImage(image,op,argument_list[0].real_reference,
9046             exception);
9047           (void) SetPixelChannelMask(image,channel_mask);
9048           break;
9049         }
9050         case 56:  /* Transparent */
9051         {
9052           double
9053             opacity;
9054
9055           MagickBooleanType
9056             invert;
9057
9058           PixelInfo
9059             target;
9060
9061           (void) QueryColorCompliance("none",AllCompliance,&target,
9062             exception);
9063           if (attribute_flag[0] != 0)
9064             (void) QueryColorCompliance(argument_list[0].string_reference,
9065               AllCompliance,&target,exception);
9066           opacity=TransparentAlpha;
9067           if (attribute_flag[1] != 0)
9068             opacity=SiPrefixToDouble(argument_list[1].string_reference,
9069               QuantumRange);
9070           if (attribute_flag[2] != 0)
9071             image->fuzz=SiPrefixToDouble(argument_list[2].string_reference,
9072               QuantumRange);
9073           if (attribute_flag[3] == 0)
9074             argument_list[3].integer_reference=0;
9075           invert=MagickFalse;
9076           if (attribute_flag[3] != 0)
9077             invert=(MagickBooleanType) argument_list[3].integer_reference;
9078           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9079             invert,exception);
9080           break;
9081         }
9082         case 57:  /* Threshold */
9083         {
9084           double
9085             threshold;
9086
9087           if (attribute_flag[0] == 0)
9088             argument_list[0].string_reference="50%";
9089           if (attribute_flag[1] != 0)
9090             channel=(ChannelType) argument_list[1].integer_reference;
9091           threshold=SiPrefixToDouble(argument_list[0].string_reference,
9092             QuantumRange);
9093           channel_mask=SetPixelChannelMask(image,channel);
9094           (void) BilevelImage(image,threshold);
9095           (void) SetPixelChannelMask(image,channel_mask);
9096           break;
9097         }
9098         case 58:  /* Charcoal */
9099         {
9100           if (attribute_flag[0] != 0)
9101             {
9102               flags=ParseGeometry(argument_list[0].string_reference,
9103                 &geometry_info);
9104               if ((flags & SigmaValue) == 0)
9105                 geometry_info.sigma=1.0;
9106             }
9107           if (attribute_flag[1] != 0)
9108             geometry_info.rho=argument_list[1].real_reference;
9109           if (attribute_flag[2] != 0)
9110             geometry_info.sigma=argument_list[2].real_reference;
9111           if (attribute_flag[3] != 0)
9112             geometry_info.xi=argument_list[3].real_reference;
9113           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9114             geometry_info.xi,exception);
9115           break;
9116         }
9117         case 59:  /* Trim */
9118         {
9119           if (attribute_flag[0] != 0)
9120             image->fuzz=SiPrefixToDouble(argument_list[0].string_reference,
9121               QuantumRange);
9122           image=TrimImage(image,exception);
9123           break;
9124         }
9125         case 60:  /* Wave */
9126         {
9127           PixelInterpolateMethod
9128             method;
9129
9130           if (attribute_flag[0] != 0)
9131             {
9132               flags=ParseGeometry(argument_list[0].string_reference,
9133                 &geometry_info);
9134               if ((flags & SigmaValue) == 0)
9135                 geometry_info.sigma=1.0;
9136             }
9137           if (attribute_flag[1] != 0)
9138             geometry_info.rho=argument_list[1].real_reference;
9139           if (attribute_flag[2] != 0)
9140             geometry_info.sigma=argument_list[2].real_reference;
9141           method=UndefinedInterpolatePixel;
9142           if (attribute_flag[3] != 0)
9143             method=(PixelInterpolateMethod) argument_list[3].integer_reference;
9144           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9145             method,exception);
9146           break;
9147         }
9148         case 61:  /* Separate */
9149         {
9150           if (attribute_flag[0] != 0)
9151             channel=(ChannelType) argument_list[0].integer_reference;
9152           channel_mask=SetPixelChannelMask(image,channel);
9153           (void) SeparateImage(image);
9154           (void) SetPixelChannelMask(image,channel_mask);
9155           break;
9156         }
9157         case 63:  /* Stereo */
9158         {
9159           if (attribute_flag[0] == 0)
9160             {
9161               ThrowPerlException(exception,OptionError,"StereoImageRequired",
9162                 PackageName);
9163               goto PerlException;
9164             }
9165           if (attribute_flag[1] != 0)
9166             geometry.x=argument_list[1].integer_reference;
9167           if (attribute_flag[2] != 0)
9168             geometry.y=argument_list[2].integer_reference;
9169           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9170             geometry.x,geometry.y,exception);
9171           break;
9172         }
9173         case 64:  /* Stegano */
9174         {
9175           if (attribute_flag[0] == 0)
9176             {
9177               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9178                 PackageName);
9179               goto PerlException;
9180             }
9181           if (attribute_flag[1] == 0)
9182             argument_list[1].integer_reference=0;
9183           image->offset=argument_list[1].integer_reference;
9184           image=SteganoImage(image,argument_list[0].image_reference,exception);
9185           break;
9186         }
9187         case 65:  /* Deconstruct */
9188         {
9189           image=CompareImagesLayers(image,CompareAnyLayer,exception);
9190           break;
9191         }
9192         case 66:  /* GaussianBlur */
9193         {
9194           if (attribute_flag[0] != 0)
9195             {
9196               flags=ParseGeometry(argument_list[0].string_reference,
9197                 &geometry_info);
9198               if ((flags & SigmaValue) == 0)
9199                 geometry_info.sigma=1.0;
9200             }
9201           if (attribute_flag[1] != 0)
9202             geometry_info.rho=argument_list[1].real_reference;
9203           if (attribute_flag[2] != 0)
9204             geometry_info.sigma=argument_list[2].real_reference;
9205           if (attribute_flag[3] != 0)
9206             geometry_info.xi=argument_list[3].real_reference;
9207           if (attribute_flag[4] != 0)
9208             channel=(ChannelType) argument_list[4].integer_reference;
9209           channel_mask=SetPixelChannelMask(image,channel);
9210           image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9211             geometry_info.xi,exception);
9212           if (image != (Image *) NULL)
9213             (void) SetPixelChannelMask(image,channel_mask);
9214           break;
9215         }
9216         case 67:  /* Convolve */
9217         {
9218           KernelInfo
9219             *kernel;
9220
9221           kernel=(KernelInfo *) NULL;
9222           if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9223             break;
9224           if (attribute_flag[0] != 0)
9225             {
9226               AV
9227                 *av;
9228
9229               size_t
9230                 order;
9231
9232               kernel=AcquireKernelInfo((const char *) NULL);
9233               if (kernel == (KernelInfo *) NULL)
9234                 break;
9235               av=(AV *) argument_list[0].array_reference;
9236               order=(size_t) sqrt(av_len(av)+1);
9237               kernel->width=order;
9238               kernel->height=order;
9239               kernel->values=(double *) AcquireAlignedMemory(order,order*
9240                 sizeof(*kernel->values));
9241               if (kernel->values == (double *) NULL)
9242                 {
9243                   kernel=DestroyKernelInfo(kernel);
9244                   ThrowPerlException(exception,ResourceLimitFatalError,
9245                     "MemoryAllocationFailed",PackageName);
9246                   goto PerlException;
9247                 }
9248               for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9249                 kernel->values[j]=(double) SvNV(*(av_fetch(av,j,0)));
9250               for ( ; j < (ssize_t) (order*order); j++)
9251                 kernel->values[j]=0.0;
9252             }
9253           if (attribute_flag[1] != 0)
9254             channel=(ChannelType) argument_list[1].integer_reference;
9255           if (attribute_flag[2] != 0)
9256             image->bias=SiPrefixToDouble(argument_list[2].string_reference,
9257               QuantumRange);
9258           if (attribute_flag[3] != 0)
9259             {
9260               kernel=AcquireKernelInfo(argument_list[3].string_reference);
9261               if (kernel == (KernelInfo *) NULL)
9262                 break;
9263             }
9264           channel_mask=SetPixelChannelMask(image,channel);
9265           kernel->bias=image->bias;
9266           image=ConvolveImage(image,kernel,exception);
9267           if (image != (Image *) NULL)
9268             (void) SetPixelChannelMask(image,channel_mask);
9269           kernel=DestroyKernelInfo(kernel);
9270           break;
9271         }
9272         case 68:  /* Profile */
9273         {
9274           const char
9275             *name;
9276
9277           Image
9278             *profile_image;
9279
9280           ImageInfo
9281             *profile_info;
9282
9283           StringInfo
9284             *profile;
9285
9286           name="*";
9287           if (attribute_flag[0] != 0)
9288             name=argument_list[0].string_reference;
9289           if (attribute_flag[2] != 0)
9290             image->rendering_intent=(RenderingIntent)
9291               argument_list[2].integer_reference;
9292           if (attribute_flag[3] != 0)
9293             image->black_point_compensation=
9294               argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9295           if (attribute_flag[1] != 0)
9296             {
9297               if (argument_list[1].length == 0)
9298                 {
9299                   /*
9300                     Remove a profile from the image.
9301                   */
9302                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9303                     exception);
9304                   break;
9305                 }
9306               /*
9307                 Associate user supplied profile with the image.
9308               */
9309               profile=AcquireStringInfo(argument_list[1].length);
9310               SetStringInfoDatum(profile,(const unsigned char *)
9311                 argument_list[1].string_reference);
9312               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9313                 (size_t) GetStringInfoLength(profile),exception);
9314               profile=DestroyStringInfo(profile);
9315               break;
9316             }
9317           /*
9318             Associate a profile with the image.
9319           */
9320           profile_info=
9321             CloneImageInfo(info ? info->image_info : (ImageInfo *) NULL);
9322           (void) CopyMagickString(profile_info->filename,name,MaxTextExtent);
9323           profile_image=ReadImages(profile_info,&image->exception);
9324           if (profile_image == (Image *) NULL)
9325             break;
9326           ResetImageProfileIterator(profile_image);
9327           name=GetNextImageProfile(profile_image);
9328           while (name != (const char *) NULL)
9329           {
9330             const StringInfo
9331               *profile;
9332
9333             profile=GetImageProfile(profile_image,name);
9334             if (profile != (const StringInfo *) NULL)
9335               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9336                 (size_t) GetStringInfoLength(profile),exception);
9337             name=GetNextImageProfile(profile_image);
9338           }
9339           profile_image=DestroyImage(profile_image);
9340           profile_info=DestroyImageInfo(profile_info);
9341           break;
9342         }
9343         case 69:  /* UnsharpMask */
9344         {
9345           if (attribute_flag[0] != 0)
9346             {
9347               flags=ParseGeometry(argument_list[0].string_reference,
9348                 &geometry_info);
9349               if ((flags & SigmaValue) == 0)
9350                 geometry_info.sigma=1.0;
9351               if ((flags & XiValue) == 0)
9352                 geometry_info.xi=1.0;
9353               if ((flags & PsiValue) == 0)
9354                 geometry_info.psi=0.5;
9355             }
9356           if (attribute_flag[1] != 0)
9357             geometry_info.rho=argument_list[1].real_reference;
9358           if (attribute_flag[2] != 0)
9359             geometry_info.sigma=argument_list[2].real_reference;
9360           if (attribute_flag[3] != 0)
9361             geometry_info.xi=argument_list[3].real_reference;
9362           if (attribute_flag[4] != 0)
9363             geometry_info.psi=argument_list[4].real_reference;
9364           if (attribute_flag[5] != 0)
9365             channel=(ChannelType) argument_list[5].integer_reference;
9366           channel_mask=SetPixelChannelMask(image,channel);
9367           image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9368             geometry_info.xi,geometry_info.psi,exception);
9369           if (image != (Image *) NULL)
9370             (void) SetPixelChannelMask(image,channel_mask);
9371           break;
9372         }
9373         case 70:  /* MotionBlur */
9374         {
9375           if (attribute_flag[0] != 0)
9376             {
9377               flags=ParseGeometry(argument_list[0].string_reference,
9378                 &geometry_info);
9379               if ((flags & SigmaValue) == 0)
9380                 geometry_info.sigma=1.0;
9381               if ((flags & XiValue) == 0)
9382                 geometry_info.xi=1.0;
9383             }
9384           if (attribute_flag[1] != 0)
9385             geometry_info.rho=argument_list[1].real_reference;
9386           if (attribute_flag[2] != 0)
9387             geometry_info.sigma=argument_list[2].real_reference;
9388           if (attribute_flag[3] != 0)
9389             geometry_info.xi=argument_list[3].real_reference;
9390           if (attribute_flag[4] != 0)
9391             geometry_info.psi=argument_list[4].real_reference;
9392           if (attribute_flag[5] != 0)
9393             channel=(ChannelType) argument_list[5].integer_reference;
9394           channel_mask=SetPixelChannelMask(image,channel);
9395           image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9396             geometry_info.xi,geometry_info.psi,exception);
9397           if (image != (Image *) NULL)
9398             (void) SetPixelChannelMask(image,channel_mask);
9399           break;
9400         }
9401         case 71:  /* OrderedDither */
9402         {
9403           if (attribute_flag[0] == 0)
9404             argument_list[0].string_reference="o8x8";
9405           if (attribute_flag[1] != 0)
9406             channel=(ChannelType) argument_list[1].integer_reference;
9407           channel_mask=SetPixelChannelMask(image,channel);
9408           (void) OrderedPosterizeImage(image,argument_list[0].string_reference,
9409             exception);
9410           (void) SetPixelChannelMask(image,channel_mask);
9411           break;
9412         }
9413         case 72:  /* Shave */
9414         {
9415           if (attribute_flag[0] != 0)
9416             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9417               &geometry,exception);
9418           if (attribute_flag[1] != 0)
9419             geometry.width=argument_list[1].integer_reference;
9420           if (attribute_flag[2] != 0)
9421             geometry.height=argument_list[2].integer_reference;
9422           image=ShaveImage(image,&geometry,exception);
9423           break;
9424         }
9425         case 73:  /* Level */
9426         {
9427           double
9428             black_point,
9429             gamma,
9430             white_point;
9431
9432           black_point=0.0;
9433           white_point=(MagickRealType) image->columns*image->rows;
9434           gamma=1.0;
9435           if (attribute_flag[0] != 0)
9436             {
9437               flags=ParseGeometry(argument_list[0].string_reference,
9438                 &geometry_info);
9439               black_point=geometry_info.rho;
9440               if ((flags & SigmaValue) != 0)
9441                 white_point=geometry_info.sigma;
9442               if ((flags & XiValue) != 0)
9443                 gamma=geometry_info.xi;
9444               if ((flags & PercentValue) != 0)
9445                 {
9446                   black_point*=(double) (QuantumRange/100.0);
9447                   white_point*=(double) (QuantumRange/100.0);
9448                 }
9449               if ((flags & SigmaValue) == 0)
9450                 white_point=(double) QuantumRange-black_point;
9451             }
9452           if (attribute_flag[1] != 0)
9453             black_point=argument_list[1].real_reference;
9454           if (attribute_flag[2] != 0)
9455             white_point=argument_list[2].real_reference;
9456           if (attribute_flag[3] != 0)
9457             gamma=argument_list[3].real_reference;
9458           if (attribute_flag[4] != 0)
9459             channel=(ChannelType) argument_list[4].integer_reference;
9460           if (attribute_flag[5] != 0)
9461             {
9462               argument_list[0].real_reference=argument_list[5].real_reference;
9463               attribute_flag[0]=attribute_flag[5];
9464             }
9465           channel_mask=SetPixelChannelMask(image,channel);
9466           (void) LevelImage(image,black_point,white_point,gamma,exception);
9467           (void) SetPixelChannelMask(image,channel_mask);
9468           break;
9469         }
9470         case 74:  /* Clip */
9471         {
9472           if (attribute_flag[0] == 0)
9473             argument_list[0].string_reference="#1";
9474           if (attribute_flag[1] == 0)
9475             argument_list[1].integer_reference=MagickTrue;
9476           (void) ClipImagePath(image,argument_list[0].string_reference,
9477             argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse,
9478             exception);
9479           break;
9480         }
9481         case 75:  /* AffineTransform */
9482         {
9483           DrawInfo
9484             *draw_info;
9485
9486           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9487             (DrawInfo *) NULL);
9488           if (attribute_flag[0] != 0)
9489             {
9490               AV
9491                 *av;
9492
9493               av=(AV *) argument_list[0].array_reference;
9494               if ((av_len(av) != 3) && (av_len(av) != 5))
9495                 {
9496                   ThrowPerlException(exception,OptionError,
9497                     "affine matrix must have 4 or 6 elements",PackageName);
9498                   goto PerlException;
9499                 }
9500               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9501               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9502               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9503               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9504               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9505                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9506                 {
9507                   ThrowPerlException(exception,OptionError,
9508                     "affine matrix is singular",PackageName);
9509                    goto PerlException;
9510                 }
9511               if (av_len(av) == 5)
9512                 {
9513                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9514                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9515                 }
9516             }
9517           for (j=1; j < 6; j++)
9518           {
9519             if (attribute_flag[j] == 0)
9520               continue;
9521             value=argument_list[j].string_reference;
9522             angle=argument_list[j].real_reference;
9523             current=draw_info->affine;
9524             GetAffineMatrix(&affine);
9525             switch (j)
9526             {
9527               case 1:
9528               {
9529                 /*
9530                   Translate.
9531                 */
9532                 flags=ParseGeometry(value,&geometry_info);
9533                 affine.tx=geometry_info.xi;
9534                 affine.ty=geometry_info.psi;
9535                 if ((flags & PsiValue) == 0)
9536                   affine.ty=affine.tx;
9537                 break;
9538               }
9539               case 2:
9540               {
9541                 /*
9542                   Scale.
9543                 */
9544                 flags=ParseGeometry(value,&geometry_info);
9545                 affine.sx=geometry_info.rho;
9546                 affine.sy=geometry_info.sigma;
9547                 if ((flags & SigmaValue) == 0)
9548                   affine.sy=affine.sx;
9549                 break;
9550               }
9551               case 3:
9552               {
9553                 /*
9554                   Rotate.
9555                 */
9556                 if (angle == 0.0)
9557                   break;
9558                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9559                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9560                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9561                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9562                 break;
9563               }
9564               case 4:
9565               {
9566                 /*
9567                   SkewX.
9568                 */
9569                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9570                 break;
9571               }
9572               case 5:
9573               {
9574                 /*
9575                   SkewY.
9576                 */
9577                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9578                 break;
9579               }
9580             }
9581             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9582             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9583             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9584             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9585             draw_info->affine.tx=
9586               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9587             draw_info->affine.ty=
9588               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9589           }
9590           if (attribute_flag[6] != 0)
9591             image->interpolate=(PixelInterpolateMethod)
9592               argument_list[6].integer_reference;
9593           if (attribute_flag[7] != 0)
9594             QueryColorCompliance(argument_list[7].string_reference,
9595               AllCompliance,&image->background_color,exception);
9596           image=AffineTransformImage(image,&draw_info->affine,exception);
9597           draw_info=DestroyDrawInfo(draw_info);
9598           break;
9599         }
9600         case 76:  /* Difference */
9601         {
9602           if (attribute_flag[0] == 0)
9603             {
9604               ThrowPerlException(exception,OptionError,
9605                 "ReferenceImageRequired",PackageName);
9606               goto PerlException;
9607             }
9608           if (attribute_flag[1] != 0)
9609             image->fuzz=SiPrefixToDouble(argument_list[1].string_reference,
9610               QuantumRange);
9611           (void) IsImagesEqual(image,argument_list[0].image_reference,
9612             exception);
9613           break;
9614         }
9615         case 77:  /* AdaptiveThreshold */
9616         {
9617           if (attribute_flag[0] != 0)
9618             {
9619               flags=ParseGeometry(argument_list[0].string_reference,
9620                 &geometry_info);
9621               if ((flags & PercentValue) != 0)
9622                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9623             }
9624           if (attribute_flag[1] != 0)
9625             geometry_info.rho=argument_list[1].integer_reference;
9626           if (attribute_flag[2] != 0)
9627             geometry_info.sigma=argument_list[2].integer_reference;
9628           if (attribute_flag[3] != 0)
9629             geometry_info.xi=argument_list[3].integer_reference;;
9630           image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
9631             (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
9632           break;
9633         }
9634         case 78:  /* Resample */
9635         {
9636           size_t
9637             height,
9638             width;
9639
9640           if (attribute_flag[0] != 0)
9641             {
9642               flags=ParseGeometry(argument_list[0].string_reference,
9643                 &geometry_info);
9644               if ((flags & SigmaValue) == 0)
9645                 geometry_info.sigma=geometry_info.rho;
9646             }
9647           if (attribute_flag[1] != 0)
9648             geometry_info.rho=argument_list[1].real_reference;
9649           if (attribute_flag[2] != 0)
9650             geometry_info.sigma=argument_list[2].real_reference;
9651           if (attribute_flag[3] == 0)
9652             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
9653           if (attribute_flag[4] == 0)
9654             SetImageArtifact(image,"filter:support",
9655               argument_list[4].string_reference);
9656           if (attribute_flag[5] != 0)
9657             argument_list[5].real_reference=1.0;
9658           width=(size_t) (geometry_info.rho*image->columns/
9659             (image->x_resolution == 0.0 ? 72.0 : image->x_resolution)+0.5);
9660           height=(size_t) (geometry_info.sigma*image->rows/
9661             (image->y_resolution == 0.0 ? 72.0 : image->y_resolution)+0.5);
9662           image=ResizeImage(image,width,height,(FilterTypes)
9663             argument_list[3].integer_reference,argument_list[5].real_reference,
9664             exception);
9665           if (image != (Image *) NULL)
9666             {
9667               image->x_resolution=geometry_info.rho;
9668               image->y_resolution=geometry_info.sigma;
9669             }
9670           break;
9671         }
9672         case 79:  /* Describe */
9673         {
9674           if (attribute_flag[0] == 0)
9675             argument_list[0].file_reference=(FILE *) NULL;
9676           if (attribute_flag[1] != 0)
9677             (void) SetImageArtifact(image,"identify:features",
9678               argument_list[1].string_reference);
9679           (void) IdentifyImage(image,argument_list[0].file_reference,
9680             MagickTrue,exception);
9681           break;
9682         }
9683         case 80:  /* BlackThreshold */
9684         {
9685           if (attribute_flag[0] == 0)
9686             argument_list[0].string_reference="50%";
9687           if (attribute_flag[2] != 0)
9688             channel=(ChannelType) argument_list[2].integer_reference;
9689           channel_mask=SetPixelChannelMask(image,channel);
9690           BlackThresholdImage(image,argument_list[0].string_reference,
9691             exception);
9692           (void) SetPixelChannelMask(image,channel_mask);
9693           break;
9694         }
9695         case 81:  /* WhiteThreshold */
9696         {
9697           if (attribute_flag[0] == 0)
9698             argument_list[0].string_reference="50%";
9699           if (attribute_flag[2] != 0)
9700             channel=(ChannelType) argument_list[2].integer_reference;
9701           channel_mask=SetPixelChannelMask(image,channel);
9702           WhiteThresholdImage(image,argument_list[0].string_reference,
9703             exception);
9704           (void) SetPixelChannelMask(image,channel_mask);
9705           break;
9706         }
9707         case 82:  /* RadialBlur */
9708         {
9709           if (attribute_flag[0] != 0)
9710             {
9711               flags=ParseGeometry(argument_list[0].string_reference,
9712                 &geometry_info);
9713             }
9714           if (attribute_flag[1] != 0)
9715             geometry_info.rho=argument_list[1].real_reference;
9716           if (attribute_flag[2] != 0)
9717             geometry_info.sigma=argument_list[2].real_reference;
9718           if (attribute_flag[3] != 0)
9719             channel=(ChannelType) argument_list[3].integer_reference;
9720           channel_mask=SetPixelChannelMask(image,channel);
9721           image=RadialBlurImage(image,geometry_info.rho,geometry_info.sigma,
9722             exception);
9723           if (image != (Image *) NULL)
9724             (void) SetPixelChannelMask(image,channel_mask);
9725           break;
9726         }
9727         case 83:  /* Thumbnail */
9728         {
9729           if (attribute_flag[0] != 0)
9730             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
9731               &geometry,exception);
9732           if (attribute_flag[1] != 0)
9733             geometry.width=argument_list[1].integer_reference;
9734           if (attribute_flag[2] != 0)
9735             geometry.height=argument_list[2].integer_reference;
9736           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
9737           break;
9738         }
9739         case 84:  /* Strip */
9740         {
9741           (void) StripImage(image);
9742           break;
9743         }
9744         case 85:  /* Tint */
9745         {
9746           PixelInfo
9747             tint;
9748
9749           GetPixelInfo(image,&tint);
9750           if (attribute_flag[0] != 0)
9751             (void) QueryColorCompliance(argument_list[0].string_reference,
9752               AllCompliance,&tint,exception);
9753           if (attribute_flag[1] == 0)
9754             argument_list[1].string_reference="100";
9755           image=TintImage(image,argument_list[1].string_reference,&tint,
9756             exception);
9757           break;
9758         }
9759         case 86:  /* Channel */
9760         {
9761           if (attribute_flag[0] != 0)
9762             channel=(ChannelType) argument_list[0].integer_reference;
9763           channel_mask=SetPixelChannelMask(image,channel);
9764           (void) SeparateImage(image);
9765           (void) SetPixelChannelMask(image,channel_mask);
9766           break;
9767         }
9768         case 87:  /* Splice */
9769         {
9770           if (attribute_flag[0] != 0)
9771             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
9772               &geometry,exception);
9773           if (attribute_flag[1] != 0)
9774             geometry.width=argument_list[1].integer_reference;
9775           if (attribute_flag[2] != 0)
9776             geometry.height=argument_list[2].integer_reference;
9777           if (attribute_flag[3] != 0)
9778             geometry.x=argument_list[3].integer_reference;
9779           if (attribute_flag[4] != 0)
9780             geometry.y=argument_list[4].integer_reference;
9781           if (attribute_flag[5] != 0)
9782             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
9783               QuantumRange);
9784           if (attribute_flag[6] != 0)
9785             (void) QueryColorCompliance(argument_list[6].string_reference,
9786               AllCompliance,&image->background_color,exception);
9787           if (attribute_flag[7] != 0)
9788             image->gravity=(GravityType) argument_list[7].integer_reference;
9789           image=SpliceImage(image,&geometry,exception);
9790           break;
9791         }
9792         case 88:  /* Posterize */
9793         {
9794           if (attribute_flag[0] == 0)
9795             argument_list[0].integer_reference=3;
9796           if (attribute_flag[1] == 0)
9797             argument_list[1].integer_reference=0;
9798           (void) PosterizeImage(image,argument_list[0].integer_reference,
9799             argument_list[1].integer_reference ? MagickTrue : MagickFalse,
9800             exception);
9801           break;
9802         }
9803         case 89:  /* Shadow */
9804         {
9805           if (attribute_flag[0] != 0)
9806             {
9807               flags=ParseGeometry(argument_list[0].string_reference,
9808                 &geometry_info);
9809               if ((flags & SigmaValue) == 0)
9810                 geometry_info.sigma=1.0;
9811               if ((flags & XiValue) == 0)
9812                 geometry_info.xi=4.0;
9813               if ((flags & PsiValue) == 0)
9814                 geometry_info.psi=4.0;
9815             }
9816           if (attribute_flag[1] != 0)
9817             geometry_info.rho=argument_list[1].real_reference;
9818           if (attribute_flag[2] != 0)
9819             geometry_info.sigma=argument_list[2].real_reference;
9820           if (attribute_flag[3] != 0)
9821             geometry_info.xi=argument_list[3].integer_reference;
9822           if (attribute_flag[4] != 0)
9823             geometry_info.psi=argument_list[4].integer_reference;
9824           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
9825             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-
9826             0.5),exception);
9827           break;
9828         }
9829         case 90:  /* Identify */
9830         {
9831           if (attribute_flag[0] == 0)
9832             argument_list[0].file_reference=(FILE *) NULL;
9833           if (attribute_flag[1] != 0)
9834             (void) SetImageArtifact(image,"identify:features",
9835               argument_list[1].string_reference);
9836           if ((attribute_flag[2] != 0) &&
9837               (argument_list[2].integer_reference != 0))
9838             (void) SetImageArtifact(image,"identify:unique","true");
9839           (void) IdentifyImage(image,argument_list[0].file_reference,
9840             MagickTrue,exception);
9841           break;
9842         }
9843         case 91:  /* SepiaTone */
9844         {
9845           if (attribute_flag[0] == 0)
9846             argument_list[0].real_reference=80.0*QuantumRange/100.0;
9847           image=SepiaToneImage(image,argument_list[0].real_reference,
9848             exception);
9849           break;
9850         }
9851         case 92:  /* SigmoidalContrast */
9852         {
9853           MagickBooleanType
9854             sharpen;
9855
9856           if (attribute_flag[0] != 0)
9857             {
9858               flags=ParseGeometry(argument_list[0].string_reference,
9859                 &geometry_info);
9860               if ((flags & SigmaValue) == 0)
9861                 geometry_info.sigma=QuantumRange/2.0;
9862               if ((flags & PercentValue) != 0)
9863                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
9864             }
9865           if (attribute_flag[1] != 0)
9866             geometry_info.rho=argument_list[1].real_reference;
9867           if (attribute_flag[2] != 0)
9868             geometry_info.sigma=argument_list[2].real_reference;
9869           if (attribute_flag[3] != 0)
9870             channel=(ChannelType) argument_list[3].integer_reference;
9871           sharpen=MagickTrue;
9872           if (attribute_flag[4] != 0)
9873             sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
9874               MagickFalse;
9875           channel_mask=SetPixelChannelMask(image,channel);
9876           (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
9877             geometry_info.sigma,exception);
9878           (void) SetPixelChannelMask(image,channel_mask);
9879           break;
9880         }
9881         case 93:  /* Extent */
9882         {
9883           if (attribute_flag[7] != 0)
9884             image->gravity=(GravityType) argument_list[7].integer_reference;
9885           if (attribute_flag[0] != 0)
9886             {
9887               int
9888                 flags;
9889
9890               flags=ParseGravityGeometry(image,
9891                 argument_list[0].string_reference,&geometry,exception);
9892               (void) flags;
9893               if (geometry.width == 0)
9894                 geometry.width=image->columns;
9895               if (geometry.height == 0)
9896                 geometry.height=image->rows;
9897             }
9898           if (attribute_flag[1] != 0)
9899             geometry.width=argument_list[1].integer_reference;
9900           if (attribute_flag[2] != 0)
9901             geometry.height=argument_list[2].integer_reference;
9902           if (attribute_flag[3] != 0)
9903             geometry.x=argument_list[3].integer_reference;
9904           if (attribute_flag[4] != 0)
9905             geometry.y=argument_list[4].integer_reference;
9906           if (attribute_flag[5] != 0)
9907             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
9908               QuantumRange);
9909           if (attribute_flag[6] != 0)
9910             (void) QueryColorCompliance(argument_list[6].string_reference,
9911               AllCompliance,&image->background_color,exception);
9912           image=ExtentImage(image,&geometry,exception);
9913           break;
9914         }
9915         case 94:  /* Vignette */
9916         {
9917           if (attribute_flag[0] != 0)
9918             {
9919               flags=ParseGeometry(argument_list[0].string_reference,
9920                 &geometry_info);
9921               if ((flags & SigmaValue) == 0)
9922                 geometry_info.sigma=1.0;
9923               if ((flags & XiValue) == 0)
9924                 geometry_info.xi=0.1*image->columns;
9925               if ((flags & PsiValue) == 0)
9926                 geometry_info.psi=0.1*image->rows;
9927             }
9928           if (attribute_flag[1] != 0)
9929             geometry_info.rho=argument_list[1].real_reference;
9930           if (attribute_flag[2] != 0)
9931             geometry_info.sigma=argument_list[2].real_reference;
9932           if (attribute_flag[3] != 0)
9933             geometry_info.xi=argument_list[3].integer_reference;
9934           if (attribute_flag[4] != 0)
9935             geometry_info.psi=argument_list[4].integer_reference;
9936           if (attribute_flag[5] != 0)
9937             (void) QueryColorCompliance(argument_list[5].string_reference,
9938               AllCompliance,&image->background_color,exception);
9939           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
9940             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-
9941             0.5),exception);
9942           break;
9943         }
9944         case 95:  /* ContrastStretch */
9945         {
9946           double
9947             black_point,
9948             white_point;
9949
9950           black_point=0.0;
9951           white_point=(MagickRealType) image->columns*image->rows;
9952           if (attribute_flag[0] != 0)
9953             {
9954               flags=ParseGeometry(argument_list[0].string_reference,
9955                 &geometry_info);
9956               black_point=geometry_info.rho;
9957               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
9958                 black_point;
9959               if ((flags & PercentValue) != 0)
9960                 {
9961                   black_point*=(double) image->columns*image->rows/100.0;
9962                   white_point*=(double) image->columns*image->rows/100.0;
9963                 }
9964               white_point=(MagickRealType) image->columns*image->rows-
9965                 white_point;
9966             }
9967           if (attribute_flag[1] != 0)
9968             black_point=argument_list[1].real_reference;
9969           if (attribute_flag[2] != 0)
9970             white_point=argument_list[2].real_reference;
9971           if (attribute_flag[4] != 0)
9972             channel=(ChannelType) argument_list[4].integer_reference;
9973           channel_mask=SetPixelChannelMask(image,channel);
9974           (void) ContrastStretchImage(image,black_point,white_point,exception);
9975           (void) SetPixelChannelMask(image,channel_mask);
9976           break;
9977         }
9978         case 96:  /* Sans0 */
9979         {
9980           break;
9981         }
9982         case 97:  /* Sans1 */
9983         {
9984           break;
9985         }
9986         case 98:  /* AdaptiveSharpen */
9987         {
9988           if (attribute_flag[0] != 0)
9989             {
9990               flags=ParseGeometry(argument_list[0].string_reference,
9991                 &geometry_info);
9992               if ((flags & SigmaValue) == 0)
9993                 geometry_info.sigma=1.0;
9994               if ((flags & XiValue) == 0)
9995                 geometry_info.xi=0.0;
9996             }
9997           if (attribute_flag[1] != 0)
9998             geometry_info.rho=argument_list[1].real_reference;
9999           if (attribute_flag[2] != 0)
10000             geometry_info.sigma=argument_list[2].real_reference;
10001           if (attribute_flag[3] != 0)
10002             geometry_info.xi=argument_list[3].real_reference;
10003           if (attribute_flag[4] != 0)
10004             channel=(ChannelType) argument_list[4].integer_reference;
10005           channel_mask=SetPixelChannelMask(image,channel);
10006           image=AdaptiveSharpenImage(image,geometry_info.rho,
10007             geometry_info.sigma,geometry_info.xi,exception);
10008           if (image != (Image *) NULL)
10009             (void) SetPixelChannelMask(image,channel_mask);
10010           break;
10011         }
10012         case 99:  /* Transpose */
10013         {
10014           image=TransposeImage(image,exception);
10015           break;
10016         }
10017         case 100:  /* Tranverse */
10018         {
10019           image=TransverseImage(image,exception);
10020           break;
10021         }
10022         case 101:  /* AutoOrient */
10023         {
10024           switch (image->orientation)
10025           {
10026             case TopRightOrientation:
10027             {
10028               image=FlopImage(image,exception);
10029               break;
10030             }
10031             case BottomRightOrientation:
10032             {
10033               image=RotateImage(image,180.0,exception);
10034               break;
10035             }
10036             case BottomLeftOrientation:
10037             {
10038               image=FlipImage(image,exception);
10039               break;
10040             }
10041             case LeftTopOrientation:
10042             {
10043               image=TransposeImage(image,exception);
10044               break;
10045             }
10046             case RightTopOrientation:
10047             {
10048               image=RotateImage(image,90.0,exception);
10049               break;
10050             }
10051             case RightBottomOrientation:
10052             {
10053               image=TransverseImage(image,exception);
10054               break;
10055             }
10056             case LeftBottomOrientation:
10057             {
10058               image=RotateImage(image,270.0,exception);
10059               break;
10060             }
10061             default:
10062               break;
10063           }
10064           break;
10065         }
10066         case 102:  /* AdaptiveBlur */
10067         {
10068           if (attribute_flag[0] != 0)
10069             {
10070               flags=ParseGeometry(argument_list[0].string_reference,
10071                 &geometry_info);
10072               if ((flags & SigmaValue) == 0)
10073                 geometry_info.sigma=1.0;
10074               if ((flags & XiValue) == 0)
10075                 geometry_info.xi=0.0;
10076             }
10077           if (attribute_flag[1] != 0)
10078             geometry_info.rho=argument_list[1].real_reference;
10079           if (attribute_flag[2] != 0)
10080             geometry_info.sigma=argument_list[2].real_reference;
10081           if (attribute_flag[3] != 0)
10082             geometry_info.xi=argument_list[3].real_reference;
10083           if (attribute_flag[4] != 0)
10084             channel=(ChannelType) argument_list[4].integer_reference;
10085           channel_mask=SetPixelChannelMask(image,channel);
10086           image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10087             geometry_info.xi,exception);
10088           if (image != (Image *) NULL)
10089             (void) SetPixelChannelMask(image,channel_mask);
10090           break;
10091         }
10092         case 103:  /* Sketch */
10093         {
10094           if (attribute_flag[0] != 0)
10095             {
10096               flags=ParseGeometry(argument_list[0].string_reference,
10097                 &geometry_info);
10098               if ((flags & SigmaValue) == 0)
10099                 geometry_info.sigma=1.0;
10100               if ((flags & XiValue) == 0)
10101                 geometry_info.xi=1.0;
10102             }
10103           if (attribute_flag[1] != 0)
10104             geometry_info.rho=argument_list[1].real_reference;
10105           if (attribute_flag[2] != 0)
10106             geometry_info.sigma=argument_list[2].real_reference;
10107           if (attribute_flag[3] != 0)
10108             geometry_info.xi=argument_list[3].real_reference;
10109           if (attribute_flag[4] != 0)
10110             geometry_info.psi=argument_list[4].real_reference;
10111           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10112             geometry_info.xi,geometry_info.psi,exception);
10113           break;
10114         }
10115         case 104:  /* UniqueColors */
10116         {
10117           image=UniqueImageColors(image,exception);
10118           break;
10119         }
10120         case 105:  /* AdaptiveResize */
10121         {
10122           PixelInterpolateMethod
10123             method;
10124
10125           if (attribute_flag[0] != 0)
10126             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10127               &geometry,exception);
10128           if (attribute_flag[1] != 0)
10129             geometry.width=argument_list[1].integer_reference;
10130           if (attribute_flag[2] != 0)
10131             geometry.height=argument_list[2].integer_reference;
10132           if (attribute_flag[3] != 0)
10133             image->filter=(FilterTypes) argument_list[4].integer_reference;
10134           if (attribute_flag[4] != 0)
10135             SetImageArtifact(image,"filter:support",
10136               argument_list[4].string_reference);
10137           if (attribute_flag[5] != 0)
10138             image->blur=argument_list[5].real_reference;
10139           method=UndefinedInterpolatePixel;
10140           if (attribute_flag[6] != 0)
10141             method=(PixelInterpolateMethod) argument_list[6].integer_reference;
10142           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10143             method,exception);
10144           break;
10145         }
10146         case 106:  /* ClipMask */
10147         {
10148           if (attribute_flag[0] == 0)
10149             {
10150               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10151                 PackageName);
10152               goto PerlException;
10153             }
10154           image->clip_mask=CloneImage(argument_list[0].image_reference,0,0,
10155             MagickTrue,exception);
10156           (void) NegateImage(image->clip_mask,MagickFalse,exception);
10157           break;
10158         }
10159         case 107:  /* LinearStretch */
10160         {
10161            double
10162              black_point,
10163              white_point;
10164
10165            black_point=0.0;
10166            white_point=(MagickRealType) image->columns*image->rows;
10167            if (attribute_flag[0] != 0)
10168              {
10169                flags=ParseGeometry(argument_list[0].string_reference,
10170                  &geometry_info);
10171                if ((flags & SigmaValue) != 0)
10172                   white_point=geometry_info.sigma;
10173                if ((flags & PercentValue) != 0)
10174                  {
10175                    black_point*=(double) image->columns*image->rows/100.0;
10176                    white_point*=(double) image->columns*image->rows/100.0;
10177                  }
10178                if ((flags & SigmaValue) == 0)
10179                  white_point=(double) image->columns*image->rows-black_point;
10180              }
10181           if (attribute_flag[1] != 0)
10182             black_point=argument_list[1].real_reference;
10183           if (attribute_flag[2] != 0)
10184             white_point=argument_list[2].real_reference;
10185           (void) LinearStretchImage(image,black_point,white_point,exception);
10186           break;
10187         }
10188         case 109:  /* Mask */
10189         {
10190           if (attribute_flag[0] == 0)
10191             {
10192               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10193                 PackageName);
10194               goto PerlException;
10195             }
10196           image->mask=CloneImage(argument_list[0].image_reference,0,0,
10197             MagickTrue,exception);
10198           (void) NegateImage(image->mask,MagickFalse,exception);
10199           break;
10200         }
10201         case 110:  /* Polaroid */
10202         {
10203           DrawInfo
10204             *draw_info;
10205
10206           double
10207             angle;
10208
10209           PixelInterpolateMethod
10210             method;
10211
10212           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10213             (DrawInfo *) NULL);
10214           if (attribute_flag[0] != 0)
10215             (void) SetImageProperty(image,"caption",InterpretImageProperties(
10216               info ? info->image_info : (ImageInfo *) NULL,image,
10217               argument_list[0].string_reference,exception),exception);
10218           angle=0.0;
10219           if (attribute_flag[1] != 0)
10220             angle=argument_list[1].real_reference;
10221           if (attribute_flag[2] != 0)
10222             (void) CloneString(&draw_info->font,
10223               argument_list[2].string_reference);
10224           if (attribute_flag[3] != 0)
10225             (void) QueryColorCompliance(argument_list[3].string_reference,
10226               AllCompliance,&draw_info->stroke,exception);
10227           if (attribute_flag[4] != 0)
10228             (void) QueryColorCompliance(argument_list[4].string_reference,
10229               AllCompliance,&draw_info->fill,exception);
10230           if (attribute_flag[5] != 0)
10231             draw_info->stroke_width=argument_list[5].real_reference;
10232           if (attribute_flag[6] != 0)
10233             draw_info->pointsize=argument_list[6].real_reference;
10234           if (attribute_flag[7] != 0)
10235             draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10236           if (attribute_flag[8] != 0)
10237             (void) QueryColorCompliance(argument_list[8].string_reference,
10238               AllCompliance,&image->background_color,exception);
10239           method=UndefinedInterpolatePixel;
10240           if (attribute_flag[9] != 0)
10241             method=(PixelInterpolateMethod) argument_list[9].integer_reference;
10242           image=PolaroidImage(image,draw_info,angle,method,exception);
10243           draw_info=DestroyDrawInfo(draw_info);
10244           break;
10245         }
10246         case 111:  /* FloodfillPaint */
10247         {
10248           DrawInfo
10249             *draw_info;
10250
10251           MagickBooleanType
10252             invert;
10253
10254           PixelInfo
10255             target;
10256
10257           Quantum
10258             virtual_pixel[MaxPixelChannels];
10259
10260           draw_info=CloneDrawInfo(info ? info->image_info :
10261             (ImageInfo *) NULL,(DrawInfo *) NULL);
10262           if (attribute_flag[0] != 0)
10263             flags=ParsePageGeometry(image,argument_list[0].string_reference,
10264               &geometry,exception);
10265           if (attribute_flag[1] != 0)
10266             geometry.x=argument_list[1].integer_reference;
10267           if (attribute_flag[2] != 0)
10268             geometry.y=argument_list[2].integer_reference;
10269           if (attribute_flag[3] != 0)
10270             (void) QueryColorCompliance(argument_list[3].string_reference,
10271               AllCompliance,&draw_info->fill,exception);
10272           (void) GetOneVirtualPixel(image,geometry.x,geometry.y,virtual_pixel,
10273             exception);
10274           target.red=virtual_pixel[RedPixelChannel];
10275           target.green=virtual_pixel[GreenPixelChannel];
10276           target.blue=virtual_pixel[BluePixelChannel];
10277           target.alpha=virtual_pixel[AlphaPixelChannel];
10278           if (attribute_flag[4] != 0)
10279             QueryColorCompliance(argument_list[4].string_reference,
10280               AllCompliance,&target,exception);
10281           if (attribute_flag[5] != 0)
10282             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
10283               QuantumRange);
10284           if (attribute_flag[6] != 0)
10285             channel=(ChannelType) argument_list[6].integer_reference;
10286           invert=MagickFalse;
10287           if (attribute_flag[7] != 0)
10288             invert=(MagickBooleanType) argument_list[7].integer_reference;
10289           channel_mask=SetPixelChannelMask(image,channel);
10290           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10291             geometry.y,invert,exception);
10292           (void) SetPixelChannelMask(image,channel_mask);
10293           draw_info=DestroyDrawInfo(draw_info);
10294           break;
10295         }
10296         case 112:  /* Distort */
10297         {
10298           AV
10299             *av;
10300
10301           double
10302             *coordinates;
10303
10304           DistortImageMethod
10305             method;
10306
10307           size_t
10308             number_coordinates;
10309
10310           VirtualPixelMethod
10311             virtual_pixel;
10312
10313           if (attribute_flag[0] == 0)
10314             break;
10315           method=UndefinedDistortion;
10316           if (attribute_flag[1] != 0)
10317             method=(DistortImageMethod) argument_list[1].integer_reference;
10318           av=(AV *) argument_list[0].array_reference;
10319           number_coordinates=(size_t) av_len(av)+1;
10320           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10321             sizeof(*coordinates));
10322           if (coordinates == (double *) NULL)
10323             {
10324               ThrowPerlException(exception,ResourceLimitFatalError,
10325                 "MemoryAllocationFailed",PackageName);
10326               goto PerlException;
10327             }
10328           for (j=0; j < (ssize_t) number_coordinates; j++)
10329             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10330           virtual_pixel=UndefinedVirtualPixelMethod;
10331           if (attribute_flag[2] != 0)
10332             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10333               argument_list[2].integer_reference);
10334           image=DistortImage(image,method,number_coordinates,coordinates,
10335             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10336             exception);
10337           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10338             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10339           coordinates=(double *) RelinquishMagickMemory(coordinates);
10340           break;
10341         }
10342         case 113:  /* Clut */
10343         {
10344           PixelInterpolateMethod
10345             method;
10346
10347           if (attribute_flag[0] == 0)
10348             {
10349               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10350                 PackageName);
10351               goto PerlException;
10352             }
10353           method=UndefinedInterpolatePixel;
10354           if (attribute_flag[1] != 0)
10355             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
10356           if (attribute_flag[2] != 0)
10357             channel=(ChannelType) argument_list[2].integer_reference;
10358           channel_mask=SetPixelChannelMask(image,channel);
10359           (void) ClutImage(image,argument_list[0].image_reference,method,
10360             exception);
10361           (void) SetPixelChannelMask(image,channel_mask);
10362           break;
10363         }
10364         case 114:  /* LiquidRescale */
10365         {
10366           if (attribute_flag[0] != 0)
10367             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10368               &geometry,exception);
10369           if (attribute_flag[1] != 0)
10370             geometry.width=argument_list[1].integer_reference;
10371           if (attribute_flag[2] != 0)
10372             geometry.height=argument_list[2].integer_reference;
10373           if (attribute_flag[3] == 0)
10374             argument_list[3].real_reference=1.0;
10375           if (attribute_flag[4] == 0)
10376             argument_list[4].real_reference=0.0;
10377           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10378             argument_list[3].real_reference,argument_list[4].real_reference,
10379             exception);
10380           break;
10381         }
10382         case 115:  /* EncipherImage */
10383         {
10384           (void) EncipherImage(image,argument_list[0].string_reference,
10385             exception);
10386           break;
10387         }
10388         case 116:  /* DecipherImage */
10389         {
10390           (void) DecipherImage(image,argument_list[0].string_reference,
10391             exception);
10392           break;
10393         }
10394         case 117:  /* Deskew */
10395         {
10396           geometry_info.rho=QuantumRange/2.0;
10397           if (attribute_flag[0] != 0)
10398             flags=ParseGeometry(argument_list[0].string_reference,
10399               &geometry_info);
10400           if (attribute_flag[1] != 0)
10401             geometry_info.rho=SiPrefixToDouble(
10402               argument_list[1].string_reference,QuantumRange);
10403           image=DeskewImage(image,geometry_info.rho,exception);
10404           break;
10405         }
10406         case 118:  /* Remap */
10407         {
10408           QuantizeInfo
10409             *quantize_info;
10410
10411           if (attribute_flag[0] == 0)
10412             {
10413               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10414                 PackageName);
10415               goto PerlException;
10416             }
10417           quantize_info=AcquireQuantizeInfo(info->image_info);
10418           if (attribute_flag[1] != 0)
10419             quantize_info->dither=(MagickBooleanType)
10420               argument_list[1].integer_reference;
10421           if (attribute_flag[2] != 0)
10422             quantize_info->dither_method=(DitherMethod)
10423               argument_list[2].integer_reference;
10424           (void) RemapImages(quantize_info,image,
10425             argument_list[0].image_reference,exception);
10426           quantize_info=DestroyQuantizeInfo(quantize_info);
10427           break;
10428         }
10429         case 119:  /* SparseColor */
10430         {
10431           AV
10432             *av;
10433
10434           double
10435             *coordinates;
10436
10437           SparseColorMethod
10438             method;
10439
10440           size_t
10441             number_coordinates;
10442
10443           VirtualPixelMethod
10444             virtual_pixel;
10445
10446           if (attribute_flag[0] == 0)
10447             break;
10448           method=UndefinedColorInterpolate;
10449           if (attribute_flag[1] != 0)
10450             method=(SparseColorMethod) argument_list[1].integer_reference;
10451           av=(AV *) argument_list[0].array_reference;
10452           number_coordinates=(size_t) av_len(av)+1;
10453           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10454             sizeof(*coordinates));
10455           if (coordinates == (double *) NULL)
10456             {
10457               ThrowPerlException(exception,ResourceLimitFatalError,
10458                 "MemoryAllocationFailed",PackageName);
10459               goto PerlException;
10460             }
10461           for (j=0; j < (ssize_t) number_coordinates; j++)
10462             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10463           virtual_pixel=UndefinedVirtualPixelMethod;
10464           if (attribute_flag[2] != 0)
10465             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10466               argument_list[2].integer_reference);
10467           if (attribute_flag[3] != 0)
10468             channel=(ChannelType) argument_list[3].integer_reference;
10469           channel_mask=SetPixelChannelMask(image,channel);
10470           image=SparseColorImage(image,method,number_coordinates,coordinates,
10471             exception);
10472           if (image != (Image *) NULL)
10473             (void) SetPixelChannelMask(image,channel_mask);
10474           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10475             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10476           coordinates=(double *) RelinquishMagickMemory(coordinates);
10477           break;
10478         }
10479         case 120:  /* Function */
10480         {
10481           AV
10482             *av;
10483
10484           double
10485             *parameters;
10486
10487           MagickFunction
10488             function;
10489
10490           size_t
10491             number_parameters;
10492
10493           VirtualPixelMethod
10494             virtual_pixel;
10495
10496           if (attribute_flag[0] == 0)
10497             break;
10498           function=UndefinedFunction;
10499           if (attribute_flag[1] != 0)
10500             function=(MagickFunction) argument_list[1].integer_reference;
10501           av=(AV *) argument_list[0].array_reference;
10502           number_parameters=(size_t) av_len(av)+1;
10503           parameters=(double *) AcquireQuantumMemory(number_parameters,
10504             sizeof(*parameters));
10505           if (parameters == (double *) NULL)
10506             {
10507               ThrowPerlException(exception,ResourceLimitFatalError,
10508                 "MemoryAllocationFailed",PackageName);
10509               goto PerlException;
10510             }
10511           for (j=0; j < (ssize_t) number_parameters; j++)
10512             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10513           virtual_pixel=UndefinedVirtualPixelMethod;
10514           if (attribute_flag[2] != 0)
10515             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10516               argument_list[2].integer_reference);
10517           (void) FunctionImage(image,function,number_parameters,parameters,
10518             exception);
10519           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10520             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10521           parameters=(double *) RelinquishMagickMemory(parameters);
10522           break;
10523         }
10524         case 121:  /* SelectiveBlur */
10525         {
10526           if (attribute_flag[0] != 0)
10527             {
10528               flags=ParseGeometry(argument_list[0].string_reference,
10529                 &geometry_info);
10530               if ((flags & SigmaValue) == 0)
10531                 geometry_info.sigma=1.0;
10532               if ((flags & PercentValue) != 0)
10533                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10534             }
10535           if (attribute_flag[1] != 0)
10536             geometry_info.rho=argument_list[1].real_reference;
10537           if (attribute_flag[2] != 0)
10538             geometry_info.sigma=argument_list[2].real_reference;
10539           if (attribute_flag[3] != 0)
10540             geometry_info.xi=argument_list[3].integer_reference;;
10541           if (attribute_flag[4] != 0)
10542             geometry_info.psi=argument_list[4].integer_reference;;
10543           if (attribute_flag[5] != 0)
10544             channel=(ChannelType) argument_list[5].integer_reference;
10545           channel_mask=SetPixelChannelMask(image,channel);
10546           image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10547             geometry_info.xi,geometry_info.psi,exception);
10548           if (image != (Image *) NULL)
10549             (void) SetPixelChannelMask(image,channel_mask);
10550           break;
10551         }
10552         case 122:  /* HaldClut */
10553         {
10554           if (attribute_flag[0] == 0)
10555             {
10556               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10557                 PackageName);
10558               goto PerlException;
10559             }
10560           if (attribute_flag[1] != 0)
10561             channel=(ChannelType) argument_list[1].integer_reference;
10562           channel_mask=SetPixelChannelMask(image,channel);
10563           (void) HaldClutImage(image,argument_list[0].image_reference,
10564             exception);
10565           (void) SetPixelChannelMask(image,channel_mask);
10566           break;
10567         }
10568         case 123:  /* BlueShift */
10569         {
10570           if (attribute_flag[0] != 0)
10571             (void) ParseGeometry(argument_list[0].string_reference,
10572               &geometry_info);
10573           image=BlueShiftImage(image,geometry_info.rho,exception);
10574           break;
10575         }
10576         case 124:  /* ForwardFourierTransformImage */
10577         {
10578           image=ForwardFourierTransformImage(image,
10579             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10580             exception);
10581           break;
10582         }
10583         case 125:  /* InverseFourierTransformImage */
10584         {
10585           image=InverseFourierTransformImage(image,image->next,
10586             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10587             exception);
10588           break;
10589         }
10590         case 126:  /* ColorDecisionList */
10591         {
10592           if (attribute_flag[0] == 0)
10593             argument_list[0].string_reference=(char *) NULL;
10594           (void) ColorDecisionListImage(image,
10595             argument_list[0].string_reference,exception);
10596           break;
10597         }
10598         case 127:  /* AutoGamma */
10599         {
10600           if (attribute_flag[0] != 0)
10601             channel=(ChannelType) argument_list[0].integer_reference;
10602           channel_mask=SetPixelChannelMask(image,channel);
10603           (void) AutoGammaImage(image,exception);
10604           (void) SetPixelChannelMask(image,channel_mask);
10605           break;
10606         }
10607         case 128:  /* AutoLevel */
10608         {
10609           if (attribute_flag[0] != 0)
10610             channel=(ChannelType) argument_list[0].integer_reference;
10611           channel_mask=SetPixelChannelMask(image,channel);
10612           (void) AutoLevelImage(image,exception);
10613           (void) SetPixelChannelMask(image,channel_mask);
10614           break;
10615         }
10616         case 129:  /* LevelColors */
10617         {
10618           PixelInfo
10619             black_point,
10620             white_point;
10621
10622           (void) QueryColorCompliance("#000000",AllCompliance,
10623             &black_point,exception);
10624           (void) QueryColorCompliance("#ffffff",AllCompliance,
10625             &white_point,exception);
10626           if (attribute_flag[1] != 0)
10627              (void) QueryColorCompliance(
10628                argument_list[1].string_reference,AllCompliance,&black_point,
10629                exception);
10630           if (attribute_flag[2] != 0)
10631              (void) QueryColorCompliance(
10632                argument_list[2].string_reference,AllCompliance,&white_point,
10633                exception);
10634           if (attribute_flag[3] != 0)
10635             channel=(ChannelType) argument_list[3].integer_reference;
10636           channel_mask=SetPixelChannelMask(image,channel);
10637           (void) LevelImageColors(image,&black_point,&white_point,
10638             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10639             exception);
10640           (void) SetPixelChannelMask(image,channel_mask);
10641           break;
10642         }
10643         case 130:  /* Clamp */
10644         {
10645           if (attribute_flag[0] != 0)
10646             channel=(ChannelType) argument_list[0].integer_reference;
10647           channel_mask=SetPixelChannelMask(image,channel);
10648           (void) ClampImage(image,exception);
10649           (void) SetPixelChannelMask(image,channel_mask);
10650           break;
10651         }
10652         case 132:  /* BrightnessContrast */
10653         {
10654           double
10655             brightness,
10656             contrast;
10657
10658           brightness=0.0;
10659           contrast=0.0;
10660           if (attribute_flag[0] != 0)
10661             {
10662               flags=ParseGeometry(argument_list[0].string_reference,
10663                 &geometry_info);
10664               brightness=geometry_info.rho;
10665               if ((flags & SigmaValue) == 0)
10666                 contrast=geometry_info.sigma;
10667             }
10668           if (attribute_flag[1] != 0)
10669             brightness=argument_list[1].real_reference;
10670           if (attribute_flag[2] != 0)
10671             contrast=argument_list[2].real_reference;
10672           if (attribute_flag[4] != 0)
10673             channel=(ChannelType) argument_list[4].integer_reference;
10674           channel_mask=SetPixelChannelMask(image,channel);
10675           (void) BrightnessContrastImage(image,brightness,contrast,exception);
10676           (void) SetPixelChannelMask(image,channel_mask);
10677           break;
10678         }
10679         case 133:  /* Morphology */
10680         {
10681           KernelInfo
10682             *kernel;
10683
10684           MorphologyMethod
10685             method;
10686
10687           ssize_t
10688             iterations;
10689
10690           if (attribute_flag[0] == 0)
10691             break;
10692           kernel=AcquireKernelInfo(argument_list[0].string_reference);
10693           if (kernel == (KernelInfo *) NULL)
10694             break;
10695           if (attribute_flag[1] != 0)
10696             channel=(ChannelType) argument_list[1].integer_reference;
10697           method=UndefinedMorphology;
10698           if (attribute_flag[2] != 0)
10699             method=argument_list[2].integer_reference;
10700           iterations=1;
10701           if (attribute_flag[3] != 0)
10702             iterations=argument_list[4].integer_reference;
10703           channel_mask=SetPixelChannelMask(image,channel);
10704           image=MorphologyImage(image,method,iterations,kernel,exception);
10705           if (image != (Image *) NULL)
10706             (void) SetPixelChannelMask(image,channel_mask);
10707           kernel=DestroyKernelInfo(kernel);
10708           break;
10709         }
10710         case 108:  /* Recolor */
10711         case 134:  /* ColorMatrix */
10712         {
10713           AV
10714             *av;
10715
10716           double
10717             *color_matrix;
10718
10719           KernelInfo
10720             *kernel_info;
10721
10722           size_t
10723             order;
10724
10725           if (attribute_flag[0] == 0)
10726             break;
10727           av=(AV *) argument_list[0].array_reference;
10728           if (av == (AV *) NULL)
10729             break;
10730           order=(size_t) sqrt(av_len(av)+1);
10731           color_matrix=(double *) AcquireQuantumMemory(order,order*
10732             sizeof(*color_matrix));
10733           if (color_matrix == (double *) NULL)
10734             {
10735               ThrowPerlException(exception,ResourceLimitFatalError,
10736                 "MemoryAllocationFailed",PackageName);
10737               goto PerlException;
10738            }
10739           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10740             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10741           for ( ; j < (ssize_t) (order*order); j++)
10742             color_matrix[j]=0.0;
10743           kernel_info=AcquireKernelInfo((const char *) NULL);
10744           if (kernel_info == (KernelInfo *) NULL)
10745             break;
10746           kernel_info->width=order;
10747           kernel_info->height=order;
10748           kernel_info->values=color_matrix;
10749           image=ColorMatrixImage(image,kernel_info,exception);
10750           kernel_info->values=(double *) NULL;
10751           kernel_info=DestroyKernelInfo(kernel_info);
10752           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10753           break;
10754         }
10755         case 135:  /* Color */
10756         {
10757           PixelInfo
10758             color;
10759
10760           (void) QueryColorCompliance("none",AllCompliance,&color,
10761             exception);
10762           if (attribute_flag[0] != 0)
10763             (void) QueryColorCompliance(argument_list[0].string_reference,
10764               AllCompliance,&color,exception);
10765           (void) SetImageColor(image,&color);
10766           break;
10767         }
10768         case 136:  /* Mode */
10769         {
10770           if (attribute_flag[0] != 0)
10771             {
10772               flags=ParseGeometry(argument_list[0].string_reference,
10773                 &geometry_info);
10774               if ((flags & SigmaValue) == 0)
10775                 geometry_info.sigma=1.0;
10776             }
10777           if (attribute_flag[1] != 0)
10778             geometry_info.rho=argument_list[1].real_reference;
10779           if (attribute_flag[2] != 0)
10780             geometry_info.sigma=argument_list[2].real_reference;
10781           if (attribute_flag[3] != 0)
10782             channel=(ChannelType) argument_list[3].integer_reference;
10783           channel_mask=SetPixelChannelMask(image,channel);
10784           image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
10785             (size_t) geometry_info.sigma,exception);
10786           if (image != (Image *) NULL)
10787             (void) SetPixelChannelMask(image,channel_mask);
10788           break;
10789         }
10790         case 137:  /* Statistic */
10791         {
10792           StatisticType
10793             statistic;
10794
10795           statistic=UndefinedStatistic;
10796           if (attribute_flag[0] != 0)
10797             {
10798               flags=ParseGeometry(argument_list[0].string_reference,
10799                 &geometry_info);
10800               if ((flags & SigmaValue) == 0)
10801                 geometry_info.sigma=1.0;
10802             }
10803           if (attribute_flag[1] != 0)
10804             geometry_info.rho=argument_list[1].real_reference;
10805           if (attribute_flag[2] != 0)
10806             geometry_info.sigma=argument_list[2].real_reference;
10807           if (attribute_flag[3] != 0)
10808             channel=(ChannelType) argument_list[3].integer_reference;
10809           if (attribute_flag[4] != 0)
10810             statistic=(StatisticType) argument_list[4].integer_reference;
10811           channel_mask=SetPixelChannelMask(image,channel);
10812           image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
10813             (size_t) geometry_info.sigma,exception);
10814           if (image != (Image *) NULL)
10815             (void) SetPixelChannelMask(image,channel_mask);
10816           break;
10817         }
10818       }
10819       if (next != (Image *) NULL)
10820         (void) CatchImageException(next);
10821       if (region_image != (Image *) NULL)
10822         {
10823           /*
10824             Composite region.
10825           */ 
10826           status=CompositeImage(region_image,CopyCompositeOp,image,
10827             region_info.x,region_info.y);
10828           (void) status;
10829           (void) CatchImageException(region_image);
10830           image=DestroyImage(image);
10831           image=region_image;
10832         }
10833       if (image != (Image *) NULL)
10834         {
10835           number_images++;
10836           if (next && (next != image))
10837             {
10838               image->next=next->next;
10839               if (image->next != (Image *) NULL)
10840                 image->next->previous=image;
10841               DeleteImageFromRegistry(*pv,next);
10842             }
10843           sv_setiv(*pv,(IV) image);
10844           next=image;
10845         }
10846       if (*pv)
10847         pv++;
10848     }
10849
10850   PerlException:
10851     if (reference_vector)
10852       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
10853     InheritPerlException(exception,perl_exception);
10854     exception=DestroyExceptionInfo(exception);
10855     sv_setiv(perl_exception,(IV) number_images);
10856     SvPOK_on(perl_exception);
10857     ST(0)=sv_2mortal(perl_exception);
10858     XSRETURN(1);
10859   }
10860 \f
10861 #
10862 ###############################################################################
10863 #                                                                             #
10864 #                                                                             #
10865 #                                                                             #
10866 #   M o n t a g e                                                             #
10867 #                                                                             #
10868 #                                                                             #
10869 #                                                                             #
10870 ###############################################################################
10871 #
10872 #
10873 void
10874 Montage(ref,...)
10875   Image::Magick ref=NO_INIT
10876   ALIAS:
10877     MontageImage  = 1
10878     montage       = 2
10879     montageimage  = 3
10880   PPCODE:
10881   {
10882     AV
10883       *av;
10884
10885     char
10886       *attribute;
10887
10888     ExceptionInfo
10889       *exception;
10890
10891     HV
10892       *hv;
10893
10894     Image
10895       *image,
10896       *next;
10897
10898     PixelInfo
10899       transparent_color;
10900
10901     MontageInfo
10902       *montage_info;
10903
10904     register ssize_t
10905       i;
10906
10907     ssize_t
10908       sp;
10909
10910     struct PackageInfo
10911       *info;
10912
10913     SV
10914       *av_reference,
10915       *perl_exception,
10916       *reference,
10917       *rv,
10918       *sv;
10919
10920     PERL_UNUSED_VAR(ref);
10921     PERL_UNUSED_VAR(ix);
10922     exception=AcquireExceptionInfo();
10923     perl_exception=newSVpv("",0);
10924     sv=NULL;
10925     attribute=NULL;
10926     if (sv_isobject(ST(0)) == 0)
10927       {
10928         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
10929           PackageName);
10930         goto PerlException;
10931       }
10932     reference=SvRV(ST(0));
10933     hv=SvSTASH(reference);
10934     av=newAV();
10935     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
10936     SvREFCNT_dec(av);
10937     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
10938     if (image == (Image *) NULL)
10939       {
10940         ThrowPerlException(exception,OptionError,"NoImagesDefined",
10941           PackageName);
10942         goto PerlException;
10943       }
10944     /*
10945       Get options.
10946     */
10947     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
10948     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
10949     (void) QueryColorCompliance("none",AllCompliance,&transparent_color,
10950       exception);
10951     for (i=2; i < items; i+=2)
10952     {
10953       attribute=(char *) SvPV(ST(i-1),na);
10954       switch (*attribute)
10955       {
10956         case 'B':
10957         case 'b':
10958         {
10959           if (LocaleCompare(attribute,"background") == 0)
10960             {
10961               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
10962                 &montage_info->background_color,exception);
10963               for (next=image; next; next=next->next)
10964                 next->background_color=montage_info->background_color;
10965               break;
10966             }
10967           if (LocaleCompare(attribute,"border") == 0)
10968             {
10969               montage_info->border_width=SvIV(ST(i));
10970               break;
10971             }
10972           if (LocaleCompare(attribute,"bordercolor") == 0)
10973             {
10974               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
10975                 &montage_info->border_color,exception);
10976               for (next=image; next; next=next->next)
10977                 next->border_color=montage_info->border_color;
10978               break;
10979             }
10980           if (LocaleCompare(attribute,"borderwidth") == 0)
10981             {
10982               montage_info->border_width=SvIV(ST(i));
10983               break;
10984             }
10985           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10986             attribute);
10987           break;
10988         }
10989         case 'C':
10990         case 'c':
10991         {
10992           if (LocaleCompare(attribute,"compose") == 0)
10993             {
10994               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
10995                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
10996               if (sp < 0)
10997                 {
10998                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
10999                     SvPV(ST(i),na));
11000                   break;
11001                 }
11002               for (next=image; next; next=next->next)
11003                 next->compose=(CompositeOperator) sp;
11004               break;
11005             }
11006           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11007             attribute);
11008           break;
11009         }
11010         case 'F':
11011         case 'f':
11012         {
11013           if (LocaleCompare(attribute,"fill") == 0)
11014             {
11015               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11016                 &montage_info->fill,exception);
11017               break;
11018             }
11019           if (LocaleCompare(attribute,"font") == 0)
11020             {
11021               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
11022               break;
11023             }
11024           if (LocaleCompare(attribute,"frame") == 0)
11025             {
11026               char
11027                 *p;
11028
11029               p=SvPV(ST(i),na);
11030               if (IsGeometry(p) == MagickFalse)
11031                 {
11032                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11033                     p);
11034                   break;
11035                 }
11036               (void) CloneString(&montage_info->frame,p);
11037               if (*p == '\0')
11038                 montage_info->frame=(char *) NULL;
11039               break;
11040             }
11041           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11042             attribute);
11043           break;
11044         }
11045         case 'G':
11046         case 'g':
11047         {
11048           if (LocaleCompare(attribute,"geometry") == 0)
11049             {
11050               char
11051                 *p;
11052
11053               p=SvPV(ST(i),na);
11054               if (IsGeometry(p) == MagickFalse)
11055                 {
11056                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11057                     p);
11058                   break;
11059                 }
11060              (void) CloneString(&montage_info->geometry,p);
11061              if (*p == '\0')
11062                montage_info->geometry=(char *) NULL;
11063              break;
11064            }
11065          if (LocaleCompare(attribute,"gravity") == 0)
11066            {
11067              ssize_t
11068                in;
11069
11070              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11071                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11072              if (in < 0)
11073                {
11074                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
11075                    SvPV(ST(i),na));
11076                  return;
11077                }
11078              montage_info->gravity=(GravityType) in;
11079              for (next=image; next; next=next->next)
11080                next->gravity=(GravityType) in;
11081              break;
11082            }
11083           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11084             attribute);
11085           break;
11086         }
11087         case 'L':
11088         case 'l':
11089         {
11090           if (LocaleCompare(attribute,"label") == 0)
11091             {
11092               for (next=image; next; next=next->next)
11093                 (void) SetImageProperty(next,"label",InterpretImageProperties(
11094                   info ? info->image_info : (ImageInfo *) NULL,next,
11095                   SvPV(ST(i),na),exception),exception);
11096               break;
11097             }
11098           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11099             attribute);
11100           break;
11101         }
11102         case 'M':
11103         case 'm':
11104         {
11105           if (LocaleCompare(attribute,"mattecolor") == 0)
11106             {
11107               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11108                 &montage_info->matte_color,exception);
11109               for (next=image; next; next=next->next)
11110                 next->matte_color=montage_info->matte_color;
11111               break;
11112             }
11113           if (LocaleCompare(attribute,"mode") == 0)
11114             {
11115               ssize_t
11116                 in;
11117
11118               in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11119                 MagickModeOptions,MagickFalse,SvPV(ST(i),na));
11120               switch (in)
11121               {
11122                 default:
11123                 {
11124                   ThrowPerlException(exception,OptionError,
11125                     "UnrecognizedModeType",SvPV(ST(i),na));
11126                   break;
11127                 }
11128                 case FrameMode:
11129                 {
11130                   (void) CloneString(&montage_info->frame,"15x15+3+3");
11131                   montage_info->shadow=MagickTrue;
11132                   break;
11133                 }
11134                 case UnframeMode:
11135                 {
11136                   montage_info->frame=(char *) NULL;
11137                   montage_info->shadow=MagickFalse;
11138                   montage_info->border_width=0;
11139                   break;
11140                 }
11141                 case ConcatenateMode:
11142                 {
11143                   montage_info->frame=(char *) NULL;
11144                   montage_info->shadow=MagickFalse;
11145                   (void) CloneString(&montage_info->geometry,"+0+0");
11146                   montage_info->border_width=0;
11147                 }
11148               }
11149               break;
11150             }
11151           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11152             attribute);
11153           break;
11154         }
11155         case 'P':
11156         case 'p':
11157         {
11158           if (LocaleCompare(attribute,"pointsize") == 0)
11159             {
11160               montage_info->pointsize=SvIV(ST(i));
11161               break;
11162             }
11163           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11164             attribute);
11165           break;
11166         }
11167         case 'S':
11168         case 's':
11169         {
11170           if (LocaleCompare(attribute,"shadow") == 0)
11171             {
11172               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11173                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11174               if (sp < 0)
11175                 {
11176                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11177                     SvPV(ST(i),na));
11178                   break;
11179                 }
11180              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11181              break;
11182             }
11183           if (LocaleCompare(attribute,"stroke") == 0)
11184             {
11185               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11186                 &montage_info->stroke,exception);
11187               break;
11188             }
11189           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11190             attribute);
11191           break;
11192         }
11193         case 'T':
11194         case 't':
11195         {
11196           if (LocaleCompare(attribute,"texture") == 0)
11197             {
11198               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11199               break;
11200             }
11201           if (LocaleCompare(attribute,"tile") == 0)
11202             {
11203               char *p=SvPV(ST(i),na);
11204               if (IsGeometry(p) == MagickFalse)
11205                 {
11206                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11207                     p);
11208                   break;
11209                 }
11210               (void) CloneString(&montage_info->tile,p);
11211               if (*p == '\0')
11212                 montage_info->tile=(char *) NULL;
11213               break;
11214             }
11215           if (LocaleCompare(attribute,"title") == 0)
11216             {
11217               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11218               break;
11219             }
11220           if (LocaleCompare(attribute,"transparent") == 0)
11221             {
11222               PixelInfo
11223                 transparent_color;
11224
11225               QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11226                 &transparent_color,exception);
11227               for (next=image; next; next=next->next)
11228                 (void) TransparentPaintImage(next,&transparent_color,
11229                   TransparentAlpha,MagickFalse,exception);
11230               break;
11231             }
11232           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11233             attribute);
11234           break;
11235         }
11236         default:
11237         {
11238           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11239             attribute);
11240           break;
11241         }
11242       }
11243     }
11244     image=MontageImageList(info->image_info,montage_info,image,exception);
11245     montage_info=DestroyMontageInfo(montage_info);
11246     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11247       goto PerlException;
11248     if (transparent_color.alpha != TransparentAlpha)
11249       for (next=image; next; next=next->next)
11250         (void) TransparentPaintImage(next,&transparent_color,
11251           TransparentAlpha,MagickFalse,exception);
11252     for (  ; image; image=image->next)
11253     {
11254       AddImageToRegistry(sv,image);
11255       rv=newRV(sv);
11256       av_push(av,sv_bless(rv,hv));
11257       SvREFCNT_dec(sv);
11258     }
11259     exception=DestroyExceptionInfo(exception);
11260     ST(0)=av_reference;
11261     SvREFCNT_dec(perl_exception);
11262     XSRETURN(1);
11263
11264   PerlException:
11265     InheritPerlException(exception,perl_exception);
11266     exception=DestroyExceptionInfo(exception);
11267     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11268     SvPOK_on(perl_exception);
11269     ST(0)=sv_2mortal(perl_exception);
11270     XSRETURN(1);
11271   }
11272 \f
11273 #
11274 ###############################################################################
11275 #                                                                             #
11276 #                                                                             #
11277 #                                                                             #
11278 #   M o r p h                                                                 #
11279 #                                                                             #
11280 #                                                                             #
11281 #                                                                             #
11282 ###############################################################################
11283 #
11284 #
11285 void
11286 Morph(ref,...)
11287   Image::Magick ref=NO_INIT
11288   ALIAS:
11289     MorphImage  = 1
11290     morph       = 2
11291     morphimage  = 3
11292   PPCODE:
11293   {
11294     AV
11295       *av;
11296
11297     char
11298       *attribute;
11299
11300     ExceptionInfo
11301       *exception;
11302
11303     HV
11304       *hv;
11305
11306     Image
11307       *image;
11308
11309     register ssize_t
11310       i;
11311
11312     ssize_t
11313       number_frames;
11314
11315     struct PackageInfo
11316       *info;
11317
11318     SV
11319       *av_reference,
11320       *perl_exception,
11321       *reference,
11322       *rv,
11323       *sv;
11324
11325     PERL_UNUSED_VAR(ref);
11326     PERL_UNUSED_VAR(ix);
11327     exception=AcquireExceptionInfo();
11328     perl_exception=newSVpv("",0);
11329     sv=NULL;
11330     av=NULL;
11331     attribute=NULL;
11332     if (sv_isobject(ST(0)) == 0)
11333       {
11334         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11335           PackageName);
11336         goto PerlException;
11337       }
11338     reference=SvRV(ST(0));
11339     hv=SvSTASH(reference);
11340     av=newAV();
11341     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11342     SvREFCNT_dec(av);
11343     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11344     if (image == (Image *) NULL)
11345       {
11346         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11347           PackageName);
11348         goto PerlException;
11349       }
11350     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11351     /*
11352       Get attribute.
11353     */
11354     number_frames=30;
11355     for (i=2; i < items; i+=2)
11356     {
11357       attribute=(char *) SvPV(ST(i-1),na);
11358       switch (*attribute)
11359       {
11360         case 'F':
11361         case 'f':
11362         {
11363           if (LocaleCompare(attribute,"frames") == 0)
11364             {
11365               number_frames=SvIV(ST(i));
11366               break;
11367             }
11368           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11369             attribute);
11370           break;
11371         }
11372         default:
11373         {
11374           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11375             attribute);
11376           break;
11377         }
11378       }
11379     }
11380     image=MorphImages(image,number_frames,exception);
11381     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11382       goto PerlException;
11383     for ( ; image; image=image->next)
11384     {
11385       AddImageToRegistry(sv,image);
11386       rv=newRV(sv);
11387       av_push(av,sv_bless(rv,hv));
11388       SvREFCNT_dec(sv);
11389     }
11390     exception=DestroyExceptionInfo(exception);
11391     ST(0)=av_reference;
11392     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11393     XSRETURN(1);
11394
11395   PerlException:
11396     InheritPerlException(exception,perl_exception);
11397     exception=DestroyExceptionInfo(exception);
11398     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11399     SvPOK_on(perl_exception);
11400     ST(0)=sv_2mortal(perl_exception);
11401     XSRETURN(1);
11402   }
11403 \f
11404 #
11405 ###############################################################################
11406 #                                                                             #
11407 #                                                                             #
11408 #                                                                             #
11409 #   M o s a i c                                                               #
11410 #                                                                             #
11411 #                                                                             #
11412 #                                                                             #
11413 ###############################################################################
11414 #
11415 #
11416 void
11417 Mosaic(ref)
11418   Image::Magick ref=NO_INIT
11419   ALIAS:
11420     MosaicImage   = 1
11421     mosaic        = 2
11422     mosaicimage   = 3
11423   PPCODE:
11424   {
11425     AV
11426       *av;
11427
11428     ExceptionInfo
11429       *exception;
11430
11431     HV
11432       *hv;
11433
11434     Image
11435       *image;
11436
11437     struct PackageInfo
11438       *info;
11439
11440     SV
11441       *perl_exception,
11442       *reference,
11443       *rv,
11444       *sv;
11445
11446     PERL_UNUSED_VAR(ref);
11447     PERL_UNUSED_VAR(ix);
11448     exception=AcquireExceptionInfo();
11449     perl_exception=newSVpv("",0);
11450     sv=NULL;
11451     if (sv_isobject(ST(0)) == 0)
11452       {
11453         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11454           PackageName);
11455         goto PerlException;
11456       }
11457     reference=SvRV(ST(0));
11458     hv=SvSTASH(reference);
11459     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11460     if (image == (Image *) NULL)
11461       {
11462         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11463           PackageName);
11464         goto PerlException;
11465       }
11466     image=MergeImageLayers(image,MosaicLayer,exception);
11467     /*
11468       Create blessed Perl array for the returned image.
11469     */
11470     av=newAV();
11471     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11472     SvREFCNT_dec(av);
11473     AddImageToRegistry(sv,image);
11474     rv=newRV(sv);
11475     av_push(av,sv_bless(rv,hv));
11476     SvREFCNT_dec(sv);
11477     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11478     (void) CopyMagickString(info->image_info->filename,image->filename,
11479       MaxTextExtent);
11480     SetImageInfo(info->image_info,0,&image->exception);
11481     exception=DestroyExceptionInfo(exception);
11482     SvREFCNT_dec(perl_exception);
11483     XSRETURN(1);
11484
11485   PerlException:
11486     InheritPerlException(exception,perl_exception);
11487     exception=DestroyExceptionInfo(exception);
11488     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11489     SvPOK_on(perl_exception);  /* return messages in string context */
11490     ST(0)=sv_2mortal(perl_exception);
11491     XSRETURN(1);
11492   }
11493 \f
11494 #
11495 ###############################################################################
11496 #                                                                             #
11497 #                                                                             #
11498 #                                                                             #
11499 #   P i n g                                                                   #
11500 #                                                                             #
11501 #                                                                             #
11502 #                                                                             #
11503 ###############################################################################
11504 #
11505 #
11506 void
11507 Ping(ref,...)
11508   Image::Magick ref=NO_INIT
11509   ALIAS:
11510     PingImage  = 1
11511     ping       = 2
11512     pingimage  = 3
11513   PPCODE:
11514   {
11515     AV
11516       *av;
11517
11518     char
11519       **keep,
11520       **list;
11521
11522     ExceptionInfo
11523       *exception;
11524
11525     Image
11526       *image,
11527       *next;
11528
11529     int
11530       n;
11531
11532     MagickBooleanType
11533       status;
11534
11535     register char
11536       **p;
11537
11538     register ssize_t
11539       i;
11540
11541     ssize_t
11542       ac;
11543
11544     STRLEN
11545       *length;
11546
11547     struct PackageInfo
11548       *info,
11549       *package_info;
11550
11551     SV
11552       *perl_exception,
11553       *reference;
11554
11555     size_t
11556       count;
11557
11558     PERL_UNUSED_VAR(ref);
11559     PERL_UNUSED_VAR(ix);
11560     exception=AcquireExceptionInfo();
11561     perl_exception=newSVpv("",0);
11562     package_info=(struct PackageInfo *) NULL;
11563     ac=(items < 2) ? 1 : items-1;
11564     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
11565     keep=list;
11566     length=(STRLEN *) NULL;
11567     if (list == (char **) NULL)
11568       {
11569         ThrowPerlException(exception,ResourceLimitError,
11570           "MemoryAllocationFailed",PackageName);
11571         goto PerlException;
11572       }
11573     keep=list;
11574     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
11575     if (length == (STRLEN *) NULL)
11576       {
11577         ThrowPerlException(exception,ResourceLimitError,
11578           "MemoryAllocationFailed",PackageName);
11579         goto PerlException;
11580       }
11581     if (sv_isobject(ST(0)) == 0)
11582       {
11583         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11584           PackageName);
11585         goto PerlException;
11586       }
11587     reference=SvRV(ST(0));
11588     if (SvTYPE(reference) != SVt_PVAV)
11589       {
11590         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11591           PackageName);
11592         goto PerlException;
11593       }
11594     av=(AV *) reference;
11595     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11596       exception);
11597     package_info=ClonePackageInfo(info,exception);
11598     n=1;
11599     if (items <= 1)
11600       *list=(char *) (*package_info->image_info->filename ?
11601         package_info->image_info->filename : "XC:black");
11602     else
11603       for (n=0, i=0; i < ac; i++)
11604       {
11605         list[n]=(char *) SvPV(ST(i+1),length[n]);
11606         if ((items >= 3) && strEQcase(list[n],"blob"))
11607           {
11608             void
11609               *blob;
11610
11611             i++;
11612             blob=(void *) (SvPV(ST(i+1),length[n]));
11613             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
11614           }
11615         if ((items >= 3) && strEQcase(list[n],"filename"))
11616           continue;
11617         if ((items >= 3) && strEQcase(list[n],"file"))
11618           {
11619             FILE
11620               *file;
11621
11622             PerlIO
11623               *io_info;
11624
11625             i++;
11626             io_info=IoIFP(sv_2io(ST(i+1)));
11627             if (io_info == (PerlIO *) NULL)
11628               {
11629                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11630                   PackageName);
11631                 continue;
11632               }
11633             file=PerlIO_findFILE(io_info);
11634             if (file == (FILE *) NULL)
11635               {
11636                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11637                   PackageName);
11638                 continue;
11639               }
11640             SetImageInfoFile(package_info->image_info,file);
11641           }
11642         if ((items >= 3) && strEQcase(list[n],"magick"))
11643           continue;
11644         n++;
11645       }
11646     list[n]=(char *) NULL;
11647     keep=list;
11648     status=ExpandFilenames(&n,&list);
11649     if (status == MagickFalse)
11650       {
11651         ThrowPerlException(exception,ResourceLimitError,
11652           "MemoryAllocationFailed",PackageName);
11653         goto PerlException;
11654       }
11655     count=0;
11656     for (i=0; i < n; i++)
11657     {
11658       (void) CopyMagickString(package_info->image_info->filename,list[i],
11659         MaxTextExtent);
11660       image=PingImage(package_info->image_info,exception);
11661       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11662         break;
11663       if ((package_info->image_info->file != (FILE *) NULL) ||
11664           (package_info->image_info->blob != (void *) NULL))
11665         DisassociateImageStream(image);
11666       count+=GetImageListLength(image);
11667       EXTEND(sp,4*count);
11668       for (next=image; next; next=next->next)
11669       {
11670         PUSHs(sv_2mortal(newSViv(next->columns)));
11671         PUSHs(sv_2mortal(newSViv(next->rows)));
11672         PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
11673         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
11674       }
11675       image=DestroyImageList(image);
11676     }
11677     /*
11678       Free resources.
11679     */
11680     for (i=0; i < n; i++)
11681       if (list[i] != (char *) NULL)
11682         for (p=keep; list[i] != *p++; )
11683           if (*p == NULL)
11684             {
11685               list[i]=(char *) RelinquishMagickMemory(list[i]);
11686               break;
11687             }
11688
11689   PerlException:
11690     if (package_info != (struct PackageInfo *) NULL)
11691       DestroyPackageInfo(package_info);
11692     if (list && (list != keep))
11693       list=(char **) RelinquishMagickMemory(list);
11694     if (keep)
11695       keep=(char **) RelinquishMagickMemory(keep);
11696     if (length)
11697       length=(STRLEN *) RelinquishMagickMemory(length);
11698     InheritPerlException(exception,perl_exception);
11699     exception=DestroyExceptionInfo(exception);
11700     SvREFCNT_dec(perl_exception);  /* throw away all errors */
11701   }
11702 \f
11703 #
11704 ###############################################################################
11705 #                                                                             #
11706 #                                                                             #
11707 #                                                                             #
11708 #   P r e v i e w                                                             #
11709 #                                                                             #
11710 #                                                                             #
11711 #                                                                             #
11712 ###############################################################################
11713 #
11714 #
11715 void
11716 Preview(ref,...)
11717   Image::Magick ref=NO_INIT
11718   ALIAS:
11719     PreviewImage = 1
11720     preview      = 2
11721     previewimage = 3
11722   PPCODE:
11723   {
11724     AV
11725       *av;
11726
11727     ExceptionInfo
11728       *exception;
11729
11730     HV
11731       *hv;
11732
11733     Image
11734       *image,
11735       *preview_image;
11736
11737     PreviewType
11738       preview_type;
11739
11740     struct PackageInfo
11741       *info;
11742
11743     SV
11744       *av_reference,
11745       *perl_exception,
11746       *reference,
11747       *rv,
11748       *sv;
11749
11750     PERL_UNUSED_VAR(ref);
11751     PERL_UNUSED_VAR(ix);
11752     exception=AcquireExceptionInfo();
11753     perl_exception=newSVpv("",0);
11754     sv=NULL;
11755     av=NULL;
11756     if (sv_isobject(ST(0)) == 0)
11757       {
11758         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11759           PackageName);
11760         goto PerlException;
11761       }
11762     reference=SvRV(ST(0));
11763     hv=SvSTASH(reference);
11764     av=newAV();
11765     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11766     SvREFCNT_dec(av);
11767     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11768     if (image == (Image *) NULL)
11769       {
11770         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11771           PackageName);
11772         goto PerlException;
11773       }
11774     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11775     preview_type=GammaPreview;
11776     if (items > 1)
11777       preview_type=(PreviewType)
11778         ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
11779     for ( ; image; image=image->next)
11780     {
11781       preview_image=PreviewImage(image,preview_type,exception);
11782       if (preview_image == (Image *) NULL)
11783         goto PerlException;
11784       AddImageToRegistry(sv,preview_image);
11785       rv=newRV(sv);
11786       av_push(av,sv_bless(rv,hv));
11787       SvREFCNT_dec(sv);
11788     }
11789     exception=DestroyExceptionInfo(exception);
11790     ST(0)=av_reference;
11791     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11792     XSRETURN(1);
11793
11794   PerlException:
11795     InheritPerlException(exception,perl_exception);
11796     exception=DestroyExceptionInfo(exception);
11797     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11798     SvPOK_on(perl_exception);
11799     ST(0)=sv_2mortal(perl_exception);
11800     XSRETURN(1);
11801   }
11802 \f
11803 #
11804 ###############################################################################
11805 #                                                                             #
11806 #                                                                             #
11807 #                                                                             #
11808 #   Q u e r y C o l o r                                                       #
11809 #                                                                             #
11810 #                                                                             #
11811 #                                                                             #
11812 ###############################################################################
11813 #
11814 #
11815 void
11816 QueryColor(ref,...)
11817   Image::Magick ref=NO_INIT
11818   ALIAS:
11819     querycolor = 1
11820   PPCODE:
11821   {
11822     char
11823       *name;
11824
11825     ExceptionInfo
11826       *exception;
11827
11828     PixelInfo
11829       color;
11830
11831     register ssize_t
11832       i;
11833
11834     SV
11835       *perl_exception;
11836
11837     PERL_UNUSED_VAR(ref);
11838     PERL_UNUSED_VAR(ix);
11839     exception=AcquireExceptionInfo();
11840     perl_exception=newSVpv("",0);
11841     if (items == 1)
11842       {
11843         const ColorInfo
11844           **colorlist;
11845
11846         size_t
11847           colors;
11848
11849         colorlist=GetColorInfoList("*",&colors,exception);
11850         EXTEND(sp,colors);
11851         for (i=0; i < (ssize_t) colors; i++)
11852         {
11853           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
11854         }
11855         colorlist=(const ColorInfo **)
11856           RelinquishMagickMemory((ColorInfo **) colorlist);
11857         goto PerlException;
11858       }
11859     EXTEND(sp,5*items);
11860     for (i=1; i < items; i++)
11861     {
11862       name=(char *) SvPV(ST(i),na);
11863       if (QueryColorCompliance(name,AllCompliance,&color,exception) == MagickFalse)
11864         {
11865           PUSHs(&sv_undef);
11866           continue;
11867         }
11868       PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
11869       PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
11870       PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
11871       if (color.colorspace == CMYKColorspace)
11872         PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
11873       if (color.matte != MagickFalse)
11874         PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
11875     }
11876
11877   PerlException:
11878     InheritPerlException(exception,perl_exception);
11879     exception=DestroyExceptionInfo(exception);
11880     SvREFCNT_dec(perl_exception);
11881   }
11882 \f
11883 #
11884 ###############################################################################
11885 #                                                                             #
11886 #                                                                             #
11887 #                                                                             #
11888 #   Q u e r y C o l o r N a m e                                               #
11889 #                                                                             #
11890 #                                                                             #
11891 #                                                                             #
11892 ###############################################################################
11893 #
11894 #
11895 void
11896 QueryColorname(ref,...)
11897   Image::Magick ref=NO_INIT
11898   ALIAS:
11899     querycolorname = 1
11900   PPCODE:
11901   {
11902     AV
11903       *av;
11904
11905     char
11906       message[MaxTextExtent];
11907
11908     ExceptionInfo
11909       *exception;
11910
11911     Image
11912       *image;
11913
11914     PixelInfo
11915       target_color;
11916
11917     register ssize_t
11918       i;
11919
11920     struct PackageInfo
11921       *info;
11922
11923     SV
11924       *perl_exception,
11925       *reference;  /* reference is the SV* of ref=SvIV(reference) */
11926
11927     PERL_UNUSED_VAR(ref);
11928     PERL_UNUSED_VAR(ix);
11929     exception=AcquireExceptionInfo();
11930     perl_exception=newSVpv("",0);
11931     reference=SvRV(ST(0));
11932     av=(AV *) reference;
11933     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11934       exception);
11935     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11936     if (image == (Image *) NULL)
11937       {
11938         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11939           PackageName);
11940         goto PerlException;
11941       }
11942     EXTEND(sp,items);
11943     for (i=1; i < items; i++)
11944     {
11945       (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,&target_color,
11946         exception);
11947       (void) QueryColorname(image,&target_color,SVGCompliance,message,
11948         exception);
11949       PUSHs(sv_2mortal(newSVpv(message,0)));
11950     }
11951
11952   PerlException:
11953     InheritPerlException(exception,perl_exception);
11954     exception=DestroyExceptionInfo(exception);
11955     SvREFCNT_dec(perl_exception);
11956   }
11957 \f
11958 #
11959 ###############################################################################
11960 #                                                                             #
11961 #                                                                             #
11962 #                                                                             #
11963 #   Q u e r y F o n t                                                         #
11964 #                                                                             #
11965 #                                                                             #
11966 #                                                                             #
11967 ###############################################################################
11968 #
11969 #
11970 void
11971 QueryFont(ref,...)
11972   Image::Magick ref=NO_INIT
11973   ALIAS:
11974     queryfont = 1
11975   PPCODE:
11976   {
11977     char
11978       *name,
11979       message[MaxTextExtent];
11980
11981     ExceptionInfo
11982       *exception;
11983
11984     register ssize_t
11985       i;
11986
11987     SV
11988       *perl_exception;
11989
11990     volatile const TypeInfo
11991       *type_info;
11992
11993     PERL_UNUSED_VAR(ref);
11994     PERL_UNUSED_VAR(ix);
11995     exception=AcquireExceptionInfo();
11996     perl_exception=newSVpv("",0);
11997     if (items == 1)
11998       {
11999         const TypeInfo
12000           **typelist;
12001
12002         size_t
12003           types;
12004
12005         typelist=GetTypeInfoList("*",&types,exception);
12006         EXTEND(sp,types);
12007         for (i=0; i < (ssize_t) types; i++)
12008         {
12009           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
12010         }
12011         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
12012           typelist);
12013         goto PerlException;
12014       }
12015     EXTEND(sp,10*items);
12016     for (i=1; i < items; i++)
12017     {
12018       name=(char *) SvPV(ST(i),na);
12019       type_info=GetTypeInfo(name,exception);
12020       if (type_info == (TypeInfo *) NULL)
12021         {
12022           PUSHs(&sv_undef);
12023           continue;
12024         }
12025       if (type_info->name == (char *) NULL)
12026         PUSHs(&sv_undef);
12027       else
12028         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
12029       if (type_info->description == (char *) NULL)
12030         PUSHs(&sv_undef);
12031       else
12032         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
12033       if (type_info->family == (char *) NULL)
12034         PUSHs(&sv_undef);
12035       else
12036         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
12037       if (type_info->style == UndefinedStyle)
12038         PUSHs(&sv_undef);
12039       else
12040         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
12041           type_info->style),0)));
12042       if (type_info->stretch == UndefinedStretch)
12043         PUSHs(&sv_undef);
12044       else
12045         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
12046           type_info->stretch),0)));
12047       (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
12048         type_info->weight);
12049       PUSHs(sv_2mortal(newSVpv(message,0)));
12050       if (type_info->encoding == (char *) NULL)
12051         PUSHs(&sv_undef);
12052       else
12053         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
12054       if (type_info->foundry == (char *) NULL)
12055         PUSHs(&sv_undef);
12056       else
12057         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
12058       if (type_info->format == (char *) NULL)
12059         PUSHs(&sv_undef);
12060       else
12061         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
12062       if (type_info->metrics == (char *) NULL)
12063         PUSHs(&sv_undef);
12064       else
12065         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
12066       if (type_info->glyphs == (char *) NULL)
12067         PUSHs(&sv_undef);
12068       else
12069         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
12070     }
12071
12072   PerlException:
12073     InheritPerlException(exception,perl_exception);
12074     exception=DestroyExceptionInfo(exception);
12075     SvREFCNT_dec(perl_exception);
12076   }
12077 \f
12078 #
12079 ###############################################################################
12080 #                                                                             #
12081 #                                                                             #
12082 #                                                                             #
12083 #   Q u e r y F o n t M e t r i c s                                           #
12084 #                                                                             #
12085 #                                                                             #
12086 #                                                                             #
12087 ###############################################################################
12088 #
12089 #
12090 void
12091 QueryFontMetrics(ref,...)
12092   Image::Magick ref=NO_INIT
12093   ALIAS:
12094     queryfontmetrics = 1
12095   PPCODE:
12096   {
12097     AffineMatrix
12098       affine,
12099       current;
12100
12101     AV
12102       *av;
12103
12104     char
12105       *attribute;
12106
12107     double
12108       x,
12109       y;
12110
12111     DrawInfo
12112       *draw_info;
12113
12114     ExceptionInfo
12115       *exception;
12116
12117     GeometryInfo
12118       geometry_info;
12119
12120     Image
12121       *image;
12122
12123     MagickBooleanType
12124       status;
12125
12126     MagickStatusType
12127       flags;
12128
12129     register ssize_t
12130       i;
12131
12132     ssize_t
12133       type;
12134
12135     struct PackageInfo
12136       *info,
12137       *package_info;
12138
12139     SV
12140       *perl_exception,
12141       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12142
12143     TypeMetric
12144       metrics;
12145
12146     PERL_UNUSED_VAR(ref);
12147     PERL_UNUSED_VAR(ix);
12148     exception=AcquireExceptionInfo();
12149     package_info=(struct PackageInfo *) NULL;
12150     perl_exception=newSVpv("",0);
12151     reference=SvRV(ST(0));
12152     av=(AV *) reference;
12153     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12154       exception);
12155     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12156     if (image == (Image *) NULL)
12157       {
12158         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12159           PackageName);
12160         goto PerlException;
12161       }
12162     package_info=ClonePackageInfo(info,exception);
12163     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12164     CloneString(&draw_info->text,"");
12165     current=draw_info->affine;
12166     GetAffineMatrix(&affine);
12167     x=0.0;
12168     y=0.0;
12169     EXTEND(sp,7*items);
12170     for (i=2; i < items; i+=2)
12171     {
12172       attribute=(char *) SvPV(ST(i-1),na);
12173       switch (*attribute)
12174       {
12175         case 'A':
12176         case 'a':
12177         {
12178           if (LocaleCompare(attribute,"antialias") == 0)
12179             {
12180               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12181                 SvPV(ST(i),na));
12182               if (type < 0)
12183                 {
12184                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12185                     SvPV(ST(i),na));
12186                   break;
12187                 }
12188               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12189               break;
12190             }
12191           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12192             attribute);
12193           break;
12194         }
12195         case 'd':
12196         case 'D':
12197         {
12198           if (LocaleCompare(attribute,"density") == 0)
12199             {
12200               CloneString(&draw_info->density,SvPV(ST(i),na));
12201               break;
12202             }
12203           if (LocaleCompare(attribute,"direction") == 0)
12204             {
12205               draw_info->direction=(DirectionType) ParseCommandOption(
12206                 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12207               break;
12208             }
12209           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12210             attribute);
12211           break;
12212         }
12213         case 'e':
12214         case 'E':
12215         {
12216           if (LocaleCompare(attribute,"encoding") == 0)
12217             {
12218               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12219               break;
12220             }
12221           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12222             attribute);
12223           break;
12224         }
12225         case 'f':
12226         case 'F':
12227         {
12228           if (LocaleCompare(attribute,"family") == 0)
12229             {
12230               CloneString(&draw_info->family,SvPV(ST(i),na));
12231               break;
12232             }
12233           if (LocaleCompare(attribute,"fill") == 0)
12234             {
12235               if (info)
12236                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12237                   &draw_info->fill,&image->exception);
12238               break;
12239             }
12240           if (LocaleCompare(attribute,"font") == 0)
12241             {
12242               CloneString(&draw_info->font,SvPV(ST(i),na));
12243               break;
12244             }
12245           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12246             attribute);
12247           break;
12248         }
12249         case 'g':
12250         case 'G':
12251         {
12252           if (LocaleCompare(attribute,"geometry") == 0)
12253             {
12254               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12255               break;
12256             }
12257           if (LocaleCompare(attribute,"gravity") == 0)
12258             {
12259               draw_info->gravity=(GravityType) ParseCommandOption(
12260                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12261               break;
12262             }
12263           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12264             attribute);
12265           break;
12266         }
12267         case 'i':
12268         case 'I':
12269         {
12270           if (LocaleCompare(attribute,"interline-spacing") == 0)
12271             {
12272               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12273               draw_info->interline_spacing=geometry_info.rho;
12274               break;
12275             }
12276           if (LocaleCompare(attribute,"interword-spacing") == 0)
12277             {
12278               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12279               draw_info->interword_spacing=geometry_info.rho;
12280               break;
12281             }
12282           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12283             attribute);
12284           break;
12285         }
12286         case 'k':
12287         case 'K':
12288         {
12289           if (LocaleCompare(attribute,"kerning") == 0)
12290             {
12291               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12292               draw_info->kerning=geometry_info.rho;
12293               break;
12294             }
12295           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12296             attribute);
12297           break;
12298         }
12299         case 'p':
12300         case 'P':
12301         {
12302           if (LocaleCompare(attribute,"pointsize") == 0)
12303             {
12304               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12305               draw_info->pointsize=geometry_info.rho;
12306               break;
12307             }
12308           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12309             attribute);
12310           break;
12311         }
12312         case 'r':
12313         case 'R':
12314         {
12315           if (LocaleCompare(attribute,"rotate") == 0)
12316             {
12317               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12318               affine.rx=geometry_info.rho;
12319               affine.ry=geometry_info.sigma;
12320               if ((flags & SigmaValue) == 0)
12321                 affine.ry=affine.rx;
12322               break;
12323             }
12324           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12325             attribute);
12326           break;
12327         }
12328         case 's':
12329         case 'S':
12330         {
12331           if (LocaleCompare(attribute,"scale") == 0)
12332             {
12333               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12334               affine.sx=geometry_info.rho;
12335               affine.sy=geometry_info.sigma;
12336               if ((flags & SigmaValue) == 0)
12337                 affine.sy=affine.sx;
12338               break;
12339             }
12340           if (LocaleCompare(attribute,"skew") == 0)
12341             {
12342               double
12343                 x_angle,
12344                 y_angle;
12345
12346               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12347               x_angle=geometry_info.rho;
12348               y_angle=geometry_info.sigma;
12349               if ((flags & SigmaValue) == 0)
12350                 y_angle=x_angle;
12351               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12352               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12353               break;
12354             }
12355           if (LocaleCompare(attribute,"stroke") == 0)
12356             {
12357               if (info)
12358                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12359                   &draw_info->stroke,&image->exception);
12360               break;
12361             }
12362           if (LocaleCompare(attribute,"style") == 0)
12363             {
12364               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12365                 SvPV(ST(i),na));
12366               if (type < 0)
12367                 {
12368                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12369                     SvPV(ST(i),na));
12370                   break;
12371                 }
12372               draw_info->style=(StyleType) type;
12373               break;
12374             }
12375           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12376             attribute);
12377           break;
12378         }
12379         case 't':
12380         case 'T':
12381         {
12382           if (LocaleCompare(attribute,"text") == 0)
12383             {
12384               CloneString(&draw_info->text,SvPV(ST(i),na));
12385               break;
12386             }
12387           if (LocaleCompare(attribute,"translate") == 0)
12388             {
12389               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12390               affine.tx=geometry_info.rho;
12391               affine.ty=geometry_info.sigma;
12392               if ((flags & SigmaValue) == 0)
12393                 affine.ty=affine.tx;
12394               break;
12395             }
12396           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12397             attribute);
12398           break;
12399         }
12400         case 'w':
12401         case 'W':
12402         {
12403           if (LocaleCompare(attribute,"weight") == 0)
12404             {
12405               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12406               draw_info->weight=(size_t) geometry_info.rho;
12407               break;
12408             }
12409           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12410             attribute);
12411           break;
12412         }
12413         case 'x':
12414         case 'X':
12415         {
12416           if (LocaleCompare(attribute,"x") == 0)
12417             {
12418               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12419               x=geometry_info.rho;
12420               break;
12421             }
12422           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12423             attribute);
12424           break;
12425         }
12426         case 'y':
12427         case 'Y':
12428         {
12429           if (LocaleCompare(attribute,"y") == 0)
12430             {
12431               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12432               y=geometry_info.rho;
12433               break;
12434             }
12435           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12436             attribute);
12437           break;
12438         }
12439         default:
12440         {
12441           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12442             attribute);
12443           break;
12444         }
12445       }
12446     }
12447     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12448     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12449     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12450     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12451     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12452     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12453     if (draw_info->geometry == (char *) NULL)
12454       {
12455         draw_info->geometry=AcquireString((char *) NULL);
12456         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12457           "%.15g,%.15g",x,y);
12458       }
12459     status=GetTypeMetrics(image,draw_info,&metrics,exception);
12460     (void) CatchImageException(image);
12461     if (status == MagickFalse)
12462       PUSHs(&sv_undef);
12463     else
12464       {
12465         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12466         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12467         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12468         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12469         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12470         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12471         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12472         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12473         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12474         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12475         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12476         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12477         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12478       }
12479     draw_info=DestroyDrawInfo(draw_info);
12480
12481   PerlException:
12482     if (package_info != (struct PackageInfo *) NULL)
12483       DestroyPackageInfo(package_info);
12484     InheritPerlException(exception,perl_exception);
12485     exception=DestroyExceptionInfo(exception);
12486     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12487   }
12488 \f
12489 #
12490 ###############################################################################
12491 #                                                                             #
12492 #                                                                             #
12493 #                                                                             #
12494 #   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                         #
12495 #                                                                             #
12496 #                                                                             #
12497 #                                                                             #
12498 ###############################################################################
12499 #
12500 #
12501 void
12502 QueryMultilineFontMetrics(ref,...)
12503   Image::Magick ref=NO_INIT
12504   ALIAS:
12505     querymultilinefontmetrics = 1
12506   PPCODE:
12507   {
12508     AffineMatrix
12509       affine,
12510       current;
12511
12512     AV
12513       *av;
12514
12515     char
12516       *attribute;
12517
12518     double
12519       x,
12520       y;
12521
12522     DrawInfo
12523       *draw_info;
12524
12525     ExceptionInfo
12526       *exception;
12527
12528     GeometryInfo
12529       geometry_info;
12530
12531     Image
12532       *image;
12533
12534     MagickBooleanType
12535       status;
12536
12537     MagickStatusType
12538       flags;
12539
12540     register ssize_t
12541       i;
12542
12543     ssize_t
12544       type;
12545
12546     struct PackageInfo
12547       *info,
12548       *package_info;
12549
12550     SV
12551       *perl_exception,
12552       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12553
12554     TypeMetric
12555       metrics;
12556
12557     PERL_UNUSED_VAR(ref);
12558     PERL_UNUSED_VAR(ix);
12559     exception=AcquireExceptionInfo();
12560     package_info=(struct PackageInfo *) NULL;
12561     perl_exception=newSVpv("",0);
12562     reference=SvRV(ST(0));
12563     av=(AV *) reference;
12564     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12565       exception);
12566     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12567     if (image == (Image *) NULL)
12568       {
12569         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12570           PackageName);
12571         goto PerlException;
12572       }
12573     package_info=ClonePackageInfo(info,exception);
12574     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12575     CloneString(&draw_info->text,"");
12576     current=draw_info->affine;
12577     GetAffineMatrix(&affine);
12578     x=0.0;
12579     y=0.0;
12580     EXTEND(sp,7*items);
12581     for (i=2; i < items; i+=2)
12582     {
12583       attribute=(char *) SvPV(ST(i-1),na);
12584       switch (*attribute)
12585       {
12586         case 'A':
12587         case 'a':
12588         {
12589           if (LocaleCompare(attribute,"antialias") == 0)
12590             {
12591               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12592                 SvPV(ST(i),na));
12593               if (type < 0)
12594                 {
12595                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12596                     SvPV(ST(i),na));
12597                   break;
12598                 }
12599               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12600               break;
12601             }
12602           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12603             attribute);
12604           break;
12605         }
12606         case 'd':
12607         case 'D':
12608         {
12609           if (LocaleCompare(attribute,"density") == 0)
12610             {
12611               CloneString(&draw_info->density,SvPV(ST(i),na));
12612               break;
12613             }
12614           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12615             attribute);
12616           break;
12617         }
12618         case 'e':
12619         case 'E':
12620         {
12621           if (LocaleCompare(attribute,"encoding") == 0)
12622             {
12623               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12624               break;
12625             }
12626           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12627             attribute);
12628           break;
12629         }
12630         case 'f':
12631         case 'F':
12632         {
12633           if (LocaleCompare(attribute,"family") == 0)
12634             {
12635               CloneString(&draw_info->family,SvPV(ST(i),na));
12636               break;
12637             }
12638           if (LocaleCompare(attribute,"fill") == 0)
12639             {
12640               if (info)
12641                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12642                   &draw_info->fill,&image->exception);
12643               break;
12644             }
12645           if (LocaleCompare(attribute,"font") == 0)
12646             {
12647               CloneString(&draw_info->font,SvPV(ST(i),na));
12648               break;
12649             }
12650           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12651             attribute);
12652           break;
12653         }
12654         case 'g':
12655         case 'G':
12656         {
12657           if (LocaleCompare(attribute,"geometry") == 0)
12658             {
12659               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12660               break;
12661             }
12662           if (LocaleCompare(attribute,"gravity") == 0)
12663             {
12664               draw_info->gravity=(GravityType) ParseCommandOption(
12665                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12666               break;
12667             }
12668           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12669             attribute);
12670           break;
12671         }
12672         case 'p':
12673         case 'P':
12674         {
12675           if (LocaleCompare(attribute,"pointsize") == 0)
12676             {
12677               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12678               draw_info->pointsize=geometry_info.rho;
12679               break;
12680             }
12681           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12682             attribute);
12683           break;
12684         }
12685         case 'r':
12686         case 'R':
12687         {
12688           if (LocaleCompare(attribute,"rotate") == 0)
12689             {
12690               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12691               affine.rx=geometry_info.rho;
12692               affine.ry=geometry_info.sigma;
12693               if ((flags & SigmaValue) == 0)
12694                 affine.ry=affine.rx;
12695               break;
12696             }
12697           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12698             attribute);
12699           break;
12700         }
12701         case 's':
12702         case 'S':
12703         {
12704           if (LocaleCompare(attribute,"scale") == 0)
12705             {
12706               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12707               affine.sx=geometry_info.rho;
12708               affine.sy=geometry_info.sigma;
12709               if ((flags & SigmaValue) == 0)
12710                 affine.sy=affine.sx;
12711               break;
12712             }
12713           if (LocaleCompare(attribute,"skew") == 0)
12714             {
12715               double
12716                 x_angle,
12717                 y_angle;
12718
12719               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12720               x_angle=geometry_info.rho;
12721               y_angle=geometry_info.sigma;
12722               if ((flags & SigmaValue) == 0)
12723                 y_angle=x_angle;
12724               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12725               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12726               break;
12727             }
12728           if (LocaleCompare(attribute,"stroke") == 0)
12729             {
12730               if (info)
12731                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12732                   &draw_info->stroke,&image->exception);
12733               break;
12734             }
12735           if (LocaleCompare(attribute,"style") == 0)
12736             {
12737               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12738                 SvPV(ST(i),na));
12739               if (type < 0)
12740                 {
12741                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12742                     SvPV(ST(i),na));
12743                   break;
12744                 }
12745               draw_info->style=(StyleType) type;
12746               break;
12747             }
12748           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12749             attribute);
12750           break;
12751         }
12752         case 't':
12753         case 'T':
12754         {
12755           if (LocaleCompare(attribute,"text") == 0)
12756             {
12757               CloneString(&draw_info->text,SvPV(ST(i),na));
12758               break;
12759             }
12760           if (LocaleCompare(attribute,"translate") == 0)
12761             {
12762               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12763               affine.tx=geometry_info.rho;
12764               affine.ty=geometry_info.sigma;
12765               if ((flags & SigmaValue) == 0)
12766                 affine.ty=affine.tx;
12767               break;
12768             }
12769           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12770             attribute);
12771           break;
12772         }
12773         case 'w':
12774         case 'W':
12775         {
12776           if (LocaleCompare(attribute,"weight") == 0)
12777             {
12778               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12779               draw_info->weight=(size_t) geometry_info.rho;
12780               break;
12781             }
12782           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12783             attribute);
12784           break;
12785         }
12786         case 'x':
12787         case 'X':
12788         {
12789           if (LocaleCompare(attribute,"x") == 0)
12790             {
12791               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12792               x=geometry_info.rho;
12793               break;
12794             }
12795           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12796             attribute);
12797           break;
12798         }
12799         case 'y':
12800         case 'Y':
12801         {
12802           if (LocaleCompare(attribute,"y") == 0)
12803             {
12804               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12805               y=geometry_info.rho;
12806               break;
12807             }
12808           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12809             attribute);
12810           break;
12811         }
12812         default:
12813         {
12814           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12815             attribute);
12816           break;
12817         }
12818       }
12819     }
12820     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12821     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12822     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12823     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12824     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12825     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12826     if (draw_info->geometry == (char *) NULL)
12827       {
12828         draw_info->geometry=AcquireString((char *) NULL);
12829         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12830           "%.15g,%.15g",x,y);
12831       }
12832     status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
12833     (void) CatchException(exception);
12834     if (status == MagickFalse)
12835       PUSHs(&sv_undef);
12836     else
12837       {
12838         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12839         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12840         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12841         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12842         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12843         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12844         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12845         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12846         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12847         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12848         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12849         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12850         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12851       }
12852     draw_info=DestroyDrawInfo(draw_info);
12853
12854   PerlException:
12855     if (package_info != (struct PackageInfo *) NULL)
12856       DestroyPackageInfo(package_info);
12857     InheritPerlException(exception,perl_exception);
12858     exception=DestroyExceptionInfo(exception);
12859     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12860   }
12861 \f
12862 #
12863 ###############################################################################
12864 #                                                                             #
12865 #                                                                             #
12866 #                                                                             #
12867 #   Q u e r y F o r m a t                                                     #
12868 #                                                                             #
12869 #                                                                             #
12870 #                                                                             #
12871 ###############################################################################
12872 #
12873 #
12874 void
12875 QueryFormat(ref,...)
12876   Image::Magick ref=NO_INIT
12877   ALIAS:
12878     queryformat = 1
12879   PPCODE:
12880   {
12881     char
12882       *name;
12883
12884     ExceptionInfo
12885       *exception;
12886
12887     register ssize_t
12888       i;
12889
12890     SV
12891       *perl_exception;
12892
12893     volatile const MagickInfo
12894       *magick_info;
12895
12896     PERL_UNUSED_VAR(ref);
12897     PERL_UNUSED_VAR(ix);
12898     exception=AcquireExceptionInfo();
12899     perl_exception=newSVpv("",0);
12900     if (items == 1)
12901       {
12902         char
12903           format[MaxTextExtent];
12904
12905         const MagickInfo
12906           **format_list;
12907
12908         size_t
12909           types;
12910
12911         format_list=GetMagickInfoList("*",&types,exception);
12912         EXTEND(sp,types);
12913         for (i=0; i < (ssize_t) types; i++)
12914         {
12915           (void) CopyMagickString(format,format_list[i]->name,MaxTextExtent);
12916           LocaleLower(format);
12917           PUSHs(sv_2mortal(newSVpv(format,0)));
12918         }
12919         format_list=(const MagickInfo **)
12920           RelinquishMagickMemory((MagickInfo *) format_list);
12921         goto PerlException;
12922       }
12923     EXTEND(sp,8*items);
12924     for (i=1; i < items; i++)
12925     {
12926       name=(char *) SvPV(ST(i),na);
12927       magick_info=GetMagickInfo(name,exception);
12928       if (magick_info == (const MagickInfo *) NULL)
12929         {
12930           PUSHs(&sv_undef);
12931           continue;
12932         }
12933       PUSHs(sv_2mortal(newSViv(magick_info->adjoin)));
12934       PUSHs(sv_2mortal(newSViv(magick_info->blob_support)));
12935       PUSHs(sv_2mortal(newSViv(magick_info->raw)));
12936       PUSHs(sv_2mortal(newSViv((long) magick_info->decoder)));
12937       PUSHs(sv_2mortal(newSViv((long) magick_info->encoder)));
12938       if (magick_info->description == (char *) NULL)
12939         PUSHs(&sv_undef);
12940       else
12941         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
12942       if (magick_info->module == (char *) NULL)
12943         PUSHs(&sv_undef);
12944       else
12945         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
12946     }
12947
12948   PerlException:
12949     InheritPerlException(exception,perl_exception);
12950     exception=DestroyExceptionInfo(exception);
12951     SvREFCNT_dec(perl_exception);
12952   }
12953 \f
12954 #
12955 ###############################################################################
12956 #                                                                             #
12957 #                                                                             #
12958 #                                                                             #
12959 #   Q u e r y O p t i o n                                                     #
12960 #                                                                             #
12961 #                                                                             #
12962 #                                                                             #
12963 ###############################################################################
12964 #
12965 #
12966 void
12967 QueryOption(ref,...)
12968   Image::Magick ref=NO_INIT
12969   ALIAS:
12970     queryoption = 1
12971   PPCODE:
12972   {
12973     char
12974       **options;
12975
12976     ExceptionInfo
12977       *exception;
12978
12979     register ssize_t
12980       i;
12981
12982     ssize_t
12983       j,
12984       option;
12985
12986     SV
12987       *perl_exception;
12988
12989     PERL_UNUSED_VAR(ref);
12990     PERL_UNUSED_VAR(ix);
12991     exception=AcquireExceptionInfo();
12992     perl_exception=newSVpv("",0);
12993     EXTEND(sp,8*items);
12994     for (i=1; i < items; i++)
12995     {
12996       option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
12997         SvPV(ST(i),na));
12998       options=GetCommandOptions((CommandOption) option);
12999       if (options == (char **) NULL)
13000         PUSHs(&sv_undef);
13001       else
13002         {
13003           for (j=0; options[j] != (char *) NULL; j++)
13004             PUSHs(sv_2mortal(newSVpv(options[j],0)));
13005           options=DestroyStringList(options);
13006         }
13007     }
13008
13009     InheritPerlException(exception,perl_exception);
13010     exception=DestroyExceptionInfo(exception);
13011     SvREFCNT_dec(perl_exception);
13012   }
13013 \f
13014 #
13015 ###############################################################################
13016 #                                                                             #
13017 #                                                                             #
13018 #                                                                             #
13019 #   R e a d                                                                   #
13020 #                                                                             #
13021 #                                                                             #
13022 #                                                                             #
13023 ###############################################################################
13024 #
13025 #
13026 void
13027 Read(ref,...)
13028   Image::Magick ref=NO_INIT
13029   ALIAS:
13030     ReadImage  = 1
13031     read       = 2
13032     readimage  = 3
13033   PPCODE:
13034   {
13035     AV
13036       *av;
13037
13038     char
13039       **keep,
13040       **list;
13041
13042     ExceptionInfo
13043       *exception;
13044
13045     HV
13046       *hv;
13047
13048     Image
13049       *image;
13050
13051     int
13052       n;
13053
13054     MagickBooleanType
13055       status;
13056
13057     register char
13058       **p;
13059
13060     register ssize_t
13061       i;
13062
13063     ssize_t
13064       ac,
13065       number_images;
13066
13067     STRLEN
13068       *length;
13069
13070     struct PackageInfo
13071       *info,
13072       *package_info;
13073
13074     SV
13075       *perl_exception,  /* Perl variable for storing messages */
13076       *reference,
13077       *rv,
13078       *sv;
13079
13080     PERL_UNUSED_VAR(ref);
13081     PERL_UNUSED_VAR(ix);
13082     exception=AcquireExceptionInfo();
13083     perl_exception=newSVpv("",0);
13084     sv=NULL;
13085     package_info=(struct PackageInfo *) NULL;
13086     number_images=0;
13087     ac=(items < 2) ? 1 : items-1;
13088     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
13089     keep=list;
13090     length=(STRLEN *) NULL;
13091     if (list == (char **) NULL)
13092       {
13093         ThrowPerlException(exception,ResourceLimitError,
13094           "MemoryAllocationFailed",PackageName);
13095         goto PerlException;
13096       }
13097     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
13098     if (length == (STRLEN *) NULL)
13099       {
13100         ThrowPerlException(exception,ResourceLimitError,
13101           "MemoryAllocationFailed",PackageName);
13102         goto PerlException;
13103       }
13104     if (sv_isobject(ST(0)) == 0)
13105       {
13106         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13107           PackageName);
13108         goto PerlException;
13109       }
13110     reference=SvRV(ST(0));
13111     hv=SvSTASH(reference);
13112     if (SvTYPE(reference) != SVt_PVAV)
13113       {
13114         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13115           PackageName);
13116         goto PerlException;
13117       }
13118     av=(AV *) reference;
13119     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13120       exception);
13121     package_info=ClonePackageInfo(info,exception);
13122     n=1;
13123     if (items <= 1)
13124       *list=(char *) (*package_info->image_info->filename ?
13125         package_info->image_info->filename : "XC:black");
13126     else
13127       for (n=0, i=0; i < ac; i++)
13128       {
13129         list[n]=(char *) SvPV(ST(i+1),length[n]);
13130         if ((items >= 3) && strEQcase(list[n],"blob"))
13131           {
13132             void
13133               *blob;
13134
13135             i++;
13136             blob=(void *) (SvPV(ST(i+1),length[n]));
13137             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13138           }
13139         if ((items >= 3) && strEQcase(list[n],"filename"))
13140           continue;
13141         if ((items >= 3) && strEQcase(list[n],"file"))
13142           {
13143             FILE
13144               *file;
13145
13146             PerlIO
13147               *io_info;
13148
13149             i++;
13150             io_info=IoIFP(sv_2io(ST(i+1)));
13151             if (io_info == (PerlIO *) NULL)
13152               {
13153                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13154                   PackageName);
13155                 continue;
13156               }
13157             file=PerlIO_findFILE(io_info);
13158             if (file == (FILE *) NULL)
13159               {
13160                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13161                   PackageName);
13162                 continue;
13163               }
13164             SetImageInfoFile(package_info->image_info,file);
13165           }
13166         if ((items >= 3) && strEQcase(list[n],"magick"))
13167           continue;
13168         n++;
13169       }
13170     list[n]=(char *) NULL;
13171     keep=list;
13172     status=ExpandFilenames(&n,&list);
13173     if (status == MagickFalse)
13174       {
13175         ThrowPerlException(exception,ResourceLimitError,
13176           "MemoryAllocationFailed",PackageName);
13177         goto PerlException;
13178       }
13179     number_images=0;
13180     for (i=0; i < n; i++)
13181     {
13182       if ((package_info->image_info->file != (FILE *) NULL) ||
13183           (package_info->image_info->blob != (void *) NULL))
13184         {
13185           image=ReadImages(package_info->image_info,exception);
13186           if (image != (Image *) NULL)
13187             DisassociateImageStream(image);
13188         }
13189       else
13190         {
13191           (void) CopyMagickString(package_info->image_info->filename,list[i],
13192             MaxTextExtent);
13193           image=ReadImages(package_info->image_info,exception);
13194         }
13195       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
13196         break;
13197       for ( ; image; image=image->next)
13198       {
13199         AddImageToRegistry(sv,image);
13200         rv=newRV(sv);
13201         av_push(av,sv_bless(rv,hv));
13202         SvREFCNT_dec(sv);
13203         number_images++;
13204       }
13205     }
13206     /*
13207       Free resources.
13208     */
13209     for (i=0; i < n; i++)
13210       if (list[i] != (char *) NULL)
13211         for (p=keep; list[i] != *p++; )
13212           if (*p == (char *) NULL)
13213             {
13214               list[i]=(char *) RelinquishMagickMemory(list[i]);
13215               break;
13216             }
13217
13218   PerlException:
13219     if (package_info != (struct PackageInfo *) NULL)
13220       DestroyPackageInfo(package_info);
13221     if (list && (list != keep))
13222       list=(char **) RelinquishMagickMemory(list);
13223     if (keep)
13224       keep=(char **) RelinquishMagickMemory(keep);
13225     if (length)
13226       length=(STRLEN *) RelinquishMagickMemory(length);
13227     InheritPerlException(exception,perl_exception);
13228     exception=DestroyExceptionInfo(exception);
13229     sv_setiv(perl_exception,(IV) number_images);
13230     SvPOK_on(perl_exception);
13231     ST(0)=sv_2mortal(perl_exception);
13232     XSRETURN(1);
13233   }
13234 \f
13235 #
13236 ###############################################################################
13237 #                                                                             #
13238 #                                                                             #
13239 #                                                                             #
13240 #   R e m o t e                                                               #
13241 #                                                                             #
13242 #                                                                             #
13243 #                                                                             #
13244 ###############################################################################
13245 #
13246 #
13247 void
13248 Remote(ref,...)
13249   Image::Magick ref=NO_INIT
13250   ALIAS:
13251     RemoteCommand  = 1
13252     remote         = 2
13253     remoteCommand  = 3
13254   PPCODE:
13255   {
13256     AV
13257       *av;
13258
13259     ExceptionInfo
13260       *exception;
13261
13262     register ssize_t
13263       i;
13264
13265     SV
13266       *perl_exception,
13267       *reference;
13268
13269     struct PackageInfo
13270       *info;
13271
13272     PERL_UNUSED_VAR(ref);
13273     PERL_UNUSED_VAR(ix);
13274     exception=AcquireExceptionInfo();
13275     perl_exception=newSVpv("",0);
13276     reference=SvRV(ST(0));
13277     av=(AV *) reference;
13278     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13279       exception);
13280     for (i=1; i < items; i++)
13281       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13282         SvPV(ST(i),na),exception);
13283     InheritPerlException(exception,perl_exception);
13284     exception=DestroyExceptionInfo(exception);
13285     SvREFCNT_dec(perl_exception);    /* throw away all errors */
13286   }
13287 \f
13288 #
13289 ###############################################################################
13290 #                                                                             #
13291 #                                                                             #
13292 #                                                                             #
13293 #   S e t                                                                     #
13294 #                                                                             #
13295 #                                                                             #
13296 #                                                                             #
13297 ###############################################################################
13298 #
13299 #
13300 void
13301 Set(ref,...)
13302   Image::Magick ref=NO_INIT
13303   ALIAS:
13304     SetAttributes  = 1
13305     SetAttribute   = 2
13306     set            = 3
13307     setattributes  = 4
13308     setattribute   = 5
13309   PPCODE:
13310   {
13311     ExceptionInfo
13312       *exception;
13313
13314     Image
13315       *image;
13316
13317     register ssize_t
13318       i;
13319
13320     struct PackageInfo
13321       *info;
13322
13323     SV
13324       *perl_exception,
13325       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13326
13327     PERL_UNUSED_VAR(ref);
13328     PERL_UNUSED_VAR(ix);
13329     exception=AcquireExceptionInfo();
13330     perl_exception=newSVpv("",0);
13331     if (sv_isobject(ST(0)) == 0)
13332       {
13333         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13334           PackageName);
13335         goto PerlException;
13336       }
13337     reference=SvRV(ST(0));
13338     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13339     if (items == 2)
13340       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13341     else
13342       for (i=2; i < items; i+=2)
13343         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13344
13345   PerlException:
13346     InheritPerlException(exception,perl_exception);
13347     exception=DestroyExceptionInfo(exception);
13348     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13349     SvPOK_on(perl_exception);
13350     ST(0)=sv_2mortal(perl_exception);
13351     XSRETURN(1);
13352   }
13353 \f
13354 #
13355 ###############################################################################
13356 #                                                                             #
13357 #                                                                             #
13358 #                                                                             #
13359 #   S e t P i x e l                                                           #
13360 #                                                                             #
13361 #                                                                             #
13362 #                                                                             #
13363 ###############################################################################
13364 #
13365 #
13366 void
13367 SetPixel(ref,...)
13368   Image::Magick ref=NO_INIT
13369   ALIAS:
13370     setpixel = 1
13371     setPixel = 2
13372   PPCODE:
13373   {
13374     AV
13375       *av;
13376
13377     char
13378       *attribute;
13379
13380     ChannelType
13381       channel,
13382       channel_mask;
13383
13384     ExceptionInfo
13385       *exception;
13386
13387     Image
13388       *image;
13389
13390     MagickBooleanType
13391       normalize;
13392
13393     RectangleInfo
13394       region;
13395
13396     register ssize_t
13397       i;
13398
13399     register Quantum
13400       *q;
13401
13402     ssize_t
13403       option;
13404
13405     struct PackageInfo
13406       *info;
13407
13408     SV
13409       *perl_exception,
13410       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13411
13412     PERL_UNUSED_VAR(ref);
13413     PERL_UNUSED_VAR(ix);
13414     exception=AcquireExceptionInfo();
13415     perl_exception=newSVpv("",0);
13416     reference=SvRV(ST(0));
13417     av=(AV *) reference;
13418     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13419       exception);
13420     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13421     if (image == (Image *) NULL)
13422       {
13423         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13424           PackageName);
13425         goto PerlException;
13426       }
13427     av=(AV *) NULL;
13428     normalize=MagickTrue;
13429     region.x=0;
13430     region.y=0;
13431     region.width=image->columns;
13432     region.height=1;
13433     if (items == 1)
13434       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13435     channel=DefaultChannels;
13436     for (i=2; i < items; i+=2)
13437     {
13438       attribute=(char *) SvPV(ST(i-1),na);
13439       switch (*attribute)
13440       {
13441         case 'C':
13442         case 'c':
13443         {
13444           if (LocaleCompare(attribute,"channel") == 0)
13445             {
13446               ssize_t
13447                 option;
13448
13449               option=ParseChannelOption(SvPV(ST(i),na));
13450               if (option < 0)
13451                 {
13452                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13453                     SvPV(ST(i),na));
13454                   return;
13455                 }
13456               channel=(ChannelType) option;
13457               break;
13458             }
13459           if (LocaleCompare(attribute,"color") == 0)
13460             {
13461               if (SvTYPE(ST(i)) != SVt_RV)
13462                 {
13463                   char
13464                     message[MaxTextExtent];
13465
13466                   (void) FormatLocaleString(message,MaxTextExtent,
13467                     "invalid %.60s value",attribute);
13468                   ThrowPerlException(exception,OptionError,message,
13469                     SvPV(ST(i),na));
13470                 }
13471               av=(AV *) SvRV(ST(i));
13472               break;
13473             }
13474           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13475             attribute);
13476           break;
13477         }
13478         case 'g':
13479         case 'G':
13480         {
13481           if (LocaleCompare(attribute,"geometry") == 0)
13482             {
13483               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
13484               break;
13485             }
13486           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13487             attribute);
13488           break;
13489         }
13490         case 'N':
13491         case 'n':
13492         {
13493           if (LocaleCompare(attribute,"normalize") == 0)
13494             {
13495               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13496                 SvPV(ST(i),na));
13497               if (option < 0)
13498                 {
13499                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13500                     SvPV(ST(i),na));
13501                   break;
13502                 }
13503              normalize=option != 0 ? MagickTrue : MagickFalse;
13504              break;
13505             }
13506           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13507             attribute);
13508           break;
13509         }
13510         case 'x':
13511         case 'X':
13512         {
13513           if (LocaleCompare(attribute,"x") == 0)
13514             {
13515               region.x=SvIV(ST(i));
13516               break;
13517             }
13518           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13519             attribute);
13520           break;
13521         }
13522         case 'y':
13523         case 'Y':
13524         {
13525           if (LocaleCompare(attribute,"y") == 0)
13526             {
13527               region.y=SvIV(ST(i));
13528               break;
13529             }
13530           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13531             attribute);
13532           break;
13533         }
13534         default:
13535         {
13536           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13537             attribute);
13538           break;
13539         }
13540       }
13541     }
13542     (void) SetImageStorageClass(image,DirectClass,exception);
13543     channel_mask=SetPixelChannelMask(image,channel);
13544     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
13545     if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
13546         (SvTYPE(av) != SVt_PVAV))
13547       PUSHs(&sv_undef);
13548     else
13549       {
13550         double
13551           scale;
13552
13553         register ssize_t
13554           i;
13555
13556         i=0;
13557         scale=1.0;
13558         if (normalize != MagickFalse)
13559           scale=QuantumRange;
13560         if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
13561             (i <= av_len(av)))
13562           {
13563             SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
13564               av_fetch(av,i,0)))),q);
13565             i++;
13566           }
13567         if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
13568             (i <= av_len(av)))
13569           {
13570             SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
13571               av_fetch(av,i,0)))),q);
13572             i++;
13573           }
13574         if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
13575             (i <= av_len(av)))
13576           {
13577             SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
13578               av_fetch(av,i,0)))),q);
13579             i++;
13580           }
13581         if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
13582             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
13583           {
13584             SetPixelBlack(image,ClampToQuantum(scale*
13585               SvNV(*(av_fetch(av,i,0)))),q);
13586             i++;
13587           }
13588         if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
13589             (i <= av_len(av)))
13590           {
13591             SetPixelAlpha(image,ClampToQuantum(scale*
13592               SvNV(*(av_fetch(av,i,0)))),q);
13593             i++;
13594           }
13595         (void) SyncAuthenticPixels(image,exception);
13596       }
13597     (void) SetPixelChannelMask(image,channel_mask);
13598
13599   PerlException:
13600     InheritPerlException(exception,perl_exception);
13601     exception=DestroyExceptionInfo(exception);
13602     SvREFCNT_dec(perl_exception);
13603   }
13604 \f
13605 #
13606 ###############################################################################
13607 #                                                                             #
13608 #                                                                             #
13609 #                                                                             #
13610 #   S m u s h                                                                 #
13611 #                                                                             #
13612 #                                                                             #
13613 #                                                                             #
13614 ###############################################################################
13615 #
13616 #
13617 void
13618 Smush(ref,...)
13619   Image::Magick ref=NO_INIT
13620   ALIAS:
13621     SmushImage  = 1
13622     smush       = 2
13623     smushimage  = 3
13624   PPCODE:
13625   {
13626     AV
13627       *av;
13628
13629     char
13630       *attribute;
13631
13632     ExceptionInfo
13633       *exception;
13634
13635     HV
13636       *hv;
13637
13638     Image
13639       *image;
13640
13641     register ssize_t
13642       i;
13643
13644     ssize_t
13645       offset,
13646       stack;
13647
13648     struct PackageInfo
13649       *info;
13650
13651     SV
13652       *av_reference,
13653       *perl_exception,
13654       *reference,
13655       *rv,
13656       *sv;
13657
13658     PERL_UNUSED_VAR(ref);
13659     PERL_UNUSED_VAR(ix);
13660     exception=AcquireExceptionInfo();
13661     perl_exception=newSVpv("",0);
13662     sv=NULL;
13663     attribute=NULL;
13664     av=NULL;
13665     if (sv_isobject(ST(0)) == 0)
13666       {
13667         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13668           PackageName);
13669         goto PerlException;
13670       }
13671     reference=SvRV(ST(0));
13672     hv=SvSTASH(reference);
13673     av=newAV();
13674     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13675     SvREFCNT_dec(av);
13676     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13677     if (image == (Image *) NULL)
13678       {
13679         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13680           PackageName);
13681         goto PerlException;
13682       }
13683     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13684     /*
13685       Get options.
13686     */
13687     offset=0;
13688     stack=MagickTrue;
13689     for (i=2; i < items; i+=2)
13690     {
13691       attribute=(char *) SvPV(ST(i-1),na);
13692       switch (*attribute)
13693       {
13694         case 'O':
13695         case 'o':
13696         {
13697           if (LocaleCompare(attribute,"offset") == 0)
13698             {
13699               offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
13700               break;
13701             }
13702           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13703             attribute);
13704           break;
13705         }
13706         case 'S':
13707         case 's':
13708         {
13709           if (LocaleCompare(attribute,"stack") == 0)
13710             {
13711               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13712                 SvPV(ST(i),na));
13713               if (stack < 0)
13714                 {
13715                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13716                     SvPV(ST(i),na));
13717                   return;
13718                 }
13719               break;
13720             }
13721           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13722             attribute);
13723           break;
13724         }
13725         default:
13726         {
13727           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13728             attribute);
13729           break;
13730         }
13731       }
13732     }
13733     image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
13734       exception);
13735     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
13736       goto PerlException;
13737     for ( ; image; image=image->next)
13738     {
13739       AddImageToRegistry(sv,image);
13740       rv=newRV(sv);
13741       av_push(av,sv_bless(rv,hv));
13742       SvREFCNT_dec(sv);
13743     }
13744     exception=DestroyExceptionInfo(exception);
13745     ST(0)=av_reference;
13746     SvREFCNT_dec(perl_exception);
13747     XSRETURN(1);
13748
13749   PerlException:
13750     InheritPerlException(exception,perl_exception);
13751     exception=DestroyExceptionInfo(exception);
13752     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
13753     SvPOK_on(perl_exception);
13754     ST(0)=sv_2mortal(perl_exception);
13755     XSRETURN(1);
13756   }
13757 \f
13758 #
13759 ###############################################################################
13760 #                                                                             #
13761 #                                                                             #
13762 #                                                                             #
13763 #   S t a t i s t i c s                                                       #
13764 #                                                                             #
13765 #                                                                             #
13766 #                                                                             #
13767 ###############################################################################
13768 #
13769 #
13770 void
13771 Statistics(ref,...)
13772   Image::Magick ref=NO_INIT
13773   ALIAS:
13774     StatisticsImage = 1
13775     statistics      = 2
13776     statisticsimage = 3
13777   PPCODE:
13778   {
13779 #define ChannelStatistics(channel) \
13780 { \
13781   (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
13782     (double) channel_statistics[channel].depth); \
13783   PUSHs(sv_2mortal(newSVpv(message,0))); \
13784   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13785     channel_statistics[channel].minima/scale); \
13786   PUSHs(sv_2mortal(newSVpv(message,0))); \
13787   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13788     channel_statistics[channel].maxima/scale); \
13789   PUSHs(sv_2mortal(newSVpv(message,0))); \
13790   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13791     channel_statistics[channel].mean/scale); \
13792   PUSHs(sv_2mortal(newSVpv(message,0))); \
13793   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13794     channel_statistics[channel].standard_deviation/scale); \
13795   PUSHs(sv_2mortal(newSVpv(message,0))); \
13796   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13797     channel_statistics[channel].kurtosis); \
13798   PUSHs(sv_2mortal(newSVpv(message,0))); \
13799   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13800     channel_statistics[channel].skewness); \
13801   PUSHs(sv_2mortal(newSVpv(message,0))); \
13802 }
13803
13804     AV
13805       *av;
13806
13807     char
13808       message[MaxTextExtent];
13809
13810     ChannelStatistics
13811       *channel_statistics;
13812
13813     double
13814       scale;
13815
13816     ExceptionInfo
13817       *exception;
13818
13819     Image
13820       *image;
13821
13822     ssize_t
13823       count;
13824
13825     struct PackageInfo
13826       *info;
13827
13828     SV
13829       *perl_exception,
13830       *reference;
13831
13832     PERL_UNUSED_VAR(ref);
13833     PERL_UNUSED_VAR(ix);
13834     exception=AcquireExceptionInfo();
13835     perl_exception=newSVpv("",0);
13836     av=NULL;
13837     if (sv_isobject(ST(0)) == 0)
13838       {
13839         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13840           PackageName);
13841         goto PerlException;
13842       }
13843     reference=SvRV(ST(0));
13844     av=newAV();
13845     SvREFCNT_dec(av);
13846     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13847     if (image == (Image *) NULL)
13848       {
13849         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13850           PackageName);
13851         goto PerlException;
13852       }
13853     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13854     count=0;
13855     for ( ; image; image=image->next)
13856     {
13857       channel_statistics=GetImageStatistics(image,&image->exception);
13858       if (channel_statistics == (ChannelStatistics *) NULL)
13859         continue;
13860       count++;
13861       EXTEND(sp,35*count);
13862       scale=(double) QuantumRange;
13863       ChannelStatistics(RedChannel);
13864       ChannelStatistics(GreenChannel);
13865       ChannelStatistics(BlueChannel);
13866       if (image->colorspace == CMYKColorspace)
13867         ChannelStatistics(BlackChannel);
13868       if (image->matte != MagickFalse)
13869         ChannelStatistics(AlphaChannel);
13870       channel_statistics=(ChannelStatistics *)
13871         RelinquishMagickMemory(channel_statistics);
13872     }
13873
13874   PerlException:
13875     InheritPerlException(exception,perl_exception);
13876     exception=DestroyExceptionInfo(exception);
13877     SvREFCNT_dec(perl_exception);
13878   }
13879 \f
13880 #
13881 ###############################################################################
13882 #                                                                             #
13883 #                                                                             #
13884 #                                                                             #
13885 #   S y n c A u t h e n t i c P i x e l s                                     #
13886 #                                                                             #
13887 #                                                                             #
13888 #                                                                             #
13889 ###############################################################################
13890 #
13891 #
13892 void
13893 SyncAuthenticPixels(ref,...)
13894   Image::Magick ref = NO_INIT
13895   ALIAS:
13896     Syncauthenticpixels = 1
13897     SyncImagePixels = 2
13898     syncimagepixels = 3
13899   CODE:
13900   {
13901     ExceptionInfo
13902       *exception;
13903
13904     Image
13905       *image;
13906
13907     MagickBooleanType
13908       status;
13909
13910     struct PackageInfo
13911       *info;
13912
13913     SV
13914       *perl_exception,
13915       *reference;
13916
13917     PERL_UNUSED_VAR(ref);
13918     PERL_UNUSED_VAR(ix);
13919     exception=AcquireExceptionInfo();
13920     perl_exception=newSVpv("",0);
13921     if (sv_isobject(ST(0)) == 0)
13922       {
13923         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13924           PackageName);
13925         goto PerlException;
13926       }
13927
13928     reference=SvRV(ST(0));
13929     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13930     if (image == (Image *) NULL)
13931       {
13932         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13933           PackageName);
13934         goto PerlException;
13935       }
13936
13937     status=SyncAuthenticPixels(image,exception);
13938     if (status != MagickFalse)
13939       return;
13940     InheritException(exception,&image->exception);
13941
13942   PerlException:
13943     InheritPerlException(exception,perl_exception);
13944     exception=DestroyExceptionInfo(exception);
13945     SvREFCNT_dec(perl_exception);  /* throw away all errors */
13946   }
13947 \f
13948 #
13949 ###############################################################################
13950 #                                                                             #
13951 #                                                                             #
13952 #                                                                             #
13953 #   T r a n s f o r m                                                         #
13954 #                                                                             #
13955 #                                                                             #
13956 #                                                                             #
13957 ###############################################################################
13958 #
13959 #
13960 void
13961 Transform(ref,...)
13962   Image::Magick ref=NO_INIT
13963   ALIAS:
13964     TransformImage = 1
13965     transform      = 2
13966     transformimage = 3
13967   PPCODE:
13968   {
13969     AV
13970       *av;
13971
13972     char
13973       *attribute,
13974       *crop_geometry,
13975       *geometry;
13976
13977     ExceptionInfo
13978       *exception;
13979
13980     HV
13981       *hv;
13982
13983     Image
13984       *clone,
13985       *image;
13986
13987     register ssize_t
13988       i;
13989
13990     struct PackageInfo
13991       *info;
13992
13993     SV
13994       *av_reference,
13995       *perl_exception,
13996       *reference,
13997       *rv,
13998       *sv;
13999
14000     PERL_UNUSED_VAR(ref);
14001     PERL_UNUSED_VAR(ix);
14002     exception=AcquireExceptionInfo();
14003     perl_exception=newSVpv("",0);
14004     sv=NULL;
14005     av=NULL;
14006     attribute=NULL;
14007     if (sv_isobject(ST(0)) == 0)
14008       {
14009         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14010           PackageName);
14011         goto PerlException;
14012       }
14013     reference=SvRV(ST(0));
14014     hv=SvSTASH(reference);
14015     av=newAV();
14016     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14017     SvREFCNT_dec(av);
14018     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14019     if (image == (Image *) NULL)
14020       {
14021         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14022           PackageName);
14023         goto PerlException;
14024       }
14025     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14026     /*
14027       Get attribute.
14028     */
14029     crop_geometry=(char *) NULL;
14030     geometry=(char *) NULL;
14031     for (i=2; i < items; i+=2)
14032     {
14033       attribute=(char *) SvPV(ST(i-1),na);
14034       switch (*attribute)
14035       {
14036         case 'c':
14037         case 'C':
14038         {
14039           if (LocaleCompare(attribute,"crop") == 0)
14040             {
14041               crop_geometry=SvPV(ST(i),na);
14042               break;
14043             }
14044           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14045             attribute);
14046           break;
14047         }
14048         case 'g':
14049         case 'G':
14050         {
14051           if (LocaleCompare(attribute,"geometry") == 0)
14052             {
14053               geometry=SvPV(ST(i),na);
14054               break;
14055             }
14056          if (LocaleCompare(attribute,"gravity") == 0)
14057            {
14058              Image
14059                *next;
14060
14061              ssize_t
14062                in;
14063
14064              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
14065                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
14066              if (in < 0)
14067                {
14068                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
14069                    SvPV(ST(i),na));
14070                  return;
14071                }
14072              for (next=image; next; next=next->next)
14073                next->gravity=(GravityType) in;
14074              break;
14075            }
14076           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14077             attribute);
14078           break;
14079         }
14080         default:
14081         {
14082           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14083             attribute);
14084           break;
14085         }
14086       }
14087     }
14088     for ( ; image; image=image->next)
14089     {
14090       clone=CloneImage(image,0,0,MagickTrue,exception);
14091       if ((clone == (Image *) NULL) || (exception->severity >= ErrorException))
14092         goto PerlException;
14093       TransformImage(&clone,crop_geometry,geometry);
14094       for ( ; clone; clone=clone->next)
14095       {
14096         AddImageToRegistry(sv,clone);
14097         rv=newRV(sv);
14098         av_push(av,sv_bless(rv,hv));
14099         SvREFCNT_dec(sv);
14100       }
14101     }
14102     exception=DestroyExceptionInfo(exception);
14103     ST(0)=av_reference;
14104     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
14105     XSRETURN(1);
14106
14107   PerlException:
14108     InheritPerlException(exception,perl_exception);
14109     exception=DestroyExceptionInfo(exception);
14110     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14111     SvPOK_on(perl_exception);
14112     ST(0)=sv_2mortal(perl_exception);
14113     XSRETURN(1);
14114   }
14115 \f
14116 #
14117 ###############################################################################
14118 #                                                                             #
14119 #                                                                             #
14120 #                                                                             #
14121 #   W r i t e                                                                 #
14122 #                                                                             #
14123 #                                                                             #
14124 #                                                                             #
14125 ###############################################################################
14126 #
14127 #
14128 void
14129 Write(ref,...)
14130   Image::Magick ref=NO_INIT
14131   ALIAS:
14132     WriteImage    = 1
14133     write         = 2
14134     writeimage    = 3
14135   PPCODE:
14136   {
14137     char
14138       filename[MaxTextExtent];
14139
14140     ExceptionInfo
14141       *exception;
14142
14143     Image
14144       *image,
14145       *next;
14146
14147     register ssize_t
14148       i;
14149
14150     ssize_t
14151       number_images,
14152       scene;
14153
14154     struct PackageInfo
14155       *info,
14156       *package_info;
14157
14158     SV
14159       *perl_exception,
14160       *reference;
14161
14162     PERL_UNUSED_VAR(ref);
14163     PERL_UNUSED_VAR(ix);
14164     exception=AcquireExceptionInfo();
14165     perl_exception=newSVpv("",0);
14166     number_images=0;
14167     package_info=(struct PackageInfo *) NULL;
14168     if (sv_isobject(ST(0)) == 0)
14169       {
14170         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14171           PackageName);
14172         goto PerlException;
14173       }
14174     reference=SvRV(ST(0));
14175     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14176     if (image == (Image *) NULL)
14177       {
14178         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14179           PackageName);
14180         goto PerlException;
14181       }
14182     package_info=ClonePackageInfo(info,exception);
14183     if (items == 2)
14184       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14185     else
14186       if (items > 2)
14187         for (i=2; i < items; i+=2)
14188           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14189             exception);
14190     (void) CopyMagickString(filename,package_info->image_info->filename,
14191       MaxTextExtent);
14192     scene=0;
14193     for (next=image; next; next=next->next)
14194     {
14195       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
14196       next->scene=scene++;
14197     }
14198     SetImageInfo(package_info->image_info,(unsigned int)
14199       GetImageListLength(image),&image->exception);
14200     for (next=image; next; next=next->next)
14201     {
14202       (void) WriteImage(package_info->image_info,next,exception);
14203       number_images++;
14204       if (package_info->image_info->adjoin)
14205         break;
14206     }
14207
14208   PerlException:
14209     if (package_info != (struct PackageInfo *) NULL)
14210       DestroyPackageInfo(package_info);
14211     InheritPerlException(exception,perl_exception);
14212     exception=DestroyExceptionInfo(exception);
14213     sv_setiv(perl_exception,(IV) number_images);
14214     SvPOK_on(perl_exception);
14215     ST(0)=sv_2mortal(perl_exception);
14216     XSRETURN(1);
14217   }