]> granicus.if.org Git - imagemagick/blob - PerlMagick/Magick.xs
(no commit message)
[imagemagick] / PerlMagick / Magick.xs
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                         PPPP   EEEEE  RRRR   L                              %
6 %                         P   P  E      R   R  L                              %
7 %                         PPPP   EEE    RRRR   L                              %
8 %                         P      E      R  R   L                              %
9 %                         P      EEEEE  R   R  LLLLL                          %
10 %                                                                             %
11 %                  M   M   AAA    GGGG  IIIII   CCCC  K   K                   %
12 %                  MM MM  A   A  G        I    C      K  K                    %
13 %                  M M M  AAAAA  G GGG    I    C      KKK                     %
14 %                  M   M  A   A  G   G    I    C      K  K                    %
15 %                  M   M  A   A   GGGG  IIIII   CCCC  K   K                   %
16 %                                                                             %
17 %                                                                             %
18 %                Object-oriented Perl interface to ImageMagick                %
19 %                                                                             %
20 %                            Software Design                                  %
21 %                              Kyle Shorter                                   %
22 %                              John Cristy                                    %
23 %                             February 1997                                   %
24 %                                                                             %
25 %                                                                             %
26 %  Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization      %
27 %  dedicated to making software imaging solutions freely available.           %
28 %                                                                             %
29 %  You may not use this file except in compliance with the License.  You may  %
30 %  obtain a copy of the License at                                            %
31 %                                                                             %
32 %    http://www.imagemagick.org/script/license.php                            %
33 %                                                                             %
34 %  Unless required by applicable law or agreed to in writing, software        %
35 %  distributed under the License is distributed on an "AS IS" BASIS,          %
36 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
37 %  See the License for the specific language governing permissions and        %
38 %  limitations under the License.                                             %
39 %                                                                             %
40 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
41 %
42 %  PerlMagick is an objected-oriented Perl interface to ImageMagick.  Use
43 %  the module to read, manipulate, or write an image or image sequence from
44 %  within a Perl script.  This makes PerlMagick suitable for Web CGI scripts.
45 %
46 */
47 \f
48 /*
49   Include declarations.
50 */
51 #if defined(__cplusplus) || defined(c_plusplus)
52 extern "C" {
53 #endif
54
55 #define PERL_NO_GET_CONTEXT
56 #include "EXTERN.h"
57 #include "perl.h"
58 #include "XSUB.h"
59 #include <math.h>
60 #include <MagickCore/MagickCore.h>
61 #undef tainted
62
63 #if defined(__cplusplus) || defined(c_plusplus)
64 }
65 #endif
66 \f
67 /*
68   Define declarations.
69 */
70 #ifndef aTHX_
71 #define aTHX_
72 #define pTHX_
73 #define dTHX
74 #endif
75 #define DegreesToRadians(x)  (MagickPI*(x)/180.0)
76 #define EndOf(array)  (&array[NumberOf(array)])
77 #define MaxArguments  33
78 #ifndef na
79 #define na  PL_na
80 #endif
81 #define NumberOf(array)  (sizeof(array)/sizeof(*array))
82 #define PackageName   "Image::Magick"
83 #if PERL_VERSION <= 6
84 #define PerlIO  FILE
85 #define PerlIO_importFILE(f, fl)  (f)
86 #define PerlIO_findFILE(f)  NULL
87 #endif
88 #ifndef sv_undef
89 #define sv_undef  PL_sv_undef
90 #endif
91
92 #define AddImageToRegistry(sv,image) \
93 { \
94   if (magick_registry != (SplayTreeInfo *) NULL) \
95     { \
96       (void) AddValueToSplayTree(magick_registry,image,image); \
97       (sv)=newSViv((IV) image); \
98     } \
99 }
100
101 #define DeleteImageFromRegistry(reference,image) \
102 { \
103   if (magick_registry != (SplayTreeInfo *) NULL) \
104     { \
105       if (GetImageReferenceCount(image) == 1) \
106        (void) DeleteNodeByValueFromSplayTree(magick_registry,image); \
107       image=DestroyImage(image); \
108       sv_setiv(reference,0); \
109     } \
110 }
111
112 #define InheritPerlException(exception,perl_exception) \
113 { \
114   char \
115     message[MaxTextExtent]; \
116  \
117   if ((exception)->severity != UndefinedException) \
118     { \
119       (void) FormatLocaleString(message,MaxTextExtent,"Exception %d: %s%s%s%s",\
120         (exception)->severity, (exception)->reason ? \
121         GetLocaleExceptionMessage((exception)->severity,(exception)->reason) : \
122         "Unknown", (exception)->description ? " (" : "", \
123         (exception)->description ? GetLocaleExceptionMessage( \
124         (exception)->severity,(exception)->description) : "", \
125         (exception)->description ? ")" : ""); \
126       if ((perl_exception) != (SV *) NULL) \
127         { \
128           if (SvCUR(perl_exception)) \
129             sv_catpv(perl_exception,"\n"); \
130           sv_catpv(perl_exception,message); \
131         } \
132     } \
133 }
134
135 #define ThrowPerlException(exception,severity,tag,reason) \
136   (void) ThrowMagickException(exception,GetMagickModule(),severity, \
137     tag,"`%s'",reason); \
138 \f
139 /*
140   Typedef and structure declarations.
141 */
142 typedef enum
143 {
144   ArrayReference = (~0),
145   RealReference = (~0)-1,
146   FileReference = (~0)-2,
147   ImageReference = (~0)-3,
148   IntegerReference = (~0)-4,
149   StringReference = (~0)-5
150 } MagickReference;
151
152 typedef struct _Arguments
153 {
154   const char
155     *method;
156
157   ssize_t
158     type;
159 } Arguments;
160
161 struct ArgumentList
162 {
163   ssize_t
164     integer_reference;
165
166   MagickRealType
167     real_reference;
168
169   const char
170     *string_reference;
171
172   Image
173     *image_reference;
174
175   SV
176     *array_reference;
177
178   FILE
179     *file_reference;
180
181   size_t
182     length;
183 };
184
185 struct PackageInfo
186 {
187   ImageInfo
188     *image_info;
189 };
190
191 typedef void
192   *Image__Magick;  /* data type for the Image::Magick package */
193 \f
194 /*
195   Static declarations.
196 */
197 static struct
198   Methods
199   {
200     const char
201       *name;
202
203     Arguments
204       arguments[MaxArguments];
205   } Methods[] =
206   {
207     { "Comment", { {"comment", StringReference} } },
208     { "Label", { {"label", StringReference} } },
209     { "AddNoise", { {"noise", MagickNoiseOptions},
210       {"channel", MagickChannelOptions} } },
211     { "Colorize", { {"fill", StringReference}, {"opacity", StringReference} } },
212     { "Border", { {"geometry", StringReference}, {"width", IntegerReference},
213       {"height", IntegerReference}, {"fill", StringReference},
214       {"bordercolor", StringReference}, {"color", StringReference},
215       {"compose", MagickComposeOptions} } },
216     { "Blur", { {"geometry", StringReference}, {"radius", RealReference},
217       {"sigma", RealReference}, {"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}, {"opacity", StringReference} } },
432     { "Channel", { {"channel", MagickChannelOptions} } },
433     { "Splice", { {"geometry", StringReference}, {"width", IntegerReference},
434       {"height", IntegerReference}, {"x", IntegerReference},
435       {"y", IntegerReference}, {"fuzz", StringReference},
436       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
437     { "Posterize", { {"levels", IntegerReference},
438       {"dither", MagickBooleanOptions} } },
439     { "Shadow", { {"geometry", StringReference}, {"opacity", RealReference},
440       {"sigma", RealReference}, {"x", IntegerReference},
441       {"y", IntegerReference} } },
442     { "Identify", { {"file", FileReference}, {"features", StringReference},
443       {"unique", MagickBooleanOptions} } },
444     { "SepiaTone", { {"threshold", RealReference} } },
445     { "SigmoidalContrast", { {"geometry", StringReference},
446       {"contrast", RealReference}, {"mid-point", RealReference},
447       {"channel", MagickChannelOptions}, {"sharpen", MagickBooleanOptions} } },
448     { "Extent", { {"geometry", StringReference}, {"width", IntegerReference},
449       {"height", IntegerReference}, {"x", IntegerReference},
450       {"y", IntegerReference}, {"fuzz", StringReference},
451       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
452     { "Vignette", { {"geometry", StringReference}, {"radius", RealReference},
453       {"sigma", RealReference}, {"x", IntegerReference},
454       {"y", IntegerReference}, {"background", StringReference} } },
455     { "ContrastStretch", { {"levels", StringReference},
456       {"black-point", RealReference},{"white-point", RealReference},
457       {"channel", MagickChannelOptions} } },
458     { "Sans0", },
459     { "Sans1", },
460     { "AdaptiveSharpen", { {"geometry", StringReference},
461       {"radius", RealReference}, {"sigma", RealReference},
462       {"bias", RealReference}, {"channel", MagickChannelOptions} } },
463     { "Transpose", },
464     { "Transverse", },
465     { "AutoOrient", },
466     { "AdaptiveBlur", { {"geometry", StringReference},
467       {"radius", RealReference}, {"sigma", RealReference},
468       {"bias", RealReference}, {"channel", MagickChannelOptions} } },
469     { "Sketch", { {"geometry", StringReference},
470       {"radius", RealReference}, {"sigma", RealReference},
471       {"angle", RealReference}, {"bias", RealReference} } },
472     { "UniqueColors", },
473     { "AdaptiveResize", { {"geometry", StringReference},
474       {"width", IntegerReference}, {"height", IntegerReference},
475       {"filter", MagickFilterOptions}, {"support", StringReference },
476       {"blur", RealReference }, {"interpolate", MagickInterpolateOptions} } },
477     { "ClipMask", { {"mask", ImageReference} } },
478     { "LinearStretch", { {"levels", StringReference},
479       {"black-point", RealReference},{"white-point", RealReference} } },
480     { "Recolor", { {"matrix", ArrayReference} } },
481     { "Mask", { {"mask", ImageReference} } },
482     { "Polaroid", { {"caption", StringReference}, {"angle", RealReference},
483       {"font", StringReference}, {"stroke", StringReference},
484       {"fill", StringReference}, {"strokewidth", RealReference},
485       {"pointsize", RealReference}, {"gravity", MagickGravityOptions},
486       {"background", StringReference},
487       {"interpolate", MagickInterpolateOptions} } },
488     { "FloodfillPaint", { {"geometry", StringReference},
489       {"x", IntegerReference}, {"y", IntegerReference},
490       {"fill", StringReference}, {"bordercolor", StringReference},
491       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
492       {"invert", MagickBooleanOptions} } },
493     { "Distort", { {"points", ArrayReference}, {"method", MagickDistortOptions},
494       {"virtual-pixel", MagickVirtualPixelOptions},
495       {"best-fit", MagickBooleanOptions} } },
496     { "Clut", { {"image", ImageReference},
497       {"interpolate", MagickInterpolateOptions},
498       {"channel", MagickChannelOptions} } },
499     { "LiquidRescale", { {"geometry", StringReference},
500       {"width", IntegerReference}, {"height", IntegerReference},
501       {"delta-x", RealReference}, {"rigidity", RealReference } } },
502     { "Encipher", { {"passphrase", StringReference} } },
503     { "Decipher", { {"passphrase", StringReference} } },
504     { "Deskew", { {"geometry", StringReference},
505       {"threshold", StringReference} } },
506     { "Remap", { {"image", ImageReference}, {"dither", MagickBooleanOptions},
507       {"dither-method", MagickDitherOptions} } },
508     { "SparseColor", { {"points", ArrayReference},
509       {"method", MagickSparseColorOptions},
510       {"virtual-pixel", MagickVirtualPixelOptions},
511       {"channel", MagickChannelOptions} } },
512     { "Function", { {"parameters", ArrayReference},
513       {"function", MagickFunctionOptions},
514       {"virtual-pixel", MagickVirtualPixelOptions} } },
515     { "SelectiveBlur", { {"geometry", StringReference},
516       {"radius", RealReference}, {"sigma", RealReference},
517       {"threshold", RealReference}, {"bias", RealReference},
518       {"channel", MagickChannelOptions} } },
519     { "HaldClut", { {"image", ImageReference},
520       {"channel", MagickChannelOptions} } },
521     { "BlueShift", { {"factor", StringReference} } },
522     { "ForwardFourierTransform", { {"magnitude", MagickBooleanOptions} } },
523     { "InverseFourierTransform", { {"magnitude", MagickBooleanOptions} } },
524     { "ColorDecisionList", {
525       {"color-correction-collection", StringReference} } },
526     { "AutoGamma", { {"channel", MagickChannelOptions} } },
527     { "AutoLevel", { {"channel", MagickChannelOptions} } },
528     { "LevelColors", { {"invert", MagickBooleanOptions},
529       {"black-point", StringReference}, {"white-point", StringReference},
530       {"channel", MagickChannelOptions}, {"invert", MagickBooleanOptions} } },
531     { "Clamp", { {"channel", MagickChannelOptions} } },
532     { "BrightnessContrast", { {"levels", StringReference},
533       {"brightness", RealReference},{"contrast", RealReference},
534       {"channel", MagickChannelOptions} } },
535     { "Morphology", { {"kernel", StringReference},
536       {"channel", MagickChannelOptions}, {"method", MagickMorphologyOptions},
537       {"iterations", IntegerReference} } },
538     { "ColorMatrix", { {"matrix", ArrayReference} } },
539     { "Color", { {"color", StringReference} } },
540     { "Mode", { {"geometry", StringReference},
541       {"width", IntegerReference},{"height", IntegerReference},
542       {"channel", MagickChannelOptions} } },
543     { "Statistic", { {"geometry", StringReference},
544       {"width", IntegerReference},{"height", IntegerReference},
545       {"channel", MagickChannelOptions}, {"type", MagickStatisticOptions} } }
546   };
547
548 static SplayTreeInfo
549   *magick_registry = (SplayTreeInfo *) NULL;
550 \f
551 /*
552   Forward declarations.
553 */
554 static Image
555   *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
556
557 static ssize_t
558   strEQcase(const char *,const char *);
559 \f
560 /*
561 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
562 %                                                                             %
563 %                                                                             %
564 %                                                                             %
565 %   C l o n e P a c k a g e I n f o                                           %
566 %                                                                             %
567 %                                                                             %
568 %                                                                             %
569 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
570 %
571 %  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
572 %  a new one.
573 %
574 %  The format of the ClonePackageInfo routine is:
575 %
576 %      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
577 %        exception)
578 %
579 %  A description of each parameter follows:
580 %
581 %    o info: a structure of type info.
582 %
583 %    o exception: Return any errors or warnings in this structure.
584 %
585 */
586 static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
587   ExceptionInfo *exception)
588 {
589   struct PackageInfo
590     *clone_info;
591
592   clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
593   if (clone_info == (struct PackageInfo *) NULL)
594     {
595       ThrowPerlException(exception,ResourceLimitError,
596         "UnableToClonePackageInfo",PackageName);
597       return((struct PackageInfo *) NULL);
598     }
599   if (info == (struct PackageInfo *) NULL)
600     {
601       clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
602       return(clone_info);
603     }
604   *clone_info=(*info);
605   clone_info->image_info=CloneImageInfo(info->image_info);
606   return(clone_info);
607 }
608 \f
609 /*
610 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
611 %                                                                             %
612 %                                                                             %
613 %                                                                             %
614 %   c o n s t a n t                                                           %
615 %                                                                             %
616 %                                                                             %
617 %                                                                             %
618 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
619 %
620 %  constant() returns a double value for the specified name.
621 %
622 %  The format of the constant routine is:
623 %
624 %      double constant(char *name,ssize_t sans)
625 %
626 %  A description of each parameter follows:
627 %
628 %    o value: Method constant returns a double value for the specified name.
629 %
630 %    o name: The name of the constant.
631 %
632 %    o sans: This integer value is not used.
633 %
634 */
635 static double constant(char *name,ssize_t sans)
636 {
637   (void) sans;
638   errno=0;
639   switch (*name)
640   {
641     case 'B':
642     {
643       if (strEQ(name,"BlobError"))
644         return(BlobError);
645       if (strEQ(name,"BlobWarning"))
646         return(BlobWarning);
647       break;
648     }
649     case 'C':
650     {
651       if (strEQ(name,"CacheError"))
652         return(CacheError);
653       if (strEQ(name,"CacheWarning"))
654         return(CacheWarning);
655       if (strEQ(name,"CoderError"))
656         return(CoderError);
657       if (strEQ(name,"CoderWarning"))
658         return(CoderWarning);
659       if (strEQ(name,"ConfigureError"))
660         return(ConfigureError);
661       if (strEQ(name,"ConfigureWarning"))
662         return(ConfigureWarning);
663       if (strEQ(name,"CorruptImageError"))
664         return(CorruptImageError);
665       if (strEQ(name,"CorruptImageWarning"))
666         return(CorruptImageWarning);
667       break;
668     }
669     case 'D':
670     {
671       if (strEQ(name,"DelegateError"))
672         return(DelegateError);
673       if (strEQ(name,"DelegateWarning"))
674         return(DelegateWarning);
675       if (strEQ(name,"DrawError"))
676         return(DrawError);
677       if (strEQ(name,"DrawWarning"))
678         return(DrawWarning);
679       break;
680     }
681     case 'E':
682     {
683       if (strEQ(name,"ErrorException"))
684         return(ErrorException);
685       if (strEQ(name,"ExceptionError"))
686         return(CoderError);
687       if (strEQ(name,"ExceptionWarning"))
688         return(CoderWarning);
689       break;
690     }
691     case 'F':
692     {
693       if (strEQ(name,"FatalErrorException"))
694         return(FatalErrorException);
695       if (strEQ(name,"FileOpenError"))
696         return(FileOpenError);
697       if (strEQ(name,"FileOpenWarning"))
698         return(FileOpenWarning);
699       break;
700     }
701     case 'I':
702     {
703       if (strEQ(name,"ImageError"))
704         return(ImageError);
705       if (strEQ(name,"ImageWarning"))
706         return(ImageWarning);
707       break;
708     }
709     case 'M':
710     {
711       if (strEQ(name,"MaxRGB"))
712         return(QuantumRange);
713       if (strEQ(name,"MissingDelegateError"))
714         return(MissingDelegateError);
715       if (strEQ(name,"MissingDelegateWarning"))
716         return(MissingDelegateWarning);
717       if (strEQ(name,"ModuleError"))
718         return(ModuleError);
719       if (strEQ(name,"ModuleWarning"))
720         return(ModuleWarning);
721       break;
722     }
723     case 'O':
724     {
725       if (strEQ(name,"Opaque"))
726         return(OpaqueAlpha);
727       if (strEQ(name,"OptionError"))
728         return(OptionError);
729       if (strEQ(name,"OptionWarning"))
730         return(OptionWarning);
731       break;
732     }
733     case 'Q':
734     {
735       if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
736         return(MAGICKCORE_QUANTUM_DEPTH);
737       if (strEQ(name,"QuantumDepth"))
738         return(MAGICKCORE_QUANTUM_DEPTH);
739       if (strEQ(name,"QuantumRange"))
740         return(QuantumRange);
741       break;
742     }
743     case 'R':
744     {
745       if (strEQ(name,"ResourceLimitError"))
746         return(ResourceLimitError);
747       if (strEQ(name,"ResourceLimitWarning"))
748         return(ResourceLimitWarning);
749       if (strEQ(name,"RegistryError"))
750         return(RegistryError);
751       if (strEQ(name,"RegistryWarning"))
752         return(RegistryWarning);
753       break;
754     }
755     case 'S':
756     {
757       if (strEQ(name,"StreamError"))
758         return(StreamError);
759       if (strEQ(name,"StreamWarning"))
760         return(StreamWarning);
761       if (strEQ(name,"Success"))
762         return(0);
763       break;
764     }
765     case 'T':
766     {
767       if (strEQ(name,"Transparent"))
768         return(TransparentAlpha);
769       if (strEQ(name,"TypeError"))
770         return(TypeError);
771       if (strEQ(name,"TypeWarning"))
772         return(TypeWarning);
773       break;
774     }
775     case 'W':
776     {
777       if (strEQ(name,"WarningException"))
778         return(WarningException);
779       break;
780     }
781     case 'X':
782     {
783       if (strEQ(name,"XServerError"))
784         return(XServerError);
785       if (strEQ(name,"XServerWarning"))
786         return(XServerWarning);
787       break;
788     }
789   }
790   errno=EINVAL;
791   return(0);
792 }
793 \f
794 /*
795 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
796 %                                                                             %
797 %                                                                             %
798 %                                                                             %
799 %   D e s t r o y P a c k a g e I n f o                                       %
800 %                                                                             %
801 %                                                                             %
802 %                                                                             %
803 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
804 %
805 %  Method DestroyPackageInfo frees a previously created info structure.
806 %
807 %  The format of the DestroyPackageInfo routine is:
808 %
809 %      DestroyPackageInfo(struct PackageInfo *info)
810 %
811 %  A description of each parameter follows:
812 %
813 %    o info: a structure of type info.
814 %
815 */
816 static void DestroyPackageInfo(struct PackageInfo *info)
817 {
818   info->image_info=DestroyImageInfo(info->image_info);
819   info=(struct PackageInfo *) RelinquishMagickMemory(info);
820 }
821 \f
822 /*
823 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
824 %                                                                             %
825 %                                                                             %
826 %                                                                             %
827 %   G e t L i s t                                                             %
828 %                                                                             %
829 %                                                                             %
830 %                                                                             %
831 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
832 %
833 %  Method GetList is recursively called by SetupList to traverse the
834 %  Image__Magick reference.  If building an reference_vector (see SetupList),
835 %  *current is the current position in *reference_vector and *last is the final
836 %  entry in *reference_vector.
837 %
838 %  The format of the GetList routine is:
839 %
840 %      GetList(info)
841 %
842 %  A description of each parameter follows:
843 %
844 %    o info: a structure of type info.
845 %
846 */
847 static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
848   ssize_t *current,ssize_t *last,ExceptionInfo *exception)
849 {
850   Image
851     *image;
852
853   if (reference == (SV *) NULL)
854     return(NULL);
855   switch (SvTYPE(reference))
856   {
857     case SVt_PVAV:
858     {
859       AV
860         *av;
861
862       Image
863         *head,
864         *previous;
865
866       register ssize_t
867         i;
868
869       ssize_t
870         n;
871
872       /*
873         Array of images.
874       */
875       previous=(Image *) NULL;
876       head=(Image *) NULL;
877       av=(AV *) reference;
878       n=av_len(av);
879       for (i=0; i <= n; i++)
880       {
881         SV
882           **rv;
883
884         rv=av_fetch(av,i,0);
885         if (rv && *rv && sv_isobject(*rv))
886           {
887             image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
888               exception);
889             if (image == (Image *) NULL)
890               continue;
891             if (image == previous)
892               {
893                 image=CloneImage(image,0,0,MagickTrue,exception);
894                 if (image == (Image *) NULL)
895                   return(NULL);
896               }
897             image->previous=previous;
898             *(previous ? &previous->next : &head)=image;
899             for (previous=image; previous->next; previous=previous->next) ;
900           }
901       }
902       return(head);
903     }
904     case SVt_PVMG:
905     {
906       /*
907         Blessed scalar, one image.
908       */
909       image=(Image *) SvIV(reference);
910       if (image == (Image *) NULL)
911         return(NULL);
912       image->previous=(Image *) NULL;
913       image->next=(Image *) NULL;
914       if (reference_vector)
915         {
916           if (*current == *last)
917             {
918               *last+=256;
919               if (*reference_vector == (SV **) NULL)
920                 *reference_vector=(SV **) AcquireQuantumMemory(*last,
921                   sizeof(*reference_vector));
922               else
923                 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
924                   *last,sizeof(*reference_vector));
925             }
926           if (*reference_vector == (SV **) NULL)
927             {
928               ThrowPerlException(exception,ResourceLimitError,
929                 "MemoryAllocationFailed",PackageName);
930               return((Image *) NULL);
931             }
932           (*reference_vector)[*current]=reference;
933           (*reference_vector)[++(*current)]=NULL;
934         }
935       return(image);
936     }
937     default:
938       break;
939   }
940   (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
941     (double) SvTYPE(reference));
942   return((Image *) NULL);
943 }
944 \f
945 /*
946 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
947 %                                                                             %
948 %                                                                             %
949 %                                                                             %
950 %   G e t P a c k a g e I n f o                                               %
951 %                                                                             %
952 %                                                                             %
953 %                                                                             %
954 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
955 %
956 %  Method GetPackageInfo looks up or creates an info structure for the given
957 %  Image__Magick reference.  If it does create a new one, the information in
958 %  package_info is used to initialize it.
959 %
960 %  The format of the GetPackageInfo routine is:
961 %
962 %      struct PackageInfo *GetPackageInfo(void *reference,
963 %        struct PackageInfo *package_info,ExceptionInfo *exception)
964 %
965 %  A description of each parameter follows:
966 %
967 %    o info: a structure of type info.
968 %
969 %    o exception: Return any errors or warnings in this structure.
970 %
971 */
972 static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
973   struct PackageInfo *package_info,ExceptionInfo *exception)
974 {
975   char
976     message[MaxTextExtent];
977
978   struct PackageInfo
979     *clone_info;
980
981   SV
982     *sv;
983
984   (void) FormatLocaleString(message,MaxTextExtent,"%s::package%s%p",
985     PackageName,XS_VERSION,reference);
986   sv=perl_get_sv(message,(TRUE | 0x02));
987   if (sv == (SV *) NULL)
988     {
989       ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
990         message);
991       return(package_info);
992     }
993   if (SvREFCNT(sv) == 0)
994     (void) SvREFCNT_inc(sv);
995   if (SvIOKp(sv) && (clone_info=(struct PackageInfo *) SvIV(sv)))
996     return(clone_info);
997   clone_info=ClonePackageInfo(package_info,exception);
998   sv_setiv(sv,(IV) clone_info);
999   return(clone_info);
1000 }
1001 \f
1002 /*
1003 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1004 %                                                                             %
1005 %                                                                             %
1006 %                                                                             %
1007 %   S e t A t t r i b u t e                                                   %
1008 %                                                                             %
1009 %                                                                             %
1010 %                                                                             %
1011 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1012 %
1013 %  SetAttribute() sets the attribute to the value in sval.  This can change
1014 %  either or both of image or info.
1015 %
1016 %  The format of the SetAttribute routine is:
1017 %
1018 %      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1019 %        SV *sval,ExceptionInfo *exception)
1020 %
1021 %  A description of each parameter follows:
1022 %
1023 %    o list: a list of strings.
1024 %
1025 %    o string: a character string.
1026 %
1027 */
1028
1029 static double SiPrefixToDouble(const char *string,const double interval)
1030 {
1031   char
1032     *q;
1033
1034   double
1035     scale,
1036     value;
1037
1038   value=InterpretLocaleValue(string,&q);
1039   scale=1000.0;
1040   if ((*q != '\0') && (tolower((int) ((unsigned char) *(q+1))) == 'i'))
1041     scale=1024.0;
1042   switch (tolower((int) ((unsigned char) *q)))
1043   {
1044     case '%': value*=pow(scale,0)*interval/100.0; break;
1045     case 'k': value*=pow(scale,1); break;
1046     case 'm': value*=pow(scale,2); break;
1047     case 'g': value*=pow(scale,3); break;
1048     case 't': value*=pow(scale,4); break;
1049     case 'p': value*=pow(scale,5); break;
1050     case 'e': value*=pow(scale,6); break;
1051     case 'z': value*=pow(scale,7); break;
1052     case 'y': value*=pow(scale,8); break;
1053     default:  break;
1054   }
1055   return(value);
1056 }
1057
1058 static inline ssize_t StringToLong(const char *value)
1059 {
1060   return(strtol(value,(char **) NULL,10));
1061 }
1062
1063 static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1064   const char *attribute,SV *sval,ExceptionInfo *exception)
1065 {
1066   GeometryInfo
1067     geometry_info;
1068
1069   long
1070     x,
1071     y;
1072
1073   PixelInfo
1074     pixel;
1075
1076   MagickStatusType
1077     flags;
1078
1079   PixelPacket
1080     *color,
1081     target_color;
1082
1083   ssize_t
1084     sp;
1085
1086   switch (*attribute)
1087   {
1088     case 'A':
1089     case 'a':
1090     {
1091       if (LocaleCompare(attribute,"adjoin") == 0)
1092         {
1093           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1094             SvPV(sval,na)) : SvIV(sval);
1095           if (sp < 0)
1096             {
1097               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1098                 SvPV(sval,na));
1099               break;
1100             }
1101           if (info)
1102             info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1103           break;
1104         }
1105       if (LocaleCompare(attribute,"alpha") == 0)
1106         {
1107           sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaOptions,MagickFalse,
1108             SvPV(sval,na)) : SvIV(sval);
1109           if (sp < 0)
1110             {
1111               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1112                 SvPV(sval,na));
1113               break;
1114             }
1115           for ( ; image; image=image->next)
1116             (void) SetImageAlphaChannel(image,(AlphaChannelType) sp,exception);
1117           break;
1118         }
1119       if (LocaleCompare(attribute,"antialias") == 0)
1120         {
1121           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1122             SvPV(sval,na)) : SvIV(sval);
1123           if (sp < 0)
1124             {
1125               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1126                 SvPV(sval,na));
1127               break;
1128             }
1129           if (info)
1130             info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1131           break;
1132         }
1133       if (LocaleCompare(attribute,"area-limit") == 0)
1134         {
1135           MagickSizeType
1136             limit;
1137
1138           limit=MagickResourceInfinity;
1139           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1140             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1141           (void) SetMagickResourceLimit(AreaResource,limit);
1142           break;
1143         }
1144       if (LocaleCompare(attribute,"attenuate") == 0)
1145         {
1146           if (info)
1147             (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1148           break;
1149         }
1150       if (LocaleCompare(attribute,"authenticate") == 0)
1151         {
1152           if (info)
1153             (void) CloneString(&info->image_info->authenticate,SvPV(sval,na));
1154           break;
1155         }
1156       if (info)
1157         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1158       for ( ; image; image=image->next)
1159         SetImageProperty(image,attribute,SvPV(sval,na));
1160       break;
1161     }
1162     case 'B':
1163     case 'b':
1164     {
1165       if (LocaleCompare(attribute,"background") == 0)
1166         {
1167           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1168           if (info)
1169             info->image_info->background_color=target_color;
1170           for ( ; image; image=image->next)
1171             image->background_color=target_color;
1172           break;
1173         }
1174       if (LocaleCompare(attribute,"bias") == 0)
1175         {
1176           for ( ; image; image=image->next)
1177             image->bias=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1178           break;
1179         }
1180       if (LocaleCompare(attribute,"blue-primary") == 0)
1181         {
1182           for ( ; image; image=image->next)
1183           {
1184             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1185             image->chromaticity.blue_primary.x=geometry_info.rho;
1186             image->chromaticity.blue_primary.y=geometry_info.sigma;
1187             if ((flags & SigmaValue) == 0)
1188               image->chromaticity.blue_primary.y=
1189                 image->chromaticity.blue_primary.x;
1190           }
1191           break;
1192         }
1193       if (LocaleCompare(attribute,"bordercolor") == 0)
1194         {
1195           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1196           if (info)
1197             info->image_info->border_color=target_color;
1198           for ( ; image; image=image->next)
1199             image->border_color=target_color;
1200           break;
1201         }
1202       if (info)
1203         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1204       for ( ; image; image=image->next)
1205         SetImageProperty(image,attribute,SvPV(sval,na));
1206       break;
1207     }
1208     case 'C':
1209     case 'c':
1210     {
1211       if (LocaleCompare(attribute,"cache-threshold") == 0)
1212         {
1213           (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1214             SiPrefixToDouble(SvPV(sval,na),100.0));
1215           (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1216             (2*SiPrefixToDouble(SvPV(sval,na),100.0)));
1217           break;
1218         }
1219       if (LocaleCompare(attribute,"clip-mask") == 0)
1220         {
1221           Image
1222             *clip_mask;
1223
1224           clip_mask=(Image *) NULL;
1225           if (SvPOK(sval))
1226             clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1227           for ( ; image; image=image->next)
1228             SetImageClipMask(image,clip_mask,exception);
1229           break;
1230         }
1231       if (LocaleNCompare(attribute,"colormap",8) == 0)
1232         {
1233           for ( ; image; image=image->next)
1234           {
1235             int
1236               items;
1237
1238             long
1239               i;
1240
1241             if (image->storage_class == DirectClass)
1242               continue;
1243             i=0;
1244             items=sscanf(attribute,"%*[^[][%ld",&i);
1245             (void) items;
1246             if (i > (ssize_t) image->colors)
1247               i%=image->colors;
1248             if ((strchr(SvPV(sval,na),',') == 0) ||
1249                 (strchr(SvPV(sval,na),')') != 0))
1250               QueryColorDatabase(SvPV(sval,na),image->colormap+i,exception);
1251             else
1252               {
1253                 color=image->colormap+i;
1254                 pixel.red=color->red;
1255                 pixel.green=color->green;
1256                 pixel.blue=color->blue;
1257                 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1258                 pixel.red=geometry_info.rho;
1259                 pixel.green=geometry_info.sigma;
1260                 pixel.blue=geometry_info.xi;
1261                 color->red=ClampToQuantum(pixel.red);
1262                 color->green=ClampToQuantum(pixel.green);
1263                 color->blue=ClampToQuantum(pixel.blue);
1264               }
1265           }
1266           break;
1267         }
1268       if (LocaleCompare(attribute,"colorspace") == 0)
1269         {
1270           sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1271             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1272           if (sp < 0)
1273             {
1274               ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1275                 SvPV(sval,na));
1276               break;
1277             }
1278           for ( ; image; image=image->next)
1279             (void) TransformImageColorspace(image,(ColorspaceType) sp);
1280           break;
1281         }
1282       if (LocaleCompare(attribute,"comment") == 0)
1283         {
1284           for ( ; image; image=image->next)
1285             (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1286               info ? info->image_info : (ImageInfo *) NULL,image,
1287               SvPV(sval,na),exception));
1288           break;
1289         }
1290       if (LocaleCompare(attribute,"compression") == 0)
1291         {
1292           sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1293             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1294           if (sp < 0)
1295             {
1296               ThrowPerlException(exception,OptionError,
1297                 "UnrecognizedImageCompression",SvPV(sval,na));
1298               break;
1299             }
1300           if (info)
1301             info->image_info->compression=(CompressionType) sp;
1302           for ( ; image; image=image->next)
1303             image->compression=(CompressionType) sp;
1304           break;
1305         }
1306       if (info)
1307         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1308       for ( ; image; image=image->next)
1309         SetImageProperty(image,attribute,SvPV(sval,na));
1310       break;
1311     }
1312     case 'D':
1313     case 'd':
1314     {
1315       if (LocaleCompare(attribute,"debug") == 0)
1316         {
1317           SetLogEventMask(SvPV(sval,na));
1318           break;
1319         }
1320       if (LocaleCompare(attribute,"delay") == 0)
1321         {
1322           flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1323           for ( ; image; image=image->next)
1324           {
1325             image->delay=(size_t) floor(geometry_info.rho+0.5);
1326             if ((flags & SigmaValue) != 0)
1327               image->ticks_per_second=(ssize_t)
1328                 floor(geometry_info.sigma+0.5);
1329           }
1330           break;
1331         }
1332       if (LocaleCompare(attribute,"disk-limit") == 0)
1333         {
1334           MagickSizeType
1335             limit;
1336
1337           limit=MagickResourceInfinity;
1338           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1339             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1340           (void) SetMagickResourceLimit(DiskResource,limit);
1341           break;
1342         }
1343       if (LocaleCompare(attribute,"density") == 0)
1344         {
1345           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1346             {
1347               ThrowPerlException(exception,OptionError,"MissingGeometry",
1348                 SvPV(sval,na));
1349               break;
1350             }
1351           if (info)
1352             (void) CloneString(&info->image_info->density,SvPV(sval,na));
1353           for ( ; image; image=image->next)
1354           {
1355             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1356             image->x_resolution=geometry_info.rho;
1357             image->y_resolution=geometry_info.sigma;
1358             if ((flags & SigmaValue) == 0)
1359               image->y_resolution=image->x_resolution;
1360           }
1361           break;
1362         }
1363       if (LocaleCompare(attribute,"depth") == 0)
1364         {
1365           if (info)
1366             info->image_info->depth=SvIV(sval);
1367           for ( ; image; image=image->next)
1368             (void) SetImageDepth(image,SvIV(sval));
1369           break;
1370         }
1371       if (LocaleCompare(attribute,"dispose") == 0)
1372         {
1373           sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1374             SvPV(sval,na)) : SvIV(sval);
1375           if (sp < 0)
1376             {
1377               ThrowPerlException(exception,OptionError,
1378                 "UnrecognizedDisposeMethod",SvPV(sval,na));
1379               break;
1380             }
1381           for ( ; image; image=image->next)
1382             image->dispose=(DisposeType) sp;
1383           break;
1384         }
1385       if (LocaleCompare(attribute,"dither") == 0)
1386         {
1387           if (info)
1388             {
1389               sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1390                 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1391               if (sp < 0)
1392                 {
1393                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
1394                     SvPV(sval,na));
1395                   break;
1396                 }
1397               info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1398             }
1399           break;
1400         }
1401       if (LocaleCompare(attribute,"display") == 0)
1402         {
1403           display:
1404           if (info)
1405             (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1406           break;
1407         }
1408       if (info)
1409         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1410       for ( ; image; image=image->next)
1411         SetImageProperty(image,attribute,SvPV(sval,na));
1412       break;
1413     }
1414     case 'E':
1415     case 'e':
1416     {
1417       if (LocaleCompare(attribute,"endian") == 0)
1418         {
1419           sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1420             SvPV(sval,na)) : SvIV(sval);
1421           if (sp < 0)
1422             {
1423               ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1424                 SvPV(sval,na));
1425               break;
1426             }
1427           if (info)
1428             info->image_info->endian=(EndianType) sp;
1429           for ( ; image; image=image->next)
1430             image->endian=(EndianType) sp;
1431           break;
1432         }
1433       if (LocaleCompare(attribute,"extract") == 0)
1434         {
1435           /*
1436             Set image extract geometry.
1437           */
1438           (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1439           break;
1440         }
1441       if (info)
1442         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1443       for ( ; image; image=image->next)
1444         SetImageProperty(image,attribute,SvPV(sval,na));
1445       break;
1446     }
1447     case 'F':
1448     case 'f':
1449     {
1450       if (LocaleCompare(attribute,"filename") == 0)
1451         {
1452           if (info)
1453             (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1454               MaxTextExtent);
1455           for ( ; image; image=image->next)
1456             (void) CopyMagickString(image->filename,SvPV(sval,na),
1457               MaxTextExtent);
1458           break;
1459         }
1460       if (LocaleCompare(attribute,"file") == 0)
1461         {
1462           FILE
1463             *file;
1464
1465           PerlIO
1466             *io_info;
1467
1468           if (info == (struct PackageInfo *) NULL)
1469             break;
1470           io_info=IoIFP(sv_2io(sval));
1471           if (io_info == (PerlIO *) NULL)
1472             {
1473               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1474                 PackageName);
1475               break;
1476             }
1477           file=PerlIO_findFILE(io_info);
1478           if (file == (FILE *) NULL)
1479             {
1480               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1481                 PackageName);
1482               break;
1483             }
1484           SetImageInfoFile(info->image_info,file);
1485           break;
1486         }
1487       if (LocaleCompare(attribute,"fill") == 0)
1488         {
1489           if (info)
1490             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1491           break;
1492         }
1493       if (LocaleCompare(attribute,"font") == 0)
1494         {
1495           if (info)
1496             (void) CloneString(&info->image_info->font,SvPV(sval,na));
1497           break;
1498         }
1499       if (LocaleCompare(attribute,"foreground") == 0)
1500         break;
1501       if (LocaleCompare(attribute,"fuzz") == 0)
1502         {
1503           if (info)
1504             info->image_info->fuzz=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1505           for ( ; image; image=image->next)
1506             image->fuzz=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1507           break;
1508         }
1509       if (info)
1510         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1511       for ( ; image; image=image->next)
1512         SetImageProperty(image,attribute,SvPV(sval,na));
1513       break;
1514     }
1515     case 'G':
1516     case 'g':
1517     {
1518       if (LocaleCompare(attribute,"gamma") == 0)
1519         {
1520           for ( ; image; image=image->next)
1521             image->gamma=SvNV(sval);
1522           break;
1523         }
1524       if (LocaleCompare(attribute,"gravity") == 0)
1525         {
1526           sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1527             SvPV(sval,na)) : SvIV(sval);
1528           if (sp < 0)
1529             {
1530               ThrowPerlException(exception,OptionError,
1531                 "UnrecognizedGravityType",SvPV(sval,na));
1532               break;
1533             }
1534           if (info)
1535             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1536           for ( ; image; image=image->next)
1537             image->gravity=(GravityType) sp;
1538           break;
1539         }
1540       if (LocaleCompare(attribute,"green-primary") == 0)
1541         {
1542           for ( ; image; image=image->next)
1543           {
1544             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1545             image->chromaticity.green_primary.x=geometry_info.rho;
1546             image->chromaticity.green_primary.y=geometry_info.sigma;
1547             if ((flags & SigmaValue) == 0)
1548               image->chromaticity.green_primary.y=
1549                 image->chromaticity.green_primary.x;
1550           }
1551           break;
1552         }
1553       if (info)
1554         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1555       for ( ; image; image=image->next)
1556         SetImageProperty(image,attribute,SvPV(sval,na));
1557       break;
1558     }
1559     case 'I':
1560     case 'i':
1561     {
1562       if (LocaleNCompare(attribute,"index",5) == 0)
1563         {
1564           int
1565             items;
1566
1567           long
1568             index;
1569
1570           register Quantum
1571             *q;
1572
1573           CacheView
1574             *image_view;
1575
1576           for ( ; image; image=image->next)
1577           {
1578             if (image->storage_class != PseudoClass)
1579               continue;
1580             x=0;
1581             y=0;
1582             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1583             (void) items;
1584             image_view=AcquireCacheView(image);
1585             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1586             if (q != (Quantum *) NULL)
1587               {
1588                 items=sscanf(SvPV(sval,na),"%ld",&index);
1589                 if ((index >= 0) && (index < (ssize_t) image->colors))
1590                   SetPixelIndex(image,index,q);
1591                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1592               }
1593             image_view=DestroyCacheView(image_view);
1594           }
1595           break;
1596         }
1597       if (LocaleCompare(attribute,"iterations") == 0)
1598         {
1599   iterations:
1600           for ( ; image; image=image->next)
1601             image->iterations=SvIV(sval);
1602           break;
1603         }
1604       if (LocaleCompare(attribute,"interlace") == 0)
1605         {
1606           sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1607             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1608           if (sp < 0)
1609             {
1610               ThrowPerlException(exception,OptionError,
1611                 "UnrecognizedInterlaceType",SvPV(sval,na));
1612               break;
1613             }
1614           if (info)
1615             info->image_info->interlace=(InterlaceType) sp;
1616           for ( ; image; image=image->next)
1617             image->interlace=(InterlaceType) sp;
1618           break;
1619         }
1620       if (info)
1621         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1622       for ( ; image; image=image->next)
1623         SetImageProperty(image,attribute,SvPV(sval,na));
1624       break;
1625     }
1626     case 'L':
1627     case 'l':
1628     {
1629       if (LocaleCompare(attribute,"label") == 0)
1630         {
1631           for ( ; image; image=image->next)
1632             (void) SetImageProperty(image,"label",InterpretImageProperties(
1633               info ? info->image_info : (ImageInfo *) NULL,image,
1634               SvPV(sval,na),exception));
1635           break;
1636         }
1637       if (LocaleCompare(attribute,"loop") == 0)
1638         goto iterations;
1639       if (info)
1640         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1641       for ( ; image; image=image->next)
1642         SetImageProperty(image,attribute,SvPV(sval,na));
1643       break;
1644     }
1645     case 'M':
1646     case 'm':
1647     {
1648       if (LocaleCompare(attribute,"magick") == 0)
1649         {
1650           if (info)
1651             (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
1652               "%s:",SvPV(sval,na));
1653           for ( ; image; image=image->next)
1654             (void) CopyMagickString(image->magick,SvPV(sval,na),MaxTextExtent);
1655           break;
1656         }
1657       if (LocaleCompare(attribute,"map-limit") == 0)
1658         {
1659           MagickSizeType
1660             limit;
1661
1662           limit=MagickResourceInfinity;
1663           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1664             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1665           (void) SetMagickResourceLimit(MapResource,limit);
1666           break;
1667         }
1668       if (LocaleCompare(attribute,"mask") == 0)
1669         {
1670           Image
1671             *mask;
1672
1673           mask=(Image *) NULL;
1674           if (SvPOK(sval))
1675             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1676           for ( ; image; image=image->next)
1677             SetImageMask(image,mask,exception);
1678           break;
1679         }
1680       if (LocaleCompare(attribute,"mattecolor") == 0)
1681         {
1682           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1683           if (info)
1684             info->image_info->matte_color=target_color;
1685           for ( ; image; image=image->next)
1686             image->matte_color=target_color;
1687           break;
1688         }
1689       if (LocaleCompare(attribute,"matte") == 0)
1690         {
1691           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1692             SvPV(sval,na)) : SvIV(sval);
1693           if (sp < 0)
1694             {
1695               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1696                 SvPV(sval,na));
1697               break;
1698             }
1699           for ( ; image; image=image->next)
1700             image->matte=sp != 0 ? MagickTrue : MagickFalse;
1701           break;
1702         }
1703       if (LocaleCompare(attribute,"memory-limit") == 0)
1704         {
1705           MagickSizeType
1706             limit;
1707
1708           limit=MagickResourceInfinity;
1709           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1710             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1711           (void) SetMagickResourceLimit(MemoryResource,limit);
1712           break;
1713         }
1714       if (LocaleCompare(attribute,"monochrome") == 0)
1715         {
1716           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1717             SvPV(sval,na)) : SvIV(sval);
1718           if (sp < 0)
1719             {
1720               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1721                 SvPV(sval,na));
1722               break;
1723             }
1724           if (info)
1725             info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1726           for ( ; image; image=image->next)
1727             (void) SetImageType(image,BilevelType,exception);
1728           break;
1729         }
1730       if (info)
1731         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1732       for ( ; image; image=image->next)
1733         SetImageProperty(image,attribute,SvPV(sval,na));
1734       break;
1735     }
1736     case 'O':
1737     case 'o':
1738     {
1739       if (LocaleCompare(attribute,"option") == 0)
1740         {
1741           if (info)
1742             DefineImageOption(info->image_info,SvPV(sval,na));
1743           break;
1744         }
1745       if (LocaleCompare(attribute,"orientation") == 0)
1746         {
1747           sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1748             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1749           if (sp < 0)
1750             {
1751               ThrowPerlException(exception,OptionError,
1752                 "UnrecognizedOrientationType",SvPV(sval,na));
1753               break;
1754             }
1755           if (info)
1756             info->image_info->orientation=(OrientationType) sp;
1757           for ( ; image; image=image->next)
1758             image->orientation=(OrientationType) sp;
1759           break;
1760         }
1761       if (info)
1762         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1763       for ( ; image; image=image->next)
1764         SetImageProperty(image,attribute,SvPV(sval,na));
1765       break;
1766     }
1767     case 'P':
1768     case 'p':
1769     {
1770       if (LocaleCompare(attribute,"page") == 0)
1771         {
1772           char
1773             *geometry;
1774
1775           geometry=GetPageGeometry(SvPV(sval,na));
1776           if (info)
1777             (void) CloneString(&info->image_info->page,geometry);
1778           for ( ; image; image=image->next)
1779             (void) ParsePageGeometry(image,geometry,&image->page,exception);
1780           geometry=(char *) RelinquishMagickMemory(geometry);
1781           break;
1782         }
1783       if (LocaleCompare(attribute,"pen") == 0)
1784         {
1785           if (info)
1786             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1787           break;
1788         }
1789       if (LocaleNCompare(attribute,"pixel",5) == 0)
1790         {
1791           int
1792             items;
1793
1794           PixelInfo
1795             pixel;
1796
1797           register Quantum
1798             *q;
1799
1800           CacheView
1801             *image_view;
1802
1803           for ( ; image; image=image->next)
1804           {
1805             if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1806               break;
1807             x=0;
1808             y=0;
1809             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1810             (void) items;
1811             image_view=AcquireCacheView(image);
1812             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1813             if (q != (Quantum *) NULL)
1814               {
1815                 if ((strchr(SvPV(sval,na),',') == 0) ||
1816                     (strchr(SvPV(sval,na),')') != 0))
1817                   QueryMagickColor(SvPV(sval,na),&pixel,exception);
1818                 else
1819                   {
1820                     GetPixelInfo(image,&pixel);
1821                     flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1822                     pixel.red=geometry_info.rho;
1823                     if ((flags & SigmaValue) != 0)
1824                       pixel.green=geometry_info.sigma;
1825                     if ((flags & XiValue) != 0)
1826                       pixel.blue=geometry_info.xi;
1827                     if ((flags & PsiValue) != 0)
1828                       pixel.alpha=geometry_info.psi;
1829                     if ((flags & ChiValue) != 0)
1830                       pixel.black=geometry_info.chi;
1831                   }
1832                 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1833                 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1834                 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1835                 if (image->colorspace == CMYKColorspace)
1836                   SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1837                 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1838                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1839               }
1840             image_view=DestroyCacheView(image_view);
1841           }
1842           break;
1843         }
1844       if (LocaleCompare(attribute,"pointsize") == 0)
1845         {
1846           if (info)
1847             {
1848               (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1849               info->image_info->pointsize=geometry_info.rho;
1850             }
1851           break;
1852         }
1853       if (LocaleCompare(attribute,"preview") == 0)
1854         {
1855           sp=SvPOK(sval) ? ParseCommandOption(MagickPreviewOptions,MagickFalse,
1856             SvPV(sval,na)) : SvIV(sval);
1857           if (sp < 0)
1858             {
1859               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1860                 SvPV(sval,na));
1861               break;
1862             }
1863           if (info)
1864             info->image_info->preview_type=(PreviewType) sp;
1865           break;
1866         }
1867       if (info)
1868         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1869       for ( ; image; image=image->next)
1870         SetImageProperty(image,attribute,SvPV(sval,na));
1871       break;
1872     }
1873     case 'Q':
1874     case 'q':
1875     {
1876       if (LocaleCompare(attribute,"quality") == 0)
1877         {
1878           if (info)
1879             info->image_info->quality=SvIV(sval);
1880           for ( ; image; image=image->next)
1881             image->quality=SvIV(sval);
1882           break;
1883         }
1884       if (info)
1885         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1886       for ( ; image; image=image->next)
1887         SetImageProperty(image,attribute,SvPV(sval,na));
1888       break;
1889     }
1890     case 'R':
1891     case 'r':
1892     {
1893       if (LocaleCompare(attribute,"red-primary") == 0)
1894         {
1895           for ( ; image; image=image->next)
1896           {
1897             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1898             image->chromaticity.red_primary.x=geometry_info.rho;
1899             image->chromaticity.red_primary.y=geometry_info.sigma;
1900             if ((flags & SigmaValue) == 0)
1901               image->chromaticity.red_primary.y=
1902                 image->chromaticity.red_primary.x;
1903           }
1904           break;
1905         }
1906       if (LocaleCompare(attribute,"render") == 0)
1907         {
1908           sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1909             SvPV(sval,na)) : SvIV(sval);
1910           if (sp < 0)
1911             {
1912               ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1913                 SvPV(sval,na));
1914               break;
1915             }
1916          for ( ; image; image=image->next)
1917            image->rendering_intent=(RenderingIntent) sp;
1918          break;
1919        }
1920       if (LocaleCompare(attribute,"repage") == 0)
1921         {
1922           RectangleInfo
1923             geometry;
1924
1925           for ( ; image; image=image->next)
1926           {
1927             flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
1928             if ((flags & WidthValue) != 0)
1929               {
1930                 if ((flags & HeightValue) == 0)
1931                   geometry.height=geometry.width;
1932                 image->page.width=geometry.width;
1933                 image->page.height=geometry.height;
1934               }
1935             if ((flags & AspectValue) != 0)
1936               {
1937                 if ((flags & XValue) != 0)
1938                   image->page.x+=geometry.x;
1939                 if ((flags & YValue) != 0)
1940                   image->page.y+=geometry.y;
1941               }
1942             else
1943               {
1944                 if ((flags & XValue) != 0)
1945                   {
1946                     image->page.x=geometry.x;
1947                     if (((flags & WidthValue) != 0) && (geometry.x > 0))
1948                       image->page.width=image->columns+geometry.x;
1949                   }
1950                 if ((flags & YValue) != 0)
1951                   {
1952                     image->page.y=geometry.y;
1953                     if (((flags & HeightValue) != 0) && (geometry.y > 0))
1954                       image->page.height=image->rows+geometry.y;
1955                   }
1956               }
1957           }
1958           break;
1959         }
1960       if (info)
1961         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1962       for ( ; image; image=image->next)
1963         SetImageProperty(image,attribute,SvPV(sval,na));
1964       break;
1965     }
1966     case 'S':
1967     case 's':
1968     {
1969       if (LocaleCompare(attribute,"sampling-factor") == 0)
1970         {
1971           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1972             {
1973               ThrowPerlException(exception,OptionError,"MissingGeometry",
1974                 SvPV(sval,na));
1975               break;
1976             }
1977           if (info)
1978             (void) CloneString(&info->image_info->sampling_factor,
1979               SvPV(sval,na));
1980           break;
1981         }
1982       if (LocaleCompare(attribute,"scene") == 0)
1983         {
1984           for ( ; image; image=image->next)
1985             image->scene=SvIV(sval);
1986           break;
1987         }
1988       if (LocaleCompare(attribute,"server") == 0)
1989         goto display;
1990       if (LocaleCompare(attribute,"size") == 0)
1991         {
1992           if (info)
1993             {
1994               if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1995                 {
1996                   ThrowPerlException(exception,OptionError,"MissingGeometry",
1997                     SvPV(sval,na));
1998                   break;
1999                 }
2000               (void) CloneString(&info->image_info->size,SvPV(sval,na));
2001             }
2002           break;
2003         }
2004       if (LocaleCompare(attribute,"stroke") == 0)
2005         {
2006           if (info)
2007             (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2008           break;
2009         }
2010       if (info)
2011         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2012       for ( ; image; image=image->next)
2013         SetImageProperty(image,attribute,SvPV(sval,na));
2014       break;
2015     }
2016     case 'T':
2017     case 't':
2018     {
2019       if (LocaleCompare(attribute,"texture") == 0)
2020         {
2021           if (info)
2022             (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2023           break;
2024         }
2025       if (LocaleCompare(attribute,"thread-limit") == 0)
2026         {
2027           MagickSizeType
2028             limit;
2029
2030           limit=MagickResourceInfinity;
2031           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2032             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
2033           (void) SetMagickResourceLimit(ThreadResource,limit);
2034           break;
2035         }
2036       if (LocaleCompare(attribute,"tile-offset") == 0)
2037         {
2038           char
2039             *geometry;
2040
2041           geometry=GetPageGeometry(SvPV(sval,na));
2042           if (info)
2043             (void) CloneString(&info->image_info->page,geometry);
2044           for ( ; image; image=image->next)
2045             (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2046               exception);
2047           geometry=(char *) RelinquishMagickMemory(geometry);
2048           break;
2049         }
2050       if (LocaleCompare(attribute,"time-limit") == 0)
2051         {
2052           MagickSizeType
2053             limit;
2054
2055           limit=MagickResourceInfinity;
2056           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2057             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
2058           (void) SetMagickResourceLimit(TimeResource,limit);
2059           break;
2060         }
2061       if (LocaleCompare(attribute,"transparent-color") == 0)
2062         {
2063           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
2064           if (info)
2065             info->image_info->transparent_color=target_color;
2066           for ( ; image; image=image->next)
2067             image->transparent_color=target_color;
2068           break;
2069         }
2070       if (LocaleCompare(attribute,"type") == 0)
2071         {
2072           sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2073             SvPV(sval,na)) : SvIV(sval);
2074           if (sp < 0)
2075             {
2076               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2077                 SvPV(sval,na));
2078               break;
2079             }
2080           if (info)
2081             info->image_info->type=(ImageType) sp;
2082           for ( ; image; image=image->next)
2083             SetImageType(image,(ImageType) sp,exception);
2084           break;
2085         }
2086       if (info)
2087         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2088       for ( ; image; image=image->next)
2089         SetImageProperty(image,attribute,SvPV(sval,na));
2090       break;
2091     }
2092     case 'U':
2093     case 'u':
2094     {
2095       if (LocaleCompare(attribute,"units") == 0)
2096         {
2097           sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2098             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2099           if (sp < 0)
2100             {
2101               ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2102                 SvPV(sval,na));
2103               break;
2104             }
2105           if (info)
2106             info->image_info->units=(ResolutionType) sp;
2107           for ( ; image; image=image->next)
2108           {
2109             ResolutionType
2110               units;
2111
2112             units=(ResolutionType) sp;
2113             if (image->units != units)
2114               switch (image->units)
2115               {
2116                 case UndefinedResolution:
2117                 case PixelsPerInchResolution:
2118                 {
2119                   if (units == PixelsPerCentimeterResolution)
2120                     {
2121                       image->x_resolution*=2.54;
2122                       image->y_resolution*=2.54;
2123                     }
2124                   break;
2125                 }
2126                 case PixelsPerCentimeterResolution:
2127                 {
2128                   if (units == PixelsPerInchResolution)
2129                     {
2130                       image->x_resolution/=2.54;
2131                       image->y_resolution/=2.54;
2132                     }
2133                   break;
2134                 }
2135               }
2136             image->units=units;
2137           }
2138           break;
2139         }
2140       if (info)
2141         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2142       for ( ; image; image=image->next)
2143         SetImageProperty(image,attribute,SvPV(sval,na));
2144       break;
2145     }
2146     case 'V':
2147     case 'v':
2148     {
2149       if (LocaleCompare(attribute,"verbose") == 0)
2150         {
2151           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2152             SvPV(sval,na)) : SvIV(sval);
2153           if (sp < 0)
2154             {
2155               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2156                 SvPV(sval,na));
2157               break;
2158             }
2159           if (info)
2160             info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2161           break;
2162         }
2163       if (LocaleCompare(attribute,"view") == 0)
2164         {
2165           if (info)
2166             (void) CloneString(&info->image_info->view,SvPV(sval,na));
2167           break;
2168         }
2169       if (LocaleCompare(attribute,"virtual-pixel") == 0)
2170         {
2171           sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2172             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2173           if (sp < 0)
2174             {
2175               ThrowPerlException(exception,OptionError,
2176                 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2177               break;
2178             }
2179           if (info)
2180             info->image_info->virtual_pixel_method=(VirtualPixelMethod) sp;
2181           for ( ; image; image=image->next)
2182             SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp);
2183           break;
2184         }
2185       if (info)
2186         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2187       for ( ; image; image=image->next)
2188         SetImageProperty(image,attribute,SvPV(sval,na));
2189       break;
2190     }
2191     case 'W':
2192     case 'w':
2193     {
2194       if (LocaleCompare(attribute,"white-point") == 0)
2195         {
2196           for ( ; image; image=image->next)
2197           {
2198             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2199             image->chromaticity.white_point.x=geometry_info.rho;
2200             image->chromaticity.white_point.y=geometry_info.sigma;
2201             if ((flags & SigmaValue) == 0)
2202               image->chromaticity.white_point.y=
2203                 image->chromaticity.white_point.x;
2204           }
2205           break;
2206         }
2207       if (info)
2208         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2209       for ( ; image; image=image->next)
2210         SetImageProperty(image,attribute,SvPV(sval,na));
2211       break;
2212     }
2213     default:
2214     {
2215       if (info)
2216         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2217       for ( ; image; image=image->next)
2218         SetImageProperty(image,attribute,SvPV(sval,na));
2219       break;
2220     }
2221   }
2222 }
2223 \f
2224 /*
2225 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2226 %                                                                             %
2227 %                                                                             %
2228 %                                                                             %
2229 %   S e t u p L i s t                                                         %
2230 %                                                                             %
2231 %                                                                             %
2232 %                                                                             %
2233 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2234 %
2235 %  Method SetupList returns the list of all the images linked by their
2236 %  image->next and image->previous link lists for use with ImageMagick.  If
2237 %  info is non-NULL, an info structure is returned in *info.  If
2238 %  reference_vector is non-NULL,an array of SV* are returned in
2239 %  *reference_vector.  Reference_vector is used when the images are going to be
2240 %  replaced with new Image*'s.
2241 %
2242 %  The format of the SetupList routine is:
2243 %
2244 %      Image *SetupList(SV *reference,struct PackageInfo **info,
2245 %        SV ***reference_vector,ExceptionInfo *exception)
2246 %
2247 %  A description of each parameter follows:
2248 %
2249 %    o list: a list of strings.
2250 %
2251 %    o string: a character string.
2252 %
2253 %    o exception: Return any errors or warnings in this structure.
2254 %
2255 */
2256 static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2257   SV ***reference_vector,ExceptionInfo *exception)
2258 {
2259   Image
2260     *image;
2261
2262   ssize_t
2263     current,
2264     last;
2265
2266   if (reference_vector)
2267     *reference_vector=NULL;
2268   if (info)
2269     *info=NULL;
2270   current=0;
2271   last=0;
2272   image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2273   if (info && (SvTYPE(reference) == SVt_PVAV))
2274     *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2275       exception);
2276   return(image);
2277 }
2278 \f
2279 /*
2280 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2281 %                                                                             %
2282 %                                                                             %
2283 %                                                                             %
2284 %   s t r E Q c a s e                                                         %
2285 %                                                                             %
2286 %                                                                             %
2287 %                                                                             %
2288 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2289 %
2290 %  strEQcase() compares two strings and returns 0 if they are the
2291 %  same or if the second string runs out first.  The comparison is case
2292 %  insensitive.
2293 %
2294 %  The format of the strEQcase routine is:
2295 %
2296 %      ssize_t strEQcase(const char *p,const char *q)
2297 %
2298 %  A description of each parameter follows:
2299 %
2300 %    o p: a character string.
2301 %
2302 %    o q: a character string.
2303 %
2304 %
2305 */
2306 static ssize_t strEQcase(const char *p,const char *q)
2307 {
2308   char
2309     c;
2310
2311   register ssize_t
2312     i;
2313
2314   for (i=0 ; (c=(*q)) != 0; i++)
2315   {
2316     if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2317         (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2318       return(0);
2319     p++;
2320     q++;
2321   }
2322   return(((*q == 0) && (*p == 0)) ? i : 0);
2323 }
2324 \f
2325 /*
2326 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2327 %                                                                             %
2328 %                                                                             %
2329 %                                                                             %
2330 %   I m a g e : : M a g i c k                                                 %
2331 %                                                                             %
2332 %                                                                             %
2333 %                                                                             %
2334 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2335 %
2336 %
2337 */
2338 MODULE = Image::Magick PACKAGE = Image::Magick
2339
2340 PROTOTYPES: ENABLE
2341
2342 BOOT:
2343   MagickCoreGenesis("PerlMagick",MagickFalse);
2344   SetWarningHandler(NULL);
2345   SetErrorHandler(NULL);
2346   magick_registry=NewSplayTree((int (*)(const void *,const void *))
2347     NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2348
2349 void
2350 UNLOAD()
2351   PPCODE:
2352   {
2353     if (magick_registry != (SplayTreeInfo *) NULL)
2354       magick_registry=DestroySplayTree(magick_registry);
2355     MagickCoreTerminus();
2356   }
2357
2358 double
2359 constant(name,argument)
2360   char *name
2361   ssize_t argument
2362 \f
2363 #
2364 ###############################################################################
2365 #                                                                             #
2366 #                                                                             #
2367 #                                                                             #
2368 #   A n i m a t e                                                             #
2369 #                                                                             #
2370 #                                                                             #
2371 #                                                                             #
2372 ###############################################################################
2373 #
2374 #
2375 void
2376 Animate(ref,...)
2377   Image::Magick ref=NO_INIT
2378   ALIAS:
2379     AnimateImage  = 1
2380     animate       = 2
2381     animateimage  = 3
2382   PPCODE:
2383   {
2384     ExceptionInfo
2385       *exception;
2386
2387     Image
2388       *image;
2389
2390     register ssize_t
2391       i;
2392
2393     struct PackageInfo
2394       *info,
2395       *package_info;
2396
2397     SV
2398       *perl_exception,
2399       *reference;
2400
2401     PERL_UNUSED_VAR(ref);
2402     PERL_UNUSED_VAR(ix);
2403     exception=AcquireExceptionInfo();
2404     perl_exception=newSVpv("",0);
2405     package_info=(struct PackageInfo *) NULL;
2406     if (sv_isobject(ST(0)) == 0)
2407       {
2408         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2409           PackageName);
2410         goto PerlException;
2411       }
2412     reference=SvRV(ST(0));
2413     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2414     if (image == (Image *) NULL)
2415       {
2416         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2417           PackageName);
2418         goto PerlException;
2419       }
2420     package_info=ClonePackageInfo(info,exception);
2421     if (items == 2)
2422       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2423     else
2424       if (items > 2)
2425         for (i=2; i < items; i+=2)
2426           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2427             exception);
2428     (void) AnimateImages(package_info->image_info,image,exception);
2429     (void) CatchImageException(image);
2430
2431   PerlException:
2432     if (package_info != (struct PackageInfo *) NULL)
2433       DestroyPackageInfo(package_info);
2434     InheritPerlException(exception,perl_exception);
2435     exception=DestroyExceptionInfo(exception);
2436     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2437     SvPOK_on(perl_exception);
2438     ST(0)=sv_2mortal(perl_exception);
2439     XSRETURN(1);
2440   }
2441 \f
2442 #
2443 ###############################################################################
2444 #                                                                             #
2445 #                                                                             #
2446 #                                                                             #
2447 #   A p p e n d                                                               #
2448 #                                                                             #
2449 #                                                                             #
2450 #                                                                             #
2451 ###############################################################################
2452 #
2453 #
2454 void
2455 Append(ref,...)
2456   Image::Magick ref=NO_INIT
2457   ALIAS:
2458     AppendImage  = 1
2459     append       = 2
2460     appendimage  = 3
2461   PPCODE:
2462   {
2463     AV
2464       *av;
2465
2466     char
2467       *attribute;
2468
2469     ExceptionInfo
2470       *exception;
2471
2472     HV
2473       *hv;
2474
2475     Image
2476       *image;
2477
2478     register ssize_t
2479       i;
2480
2481     ssize_t
2482       stack;
2483
2484     struct PackageInfo
2485       *info;
2486
2487     SV
2488       *av_reference,
2489       *perl_exception,
2490       *reference,
2491       *rv,
2492       *sv;
2493
2494     PERL_UNUSED_VAR(ref);
2495     PERL_UNUSED_VAR(ix);
2496     exception=AcquireExceptionInfo();
2497     perl_exception=newSVpv("",0);
2498     sv=NULL;
2499     attribute=NULL;
2500     av=NULL;
2501     if (sv_isobject(ST(0)) == 0)
2502       {
2503         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2504           PackageName);
2505         goto PerlException;
2506       }
2507     reference=SvRV(ST(0));
2508     hv=SvSTASH(reference);
2509     av=newAV();
2510     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2511     SvREFCNT_dec(av);
2512     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2513     if (image == (Image *) NULL)
2514       {
2515         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2516           PackageName);
2517         goto PerlException;
2518       }
2519     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2520     /*
2521       Get options.
2522     */
2523     stack=MagickTrue;
2524     for (i=2; i < items; i+=2)
2525     {
2526       attribute=(char *) SvPV(ST(i-1),na);
2527       switch (*attribute)
2528       {
2529         case 'S':
2530         case 's':
2531         {
2532           if (LocaleCompare(attribute,"stack") == 0)
2533             {
2534               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2535                 SvPV(ST(i),na));
2536               if (stack < 0)
2537                 {
2538                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
2539                     SvPV(ST(i),na));
2540                   return;
2541                 }
2542               break;
2543             }
2544           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2545             attribute);
2546           break;
2547         }
2548         default:
2549         {
2550           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2551             attribute);
2552           break;
2553         }
2554       }
2555     }
2556     image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2557     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2558       goto PerlException;
2559     for ( ; image; image=image->next)
2560     {
2561       AddImageToRegistry(sv,image);
2562       rv=newRV(sv);
2563       av_push(av,sv_bless(rv,hv));
2564       SvREFCNT_dec(sv);
2565     }
2566     exception=DestroyExceptionInfo(exception);
2567     ST(0)=av_reference;
2568     SvREFCNT_dec(perl_exception);
2569     XSRETURN(1);
2570
2571   PerlException:
2572     InheritPerlException(exception,perl_exception);
2573     exception=DestroyExceptionInfo(exception);
2574     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2575     SvPOK_on(perl_exception);
2576     ST(0)=sv_2mortal(perl_exception);
2577     XSRETURN(1);
2578   }
2579 \f
2580 #
2581 ###############################################################################
2582 #                                                                             #
2583 #                                                                             #
2584 #                                                                             #
2585 #   A v e r a g e                                                             #
2586 #                                                                             #
2587 #                                                                             #
2588 #                                                                             #
2589 ###############################################################################
2590 #
2591 #
2592 void
2593 Average(ref)
2594   Image::Magick ref=NO_INIT
2595   ALIAS:
2596     AverageImage   = 1
2597     average        = 2
2598     averageimage   = 3
2599   PPCODE:
2600   {
2601     AV
2602       *av;
2603
2604     char
2605       *p;
2606
2607     ExceptionInfo
2608       *exception;
2609
2610     HV
2611       *hv;
2612
2613     Image
2614       *image;
2615
2616     struct PackageInfo
2617       *info;
2618
2619     SV
2620       *perl_exception,
2621       *reference,
2622       *rv,
2623       *sv;
2624
2625     PERL_UNUSED_VAR(ref);
2626     PERL_UNUSED_VAR(ix);
2627     exception=AcquireExceptionInfo();
2628     perl_exception=newSVpv("",0);
2629     sv=NULL;
2630     if (sv_isobject(ST(0)) == 0)
2631       {
2632         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2633           PackageName);
2634         goto PerlException;
2635       }
2636     reference=SvRV(ST(0));
2637     hv=SvSTASH(reference);
2638     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2639     if (image == (Image *) NULL)
2640       {
2641         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2642           PackageName);
2643         goto PerlException;
2644       }
2645     image=EvaluateImages(image,MeanEvaluateOperator,exception);
2646     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2647       goto PerlException;
2648     /*
2649       Create blessed Perl array for the returned image.
2650     */
2651     av=newAV();
2652     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2653     SvREFCNT_dec(av);
2654     AddImageToRegistry(sv,image);
2655     rv=newRV(sv);
2656     av_push(av,sv_bless(rv,hv));
2657     SvREFCNT_dec(sv);
2658     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2659     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
2660       "average-%.*s",(int) (MaxTextExtent-9),
2661       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2662     (void) CopyMagickString(image->filename,info->image_info->filename,
2663       MaxTextExtent);
2664     SetImageInfo(info->image_info,0,exception);
2665     exception=DestroyExceptionInfo(exception);
2666     SvREFCNT_dec(perl_exception);
2667     XSRETURN(1);
2668
2669   PerlException:
2670     InheritPerlException(exception,perl_exception);
2671     exception=DestroyExceptionInfo(exception);
2672     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2673     SvPOK_on(perl_exception);
2674     ST(0)=sv_2mortal(perl_exception);
2675     XSRETURN(1);
2676   }
2677 \f
2678 #
2679 ###############################################################################
2680 #                                                                             #
2681 #                                                                             #
2682 #                                                                             #
2683 #   B l o b T o I m a g e                                                     #
2684 #                                                                             #
2685 #                                                                             #
2686 #                                                                             #
2687 ###############################################################################
2688 #
2689 #
2690 void
2691 BlobToImage(ref,...)
2692   Image::Magick ref=NO_INIT
2693   ALIAS:
2694     BlobToImage  = 1
2695     blobtoimage  = 2
2696     blobto       = 3
2697   PPCODE:
2698   {
2699     AV
2700       *av;
2701
2702     char
2703       **keep,
2704       **list;
2705
2706     ExceptionInfo
2707       *exception;
2708
2709     HV
2710       *hv;
2711
2712     Image
2713       *image;
2714
2715     register char
2716       **p;
2717
2718     register ssize_t
2719       i;
2720
2721     ssize_t
2722       ac,
2723       n,
2724       number_images;
2725
2726     STRLEN
2727       *length;
2728
2729     struct PackageInfo
2730       *info;
2731
2732     SV
2733       *perl_exception,
2734       *reference,
2735       *rv,
2736       *sv;
2737
2738     PERL_UNUSED_VAR(ref);
2739     PERL_UNUSED_VAR(ix);
2740     exception=AcquireExceptionInfo();
2741     perl_exception=newSVpv("",0);
2742     sv=NULL;
2743     number_images=0;
2744     ac=(items < 2) ? 1 : items-1;
2745     length=(STRLEN *) NULL;
2746     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2747     if (list == (char **) NULL)
2748       {
2749         ThrowPerlException(exception,ResourceLimitError,
2750           "MemoryAllocationFailed",PackageName);
2751         goto PerlException;
2752       }
2753     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2754     if (length == (STRLEN *) NULL)
2755       {
2756         ThrowPerlException(exception,ResourceLimitError,
2757           "MemoryAllocationFailed",PackageName);
2758         goto PerlException;
2759       }
2760     if (sv_isobject(ST(0)) == 0)
2761       {
2762         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2763           PackageName);
2764         goto PerlException;
2765       }
2766     reference=SvRV(ST(0));
2767     hv=SvSTASH(reference);
2768     if (SvTYPE(reference) != SVt_PVAV)
2769       {
2770         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2771           PackageName);
2772         goto PerlException;
2773       }
2774     av=(AV *) reference;
2775     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2776       exception);
2777     n=1;
2778     if (items <= 1)
2779       {
2780         ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2781         goto PerlException;
2782       }
2783     for (n=0, i=0; i < ac; i++)
2784     {
2785       list[n]=(char *) (SvPV(ST(i+1),length[n]));
2786       if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2787         {
2788           list[n]=(char *) (SvPV(ST(i+2),length[n]));
2789           continue;
2790         }
2791       n++;
2792     }
2793     list[n]=(char *) NULL;
2794     keep=list;
2795     for (i=number_images=0; i < n; i++)
2796     {
2797       image=BlobToImage(info->image_info,list[i],length[i],exception);
2798       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2799         break;
2800       for ( ; image; image=image->next)
2801       {
2802         AddImageToRegistry(sv,image);
2803         rv=newRV(sv);
2804         av_push(av,sv_bless(rv,hv));
2805         SvREFCNT_dec(sv);
2806         number_images++;
2807       }
2808     }
2809     /*
2810       Free resources.
2811     */
2812     for (i=0; i < n; i++)
2813       if (list[i] != (char *) NULL)
2814         for (p=keep; list[i] != *p++; )
2815           if (*p == (char *) NULL)
2816             {
2817               list[i]=(char *) RelinquishMagickMemory(list[i]);
2818               break;
2819             }
2820
2821   PerlException:
2822     if (list)
2823       list=(char **) RelinquishMagickMemory(list);
2824     if (length)
2825       length=(STRLEN *) RelinquishMagickMemory(length);
2826     InheritPerlException(exception,perl_exception);
2827     exception=DestroyExceptionInfo(exception);
2828     sv_setiv(perl_exception,(IV) number_images);
2829     SvPOK_on(perl_exception);
2830     ST(0)=sv_2mortal(perl_exception);
2831     XSRETURN(1);
2832   }
2833 \f
2834 #
2835 ###############################################################################
2836 #                                                                             #
2837 #                                                                             #
2838 #                                                                             #
2839 #   C l o n e                                                                 #
2840 #                                                                             #
2841 #                                                                             #
2842 #                                                                             #
2843 ###############################################################################
2844 #
2845 #
2846 void
2847 Clone(ref)
2848   Image::Magick ref=NO_INIT
2849   ALIAS:
2850     CopyImage   = 1
2851     copy        = 2
2852     copyimage   = 3
2853     CloneImage  = 4
2854     clone       = 5
2855     cloneimage  = 6
2856     Clone       = 7
2857   PPCODE:
2858   {
2859     AV
2860       *av;
2861
2862     ExceptionInfo
2863       *exception;
2864
2865     HV
2866       *hv;
2867
2868     Image
2869       *clone,
2870       *image;
2871
2872     struct PackageInfo
2873       *info;
2874
2875     SV
2876       *perl_exception,
2877       *reference,
2878       *rv,
2879       *sv;
2880
2881     PERL_UNUSED_VAR(ref);
2882     PERL_UNUSED_VAR(ix);
2883     exception=AcquireExceptionInfo();
2884     perl_exception=newSVpv("",0);
2885     sv=NULL;
2886     if (sv_isobject(ST(0)) == 0)
2887       {
2888         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2889           PackageName);
2890         goto PerlException;
2891       }
2892     reference=SvRV(ST(0));
2893     hv=SvSTASH(reference);
2894     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2895     if (image == (Image *) NULL)
2896       {
2897         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2898           PackageName);
2899         goto PerlException;
2900       }
2901     /*
2902       Create blessed Perl array for the returned image.
2903     */
2904     av=newAV();
2905     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2906     SvREFCNT_dec(av);
2907     for ( ; image; image=image->next)
2908     {
2909       clone=CloneImage(image,0,0,MagickTrue,exception);
2910       if ((clone == (Image *) NULL) || (exception->severity >= ErrorException))
2911         break;
2912       AddImageToRegistry(sv,clone);
2913       rv=newRV(sv);
2914       av_push(av,sv_bless(rv,hv));
2915       SvREFCNT_dec(sv);
2916     }
2917     exception=DestroyExceptionInfo(exception);
2918     SvREFCNT_dec(perl_exception);
2919     XSRETURN(1);
2920
2921   PerlException:
2922     InheritPerlException(exception,perl_exception);
2923     exception=DestroyExceptionInfo(exception);
2924     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2925     SvPOK_on(perl_exception);
2926     ST(0)=sv_2mortal(perl_exception);
2927     XSRETURN(1);
2928   }
2929 \f
2930 #
2931 ###############################################################################
2932 #                                                                             #
2933 #                                                                             #
2934 #                                                                             #
2935 #   C L O N E                                                                 #
2936 #                                                                             #
2937 #                                                                             #
2938 #                                                                             #
2939 ###############################################################################
2940 #
2941 #
2942 void
2943 CLONE(ref,...)
2944   SV *ref;
2945   CODE:
2946   {
2947     PERL_UNUSED_VAR(ref);
2948     if (magick_registry != (SplayTreeInfo *) NULL)
2949       {
2950         register Image
2951           *p;
2952
2953         ResetSplayTreeIterator(magick_registry);
2954         p=(Image *) GetNextKeyInSplayTree(magick_registry);
2955         while (p != (Image *) NULL)
2956         {
2957           ReferenceImage(p);
2958           p=(Image *) GetNextKeyInSplayTree(magick_registry);
2959         }
2960       }
2961   }
2962 \f
2963 #
2964 ###############################################################################
2965 #                                                                             #
2966 #                                                                             #
2967 #                                                                             #
2968 #   C o a l e s c e                                                           #
2969 #                                                                             #
2970 #                                                                             #
2971 #                                                                             #
2972 ###############################################################################
2973 #
2974 #
2975 void
2976 Coalesce(ref)
2977   Image::Magick ref=NO_INIT
2978   ALIAS:
2979     CoalesceImage   = 1
2980     coalesce        = 2
2981     coalesceimage   = 3
2982   PPCODE:
2983   {
2984     AV
2985       *av;
2986
2987     ExceptionInfo
2988       *exception;
2989
2990     HV
2991       *hv;
2992
2993     Image
2994       *image;
2995
2996     struct PackageInfo
2997       *info;
2998
2999     SV
3000       *av_reference,
3001       *perl_exception,
3002       *reference,
3003       *rv,
3004       *sv;
3005
3006     PERL_UNUSED_VAR(ref);
3007     PERL_UNUSED_VAR(ix);
3008     exception=AcquireExceptionInfo();
3009     perl_exception=newSVpv("",0);
3010     sv=NULL;
3011     if (sv_isobject(ST(0)) == 0)
3012       {
3013         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3014           PackageName);
3015         goto PerlException;
3016       }
3017     reference=SvRV(ST(0));
3018     hv=SvSTASH(reference);
3019     av=newAV();
3020     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3021     SvREFCNT_dec(av);
3022     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3023     if (image == (Image *) NULL)
3024       {
3025         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3026           PackageName);
3027         goto PerlException;
3028       }
3029     image=CoalesceImages(image,exception);
3030     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3031       goto PerlException;
3032     for ( ; image; image=image->next)
3033     {
3034       AddImageToRegistry(sv,image);
3035       rv=newRV(sv);
3036       av_push(av,sv_bless(rv,hv));
3037       SvREFCNT_dec(sv);
3038     }
3039     exception=DestroyExceptionInfo(exception);
3040     ST(0)=av_reference;
3041     SvREFCNT_dec(perl_exception);
3042     XSRETURN(1);
3043
3044   PerlException:
3045     InheritPerlException(exception,perl_exception);
3046     exception=DestroyExceptionInfo(exception);
3047     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3048     SvPOK_on(perl_exception);
3049     ST(0)=sv_2mortal(perl_exception);
3050     XSRETURN(1);
3051   }
3052 \f
3053 #
3054 ###############################################################################
3055 #                                                                             #
3056 #                                                                             #
3057 #                                                                             #
3058 #   C o m p a r e                                                             #
3059 #                                                                             #
3060 #                                                                             #
3061 #                                                                             #
3062 ###############################################################################
3063 #
3064 #
3065 void
3066 Compare(ref,...)
3067   Image::Magick ref=NO_INIT
3068   ALIAS:
3069     CompareImages = 1
3070     compare      = 2
3071     compareimage = 3
3072   PPCODE:
3073   {
3074     AV
3075       *av;
3076
3077     char
3078       *attribute;
3079
3080     double
3081       distortion;
3082
3083     ExceptionInfo
3084       *exception;
3085
3086     HV
3087       *hv;
3088
3089     Image
3090       *difference_image,
3091       *image,
3092       *reconstruct_image;
3093
3094     MetricType
3095       metric;
3096
3097     register ssize_t
3098       i;
3099
3100     ssize_t
3101       option;
3102
3103     struct PackageInfo
3104       *info;
3105
3106     SV
3107       *av_reference,
3108       *perl_exception,
3109       *reference,
3110       *rv,
3111       *sv;
3112
3113     PERL_UNUSED_VAR(ref);
3114     PERL_UNUSED_VAR(ix);
3115     exception=AcquireExceptionInfo();
3116     perl_exception=newSVpv("",0);
3117     sv=NULL;
3118     av=NULL;
3119     attribute=NULL;
3120     if (sv_isobject(ST(0)) == 0)
3121       {
3122         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3123           PackageName);
3124         goto PerlException;
3125       }
3126     reference=SvRV(ST(0));
3127     hv=SvSTASH(reference);
3128     av=newAV();
3129     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3130     SvREFCNT_dec(av);
3131     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3132     if (image == (Image *) NULL)
3133       {
3134         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3135           PackageName);
3136         goto PerlException;
3137       }
3138     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3139     /*
3140       Get attribute.
3141     */
3142     reconstruct_image=image;
3143     metric=RootMeanSquaredErrorMetric;
3144     for (i=2; i < items; i+=2)
3145     {
3146       attribute=(char *) SvPV(ST(i-1),na);
3147       switch (*attribute)
3148       {
3149         case 'C':
3150         case 'c':
3151         {
3152           if (LocaleCompare(attribute,"channel") == 0)
3153             {
3154               ssize_t
3155                 option;
3156
3157               option=ParseChannelOption(SvPV(ST(i),na));
3158               if (option < 0)
3159                 {
3160                   ThrowPerlException(exception,OptionError,
3161                     "UnrecognizedType",SvPV(ST(i),na));
3162                   return;
3163                 }
3164               SetPixelChannelMap(image,(ChannelType) option);
3165               break;
3166             }
3167           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3168             attribute);
3169           break;
3170         }
3171         case 'F':
3172         case 'f':
3173         {
3174           if (LocaleCompare(attribute,"fuzz") == 0)
3175             {
3176               image->fuzz=SiPrefixToDouble(SvPV(ST(i),na),100.0);
3177               break;
3178             }
3179           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3180             attribute);
3181           break;
3182         }
3183         case 'I':
3184         case 'i':
3185         {
3186           if (LocaleCompare(attribute,"image") == 0)
3187             {
3188               reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3189                 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3190               break;
3191             }
3192           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3193             attribute);
3194           break;
3195         }
3196         case 'M':
3197         case 'm':
3198         {
3199           if (LocaleCompare(attribute,"metric") == 0)
3200             {
3201               option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3202                 SvPV(ST(i),na));
3203               if (option < 0)
3204                 {
3205                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3206                     SvPV(ST(i),na));
3207                   break;
3208                 }
3209               metric=(MetricType) option;
3210               break;
3211             }
3212           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3213             attribute);
3214           break;
3215         }
3216         default:
3217         {
3218           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3219             attribute);
3220           break;
3221         }
3222       }
3223     }
3224     difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3225       exception);
3226     if (difference_image != (Image *) NULL)
3227       {
3228         difference_image->error.mean_error_per_pixel=distortion;
3229         AddImageToRegistry(sv,difference_image);
3230         rv=newRV(sv);
3231         av_push(av,sv_bless(rv,hv));
3232         SvREFCNT_dec(sv);
3233       }
3234     exception=DestroyExceptionInfo(exception);
3235     ST(0)=av_reference;
3236     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3237     XSRETURN(1);
3238
3239   PerlException:
3240     InheritPerlException(exception,perl_exception);
3241     exception=DestroyExceptionInfo(exception);
3242     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3243     SvPOK_on(perl_exception);
3244     ST(0)=sv_2mortal(perl_exception);
3245     XSRETURN(1);
3246   }
3247 \f
3248 #
3249 ###############################################################################
3250 #                                                                             #
3251 #                                                                             #
3252 #                                                                             #
3253 #   C o m p a r e L a y e r s                                                 #
3254 #                                                                             #
3255 #                                                                             #
3256 #                                                                             #
3257 ###############################################################################
3258 #
3259 #
3260 void
3261 CompareLayers(ref)
3262   Image::Magick ref=NO_INIT
3263   ALIAS:
3264     CompareImagesLayers   = 1
3265     comparelayers        = 2
3266     compareimagelayers   = 3
3267   PPCODE:
3268   {
3269     AV
3270       *av;
3271
3272     char
3273       *attribute;
3274
3275     ExceptionInfo
3276       *exception;
3277
3278     HV
3279       *hv;
3280
3281     Image
3282       *image;
3283
3284     ImageLayerMethod
3285       method;
3286
3287     register ssize_t
3288       i;
3289
3290     ssize_t
3291       option;
3292
3293     struct PackageInfo
3294       *info;
3295
3296     SV
3297       *av_reference,
3298       *perl_exception,
3299       *reference,
3300       *rv,
3301       *sv;
3302
3303     PERL_UNUSED_VAR(ref);
3304     PERL_UNUSED_VAR(ix);
3305     exception=AcquireExceptionInfo();
3306     perl_exception=newSVpv("",0);
3307     sv=NULL;
3308     if (sv_isobject(ST(0)) == 0)
3309       {
3310         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3311           PackageName);
3312         goto PerlException;
3313       }
3314     reference=SvRV(ST(0));
3315     hv=SvSTASH(reference);
3316     av=newAV();
3317     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3318     SvREFCNT_dec(av);
3319     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3320     if (image == (Image *) NULL)
3321       {
3322         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3323           PackageName);
3324         goto PerlException;
3325       }
3326     method=CompareAnyLayer;
3327     for (i=2; i < items; i+=2)
3328     {
3329       attribute=(char *) SvPV(ST(i-1),na);
3330       switch (*attribute)
3331       {
3332         case 'M':
3333         case 'm':
3334         {
3335           if (LocaleCompare(attribute,"method") == 0)
3336             {
3337               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3338                 SvPV(ST(i),na));
3339               if (option < 0)
3340                 {
3341                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3342                     SvPV(ST(i),na));
3343                   break;
3344                 }
3345                method=(ImageLayerMethod) option;
3346               break;
3347             }
3348           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3349             attribute);
3350           break;
3351         }
3352         default:
3353         {
3354           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3355             attribute);
3356           break;
3357         }
3358       }
3359     }
3360     image=CompareImagesLayers(image,method,exception);
3361     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3362       goto PerlException;
3363     for ( ; image; image=image->next)
3364     {
3365       AddImageToRegistry(sv,image);
3366       rv=newRV(sv);
3367       av_push(av,sv_bless(rv,hv));
3368       SvREFCNT_dec(sv);
3369     }
3370     exception=DestroyExceptionInfo(exception);
3371     ST(0)=av_reference;
3372     SvREFCNT_dec(perl_exception);
3373     XSRETURN(1);
3374
3375   PerlException:
3376     InheritPerlException(exception,perl_exception);
3377     exception=DestroyExceptionInfo(exception);
3378     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3379     SvPOK_on(perl_exception);
3380     ST(0)=sv_2mortal(perl_exception);
3381     XSRETURN(1);
3382   }
3383 \f
3384 #
3385 ###############################################################################
3386 #                                                                             #
3387 #                                                                             #
3388 #                                                                             #
3389 #   D e s t r o y                                                             #
3390 #                                                                             #
3391 #                                                                             #
3392 #                                                                             #
3393 ###############################################################################
3394 #
3395 #
3396 void
3397 DESTROY(ref)
3398   Image::Magick ref=NO_INIT
3399   PPCODE:
3400   {
3401     SV
3402       *reference;
3403
3404     PERL_UNUSED_VAR(ref);
3405     if (sv_isobject(ST(0)) == 0)
3406       croak("ReferenceIsNotMyType");
3407     reference=SvRV(ST(0));
3408     switch (SvTYPE(reference))
3409     {
3410       case SVt_PVAV:
3411       {
3412         char
3413           message[MaxTextExtent];
3414
3415         const SV
3416           *key;
3417
3418         HV
3419           *hv;
3420
3421         GV
3422           **gvp;
3423
3424         struct PackageInfo
3425           *info;
3426
3427         SV
3428           *sv;
3429
3430         /*
3431           Array (AV *) reference
3432         */
3433         (void) FormatLocaleString(message,MaxTextExtent,"package%s%p",
3434           XS_VERSION,reference);
3435         hv=gv_stashpv(PackageName, FALSE);
3436         if (!hv)
3437           break;
3438         gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3439         if (!gvp)
3440           break;
3441         sv=GvSV(*gvp);
3442         if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3443           {
3444             info=(struct PackageInfo *) SvIV(sv);
3445             DestroyPackageInfo(info);
3446           }
3447         key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3448         (void) key;
3449         break;
3450       }
3451       case SVt_PVMG:
3452       {
3453         Image
3454           *image;
3455
3456         /*
3457           Blessed scalar = (Image *) SvIV(reference)
3458         */
3459         image=(Image *) SvIV(reference);
3460         if (image != (Image *) NULL)
3461           DeleteImageFromRegistry(reference,image);
3462         break;
3463       }
3464       default:
3465         break;
3466     }
3467   }
3468 \f
3469 #
3470 ###############################################################################
3471 #                                                                             #
3472 #                                                                             #
3473 #                                                                             #
3474 #   D i s p l a y                                                             #
3475 #                                                                             #
3476 #                                                                             #
3477 #                                                                             #
3478 ###############################################################################
3479 #
3480 #
3481 void
3482 Display(ref,...)
3483   Image::Magick ref=NO_INIT
3484   ALIAS:
3485     DisplayImage  = 1
3486     display       = 2
3487     displayimage  = 3
3488   PPCODE:
3489   {
3490     ExceptionInfo
3491       *exception;
3492
3493     Image
3494       *image;
3495
3496     register ssize_t
3497       i;
3498
3499     struct PackageInfo
3500       *info,
3501       *package_info;
3502
3503     SV
3504       *perl_exception,
3505       *reference;
3506
3507     PERL_UNUSED_VAR(ref);
3508     PERL_UNUSED_VAR(ix);
3509     exception=AcquireExceptionInfo();
3510     perl_exception=newSVpv("",0);
3511     package_info=(struct PackageInfo *) NULL;
3512     if (sv_isobject(ST(0)) == 0)
3513       {
3514         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3515           PackageName);
3516         goto PerlException;
3517       }
3518     reference=SvRV(ST(0));
3519     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3520     if (image == (Image *) NULL)
3521       {
3522         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3523           PackageName);
3524         goto PerlException;
3525       }
3526     package_info=ClonePackageInfo(info,exception);
3527     if (items == 2)
3528       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3529     else
3530       if (items > 2)
3531         for (i=2; i < items; i+=2)
3532           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3533             exception);
3534     (void) DisplayImages(package_info->image_info,image,exception);
3535     (void) CatchImageException(image);
3536
3537   PerlException:
3538     if (package_info != (struct PackageInfo *) NULL)
3539       DestroyPackageInfo(package_info);
3540     InheritPerlException(exception,perl_exception);
3541     exception=DestroyExceptionInfo(exception);
3542     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3543     SvPOK_on(perl_exception);
3544     ST(0)=sv_2mortal(perl_exception);
3545     XSRETURN(1);
3546   }
3547 \f
3548 #
3549 ###############################################################################
3550 #                                                                             #
3551 #                                                                             #
3552 #                                                                             #
3553 #   E v a l u a t e I m a g e s                                               #
3554 #                                                                             #
3555 #                                                                             #
3556 #                                                                             #
3557 ###############################################################################
3558 #
3559 #
3560 void
3561 EvaluateImages(ref)
3562   Image::Magick ref=NO_INIT
3563   ALIAS:
3564     EvaluateImages   = 1
3565     evaluateimages   = 2
3566   PPCODE:
3567   {
3568     AV
3569       *av;
3570
3571     char
3572       *attribute,
3573       *p;
3574
3575     ExceptionInfo
3576       *exception;
3577
3578     HV
3579       *hv;
3580
3581     Image
3582       *image;
3583
3584     MagickEvaluateOperator
3585       op;
3586
3587     register ssize_t
3588       i;
3589
3590     struct PackageInfo
3591       *info;
3592
3593     SV
3594       *perl_exception,
3595       *reference,
3596       *rv,
3597       *sv;
3598
3599     PERL_UNUSED_VAR(ref);
3600     PERL_UNUSED_VAR(ix);
3601     exception=AcquireExceptionInfo();
3602     perl_exception=newSVpv("",0);
3603     sv=NULL;
3604     if (sv_isobject(ST(0)) == 0)
3605       {
3606         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3607           PackageName);
3608         goto PerlException;
3609       }
3610     reference=SvRV(ST(0));
3611     hv=SvSTASH(reference);
3612     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3613     if (image == (Image *) NULL)
3614       {
3615         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3616           PackageName);
3617         goto PerlException;
3618       }
3619     op=MeanEvaluateOperator;
3620     if (items == 2)
3621       {
3622         ssize_t
3623           in;
3624
3625         in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
3626           SvPV(ST(1),na));
3627         if (in < 0)
3628           {
3629             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3630               SvPV(ST(1),na));
3631             return;
3632           }
3633         op=(MagickEvaluateOperator) in;
3634       }
3635     else
3636       for (i=2; i < items; i+=2)
3637       {
3638         attribute=(char *) SvPV(ST(i-1),na);
3639         switch (*attribute)
3640         {
3641           case 'O':
3642           case 'o':
3643           {
3644             if (LocaleCompare(attribute,"operator") == 0)
3645               {
3646                 ssize_t
3647                   in;
3648
3649                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3650                   MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
3651                 if (in < 0)
3652                   {
3653                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3654                       SvPV(ST(i),na));
3655                     return;
3656                   }
3657                 op=(MagickEvaluateOperator) in;
3658                 break;
3659               }
3660             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3661               attribute);
3662             break;
3663           }
3664           default:
3665           {
3666             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3667               attribute);
3668             break;
3669           }
3670         }
3671       }
3672     image=EvaluateImages(image,op,exception);
3673     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3674       goto PerlException;
3675     /*
3676       Create blessed Perl array for the returned image.
3677     */
3678     av=newAV();
3679     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3680     SvREFCNT_dec(av);
3681     AddImageToRegistry(sv,image);
3682     rv=newRV(sv);
3683     av_push(av,sv_bless(rv,hv));
3684     SvREFCNT_dec(sv);
3685     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3686     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
3687       "evaluate-%.*s",(int) (MaxTextExtent-9),
3688       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3689     (void) CopyMagickString(image->filename,info->image_info->filename,
3690       MaxTextExtent);
3691     SetImageInfo(info->image_info,0,exception);
3692     exception=DestroyExceptionInfo(exception);
3693     SvREFCNT_dec(perl_exception);
3694     XSRETURN(1);
3695
3696   PerlException:
3697     InheritPerlException(exception,perl_exception);
3698     exception=DestroyExceptionInfo(exception);
3699     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3700     SvPOK_on(perl_exception);
3701     ST(0)=sv_2mortal(perl_exception);
3702     XSRETURN(1);
3703   }
3704 \f
3705 #
3706 ###############################################################################
3707 #                                                                             #
3708 #                                                                             #
3709 #                                                                             #
3710 #   F e a t u r e s                                                           #
3711 #                                                                             #
3712 #                                                                             #
3713 #                                                                             #
3714 ###############################################################################
3715 #
3716 #
3717 void
3718 Features(ref,...)
3719   Image::Magick ref=NO_INIT
3720   ALIAS:
3721     FeaturesImage = 1
3722     features      = 2
3723     featuresimage = 3
3724   PPCODE:
3725   {
3726 #define ChannelFeatures(channel,direction) \
3727 { \
3728   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3729     channel_features[channel].angular_second_moment[direction]); \
3730   PUSHs(sv_2mortal(newSVpv(message,0))); \
3731   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3732     channel_features[channel].contrast[direction]); \
3733   PUSHs(sv_2mortal(newSVpv(message,0))); \
3734   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3735     channel_features[channel].contrast[direction]); \
3736   PUSHs(sv_2mortal(newSVpv(message,0))); \
3737   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3738     channel_features[channel].variance_sum_of_squares[direction]); \
3739   PUSHs(sv_2mortal(newSVpv(message,0))); \
3740   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3741     channel_features[channel].inverse_difference_moment[direction]); \
3742   PUSHs(sv_2mortal(newSVpv(message,0))); \
3743   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3744     channel_features[channel].sum_average[direction]); \
3745   PUSHs(sv_2mortal(newSVpv(message,0))); \
3746   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3747     channel_features[channel].sum_variance[direction]); \
3748   PUSHs(sv_2mortal(newSVpv(message,0))); \
3749   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3750     channel_features[channel].sum_entropy[direction]); \
3751   PUSHs(sv_2mortal(newSVpv(message,0))); \
3752   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3753     channel_features[channel].entropy[direction]); \
3754   PUSHs(sv_2mortal(newSVpv(message,0))); \
3755   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3756     channel_features[channel].difference_variance[direction]); \
3757   PUSHs(sv_2mortal(newSVpv(message,0))); \
3758   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3759     channel_features[channel].difference_entropy[direction]); \
3760   PUSHs(sv_2mortal(newSVpv(message,0))); \
3761   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3762     channel_features[channel].measure_of_correlation_1[direction]); \
3763   PUSHs(sv_2mortal(newSVpv(message,0))); \
3764   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3765     channel_features[channel].measure_of_correlation_2[direction]); \
3766   PUSHs(sv_2mortal(newSVpv(message,0))); \
3767   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3768     channel_features[channel].maximum_correlation_coefficient[direction]); \
3769   PUSHs(sv_2mortal(newSVpv(message,0))); \
3770 }
3771
3772     AV
3773       *av;
3774
3775     char
3776       *attribute,
3777       message[MaxTextExtent];
3778
3779     ChannelFeatures
3780       *channel_features;
3781
3782     double
3783       distance;
3784
3785     ExceptionInfo
3786       *exception;
3787
3788     Image
3789       *image;
3790
3791     register ssize_t
3792       i;
3793
3794     ssize_t
3795       count;
3796
3797     struct PackageInfo
3798       *info;
3799
3800     SV
3801       *perl_exception,
3802       *reference;
3803
3804     PERL_UNUSED_VAR(ref);
3805     PERL_UNUSED_VAR(ix);
3806     exception=AcquireExceptionInfo();
3807     perl_exception=newSVpv("",0);
3808     av=NULL;
3809     if (sv_isobject(ST(0)) == 0)
3810       {
3811         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3812           PackageName);
3813         goto PerlException;
3814       }
3815     reference=SvRV(ST(0));
3816     av=newAV();
3817     SvREFCNT_dec(av);
3818     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3819     if (image == (Image *) NULL)
3820       {
3821         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3822           PackageName);
3823         goto PerlException;
3824       }
3825     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3826     distance=1;
3827     for (i=2; i < items; i+=2)
3828     {
3829       attribute=(char *) SvPV(ST(i-1),na);
3830       switch (*attribute)
3831       {
3832         case 'D':
3833         case 'd':
3834         {
3835           if (LocaleCompare(attribute,"distance") == 0)
3836             {
3837               distance=StringToLong((char *) SvPV(ST(1),na));
3838               break;
3839             }
3840           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3841             attribute);
3842           break;
3843         }
3844         default:
3845         {
3846           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3847             attribute);
3848           break;
3849         }
3850       }
3851     }
3852     count=0;
3853     for ( ; image; image=image->next)
3854     {
3855       channel_features=GetImageFeatures(image,distance,
3856         &image->exception);
3857       if (channel_features == (ChannelFeatures *) NULL)
3858         continue;
3859       count++;
3860       EXTEND(sp,75*count);
3861       for (i=0; i < 4; i++)
3862       {
3863         ChannelFeatures(RedChannel,i);
3864         ChannelFeatures(GreenChannel,i);
3865         ChannelFeatures(BlueChannel,i);
3866         if (image->colorspace == CMYKColorspace)
3867           ChannelFeatures(BlackChannel,i);
3868         if (image->matte != MagickFalse)
3869           ChannelFeatures(AlphaChannel,i);
3870       }
3871       channel_features=(ChannelFeatures *)
3872         RelinquishMagickMemory(channel_features);
3873     }
3874
3875   PerlException:
3876     InheritPerlException(exception,perl_exception);
3877     exception=DestroyExceptionInfo(exception);
3878     SvREFCNT_dec(perl_exception);
3879   }
3880 \f
3881 #
3882 ###############################################################################
3883 #                                                                             #
3884 #                                                                             #
3885 #                                                                             #
3886 #   F l a t t e n                                                             #
3887 #                                                                             #
3888 #                                                                             #
3889 #                                                                             #
3890 ###############################################################################
3891 #
3892 #
3893 void
3894 Flatten(ref)
3895   Image::Magick ref=NO_INIT
3896   ALIAS:
3897     FlattenImage   = 1
3898     flatten        = 2
3899     flattenimage   = 3
3900   PPCODE:
3901   {
3902     AV
3903       *av;
3904
3905     char
3906       *attribute,
3907       *p;
3908
3909     ExceptionInfo
3910       *exception;
3911
3912     HV
3913       *hv;
3914
3915     Image
3916       *image;
3917
3918     PixelPacket
3919       background_color;
3920
3921     register ssize_t
3922       i;
3923
3924     struct PackageInfo
3925       *info;
3926
3927     SV
3928       *perl_exception,
3929       *reference,
3930       *rv,
3931       *sv;
3932
3933     PERL_UNUSED_VAR(ref);
3934     PERL_UNUSED_VAR(ix);
3935     exception=AcquireExceptionInfo();
3936     perl_exception=newSVpv("",0);
3937     sv=NULL;
3938     if (sv_isobject(ST(0)) == 0)
3939       {
3940         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3941           PackageName);
3942         goto PerlException;
3943       }
3944     reference=SvRV(ST(0));
3945     hv=SvSTASH(reference);
3946     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3947     if (image == (Image *) NULL)
3948       {
3949         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3950           PackageName);
3951         goto PerlException;
3952       }
3953     background_color=image->background_color;
3954     if (items == 2)
3955       (void) QueryColorDatabase((char *) SvPV(ST(1),na),&background_color,
3956         exception);
3957     else
3958       for (i=2; i < items; i+=2)
3959       {
3960         attribute=(char *) SvPV(ST(i-1),na);
3961         switch (*attribute)
3962         {
3963           case 'B':
3964           case 'b':
3965           {
3966             if (LocaleCompare(attribute,"background") == 0)
3967               {
3968                 (void) QueryColorDatabase((char *) SvPV(ST(1),na),
3969                   &background_color,exception);
3970                 break;
3971               }
3972             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3973               attribute);
3974             break;
3975           }
3976           default:
3977           {
3978             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3979               attribute);
3980             break;
3981           }
3982         }
3983       }
3984     image->background_color=background_color;
3985     image=MergeImageLayers(image,FlattenLayer,exception);
3986     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3987       goto PerlException;
3988     /*
3989       Create blessed Perl array for the returned image.
3990     */
3991     av=newAV();
3992     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3993     SvREFCNT_dec(av);
3994     AddImageToRegistry(sv,image);
3995     rv=newRV(sv);
3996     av_push(av,sv_bless(rv,hv));
3997     SvREFCNT_dec(sv);
3998     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3999     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
4000       "flatten-%.*s",(int) (MaxTextExtent-9),
4001       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4002     (void) CopyMagickString(image->filename,info->image_info->filename,
4003       MaxTextExtent);
4004     SetImageInfo(info->image_info,0,exception);
4005     exception=DestroyExceptionInfo(exception);
4006     SvREFCNT_dec(perl_exception);
4007     XSRETURN(1);
4008
4009   PerlException:
4010     InheritPerlException(exception,perl_exception);
4011     exception=DestroyExceptionInfo(exception);
4012     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4013     SvPOK_on(perl_exception);  /* return messages in string context */
4014     ST(0)=sv_2mortal(perl_exception);
4015     XSRETURN(1);
4016   }
4017 \f
4018 #
4019 ###############################################################################
4020 #                                                                             #
4021 #                                                                             #
4022 #                                                                             #
4023 #   F x                                                                       #
4024 #                                                                             #
4025 #                                                                             #
4026 #                                                                             #
4027 ###############################################################################
4028 #
4029 #
4030 void
4031 Fx(ref,...)
4032   Image::Magick ref=NO_INIT
4033   ALIAS:
4034     FxImage  = 1
4035     fx       = 2
4036     fximage  = 3
4037   PPCODE:
4038   {
4039     AV
4040       *av;
4041
4042     char
4043       *attribute,
4044       expression[MaxTextExtent];
4045
4046     ChannelType
4047       channel,
4048       channel_mask;
4049
4050     ExceptionInfo
4051       *exception;
4052
4053     HV
4054       *hv;
4055
4056     Image
4057       *image;
4058
4059     register ssize_t
4060       i;
4061
4062     struct PackageInfo
4063       *info;
4064
4065     SV
4066       *av_reference,
4067       *perl_exception,
4068       *reference,
4069       *rv,
4070       *sv;
4071
4072     PERL_UNUSED_VAR(ref);
4073     PERL_UNUSED_VAR(ix);
4074     exception=AcquireExceptionInfo();
4075     perl_exception=newSVpv("",0);
4076     sv=NULL;
4077     attribute=NULL;
4078     av=NULL;
4079     if (sv_isobject(ST(0)) == 0)
4080       {
4081         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4082           PackageName);
4083         goto PerlException;
4084       }
4085     reference=SvRV(ST(0));
4086     hv=SvSTASH(reference);
4087     av=newAV();
4088     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4089     SvREFCNT_dec(av);
4090     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4091     if (image == (Image *) NULL)
4092       {
4093         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4094           PackageName);
4095         goto PerlException;
4096       }
4097     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4098     /*
4099       Get options.
4100     */
4101     channel=DefaultChannels;
4102     (void) CopyMagickString(expression,"u",MaxTextExtent);
4103     if (items == 2)
4104       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MaxTextExtent);
4105     else
4106       for (i=2; i < items; i+=2)
4107       {
4108         attribute=(char *) SvPV(ST(i-1),na);
4109         switch (*attribute)
4110         {
4111           case 'C':
4112           case 'c':
4113           {
4114             if (LocaleCompare(attribute,"channel") == 0)
4115               {
4116                 ssize_t
4117                   option;
4118
4119                 option=ParseChannelOption(SvPV(ST(i),na));
4120                 if (option < 0)
4121                   {
4122                     ThrowPerlException(exception,OptionError,
4123                       "UnrecognizedType",SvPV(ST(i),na));
4124                     return;
4125                   }
4126                 channel=(ChannelType) option;
4127                 break;
4128               }
4129             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4130               attribute);
4131             break;
4132           }
4133           case 'E':
4134           case 'e':
4135           {
4136             if (LocaleCompare(attribute,"expression") == 0)
4137               {
4138                 (void) CopyMagickString(expression,SvPV(ST(i),na),
4139                   MaxTextExtent);
4140                 break;
4141               }
4142             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4143               attribute);
4144             break;
4145           }
4146           default:
4147           {
4148             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4149               attribute);
4150             break;
4151           }
4152         }
4153       }
4154     channel_mask=SetPixelChannelMask(image,channel);
4155     image=FxImage(image,expression,exception);
4156     if (image != (Image *) NULL)
4157       (void) SetPixelChannelMask(image,channel_mask);
4158     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
4159       goto PerlException;
4160     for ( ; image; image=image->next)
4161     {
4162       AddImageToRegistry(sv,image);
4163       rv=newRV(sv);
4164       av_push(av,sv_bless(rv,hv));
4165       SvREFCNT_dec(sv);
4166     }
4167     exception=DestroyExceptionInfo(exception);
4168     ST(0)=av_reference;
4169     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4170     XSRETURN(1);
4171
4172   PerlException:
4173     InheritPerlException(exception,perl_exception);
4174     exception=DestroyExceptionInfo(exception);
4175     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4176     SvPOK_on(perl_exception);
4177     ST(0)=sv_2mortal(perl_exception);
4178     XSRETURN(1);
4179   }
4180 \f
4181 #
4182 ###############################################################################
4183 #                                                                             #
4184 #                                                                             #
4185 #                                                                             #
4186 #   G e t                                                                     #
4187 #                                                                             #
4188 #                                                                             #
4189 #                                                                             #
4190 ###############################################################################
4191 #
4192 #
4193 void
4194 Get(ref,...)
4195   Image::Magick ref=NO_INIT
4196   ALIAS:
4197     GetAttributes = 1
4198     GetAttribute  = 2
4199     get           = 3
4200     getattributes = 4
4201     getattribute  = 5
4202   PPCODE:
4203   {
4204     char
4205       *attribute,
4206       color[MaxTextExtent];
4207
4208     const char
4209       *value;
4210
4211     ExceptionInfo
4212       *exception;
4213
4214     Image
4215       *image;
4216
4217     long
4218       j;
4219
4220     register ssize_t
4221       i;
4222
4223     struct PackageInfo
4224       *info;
4225
4226     SV
4227       *perl_exception,
4228       *reference,
4229       *s;
4230
4231     PERL_UNUSED_VAR(ref);
4232     PERL_UNUSED_VAR(ix);
4233     exception=AcquireExceptionInfo();
4234     perl_exception=newSVpv("",0);
4235     if (sv_isobject(ST(0)) == 0)
4236       {
4237         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4238           PackageName);
4239         XSRETURN_EMPTY;
4240       }
4241     reference=SvRV(ST(0));
4242     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4243     if (image == (Image *) NULL && !info)
4244       XSRETURN_EMPTY;
4245     EXTEND(sp,items);
4246     for (i=1; i < items; i++)
4247     {
4248       attribute=(char *) SvPV(ST(i),na);
4249       s=NULL;
4250       switch (*attribute)
4251       {
4252         case 'A':
4253         case 'a':
4254         {
4255           if (LocaleCompare(attribute,"adjoin") == 0)
4256             {
4257               if (info)
4258                 s=newSViv((ssize_t) info->image_info->adjoin);
4259               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4260               continue;
4261             }
4262           if (LocaleCompare(attribute,"antialias") == 0)
4263             {
4264               if (info)
4265                 s=newSViv((ssize_t) info->image_info->antialias);
4266               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4267               continue;
4268             }
4269           if (LocaleCompare(attribute,"area") == 0)
4270             {
4271               s=newSViv(GetMagickResource(AreaResource));
4272               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4273               continue;
4274             }
4275           if (LocaleCompare(attribute,"attenuate") == 0)
4276             {
4277               const char
4278                 *value;
4279
4280               value=GetImageProperty(image,attribute);
4281               if (value != (const char *) NULL)
4282                 s=newSVpv(value,0);
4283               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4284               continue;
4285             }
4286           if (LocaleCompare(attribute,"authenticate") == 0)
4287             {
4288               if (info)
4289                 s=newSVpv(info->image_info->authenticate,0);
4290               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4291               continue;
4292             }
4293           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4294             attribute);
4295           break;
4296         }
4297         case 'B':
4298         case 'b':
4299         {
4300           if (LocaleCompare(attribute,"background") == 0)
4301             {
4302               if (image == (Image *) NULL)
4303                 break;
4304               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4305                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4306                 image->background_color.red,image->background_color.green,
4307                 image->background_color.blue,image->background_color.alpha);
4308               s=newSVpv(color,0);
4309               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4310               continue;
4311             }
4312           if (LocaleCompare(attribute,"base-columns") == 0)
4313             {
4314               if (image != (Image *) NULL)
4315                 s=newSViv((ssize_t) image->magick_columns);
4316               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4317               continue;
4318             }
4319           if (LocaleCompare(attribute,"base-filename") == 0)
4320             {
4321               if (image != (Image *) NULL)
4322                 s=newSVpv(image->magick_filename,0);
4323               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4324               continue;
4325             }
4326           if (LocaleCompare(attribute,"base-height") == 0)
4327             {
4328               if (image != (Image *) NULL)
4329                 s=newSViv((ssize_t) image->magick_rows);
4330               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4331               continue;
4332             }
4333           if (LocaleCompare(attribute,"base-rows") == 0)
4334             {
4335               if (image != (Image *) NULL)
4336                 s=newSViv((ssize_t) image->magick_rows);
4337               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4338               continue;
4339             }
4340           if (LocaleCompare(attribute,"base-width") == 0)
4341             {
4342               if (image != (Image *) NULL)
4343                 s=newSViv((ssize_t) image->magick_columns);
4344               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4345               continue;
4346             }
4347           if (LocaleCompare(attribute,"bias") == 0)
4348             {
4349               if (image != (Image *) NULL)
4350                 s=newSVnv(image->bias);
4351               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4352               continue;
4353             }
4354           if (LocaleCompare(attribute,"blue-primary") == 0)
4355             {
4356               if (image == (Image *) NULL)
4357                 break;
4358               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4359                 image->chromaticity.blue_primary.x,
4360                 image->chromaticity.blue_primary.y);
4361               s=newSVpv(color,0);
4362               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4363               continue;
4364             }
4365           if (LocaleCompare(attribute,"bordercolor") == 0)
4366             {
4367               if (image == (Image *) NULL)
4368                 break;
4369               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4370                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4371                 image->border_color.red,image->border_color.green,
4372                 image->border_color.blue,image->border_color.alpha);
4373               s=newSVpv(color,0);
4374               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4375               continue;
4376             }
4377           if (LocaleCompare(attribute,"bounding-box") == 0)
4378             {
4379               char
4380                 geometry[MaxTextExtent];
4381
4382               RectangleInfo
4383                 page;
4384
4385               if (image == (Image *) NULL)
4386                 break;
4387               page=GetImageBoundingBox(image,&image->exception);
4388               (void) FormatLocaleString(geometry,MaxTextExtent,
4389                 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4390                 page.height,(double) page.x,(double) page.y);
4391               s=newSVpv(geometry,0);
4392               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4393               continue;
4394             }
4395           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4396             attribute);
4397           break;
4398         }
4399         case 'C':
4400         case 'c':
4401         {
4402           if (LocaleCompare(attribute,"class") == 0)
4403             {
4404               if (image == (Image *) NULL)
4405                 break;
4406               s=newSViv(image->storage_class);
4407               (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4408                 image->storage_class));
4409               SvIOK_on(s);
4410               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4411               continue;
4412             }
4413           if (LocaleCompare(attribute,"clip-mask") == 0)
4414             {
4415               if (image != (Image *) NULL)
4416                 {
4417                   SV
4418                     *sv;
4419
4420                   sv=NULL;
4421                   if (image->mask == (Image *) NULL)
4422                     ClipImage(image,exception);
4423                   if (image->mask != (Image *) NULL)
4424                     {
4425                       AddImageToRegistry(sv,image->mask);
4426                       s=sv_bless(newRV(sv),SvSTASH(reference));
4427                     }
4428                 }
4429               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4430               continue;
4431             }
4432           if (LocaleCompare(attribute,"clip-path") == 0)
4433             {
4434               if (image != (Image *) NULL)
4435                 {
4436                   SV
4437                     *sv;
4438
4439                   sv=NULL;
4440                   if (image->clip_mask == (Image *) NULL)
4441                     ClipImage(image,exception);
4442                   if (image->clip_mask != (Image *) NULL)
4443                     {
4444                       AddImageToRegistry(sv,image->clip_mask);
4445                       s=sv_bless(newRV(sv),SvSTASH(reference));
4446                     }
4447                 }
4448               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4449               continue;
4450             }
4451           if (LocaleCompare(attribute,"compression") == 0)
4452             {
4453               j=info ? info->image_info->compression : image ?
4454                 image->compression : UndefinedCompression;
4455               if (info)
4456                 if (info->image_info->compression == UndefinedCompression)
4457                   j=image->compression;
4458               s=newSViv(j);
4459               (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4460                 j));
4461               SvIOK_on(s);
4462               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4463               continue;
4464             }
4465           if (LocaleCompare(attribute,"colorspace") == 0)
4466             {
4467               j=image ? image->colorspace : RGBColorspace;
4468               s=newSViv(j);
4469               (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4470                 j));
4471               SvIOK_on(s);
4472               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4473               continue;
4474             }
4475           if (LocaleCompare(attribute,"colors") == 0)
4476             {
4477               if (image != (Image *) NULL)
4478                 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4479                   &image->exception));
4480               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4481               continue;
4482             }
4483           if (LocaleNCompare(attribute,"colormap",8) == 0)
4484             {
4485               int
4486                 items;
4487
4488               if (image == (Image *) NULL || !image->colormap)
4489                 break;
4490               j=0;
4491               items=sscanf(attribute,"%*[^[][%ld",&j);
4492               (void) items;
4493               if (j > (ssize_t) image->colors)
4494                 j%=image->colors;
4495               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4496                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4497                 image->colormap[j].red,image->colormap[j].green,
4498                 image->colormap[j].blue,image->colormap[j].alpha);
4499               s=newSVpv(color,0);
4500               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4501               continue;
4502             }
4503           if (LocaleCompare(attribute,"columns") == 0)
4504             {
4505               if (image != (Image *) NULL)
4506                 s=newSViv((ssize_t) image->columns);
4507               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4508               continue;
4509             }
4510           if (LocaleCompare(attribute,"comment") == 0)
4511             {
4512               const char
4513                 *value;
4514
4515               value=GetImageProperty(image,attribute);
4516               if (value != (const char *) NULL)
4517                 s=newSVpv(value,0);
4518               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4519               continue;
4520             }
4521           if (LocaleCompare(attribute,"copyright") == 0)
4522             {
4523               s=newSVpv(GetMagickCopyright(),0);
4524               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4525               continue;
4526             }
4527           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4528             attribute);
4529           break;
4530         }
4531         case 'D':
4532         case 'd':
4533         {
4534           if (LocaleCompare(attribute,"density") == 0)
4535             {
4536               char
4537                 geometry[MaxTextExtent];
4538
4539               if (image == (Image *) NULL)
4540                 break;
4541               (void) FormatLocaleString(geometry,MaxTextExtent,"%.15gx%.15g",
4542                 image->x_resolution,image->y_resolution);
4543               s=newSVpv(geometry,0);
4544               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4545               continue;
4546             }
4547           if (LocaleCompare(attribute,"delay") == 0)
4548             {
4549               if (image != (Image *) NULL)
4550                 s=newSViv((ssize_t) image->delay);
4551               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4552               continue;
4553             }
4554           if (LocaleCompare(attribute,"depth") == 0)
4555             {
4556               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4557               if (image != (Image *) NULL)
4558                 s=newSViv((ssize_t) GetImageDepth(image,&image->exception));
4559               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4560               continue;
4561             }
4562           if (LocaleCompare(attribute,"directory") == 0)
4563             {
4564               if (image && image->directory)
4565                 s=newSVpv(image->directory,0);
4566               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4567               continue;
4568             }
4569           if (LocaleCompare(attribute,"dispose") == 0)
4570             {
4571               if (image == (Image *) NULL)
4572                 break;
4573
4574               s=newSViv(image->dispose);
4575               (void) sv_setpv(s,
4576                 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
4577               SvIOK_on(s);
4578               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4579               continue;
4580             }
4581           if (LocaleCompare(attribute,"disk") == 0)
4582             {
4583               s=newSViv(GetMagickResource(DiskResource));
4584               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4585               continue;
4586             }
4587           if (LocaleCompare(attribute,"dither") == 0)
4588             {
4589               if (info)
4590                 s=newSViv((ssize_t) info->image_info->dither);
4591               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4592               continue;
4593             }
4594           if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4595             {
4596               if (info && info->image_info->server_name)
4597                 s=newSVpv(info->image_info->server_name,0);
4598               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4599               continue;
4600             }
4601           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4602             attribute);
4603           break;
4604         }
4605         case 'E':
4606         case 'e':
4607         {
4608           if (LocaleCompare(attribute,"elapsed-time") == 0)
4609             {
4610               if (image != (Image *) NULL)
4611                 s=newSVnv(GetElapsedTime(&image->timer));
4612               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4613               continue;
4614             }
4615           if (LocaleCompare(attribute,"endian") == 0)
4616             {
4617               j=info ? info->image_info->endian : image ? image->endian :
4618                 UndefinedEndian;
4619               s=newSViv(j);
4620               (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
4621               SvIOK_on(s);
4622               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4623               continue;
4624             }
4625           if (LocaleCompare(attribute,"error") == 0)
4626             {
4627               if (image != (Image *) NULL)
4628                 s=newSVnv(image->error.mean_error_per_pixel);
4629               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4630               continue;
4631             }
4632           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4633             attribute);
4634           break;
4635         }
4636         case 'F':
4637         case 'f':
4638         {
4639           if (LocaleCompare(attribute,"filesize") == 0)
4640             {
4641               if (image != (Image *) NULL)
4642                 s=newSViv((ssize_t) GetBlobSize(image));
4643               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4644               continue;
4645             }
4646           if (LocaleCompare(attribute,"filename") == 0)
4647             {
4648               if (info && info->image_info->filename &&
4649                   *info->image_info->filename)
4650                 s=newSVpv(info->image_info->filename,0);
4651               if (image != (Image *) NULL)
4652                 s=newSVpv(image->filename,0);
4653               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4654               continue;
4655             }
4656           if (LocaleCompare(attribute,"filter") == 0)
4657             {
4658               s=image ? newSViv(image->filter) : newSViv(0);
4659               (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
4660                 image->filter));
4661               SvIOK_on(s);
4662               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4663               continue;
4664             }
4665           if (LocaleCompare(attribute,"font") == 0)
4666             {
4667               if (info && info->image_info->font)
4668                 s=newSVpv(info->image_info->font,0);
4669               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4670               continue;
4671             }
4672           if (LocaleCompare(attribute,"foreground") == 0)
4673             continue;
4674           if (LocaleCompare(attribute,"format") == 0)
4675             {
4676               const MagickInfo
4677                 *magick_info;
4678
4679               magick_info=(const MagickInfo *) NULL;
4680               if (info && (*info->image_info->magick != '\0'))
4681                 magick_info=GetMagickInfo(info->image_info->magick,exception);
4682               if (image != (Image *) NULL)
4683                 magick_info=GetMagickInfo(image->magick,&image->exception);
4684               if ((magick_info != (const MagickInfo *) NULL) &&
4685                   (*magick_info->description != '\0'))
4686                 s=newSVpv((char *) magick_info->description,0);
4687               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4688               continue;
4689             }
4690           if (LocaleCompare(attribute,"fuzz") == 0)
4691             {
4692               if (info)
4693                 s=newSVnv(info->image_info->fuzz);
4694               if (image != (Image *) NULL)
4695                 s=newSVnv(image->fuzz);
4696               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4697               continue;
4698             }
4699           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4700             attribute);
4701           break;
4702         }
4703         case 'G':
4704         case 'g':
4705         {
4706           if (LocaleCompare(attribute,"gamma") == 0)
4707             {
4708               if (image != (Image *) NULL)
4709                 s=newSVnv(image->gamma);
4710               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4711               continue;
4712             }
4713           if (LocaleCompare(attribute,"geometry") == 0)
4714             {
4715               if (image && image->geometry)
4716                 s=newSVpv(image->geometry,0);
4717               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4718               continue;
4719             }
4720           if (LocaleCompare(attribute,"gravity") == 0)
4721             {
4722               s=image ? newSViv(image->gravity) : newSViv(0);
4723               (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
4724                 image->gravity));
4725               SvIOK_on(s);
4726               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4727               continue;
4728             }
4729           if (LocaleCompare(attribute,"green-primary") == 0)
4730             {
4731               if (image == (Image *) NULL)
4732                 break;
4733               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4734                 image->chromaticity.green_primary.x,
4735                 image->chromaticity.green_primary.y);
4736               s=newSVpv(color,0);
4737               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4738               continue;
4739             }
4740           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4741             attribute);
4742           break;
4743         }
4744         case 'H':
4745         case 'h':
4746         {
4747           if (LocaleCompare(attribute,"height") == 0)
4748             {
4749               if (image != (Image *) NULL)
4750                 s=newSViv((ssize_t) image->rows);
4751               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4752               continue;
4753             }
4754           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4755             attribute);
4756           break;
4757         }
4758         case 'I':
4759         case 'i':
4760         {
4761           if (LocaleCompare(attribute,"icc") == 0)
4762             {
4763               if (image != (Image *) NULL)
4764                 {
4765                   const StringInfo
4766                     *profile;
4767
4768                   profile=GetImageProfile(image,"icc");
4769                   if (profile != (StringInfo *) NULL)
4770                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4771                       GetStringInfoLength(profile));
4772                 }
4773               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4774               continue;
4775             }
4776           if (LocaleCompare(attribute,"icm") == 0)
4777             {
4778               if (image != (Image *) NULL)
4779                 {
4780                   const StringInfo
4781                     *profile;
4782
4783                   profile=GetImageProfile(image,"icm");
4784                   if (profile != (const StringInfo *) NULL)
4785                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4786                       GetStringInfoLength(profile));
4787                 }
4788               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4789               continue;
4790             }
4791           if (LocaleCompare(attribute,"id") == 0)
4792             {
4793               if (image != (Image *) NULL)
4794                 {
4795                   char
4796                     key[MaxTextExtent];
4797
4798                   MagickBooleanType
4799                     status;
4800
4801                   static ssize_t
4802                     id = 0;
4803
4804                   (void) FormatLocaleString(key,MaxTextExtent,"%.20g\n",(double)
4805                     id);
4806                   status=SetImageRegistry(ImageRegistryType,key,image,
4807                     &image->exception);
4808                   (void) status;
4809                   s=newSViv(id++);
4810                 }
4811               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4812               continue;
4813             }
4814           if (LocaleNCompare(attribute,"index",5) == 0)
4815             {
4816               char
4817                 name[MaxTextExtent];
4818
4819               int
4820                 items;
4821
4822               long
4823                 x,
4824                 y;
4825
4826               register const Quantum
4827                 *p;
4828
4829               CacheView
4830                 *image_view;
4831
4832               if (image == (Image *) NULL)
4833                 break;
4834               if (image->storage_class != PseudoClass)
4835                 break;
4836               x=0;
4837               y=0;
4838               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
4839               (void) items;
4840               image_view=AcquireCacheView(image);
4841               p=GetCacheViewVirtualPixels(image_view,x,y,1,1,&image->exception);
4842               if (p != (const Quantum *) NULL)
4843                 {
4844                   (void) FormatLocaleString(name,MaxTextExtent,QuantumFormat,
4845                     GetPixelIndex(image,p));
4846                   s=newSVpv(name,0);
4847                   PUSHs(s ? sv_2mortal(s) : &sv_undef);
4848                 }
4849               image_view=DestroyCacheView(image_view);
4850               continue;
4851             }
4852           if (LocaleCompare(attribute,"iptc") == 0)
4853             {
4854               if (image != (Image *) NULL)
4855                 {
4856                   const StringInfo
4857                     *profile;
4858
4859                   profile=GetImageProfile(image,"iptc");
4860                   if (profile != (const StringInfo *) NULL)
4861                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4862                       GetStringInfoLength(profile));
4863                 }
4864               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4865               continue;
4866             }
4867           if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
4868             {
4869               if (image != (Image *) NULL)
4870                 s=newSViv((ssize_t) image->iterations);
4871               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4872               continue;
4873             }
4874           if (LocaleCompare(attribute,"interlace") == 0)
4875             {
4876               j=info ? info->image_info->interlace : image ? image->interlace :
4877                 UndefinedInterlace;
4878               s=newSViv(j);
4879               (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
4880                 j));
4881               SvIOK_on(s);
4882               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4883               continue;
4884             }
4885           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4886             attribute);
4887           break;
4888         }
4889         case 'L':
4890         case 'l':
4891         {
4892           if (LocaleCompare(attribute,"label") == 0)
4893             {
4894               const char
4895                 *value;
4896
4897               if (image == (Image *) NULL)
4898                 break;
4899               value=GetImageProperty(image,"Label");
4900               if (value != (const char *) NULL)
4901                 s=newSVpv(value,0);
4902               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4903               continue;
4904             }
4905           if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
4906             {
4907               if (image != (Image *) NULL)
4908                 s=newSViv((ssize_t) image->iterations);
4909               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4910               continue;
4911             }
4912           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4913             attribute);
4914           break;
4915         }
4916         case 'M':
4917         case 'm':
4918         {
4919           if (LocaleCompare(attribute,"magick") == 0)
4920             {
4921               if (info && *info->image_info->magick)
4922                 s=newSVpv(info->image_info->magick,0);
4923               if (image != (Image *) NULL)
4924                 s=newSVpv(image->magick,0);
4925               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4926               continue;
4927             }
4928           if (LocaleCompare(attribute,"map") == 0)
4929             {
4930               s=newSViv(GetMagickResource(MapResource));
4931               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4932               continue;
4933             }
4934           if (LocaleCompare(attribute,"maximum-error") == 0)
4935             {
4936               if (image != (Image *) NULL)
4937                 s=newSVnv(image->error.normalized_maximum_error);
4938               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4939               continue;
4940             }
4941           if (LocaleCompare(attribute,"memory") == 0)
4942             {
4943               s=newSViv(GetMagickResource(MemoryResource));
4944               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4945               continue;
4946             }
4947           if (LocaleCompare(attribute,"mean-error") == 0)
4948             {
4949               if (image != (Image *) NULL)
4950                 s=newSVnv(image->error.normalized_mean_error);
4951               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4952               continue;
4953             }
4954           if (LocaleCompare(attribute,"mime") == 0)
4955             {
4956               if (info && *info->image_info->magick)
4957                 s=newSVpv(MagickToMime(info->image_info->magick),0);
4958               if (image != (Image *) NULL)
4959                 s=newSVpv(MagickToMime(image->magick),0);
4960               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4961               continue;
4962             }
4963           if (LocaleCompare(attribute,"mattecolor") == 0)
4964             {
4965               if (image == (Image *) NULL)
4966                 break;
4967               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4968                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4969                 image->matte_color.red,image->matte_color.green,
4970                 image->matte_color.blue,image->matte_color.alpha);
4971               s=newSVpv(color,0);
4972               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4973               continue;
4974             }
4975           if (LocaleCompare(attribute,"matte") == 0)
4976             {
4977               if (image != (Image *) NULL)
4978                 s=newSViv((ssize_t) image->matte);
4979               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4980               continue;
4981             }
4982           if (LocaleCompare(attribute,"mime") == 0)
4983             {
4984               const char
4985                 *magick;
4986
4987               magick=NULL;
4988               if (info && *info->image_info->magick)
4989                 magick=info->image_info->magick;
4990               if (image != (Image *) NULL)
4991                 magick=image->magick;
4992               if (magick)
4993                 {
4994                   char
4995                     *mime;
4996
4997                   mime=MagickToMime(magick);
4998                   s=newSVpv(mime,0);
4999                   mime=(char *) RelinquishMagickMemory(mime);
5000                 }
5001               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5002               continue;
5003             }
5004           if (LocaleCompare(attribute,"monochrome") == 0)
5005             {
5006               if (image == (Image *) NULL)
5007                 continue;
5008               j=info ? info->image_info->monochrome :
5009                 IsImageMonochrome(image,&image->exception);
5010               s=newSViv(j);
5011               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5012               continue;
5013             }
5014           if (LocaleCompare(attribute,"montage") == 0)
5015             {
5016               if (image && image->montage)
5017                 s=newSVpv(image->montage,0);
5018               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5019               continue;
5020             }
5021           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5022             attribute);
5023           break;
5024         }
5025         case 'O':
5026         case 'o':
5027         {
5028           if (LocaleCompare(attribute,"orientation") == 0)
5029             {
5030               j=info ? info->image_info->orientation : image ?
5031                 image->orientation : UndefinedOrientation;
5032               s=newSViv(j);
5033               (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5034                 j));
5035               SvIOK_on(s);
5036               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5037               continue;
5038             }
5039           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5040             attribute);
5041           break;
5042         }
5043         case 'P':
5044         case 'p':
5045         {
5046           if (LocaleCompare(attribute,"page") == 0)
5047             {
5048               if (info && info->image_info->page)
5049                 s=newSVpv(info->image_info->page,0);
5050               if (image != (Image *) NULL)
5051                 {
5052                   char
5053                     geometry[MaxTextExtent];
5054
5055                   (void) FormatLocaleString(geometry,MaxTextExtent,
5056                     "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5057                     (double) image->page.height,(double) image->page.x,(double)
5058                     image->page.y);
5059                   s=newSVpv(geometry,0);
5060                 }
5061               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5062               continue;
5063             }
5064           if (LocaleCompare(attribute,"page.x") == 0)
5065             {
5066               if (image != (Image *) NULL)
5067                 s=newSViv((ssize_t) image->page.x);
5068               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5069               continue;
5070             }
5071           if (LocaleCompare(attribute,"page.y") == 0)
5072             {
5073               if (image != (Image *) NULL)
5074                 s=newSViv((ssize_t) image->page.y);
5075               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5076               continue;
5077             }
5078           if (LocaleNCompare(attribute,"pixel",5) == 0)
5079             {
5080               char
5081                 tuple[MaxTextExtent];
5082
5083               int
5084                 items;
5085
5086               long
5087                 x,
5088                 y;
5089
5090               register const Quantum
5091                 *p;
5092
5093               if (image == (Image *) NULL)
5094                 break;
5095               x=0;
5096               y=0;
5097               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5098               (void) items;
5099               p=GetVirtualPixels(image,x,y,1,1,exception);
5100               if (image->colorspace != CMYKColorspace)
5101                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5102                   QuantumFormat "," QuantumFormat "," QuantumFormat,
5103                   GetPixelRed(image,p),GetPixelGreen(image,p),
5104                   GetPixelBlue(image,p),GetPixelAlpha(image,p));
5105               else
5106                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5107                   QuantumFormat "," QuantumFormat "," QuantumFormat ","
5108                   QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5109                   GetPixelBlue(image,p),GetPixelBlack(image,p),
5110                   GetPixelAlpha(image,p));
5111               s=newSVpv(tuple,0);
5112               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5113               continue;
5114             }
5115           if (LocaleCompare(attribute,"pointsize") == 0)
5116             {
5117               if (info)
5118                 s=newSViv((ssize_t) info->image_info->pointsize);
5119               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5120               continue;
5121             }
5122           if (LocaleCompare(attribute,"preview") == 0)
5123             {
5124               s=newSViv(info->image_info->preview_type);
5125               (void) sv_setpv(s,CommandOptionToMnemonic(MagickPreviewOptions,
5126                 info->image_info->preview_type));
5127               SvIOK_on(s);
5128               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5129               continue;
5130             }
5131           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5132             attribute);
5133           break;
5134         }
5135         case 'Q':
5136         case 'q':
5137         {
5138           if (LocaleCompare(attribute,"quality") == 0)
5139             {
5140               if (info)
5141                 s=newSViv((ssize_t) info->image_info->quality);
5142               if (image != (Image *) NULL)
5143                 s=newSViv((ssize_t) image->quality);
5144               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5145               continue;
5146             }
5147           if (LocaleCompare(attribute,"quantum") == 0)
5148             {
5149               if (info)
5150                 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5151               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5152               continue;
5153             }
5154           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5155             attribute);
5156           break;
5157         }
5158         case 'R':
5159         case 'r':
5160         {
5161           if (LocaleCompare(attribute,"rendering-intent") == 0)
5162             {
5163               s=newSViv(image->rendering_intent);
5164               (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5165                 image->rendering_intent));
5166               SvIOK_on(s);
5167               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5168               continue;
5169             }
5170           if (LocaleCompare(attribute,"red-primary") == 0)
5171             {
5172               if (image == (Image *) NULL)
5173                 break;
5174               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5175                 image->chromaticity.red_primary.x,
5176                 image->chromaticity.red_primary.y);
5177               s=newSVpv(color,0);
5178               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5179               continue;
5180             }
5181           if (LocaleCompare(attribute,"rows") == 0)
5182             {
5183               if (image != (Image *) NULL)
5184                 s=newSViv((ssize_t) image->rows);
5185               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5186               continue;
5187             }
5188           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5189             attribute);
5190           break;
5191         }
5192         case 'S':
5193         case 's':
5194         {
5195           if (LocaleCompare(attribute,"sampling-factor") == 0)
5196             {
5197               if (info && info->image_info->sampling_factor)
5198                 s=newSVpv(info->image_info->sampling_factor,0);
5199               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5200               continue;
5201             }
5202           if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5203             {
5204               if (info && info->image_info->server_name)
5205                 s=newSVpv(info->image_info->server_name,0);
5206               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5207               continue;
5208             }
5209           if (LocaleCompare(attribute,"size") == 0)
5210             {
5211               if (info && info->image_info->size)
5212                 s=newSVpv(info->image_info->size,0);
5213               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5214               continue;
5215             }
5216           if (LocaleCompare(attribute,"scene") == 0)
5217             {
5218               if (image != (Image *) NULL)
5219                 s=newSViv((ssize_t) image->scene);
5220               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5221               continue;
5222             }
5223           if (LocaleCompare(attribute,"scenes") == 0)
5224             {
5225               if (image != (Image *) NULL)
5226                 s=newSViv((ssize_t) info->image_info->number_scenes);
5227               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5228               continue;
5229             }
5230           if (LocaleCompare(attribute,"signature") == 0)
5231             {
5232               const char
5233                 *value;
5234
5235               if (image == (Image *) NULL)
5236                 break;
5237               (void) SignatureImage(image,exception);
5238               value=GetImageProperty(image,"Signature");
5239               if (value != (const char *) NULL)
5240                 s=newSVpv(value,0);
5241               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5242               continue;
5243             }
5244           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5245             attribute);
5246           break;
5247         }
5248         case 'T':
5249         case 't':
5250         {
5251           if (LocaleCompare(attribute,"taint") == 0)
5252             {
5253               if (image != (Image *) NULL)
5254                 s=newSViv((ssize_t) IsTaintImage(image));
5255               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5256               continue;
5257             }
5258           if (LocaleCompare(attribute,"texture") == 0)
5259             {
5260               if (info && info->image_info->texture)
5261                 s=newSVpv(info->image_info->texture,0);
5262               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5263               continue;
5264             }
5265           if (LocaleCompare(attribute,"total-ink-density") == 0)
5266             {
5267               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5268               if (image != (Image *) NULL)
5269                 s=newSVnv(GetImageTotalInkDensity(image));
5270               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5271               continue;
5272             }
5273           if (LocaleCompare(attribute,"transparent-color") == 0)
5274             {
5275               if (image == (Image *) NULL)
5276                 break;
5277               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
5278                 QuantumFormat "," QuantumFormat "," QuantumFormat,
5279                 image->transparent_color.red,image->transparent_color.green,
5280                 image->transparent_color.blue,image->transparent_color.alpha);
5281               s=newSVpv(color,0);
5282               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5283               continue;
5284             }
5285           if (LocaleCompare(attribute,"type") == 0)
5286             {
5287               if (image == (Image *) NULL)
5288                 break;
5289               j=(ssize_t) GetImageType(image,&image->exception);
5290               s=newSViv(j);
5291               (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5292               SvIOK_on(s);
5293               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5294               continue;
5295             }
5296           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5297             attribute);
5298           break;
5299         }
5300         case 'U':
5301         case 'u':
5302         {
5303           if (LocaleCompare(attribute,"units") == 0)
5304             {
5305               j=info ? info->image_info->units : image ? image->units :
5306                 UndefinedResolution;
5307               if (info && (info->image_info->units == UndefinedResolution))
5308                 if (image)
5309                   j=image->units;
5310               if (j == UndefinedResolution)
5311                 s=newSVpv("undefined units",0);
5312               else
5313                 if (j == PixelsPerInchResolution)
5314                   s=newSVpv("pixels / inch",0);
5315                 else
5316                   s=newSVpv("pixels / centimeter",0);
5317               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5318               continue;
5319             }
5320           if (LocaleCompare(attribute,"user-time") == 0)
5321             {
5322               if (image != (Image *) NULL)
5323                 s=newSVnv(GetUserTime(&image->timer));
5324               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5325               continue;
5326             }
5327           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5328             attribute);
5329           break;
5330         }
5331         case 'V':
5332         case 'v':
5333         {
5334           if (LocaleCompare(attribute,"verbose") == 0)
5335             {
5336               if (info)
5337                 s=newSViv((ssize_t) info->image_info->verbose);
5338               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5339               continue;
5340             }
5341           if (LocaleCompare(attribute,"version") == 0)
5342             {
5343               s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5344               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5345               continue;
5346             }
5347           if (LocaleCompare(attribute,"view") == 0)
5348             {
5349               if (info && info->image_info->view)
5350                 s=newSVpv(info->image_info->view,0);
5351               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5352               continue;
5353             }
5354           if (LocaleCompare(attribute,"virtual-pixel") == 0)
5355             {
5356               if (image == (Image *) NULL)
5357                 break;
5358               j=(ssize_t) GetImageVirtualPixelMethod(image);
5359               s=newSViv(j);
5360               (void) sv_setpv(s,CommandOptionToMnemonic(
5361                 MagickVirtualPixelOptions,j));
5362               SvIOK_on(s);
5363               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5364               continue;
5365             }
5366           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5367             attribute);
5368           break;
5369         }
5370         case 'W':
5371         case 'w':
5372         {
5373           if (LocaleCompare(attribute,"white-point") == 0)
5374             {
5375               if (image == (Image *) NULL)
5376                 break;
5377               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5378                 image->chromaticity.white_point.x,
5379                 image->chromaticity.white_point.y);
5380               s=newSVpv(color,0);
5381               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5382               continue;
5383             }
5384           if (LocaleCompare(attribute,"width") == 0)
5385             {
5386               if (image != (Image *) NULL)
5387                 s=newSViv((ssize_t) image->columns);
5388               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5389               continue;
5390             }
5391           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5392              attribute);
5393           break;
5394         }
5395         case 'X':
5396         case 'x':
5397         {
5398           if (LocaleCompare(attribute,"x-resolution") == 0)
5399             {
5400               if (image != (Image *) NULL)
5401                 s=newSVnv(image->x_resolution);
5402               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5403               continue;
5404             }
5405           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5406             attribute);
5407           break;
5408         }
5409         case 'Y':
5410         case 'y':
5411         {
5412           if (LocaleCompare(attribute,"y-resolution") == 0)
5413             {
5414               if (image != (Image *) NULL)
5415                 s=newSVnv(image->y_resolution);
5416               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5417               continue;
5418             }
5419           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5420             attribute);
5421           break;
5422         }
5423         default:
5424           break;
5425       }
5426       if (image == (Image *) NULL)
5427         ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5428           attribute)
5429       else
5430         {
5431           value=GetImageProperty(image,attribute);
5432           if (value != (const char *) NULL)
5433             {
5434               s=newSVpv(value,0);
5435               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5436             }
5437           else
5438             if (*attribute != '%')
5439               ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5440                 attribute)
5441             else
5442               {
5443                  char
5444                    *meta;
5445
5446                  meta=InterpretImageProperties(info ? info->image_info :
5447                    (ImageInfo *) NULL,image,attribute,exception);
5448                  s=newSVpv(meta,0);
5449                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5450                  meta=(char *) RelinquishMagickMemory(meta);
5451               }
5452         }
5453     }
5454     exception=DestroyExceptionInfo(exception);
5455     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5456   }
5457 \f
5458 #
5459 ###############################################################################
5460 #                                                                             #
5461 #                                                                             #
5462 #                                                                             #
5463 #   G e t A u t h e n t i c P i x e l s                                       #
5464 #                                                                             #
5465 #                                                                             #
5466 #                                                                             #
5467 ###############################################################################
5468 #
5469 #
5470 void *
5471 GetAuthenticPixels(ref,...)
5472   Image::Magick ref = NO_INIT
5473   ALIAS:
5474     getauthenticpixels = 1
5475     GetImagePixels = 2
5476     getimagepixels = 3
5477   CODE:
5478   {
5479     char
5480       *attribute;
5481
5482     ExceptionInfo
5483       *exception;
5484
5485     Image
5486       *image;
5487
5488     RectangleInfo
5489       region;
5490
5491     ssize_t
5492       i;
5493
5494     struct PackageInfo
5495       *info;
5496
5497     SV
5498       *perl_exception,
5499       *reference;
5500
5501     void
5502       *blob = NULL;
5503
5504     PERL_UNUSED_VAR(ref);
5505     PERL_UNUSED_VAR(ix);
5506     exception=AcquireExceptionInfo();
5507     perl_exception=newSVpv("",0);
5508     if (sv_isobject(ST(0)) == 0)
5509       {
5510         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5511           PackageName);
5512         goto PerlException;
5513       }
5514     reference=SvRV(ST(0));
5515
5516     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5517     if (image == (Image *) NULL)
5518       {
5519         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5520           PackageName);
5521         goto PerlException;
5522       }
5523
5524     region.x=0;
5525     region.y=0;
5526     region.width=image->columns;
5527     region.height=1;
5528     if (items == 1)
5529       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5530     for (i=2; i < items; i+=2)
5531     {
5532       attribute=(char *) SvPV(ST(i-1),na);
5533       switch (*attribute)
5534       {
5535         case 'g':
5536         case 'G':
5537         {
5538           if (LocaleCompare(attribute,"geometry") == 0)
5539             {
5540               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5541               break;
5542             }
5543           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5544             attribute);
5545           break;
5546         }
5547         case 'H':
5548         case 'h':
5549         {
5550           if (LocaleCompare(attribute,"height") == 0)
5551             {
5552               region.height=SvIV(ST(i));
5553               continue;
5554             }
5555           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5556             attribute);
5557           break;
5558         }
5559         case 'X':
5560         case 'x':
5561         {
5562           if (LocaleCompare(attribute,"x") == 0)
5563             {
5564               region.x=SvIV(ST(i));
5565               continue;
5566             }
5567           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5568             attribute);
5569           break;
5570         }
5571         case 'Y':
5572         case 'y':
5573         {
5574           if (LocaleCompare(attribute,"y") == 0)
5575             {
5576               region.y=SvIV(ST(i));
5577               continue;
5578             }
5579           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5580             attribute);
5581           break;
5582         }
5583         case 'W':
5584         case 'w':
5585         {
5586           if (LocaleCompare(attribute,"width") == 0)
5587             {
5588               region.width=SvIV(ST(i));
5589               continue;
5590             }
5591           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5592             attribute);
5593           break;
5594         }
5595       }
5596     }
5597     blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5598       region.height,exception);
5599     if (blob != (void *) NULL)
5600       goto PerlEnd;
5601
5602   PerlException:
5603     InheritPerlException(exception,perl_exception);
5604     exception=DestroyExceptionInfo(exception);
5605     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5606
5607   PerlEnd:
5608     RETVAL = blob;
5609   }
5610   OUTPUT:
5611     RETVAL
5612 \f
5613 #
5614 ###############################################################################
5615 #                                                                             #
5616 #                                                                             #
5617 #                                                                             #
5618 #   G e t V i r t u a l P i x e l s                                           #
5619 #                                                                             #
5620 #                                                                             #
5621 #                                                                             #
5622 ###############################################################################
5623 #
5624 #
5625 void *
5626 GetVirtualPixels(ref,...)
5627   Image::Magick ref = NO_INIT
5628   ALIAS:
5629     getvirtualpixels = 1
5630     AcquireImagePixels = 2
5631     acquireimagepixels = 3
5632   CODE:
5633   {
5634     char
5635       *attribute;
5636
5637     const void
5638       *blob = NULL;
5639
5640     ExceptionInfo
5641       *exception;
5642
5643     Image
5644       *image;
5645
5646     RectangleInfo
5647       region;
5648
5649     ssize_t
5650       i;
5651
5652     struct PackageInfo
5653       *info;
5654
5655     SV
5656       *perl_exception,
5657       *reference;
5658
5659     PERL_UNUSED_VAR(ref);
5660     PERL_UNUSED_VAR(ix);
5661     exception=AcquireExceptionInfo();
5662     perl_exception=newSVpv("",0);
5663     if (sv_isobject(ST(0)) == 0)
5664       {
5665         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5666           PackageName);
5667         goto PerlException;
5668       }
5669     reference=SvRV(ST(0));
5670
5671     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5672     if (image == (Image *) NULL)
5673       {
5674         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5675           PackageName);
5676         goto PerlException;
5677       }
5678
5679     region.x=0;
5680     region.y=0;
5681     region.width=image->columns;
5682     region.height=1;
5683     if (items == 1)
5684       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5685     for (i=2; i < items; i+=2)
5686     {
5687       attribute=(char *) SvPV(ST(i-1),na);
5688       switch (*attribute)
5689       {
5690         case 'g':
5691         case 'G':
5692         {
5693           if (LocaleCompare(attribute,"geometry") == 0)
5694             {
5695               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5696               break;
5697             }
5698           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5699             attribute);
5700           break;
5701         }
5702         case 'H':
5703         case 'h':
5704         {
5705           if (LocaleCompare(attribute,"height") == 0)
5706             {
5707               region.height=SvIV(ST(i));
5708               continue;
5709             }
5710           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5711             attribute);
5712           break;
5713         }
5714         case 'X':
5715         case 'x':
5716         {
5717           if (LocaleCompare(attribute,"x") == 0)
5718             {
5719               region.x=SvIV(ST(i));
5720               continue;
5721             }
5722           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5723             attribute);
5724           break;
5725         }
5726         case 'Y':
5727         case 'y':
5728         {
5729           if (LocaleCompare(attribute,"y") == 0)
5730             {
5731               region.y=SvIV(ST(i));
5732               continue;
5733             }
5734           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5735             attribute);
5736           break;
5737         }
5738         case 'W':
5739         case 'w':
5740         {
5741           if (LocaleCompare(attribute,"width") == 0)
5742             {
5743               region.width=SvIV(ST(i));
5744               continue;
5745             }
5746           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5747             attribute);
5748           break;
5749         }
5750       }
5751     }
5752     blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
5753       region.height,exception);
5754     if (blob != (void *) NULL)
5755       goto PerlEnd;
5756
5757   PerlException:
5758     InheritPerlException(exception,perl_exception);
5759     exception=DestroyExceptionInfo(exception);
5760     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5761
5762   PerlEnd:
5763     RETVAL = (void *) blob;
5764   }
5765   OUTPUT:
5766     RETVAL
5767 \f
5768 #
5769 ###############################################################################
5770 #                                                                             #
5771 #                                                                             #
5772 #                                                                             #
5773 #   G e t A u t h e n t i c M e t a c o n t e n t                             #
5774 #                                                                             #
5775 #                                                                             #
5776 #                                                                             #
5777 ###############################################################################
5778 #
5779 #
5780 void *
5781 GetAuthenticMetacontent(ref,...)
5782   Image::Magick ref = NO_INIT
5783   ALIAS:
5784     getauthenticmetacontent = 1
5785     GetMetacontent = 2
5786     getmetacontent = 3
5787   CODE:
5788   {
5789     ExceptionInfo
5790       *exception;
5791
5792     Image
5793       *image;
5794
5795     struct PackageInfo
5796       *info;
5797
5798     SV
5799       *perl_exception,
5800       *reference;
5801
5802     void
5803       *blob = NULL;
5804
5805     PERL_UNUSED_VAR(ref);
5806     PERL_UNUSED_VAR(ix);
5807     exception=AcquireExceptionInfo();
5808     perl_exception=newSVpv("",0);
5809     if (sv_isobject(ST(0)) == 0)
5810       {
5811         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5812           PackageName);
5813         goto PerlException;
5814       }
5815     reference=SvRV(ST(0));
5816
5817     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5818     if (image == (Image *) NULL)
5819       {
5820         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5821           PackageName);
5822         goto PerlException;
5823       }
5824
5825     blob=(void *) GetAuthenticMetacontent(image);
5826     if (blob != (void *) NULL)
5827       goto PerlEnd;
5828
5829   PerlException:
5830     InheritPerlException(exception,perl_exception);
5831     exception=DestroyExceptionInfo(exception);
5832     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5833
5834   PerlEnd:
5835     RETVAL = blob;
5836   }
5837   OUTPUT:
5838     RETVAL
5839 \f
5840 #
5841 ###############################################################################
5842 #                                                                             #
5843 #                                                                             #
5844 #                                                                             #
5845 #   G e t V i r t u a l M e t a c o n t e n t                                 #
5846 #                                                                             #
5847 #                                                                             #
5848 #                                                                             #
5849 ###############################################################################
5850 #
5851 #
5852 void *
5853 GetVirtualMetacontent(ref,...)
5854   Image::Magick ref = NO_INIT
5855   ALIAS:
5856     getvirtualmetacontent = 1
5857   CODE:
5858   {
5859     ExceptionInfo
5860       *exception;
5861
5862     Image
5863       *image;
5864
5865     struct PackageInfo
5866       *info;
5867
5868     SV
5869       *perl_exception,
5870       *reference;
5871
5872     void
5873       *blob = NULL;
5874
5875     PERL_UNUSED_VAR(ref);
5876     PERL_UNUSED_VAR(ix);
5877     exception=AcquireExceptionInfo();
5878     perl_exception=newSVpv("",0);
5879     if (sv_isobject(ST(0)) == 0)
5880       {
5881         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5882           PackageName);
5883         goto PerlException;
5884       }
5885     reference=SvRV(ST(0));
5886
5887     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5888     if (image == (Image *) NULL)
5889       {
5890         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5891           PackageName);
5892         goto PerlException;
5893       }
5894
5895     blob=(void *) GetVirtualMetacontent(image);
5896     if (blob != (void *) NULL)
5897       goto PerlEnd;
5898
5899   PerlException:
5900     InheritPerlException(exception,perl_exception);
5901     exception=DestroyExceptionInfo(exception);
5902     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5903
5904   PerlEnd:
5905     RETVAL = blob;
5906   }
5907   OUTPUT:
5908     RETVAL
5909 \f
5910 #
5911 ###############################################################################
5912 #                                                                             #
5913 #                                                                             #
5914 #                                                                             #
5915 #   H i s t o g r a m                                                         #
5916 #                                                                             #
5917 #                                                                             #
5918 #                                                                             #
5919 ###############################################################################
5920 #
5921 #
5922 void
5923 Histogram(ref,...)
5924   Image::Magick ref=NO_INIT
5925   ALIAS:
5926     HistogramImage = 1
5927     histogram      = 2
5928     histogramimage = 3
5929   PPCODE:
5930   {
5931     AV
5932       *av;
5933
5934     char
5935       message[MaxTextExtent];
5936
5937     PixelPacket
5938       *histogram;
5939
5940     ExceptionInfo
5941       *exception;
5942
5943     Image
5944       *image;
5945
5946     register ssize_t
5947       i;
5948
5949     ssize_t
5950       count;
5951
5952     struct PackageInfo
5953       *info;
5954
5955     SV
5956       *perl_exception,
5957       *reference;
5958
5959     size_t
5960       number_colors;
5961
5962     PERL_UNUSED_VAR(ref);
5963     PERL_UNUSED_VAR(ix);
5964     exception=AcquireExceptionInfo();
5965     perl_exception=newSVpv("",0);
5966     av=NULL;
5967     if (sv_isobject(ST(0)) == 0)
5968       {
5969         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5970           PackageName);
5971         goto PerlException;
5972       }
5973     reference=SvRV(ST(0));
5974     av=newAV();
5975     SvREFCNT_dec(av);
5976     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5977     if (image == (Image *) NULL)
5978       {
5979         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5980           PackageName);
5981         goto PerlException;
5982       }
5983     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
5984     count=0;
5985     for ( ; image; image=image->next)
5986     {
5987       histogram=GetImageHistogram(image,&number_colors,&image->exception);
5988       if (histogram == (PixelPacket *) NULL)
5989         continue;
5990       count+=(ssize_t) number_colors;
5991       EXTEND(sp,6*count);
5992       for (i=0; i < (ssize_t) number_colors; i++)
5993       {
5994         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
5995           histogram[i].red);
5996         PUSHs(sv_2mortal(newSVpv(message,0)));
5997         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
5998           histogram[i].green);
5999         PUSHs(sv_2mortal(newSVpv(message,0)));
6000         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
6001           histogram[i].blue);
6002         PUSHs(sv_2mortal(newSVpv(message,0)));
6003         if (image->colorspace == CMYKColorspace)
6004           {
6005             (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
6006               histogram[i].black);
6007             PUSHs(sv_2mortal(newSVpv(message,0)));
6008           }
6009         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
6010           histogram[i].alpha);
6011         PUSHs(sv_2mortal(newSVpv(message,0)));
6012         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
6013           histogram[i].count);
6014         PUSHs(sv_2mortal(newSVpv(message,0)));
6015       }
6016       histogram=(PixelPacket *) RelinquishMagickMemory(histogram);
6017     }
6018
6019   PerlException:
6020     InheritPerlException(exception,perl_exception);
6021     exception=DestroyExceptionInfo(exception);
6022     SvREFCNT_dec(perl_exception);
6023   }
6024 \f
6025 #
6026 ###############################################################################
6027 #                                                                             #
6028 #                                                                             #
6029 #                                                                             #
6030 #   G e t P i x e l                                                           #
6031 #                                                                             #
6032 #                                                                             #
6033 #                                                                             #
6034 ###############################################################################
6035 #
6036 #
6037 void
6038 GetPixel(ref,...)
6039   Image::Magick ref=NO_INIT
6040   ALIAS:
6041     getpixel = 1
6042     getPixel = 2
6043   PPCODE:
6044   {
6045     AV
6046       *av;
6047
6048     char
6049       *attribute;
6050
6051     ExceptionInfo
6052       *exception;
6053
6054     Image
6055       *image;
6056
6057     MagickBooleanType
6058       normalize;
6059
6060     RectangleInfo
6061       region;
6062
6063     register const Quantum
6064       *p;
6065
6066     register ssize_t
6067       i;
6068
6069     ssize_t
6070       option;
6071
6072     struct PackageInfo
6073       *info;
6074
6075     SV
6076       *perl_exception,
6077       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6078
6079     PERL_UNUSED_VAR(ref);
6080     PERL_UNUSED_VAR(ix);
6081     exception=AcquireExceptionInfo();
6082     perl_exception=newSVpv("",0);
6083     reference=SvRV(ST(0));
6084     av=(AV *) reference;
6085     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6086       exception);
6087     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6088     if (image == (Image *) NULL)
6089       {
6090         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6091           PackageName);
6092         goto PerlException;
6093       }
6094     normalize=MagickTrue;
6095     region.x=0;
6096     region.y=0;
6097     region.width=image->columns;
6098     region.height=1;
6099     if (items == 1)
6100       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6101     for (i=2; i < items; i+=2)
6102     {
6103       attribute=(char *) SvPV(ST(i-1),na);
6104       switch (*attribute)
6105       {
6106         case 'C':
6107         case 'c':
6108         {
6109           if (LocaleCompare(attribute,"channel") == 0)
6110             {
6111               ssize_t
6112                 option;
6113
6114               option=ParseChannelOption(SvPV(ST(i),na));
6115               if (option < 0)
6116                 {
6117                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6118                     SvPV(ST(i),na));
6119                   return;
6120                 }
6121               SetPixelChannelMap(image,(ChannelType) option);
6122               break;
6123             }
6124           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6125             attribute);
6126           break;
6127         }
6128         case 'g':
6129         case 'G':
6130         {
6131           if (LocaleCompare(attribute,"geometry") == 0)
6132             {
6133               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6134               break;
6135             }
6136           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6137             attribute);
6138           break;
6139         }
6140         case 'N':
6141         case 'n':
6142         {
6143           if (LocaleCompare(attribute,"normalize") == 0)
6144             {
6145               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6146                 SvPV(ST(i),na));
6147               if (option < 0)
6148                 {
6149                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6150                     SvPV(ST(i),na));
6151                   break;
6152                 }
6153              normalize=option != 0 ? MagickTrue : MagickFalse;
6154              break;
6155             }
6156           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6157             attribute);
6158           break;
6159         }
6160         case 'x':
6161         case 'X':
6162         {
6163           if (LocaleCompare(attribute,"x") == 0)
6164             {
6165               region.x=SvIV(ST(i));
6166               break;
6167             }
6168           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6169             attribute);
6170           break;
6171         }
6172         case 'y':
6173         case 'Y':
6174         {
6175           if (LocaleCompare(attribute,"y") == 0)
6176             {
6177               region.y=SvIV(ST(i));
6178               break;
6179             }
6180           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6181             attribute);
6182           break;
6183         }
6184         default:
6185         {
6186           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6187             attribute);
6188           break;
6189         }
6190       }
6191     }
6192     p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6193     if (p == (const Quantum *) NULL)
6194       PUSHs(&sv_undef);
6195     else
6196       {
6197         double
6198           scale;
6199
6200         scale=1.0;
6201         if (normalize != MagickFalse)
6202           scale=1.0/QuantumRange;
6203         if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
6204           PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6205         if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6206           PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6207         if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6208           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6209         if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6210             (image->colorspace == CMYKColorspace))
6211           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6212         if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
6213           PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6214       }
6215
6216   PerlException:
6217     InheritPerlException(exception,perl_exception);
6218     exception=DestroyExceptionInfo(exception);
6219     SvREFCNT_dec(perl_exception);
6220   }
6221 \f
6222 #
6223 ###############################################################################
6224 #                                                                             #
6225 #                                                                             #
6226 #                                                                             #
6227 #   G e t P i x e l s                                                         #
6228 #                                                                             #
6229 #                                                                             #
6230 #                                                                             #
6231 ###############################################################################
6232 #
6233 #
6234 void
6235 GetPixels(ref,...)
6236   Image::Magick ref=NO_INIT
6237   ALIAS:
6238     getpixels = 1
6239     getPixels = 2
6240   PPCODE:
6241   {
6242     AV
6243       *av;
6244
6245     char
6246       *attribute;
6247
6248     const char
6249       *map;
6250
6251     ExceptionInfo
6252       *exception;
6253
6254     Image
6255       *image;
6256
6257     MagickBooleanType
6258       normalize,
6259       status;
6260
6261     RectangleInfo
6262       region;
6263
6264     register ssize_t
6265       i;
6266
6267     ssize_t
6268       option;
6269
6270     struct PackageInfo
6271       *info;
6272
6273     SV
6274       *perl_exception,
6275       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6276
6277     PERL_UNUSED_VAR(ref);
6278     PERL_UNUSED_VAR(ix);
6279     exception=AcquireExceptionInfo();
6280     perl_exception=newSVpv("",0);
6281     reference=SvRV(ST(0));
6282     av=(AV *) reference;
6283     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6284       exception);
6285     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6286     if (image == (Image *) NULL)
6287       {
6288         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6289           PackageName);
6290         goto PerlException;
6291       }
6292     map="RGB";
6293     if (image->matte != MagickFalse)
6294       map="RGBA";
6295     if (image->colorspace == CMYKColorspace)
6296       {
6297         map="CMYK";
6298         if (image->matte != MagickFalse)
6299           map="CMYKA";
6300       }
6301     normalize=MagickFalse;
6302     region.x=0;
6303     region.y=0;
6304     region.width=image->columns;
6305     region.height=1;
6306     if (items == 1)
6307       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6308     for (i=2; i < items; i+=2)
6309     {
6310       attribute=(char *) SvPV(ST(i-1),na);
6311       switch (*attribute)
6312       {
6313         case 'g':
6314         case 'G':
6315         {
6316           if (LocaleCompare(attribute,"geometry") == 0)
6317             {
6318               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6319               break;
6320             }
6321           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6322             attribute);
6323           break;
6324         }
6325         case 'H':
6326         case 'h':
6327         {
6328           if (LocaleCompare(attribute,"height") == 0)
6329             {
6330               region.height=SvIV(ST(i));
6331               break;
6332             }
6333           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6334             attribute);
6335           break;
6336         }
6337         case 'M':
6338         case 'm':
6339         {
6340           if (LocaleCompare(attribute,"map") == 0)
6341             {
6342               map=SvPV(ST(i),na);
6343               break;
6344             }
6345           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6346             attribute);
6347           break;
6348         }
6349         case 'N':
6350         case 'n':
6351         {
6352           if (LocaleCompare(attribute,"normalize") == 0)
6353             {
6354               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6355                 SvPV(ST(i),na));
6356               if (option < 0)
6357                 {
6358                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6359                     SvPV(ST(i),na));
6360                   break;
6361                 }
6362              normalize=option != 0 ? MagickTrue : MagickFalse;
6363              break;
6364             }
6365           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6366             attribute);
6367           break;
6368         }
6369         case 'W':
6370         case 'w':
6371         {
6372           if (LocaleCompare(attribute,"width") == 0)
6373             {
6374               region.width=SvIV(ST(i));
6375               break;
6376             }
6377           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6378             attribute);
6379           break;
6380         }
6381         case 'x':
6382         case 'X':
6383         {
6384           if (LocaleCompare(attribute,"x") == 0)
6385             {
6386               region.x=SvIV(ST(i));
6387               break;
6388             }
6389           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6390             attribute);
6391           break;
6392         }
6393         case 'y':
6394         case 'Y':
6395         {
6396           if (LocaleCompare(attribute,"y") == 0)
6397             {
6398               region.y=SvIV(ST(i));
6399               break;
6400             }
6401           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6402             attribute);
6403           break;
6404         }
6405         default:
6406         {
6407           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6408             attribute);
6409           break;
6410         }
6411       }
6412     }
6413     if (normalize != MagickFalse)
6414       {
6415         float
6416           *pixels;
6417
6418         pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6419           region.height*sizeof(*pixels));
6420         if (pixels == (float *) NULL)
6421           {
6422             ThrowPerlException(exception,ResourceLimitError,
6423               "MemoryAllocationFailed",PackageName);
6424             goto PerlException;
6425           }
6426         status=ExportImagePixels(image,region.x,region.y,region.width,
6427           region.height,map,FloatPixel,pixels,exception);
6428         if (status == MagickFalse)
6429           PUSHs(&sv_undef);
6430         else
6431           {
6432             EXTEND(sp,strlen(map)*region.width*region.height);
6433             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6434               PUSHs(sv_2mortal(newSVnv(pixels[i])));
6435           }
6436         pixels=(float *) RelinquishMagickMemory(pixels);
6437       }
6438     else
6439       {
6440         Quantum
6441           *pixels;
6442
6443         pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6444           region.height*sizeof(*pixels));
6445         if (pixels == (Quantum *) NULL)
6446           {
6447             ThrowPerlException(exception,ResourceLimitError,
6448               "MemoryAllocationFailed",PackageName);
6449             goto PerlException;
6450           }
6451         status=ExportImagePixels(image,region.x,region.y,region.width,
6452           region.height,map,QuantumPixel,pixels,exception);
6453         if (status == MagickFalse)
6454           PUSHs(&sv_undef);
6455         else
6456           {
6457             EXTEND(sp,strlen(map)*region.width*region.height);
6458             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6459               PUSHs(sv_2mortal(newSViv(pixels[i])));
6460           }
6461         pixels=(Quantum *) RelinquishMagickMemory(pixels);
6462       }
6463
6464   PerlException:
6465     InheritPerlException(exception,perl_exception);
6466     exception=DestroyExceptionInfo(exception);
6467     SvREFCNT_dec(perl_exception);
6468   }
6469 \f
6470 #
6471 ###############################################################################
6472 #                                                                             #
6473 #                                                                             #
6474 #                                                                             #
6475 #   I m a g e T o B l o b                                                     #
6476 #                                                                             #
6477 #                                                                             #
6478 #                                                                             #
6479 ###############################################################################
6480 #
6481 #
6482 void
6483 ImageToBlob(ref,...)
6484   Image::Magick ref=NO_INIT
6485   ALIAS:
6486     ImageToBlob  = 1
6487     imagetoblob  = 2
6488     toblob       = 3
6489     blob         = 4
6490   PPCODE:
6491   {
6492     char
6493       filename[MaxTextExtent];
6494
6495     ExceptionInfo
6496       *exception;
6497
6498     Image
6499       *image,
6500       *next;
6501
6502     register ssize_t
6503       i;
6504
6505     struct PackageInfo
6506       *info,
6507       *package_info;
6508
6509     size_t
6510       length;
6511
6512     ssize_t
6513       scene;
6514
6515     SV
6516       *perl_exception,
6517       *reference;
6518
6519     void
6520       *blob;
6521
6522     PERL_UNUSED_VAR(ref);
6523     PERL_UNUSED_VAR(ix);
6524     exception=AcquireExceptionInfo();
6525     perl_exception=newSVpv("",0);
6526     package_info=(struct PackageInfo *) NULL;
6527     if (sv_isobject(ST(0)) == 0)
6528       {
6529         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6530           PackageName);
6531         goto PerlException;
6532       }
6533     reference=SvRV(ST(0));
6534     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6535     if (image == (Image *) NULL)
6536       {
6537         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6538           PackageName);
6539         goto PerlException;
6540       }
6541     package_info=ClonePackageInfo(info,exception);
6542     for (i=2; i < items; i+=2)
6543       SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6544     (void) CopyMagickString(filename,package_info->image_info->filename,
6545       MaxTextExtent);
6546     scene=0;
6547     for (next=image; next; next=next->next)
6548     {
6549       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
6550       next->scene=scene++;
6551     }
6552     SetImageInfo(package_info->image_info,(unsigned int)
6553       GetImageListLength(image),&image->exception);
6554     EXTEND(sp,(ssize_t) GetImageListLength(image));
6555     for ( ; image; image=image->next)
6556     {
6557       length=0;
6558       blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6559       if (blob != (char *) NULL)
6560         {
6561           PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6562           blob=(unsigned char *) RelinquishMagickMemory(blob);
6563         }
6564       if (package_info->image_info->adjoin)
6565         break;
6566     }
6567
6568   PerlException:
6569     if (package_info != (struct PackageInfo *) NULL)
6570       DestroyPackageInfo(package_info);
6571     InheritPerlException(exception,perl_exception);
6572     exception=DestroyExceptionInfo(exception);
6573     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6574   }
6575 \f
6576 #
6577 ###############################################################################
6578 #                                                                             #
6579 #                                                                             #
6580 #                                                                             #
6581 #   L a y e r s                                                               #
6582 #                                                                             #
6583 #                                                                             #
6584 #                                                                             #
6585 ###############################################################################
6586 #
6587 #
6588 void
6589 Layers(ref,...)
6590   Image::Magick ref=NO_INIT
6591   ALIAS:
6592     Layers                = 1
6593     layers           = 2
6594     OptimizeImageLayers   = 3
6595     optimizelayers        = 4
6596     optimizeimagelayers   = 5
6597   PPCODE:
6598   {
6599     AV
6600       *av;
6601
6602     char
6603       *attribute;
6604
6605     CompositeOperator
6606       compose;
6607
6608     ExceptionInfo
6609       *exception;
6610
6611     HV
6612       *hv;
6613
6614     Image
6615       *image,
6616       *layers;
6617
6618     ImageLayerMethod
6619       method;
6620
6621     register ssize_t
6622       i;
6623
6624     ssize_t
6625       option,
6626       sp;
6627
6628     struct PackageInfo
6629       *info;
6630
6631     SV
6632       *av_reference,
6633       *perl_exception,
6634       *reference,
6635       *rv,
6636       *sv;
6637
6638     PERL_UNUSED_VAR(ref);
6639     PERL_UNUSED_VAR(ix);
6640     exception=AcquireExceptionInfo();
6641     perl_exception=newSVpv("",0);
6642     sv=NULL;
6643     if (sv_isobject(ST(0)) == 0)
6644       {
6645         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6646           PackageName);
6647         goto PerlException;
6648       }
6649     reference=SvRV(ST(0));
6650     hv=SvSTASH(reference);
6651     av=newAV();
6652     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
6653     SvREFCNT_dec(av);
6654     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6655     if (image == (Image *) NULL)
6656       {
6657         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6658           PackageName);
6659         goto PerlException;
6660       }
6661     compose=image->compose;
6662     method=OptimizeLayer;
6663     for (i=2; i < items; i+=2)
6664     {
6665       attribute=(char *) SvPV(ST(i-1),na);
6666       switch (*attribute)
6667       {
6668         case 'C':
6669         case 'c':
6670         {
6671           if (LocaleCompare(attribute,"compose") == 0)
6672             {
6673               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
6674                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
6675               if (sp < 0)
6676                 {
6677                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6678                     SvPV(ST(i),na));
6679                   break;
6680                 }
6681               compose=(CompositeOperator) sp;
6682               break;
6683             }
6684           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6685             attribute);
6686           break;
6687         }
6688         case 'M':
6689         case 'm':
6690         {
6691           if (LocaleCompare(attribute,"method") == 0)
6692             {
6693               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
6694                 SvPV(ST(i),na));
6695               if (option < 0)
6696                 {
6697                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6698                     SvPV(ST(i),na));
6699                   break;
6700                 }
6701               method=(ImageLayerMethod) option;
6702               break;
6703             }
6704           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6705             attribute);
6706           break;
6707         }
6708         default:
6709         {
6710           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6711             attribute);
6712           break;
6713         }
6714       }
6715     }
6716     layers=(Image *) NULL;
6717     switch (method)
6718     {
6719       case CompareAnyLayer:
6720       case CompareClearLayer:
6721       case CompareOverlayLayer:
6722       default:
6723       {
6724         layers=CompareImagesLayers(image,method,exception);
6725         break;
6726       }
6727       case MergeLayer:
6728       case FlattenLayer:
6729       case MosaicLayer:
6730       {
6731         layers=MergeImageLayers(image,method,exception);
6732         break;
6733       }
6734       case DisposeLayer:
6735       {
6736         layers=DisposeImages(image,exception);
6737         break;
6738       }
6739       case OptimizeImageLayer:
6740       {
6741         layers=OptimizeImageLayers(image,exception);
6742         break;
6743       }
6744       case OptimizePlusLayer:
6745       {
6746         layers=OptimizePlusImageLayers(image,exception);
6747         break;
6748       }
6749       case OptimizeTransLayer:
6750       {
6751         OptimizeImageTransparency(image,exception);
6752         InheritException(&(image->exception),exception);
6753         break;
6754       }
6755       case RemoveDupsLayer:
6756       {
6757         RemoveDuplicateLayers(&image,exception);
6758         InheritException(&(image->exception),exception);
6759         break;
6760       }
6761       case RemoveZeroLayer:
6762       {
6763         RemoveZeroDelayLayers(&image,exception);
6764         InheritException(&(image->exception),exception);
6765         break;
6766       }
6767       case OptimizeLayer:
6768       {
6769         QuantizeInfo
6770           *quantize_info;
6771
6772         /*
6773           General Purpose, GIF Animation Optimizer.
6774         */
6775         layers=CoalesceImages(image,exception);
6776         if (layers == (Image *) NULL)
6777           break;
6778         InheritException(&(layers->exception),exception);
6779         image=layers;
6780         layers=OptimizeImageLayers(image,exception);
6781         if (layers == (Image *) NULL)
6782           break;
6783         InheritException(&(layers->exception),exception);
6784         image=DestroyImageList(image);
6785         image=layers;
6786         layers=(Image *) NULL;
6787         OptimizeImageTransparency(image,exception);
6788         InheritException(&(image->exception),exception);
6789         quantize_info=AcquireQuantizeInfo(info->image_info);
6790         (void) RemapImages(quantize_info,image,(Image *) NULL,exception);
6791         quantize_info=DestroyQuantizeInfo(quantize_info);
6792         break;
6793       }
6794       case CompositeLayer:
6795       {
6796         Image
6797           *source;
6798
6799         RectangleInfo
6800           geometry;
6801
6802         /*
6803           Split image sequence at the first 'NULL:' image.
6804         */
6805         source=image;
6806         while (source != (Image *) NULL)
6807         {
6808           source=GetNextImageInList(source);
6809           if ((source != (Image *) NULL) &&
6810               (LocaleCompare(source->magick,"NULL") == 0))
6811             break;
6812         }
6813         if (source != (Image *) NULL)
6814           {
6815             if ((GetPreviousImageInList(source) == (Image *) NULL) ||
6816                 (GetNextImageInList(source) == (Image *) NULL))
6817               source=(Image *) NULL;
6818             else
6819               {
6820                 /*
6821                   Separate the two lists, junk the null: image.
6822                 */
6823                 source=SplitImageList(source->previous);
6824                 DeleteImageFromList(&source);
6825               }
6826           }
6827         if (source == (Image *) NULL)
6828           {
6829             (void) ThrowMagickException(exception,GetMagickModule(),
6830               OptionError,"MissingNullSeparator","layers Composite");
6831             break;
6832           }
6833         /*
6834           Adjust offset with gravity and virtual canvas.
6835         */
6836         SetGeometry(image,&geometry);
6837         (void) ParseAbsoluteGeometry(image->geometry,&geometry);
6838         geometry.width=source->page.width != 0 ? source->page.width :
6839           source->columns;
6840         geometry.height=source->page.height != 0 ? source->page.height :
6841           source->rows;
6842         GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
6843           image->columns,image->page.height != 0 ? image->page.height :
6844           image->rows,image->gravity,&geometry);
6845         CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
6846         source=DestroyImageList(source);
6847         InheritException(&(image->exception),exception);
6848         break;
6849       }
6850     }
6851     if (layers != (Image *) NULL)
6852       {
6853         InheritException(&(layers->exception),exception);
6854         image=layers;
6855       }
6856     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
6857       goto PerlException;
6858     for ( ; image; image=image->next)
6859     {
6860       AddImageToRegistry(sv,image);
6861       rv=newRV(sv);
6862       av_push(av,sv_bless(rv,hv));
6863       SvREFCNT_dec(sv);
6864     }
6865     exception=DestroyExceptionInfo(exception);
6866     ST(0)=av_reference;
6867     SvREFCNT_dec(perl_exception);
6868     XSRETURN(1);
6869
6870   PerlException:
6871     InheritPerlException(exception,perl_exception);
6872     exception=DestroyExceptionInfo(exception);
6873     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
6874     SvPOK_on(perl_exception);
6875     ST(0)=sv_2mortal(perl_exception);
6876     XSRETURN(1);
6877   }
6878 \f
6879 #
6880 ###############################################################################
6881 #                                                                             #
6882 #                                                                             #
6883 #                                                                             #
6884 #   M a g i c k T o M i m e                                                   #
6885 #                                                                             #
6886 #                                                                             #
6887 #                                                                             #
6888 ###############################################################################
6889 #
6890 #
6891 SV *
6892 MagickToMime(ref,name)
6893   Image::Magick ref=NO_INIT
6894   char *name
6895   ALIAS:
6896     magicktomime = 1
6897   CODE:
6898   {
6899     char
6900       *mime;
6901
6902     PERL_UNUSED_VAR(ref);
6903     PERL_UNUSED_VAR(ix);
6904     mime=MagickToMime(name);
6905     RETVAL=newSVpv(mime,0);
6906     mime=(char *) RelinquishMagickMemory(mime);
6907   }
6908   OUTPUT:
6909     RETVAL
6910 \f
6911 #
6912 ###############################################################################
6913 #                                                                             #
6914 #                                                                             #
6915 #                                                                             #
6916 #   M o g r i f y                                                             #
6917 #                                                                             #
6918 #                                                                             #
6919 #                                                                             #
6920 ###############################################################################
6921 #
6922 #
6923 void
6924 Mogrify(ref,...)
6925   Image::Magick ref=NO_INIT
6926   ALIAS:
6927     Comment            =   1
6928     CommentImage       =   2
6929     Label              =   3
6930     LabelImage         =   4
6931     AddNoise           =   5
6932     AddNoiseImage      =   6
6933     Colorize           =   7
6934     ColorizeImage      =   8
6935     Border             =   9
6936     BorderImage        =  10
6937     Blur               =  11
6938     BlurImage          =  12
6939     Chop               =  13
6940     ChopImage          =  14
6941     Crop               =  15
6942     CropImage          =  16
6943     Despeckle          =  17
6944     DespeckleImage     =  18
6945     Edge               =  19
6946     EdgeImage          =  20
6947     Emboss             =  21
6948     EmbossImage        =  22
6949     Enhance            =  23
6950     EnhanceImage       =  24
6951     Flip               =  25
6952     FlipImage          =  26
6953     Flop               =  27
6954     FlopImage          =  28
6955     Frame              =  29
6956     FrameImage         =  30
6957     Implode            =  31
6958     ImplodeImage       =  32
6959     Magnify            =  33
6960     MagnifyImage       =  34
6961     MedianFilter       =  35
6962     MedianConvolveImage  =  36
6963     Minify             =  37
6964     MinifyImage        =  38
6965     OilPaint           =  39
6966     OilPaintImage      =  40
6967     ReduceNoise        =  41
6968     ReduceNoiseImage   =  42
6969     Roll               =  43
6970     RollImage          =  44
6971     Rotate             =  45
6972     RotateImage        =  46
6973     Sample             =  47
6974     SampleImage        =  48
6975     Scale              =  49
6976     ScaleImage         =  50
6977     Shade              =  51
6978     ShadeImage         =  52
6979     Sharpen            =  53
6980     SharpenImage       =  54
6981     Shear              =  55
6982     ShearImage         =  56
6983     Spread             =  57
6984     SpreadImage        =  58
6985     Swirl              =  59
6986     SwirlImage         =  60
6987     Resize             =  61
6988     ResizeImage        =  62
6989     Zoom               =  63
6990     ZoomImage          =  64
6991     Annotate           =  65
6992     AnnotateImage      =  66
6993     ColorFloodfill     =  67
6994     ColorFloodfillImage=  68
6995     Composite          =  69
6996     CompositeImage     =  70
6997     Contrast           =  71
6998     ContrastImage      =  72
6999     CycleColormap      =  73
7000     CycleColormapImage =  74
7001     Draw               =  75
7002     DrawImage          =  76
7003     Equalize           =  77
7004     EqualizeImage      =  78
7005     Gamma              =  79
7006     GammaImage         =  80
7007     Map                =  81
7008     MapImage           =  82
7009     MatteFloodfill     =  83
7010     MatteFloodfillImage=  84
7011     Modulate           =  85
7012     ModulateImage      =  86
7013     Negate             =  87
7014     NegateImage        =  88
7015     Normalize          =  89
7016     NormalizeImage     =  90
7017     NumberColors       =  91
7018     NumberColorsImage  =  92
7019     Opaque             =  93
7020     OpaqueImage        =  94
7021     Quantize           =  95
7022     QuantizeImage      =  96
7023     Raise              =  97
7024     RaiseImage         =  98
7025     Segment            =  99
7026     SegmentImage       = 100
7027     Signature          = 101
7028     SignatureImage     = 102
7029     Solarize           = 103
7030     SolarizeImage      = 104
7031     Sync               = 105
7032     SyncImage          = 106
7033     Texture            = 107
7034     TextureImage       = 108
7035     Evaluate           = 109
7036     EvaluateImage      = 110
7037     Transparent        = 111
7038     TransparentImage   = 112
7039     Threshold          = 113
7040     ThresholdImage     = 114
7041     Charcoal           = 115
7042     CharcoalImage      = 116
7043     Trim               = 117
7044     TrimImage          = 118
7045     Wave               = 119
7046     WaveImage          = 120
7047     Separate           = 121
7048     SeparateImage      = 122
7049     Stereo             = 125
7050     StereoImage        = 126
7051     Stegano            = 127
7052     SteganoImage       = 128
7053     Deconstruct        = 129
7054     DeconstructImage   = 130
7055     GaussianBlur       = 131
7056     GaussianBlurImage  = 132
7057     Convolve           = 133
7058     ConvolveImage      = 134
7059     Profile            = 135
7060     ProfileImage       = 136
7061     UnsharpMask        = 137
7062     UnsharpMaskImage   = 138
7063     MotionBlur         = 139
7064     MotionBlurImage    = 140
7065     OrderedDither      = 141
7066     OrderedDitherImage = 142
7067     Shave              = 143
7068     ShaveImage         = 144
7069     Level              = 145
7070     LevelImage         = 146
7071     Clip               = 147
7072     ClipImage          = 148
7073     AffineTransform    = 149
7074     AffineTransformImage = 150
7075     Difference         = 151
7076     DifferenceImage    = 152
7077     AdaptiveThreshold  = 153
7078     AdaptiveThresholdImage = 154
7079     Resample           = 155
7080     ResampleImage      = 156
7081     Describe           = 157
7082     DescribeImage      = 158
7083     BlackThreshold     = 159
7084     BlackThresholdImage= 160
7085     WhiteThreshold     = 161
7086     WhiteThresholdImage= 162
7087     RadialBlur         = 163
7088     RadialBlurImage    = 164
7089     Thumbnail          = 165
7090     ThumbnailImage     = 166
7091     Strip              = 167
7092     StripImage         = 168
7093     Tint               = 169
7094     TintImage          = 170
7095     Channel            = 171
7096     ChannelImage       = 172
7097     Splice             = 173
7098     SpliceImage        = 174
7099     Posterize          = 175
7100     PosterizeImage     = 176
7101     Shadow             = 177
7102     ShadowImage        = 178
7103     Identify           = 179
7104     IdentifyImage      = 180
7105     SepiaTone          = 181
7106     SepiaToneImage     = 182
7107     SigmoidalContrast  = 183
7108     SigmoidalContrastImage = 184
7109     Extent             = 185
7110     ExtentImage        = 186
7111     Vignette           = 187
7112     VignetteImage      = 188
7113     ContrastStretch    = 189
7114     ContrastStretchImage = 190
7115     Sans0              = 191
7116     Sans0Image         = 192
7117     Sans1              = 193
7118     Sans1Image         = 194
7119     AdaptiveSharpen    = 195
7120     AdaptiveSharpenImage = 196
7121     Transpose          = 197
7122     TransposeImage     = 198
7123     Transverse         = 199
7124     TransverseImage    = 200
7125     AutoOrient         = 201
7126     AutoOrientImage    = 202
7127     AdaptiveBlur       = 203
7128     AdaptiveBlurImage  = 204
7129     Sketch             = 205
7130     SketchImage        = 206
7131     UniqueColors       = 207
7132     UniqueColorsImage  = 208
7133     AdaptiveResize     = 209
7134     AdaptiveResizeImage= 210
7135     ClipMask           = 211
7136     ClipMaskImage      = 212
7137     LinearStretch      = 213
7138     LinearStretchImage = 214
7139     RecolorImage       = 215
7140     Recolor            = 216
7141     Mask               = 217
7142     MaskImage          = 218
7143     Polaroid           = 219
7144     PolaroidImage      = 220
7145     FloodfillPaint     = 221
7146     FloodfillPaintImage= 222
7147     Distort            = 223
7148     DistortImage       = 224
7149     Clut               = 225
7150     ClutImage          = 226
7151     LiquidRescale      = 227
7152     LiquidRescaleImage = 228
7153     Encipher           = 229
7154     EncipherImage      = 230
7155     Decipher           = 231
7156     DecipherImage      = 232
7157     Deskew             = 233
7158     DeskewImage        = 234
7159     Remap              = 235
7160     RemapImage         = 236
7161     SparseColor        = 237
7162     SparseColorImage   = 238
7163     Function           = 239
7164     FunctionImage      = 240
7165     SelectiveBlur      = 241
7166     SelectiveBlurImage = 242
7167     HaldClut           = 243
7168     HaldClutImage      = 244
7169     BlueShift          = 245
7170     BlueShiftImage     = 246
7171     ForwardFourierTransform  = 247
7172     ForwardFourierTransformImage = 248
7173     InverseFourierTransform = 249
7174     InverseFourierTransformImage = 250
7175     ColorDecisionList  = 251
7176     ColorDecisionListImage = 252
7177     AutoGamma          = 253
7178     AutoGammaImage     = 254
7179     AutoLevel          = 255
7180     AutoLevelImage     = 256
7181     LevelColors        = 257
7182     LevelImageColors   = 258
7183     Clamp              = 259
7184     ClampImage         = 260
7185     BrightnessContrast = 263
7186     BrightnessContrastImage = 264
7187     Morphology         = 265
7188     MorphologyImage    = 266
7189     ColorMatrix        = 267
7190     ColorMatrixImage   = 268
7191     Color              = 269
7192     ColorImage         = 270
7193     Mode               = 271
7194     ModeImage          = 272
7195     Statistic          = 273
7196     StatisticImage     = 274
7197     MogrifyRegion      = 666
7198   PPCODE:
7199   {
7200     AffineMatrix
7201       affine,
7202       current;
7203
7204     char
7205       attribute_flag[MaxArguments],
7206       message[MaxTextExtent];
7207
7208     ChannelType
7209       channel,
7210       channel_mask;
7211
7212     CompositeOperator
7213       compose;
7214
7215     const char
7216       *attribute,
7217       *value;
7218
7219     double
7220       angle;
7221
7222     ExceptionInfo
7223       *exception;
7224
7225     GeometryInfo
7226       geometry_info;
7227
7228     Image
7229       *image,
7230       *next,
7231       *region_image;
7232
7233     MagickBooleanType
7234       status;
7235
7236     MagickStatusType
7237       flags;
7238
7239     PixelPacket
7240       fill_color;
7241
7242     RectangleInfo
7243       geometry,
7244       region_info;
7245
7246     register ssize_t
7247       i;
7248
7249     ssize_t
7250       base,
7251       j,
7252       number_images;
7253
7254     struct Methods
7255       *rp;
7256
7257     struct PackageInfo
7258       *info;
7259
7260     SV
7261       *perl_exception,
7262       **pv,
7263       *reference,
7264       **reference_vector;
7265
7266     struct ArgumentList
7267       argument_list[MaxArguments];
7268
7269     PERL_UNUSED_VAR(ref);
7270     PERL_UNUSED_VAR(ix);
7271     exception=AcquireExceptionInfo();
7272     perl_exception=newSVpv("",0);
7273     reference_vector=NULL;
7274     region_image=NULL;
7275     number_images=0;
7276     base=2;
7277     if (sv_isobject(ST(0)) == 0)
7278       {
7279         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7280           PackageName);
7281         goto PerlException;
7282       }
7283     reference=SvRV(ST(0));
7284     region_info.width=0;
7285     region_info.height=0;
7286     region_info.x=0;
7287     region_info.y=0;
7288     region_image=(Image *) NULL;
7289     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7290     if (ix && (ix != 666))
7291       {
7292         /*
7293           Called as Method(...)
7294         */
7295         ix=(ix+1)/2;
7296         rp=(&Methods[ix-1]);
7297         attribute=rp->name;
7298       }
7299     else
7300       {
7301         /*
7302           Called as Mogrify("Method",...)
7303         */
7304         attribute=(char *) SvPV(ST(1),na);
7305         if (ix)
7306           {
7307             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7308             attribute=(char *) SvPV(ST(2),na);
7309             base++;
7310           }
7311         for (rp=Methods; ; rp++)
7312         {
7313           if (rp >= EndOf(Methods))
7314             {
7315               ThrowPerlException(exception,OptionError,
7316                 "UnrecognizedPerlMagickMethod",attribute);
7317               goto PerlException;
7318             }
7319           if (strEQcase(attribute,rp->name))
7320             break;
7321         }
7322         ix=rp-Methods+1;
7323         base++;
7324       }
7325     if (image == (Image *) NULL)
7326       {
7327         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7328         goto PerlException;
7329       }
7330     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7331     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7332     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7333     {
7334       Arguments
7335         *pp,
7336         *qq;
7337
7338       ssize_t
7339         ssize_test;
7340
7341       struct ArgumentList
7342         *al;
7343
7344       SV
7345         *sv;
7346
7347       sv=NULL;
7348       ssize_test=0;
7349       pp=(Arguments *) NULL;
7350       qq=rp->arguments;
7351       if (i == items)
7352         {
7353           pp=rp->arguments,
7354           sv=ST(i-1);
7355         }
7356       else
7357         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7358         {
7359           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7360             break;
7361           if (strEQcase(attribute,qq->method) > ssize_test)
7362             {
7363               pp=qq;
7364               ssize_test=strEQcase(attribute,qq->method);
7365             }
7366         }
7367       if (pp == (Arguments *) NULL)
7368         {
7369           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7370             attribute);
7371           goto continue_outer_loop;
7372         }
7373       al=(&argument_list[pp-rp->arguments]);
7374       switch (pp->type)
7375       {
7376         case ArrayReference:
7377         {
7378           if (SvTYPE(sv) != SVt_RV)
7379             {
7380               (void) FormatLocaleString(message,MaxTextExtent,
7381                 "invalid %.60s value",pp->method);
7382               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7383               goto continue_outer_loop;
7384             }
7385           al->array_reference=SvRV(sv);
7386           break;
7387         }
7388         case RealReference:
7389         {
7390           al->real_reference=SvNV(sv);
7391           break;
7392         }
7393         case FileReference:
7394         {
7395           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7396           break;
7397         }
7398         case ImageReference:
7399         {
7400           if (!sv_isobject(sv) ||
7401               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7402                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7403             {
7404               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7405                 PackageName);
7406               goto PerlException;
7407             }
7408           break;
7409         }
7410         case IntegerReference:
7411         {
7412           al->integer_reference=SvIV(sv);
7413           break;
7414         }
7415         case StringReference:
7416         {
7417           al->string_reference=(char *) SvPV(sv,al->length);
7418           if (sv_isobject(sv))
7419             al->image_reference=SetupList(aTHX_ SvRV(sv),
7420               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7421           break;
7422         }
7423         default:
7424         {
7425           /*
7426             Is a string; look up name.
7427           */
7428           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7429             {
7430               al->string_reference=(char *) SvPV(sv,al->length);
7431               al->integer_reference=(-1);
7432               break;
7433             }
7434           al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7435             MagickFalse,SvPV(sv,na));
7436           if (pp->type == MagickChannelOptions)
7437             al->integer_reference=ParseChannelOption(SvPV(sv,na));
7438           if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7439             {
7440               (void) FormatLocaleString(message,MaxTextExtent,
7441                 "invalid %.60s value",pp->method);
7442               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7443               goto continue_outer_loop;
7444             }
7445           break;
7446         }
7447       }
7448       attribute_flag[pp-rp->arguments]++;
7449       continue_outer_loop: ;
7450     }
7451     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7452     pv=reference_vector;
7453     SetGeometryInfo(&geometry_info);
7454     channel=DefaultChannels;
7455     for (next=image; next; next=next->next)
7456     {
7457       image=next;
7458       SetGeometry(image,&geometry);
7459       if ((region_info.width*region_info.height) != 0)
7460         {
7461           region_image=image;
7462           image=CropImage(image,&region_info,exception);
7463         }
7464       switch (ix)
7465       {
7466         default:
7467         {
7468           (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double) ix);
7469           ThrowPerlException(exception,OptionError,
7470             "UnrecognizedPerlMagickMethod",message);
7471           goto PerlException;
7472         }
7473         case 1:  /* Comment */
7474         {
7475           if (attribute_flag[0] == 0)
7476             argument_list[0].string_reference=(char *) NULL;
7477           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7478             info ? info->image_info : (ImageInfo *) NULL,image,
7479             argument_list[0].string_reference,exception));
7480           break;
7481         }
7482         case 2:  /* Label */
7483         {
7484           if (attribute_flag[0] == 0)
7485             argument_list[0].string_reference=(char *) NULL;
7486           (void) SetImageProperty(image,"label",InterpretImageProperties(
7487             info ? info->image_info : (ImageInfo *) NULL,image,
7488             argument_list[0].string_reference,exception));
7489           break;
7490         }
7491         case 3:  /* AddNoise */
7492         {
7493           if (attribute_flag[0] == 0)
7494             argument_list[0].integer_reference=UniformNoise;
7495           if (attribute_flag[1] != 0)
7496             channel=(ChannelType) argument_list[1].integer_reference;
7497           channel_mask=SetPixelChannelMask(image,channel);
7498           image=AddNoiseImage(image,(NoiseType)
7499             argument_list[0].integer_reference,exception);
7500           if (image != (Image *) NULL)
7501             (void) SetPixelChannelMask(image,channel_mask);
7502           break;
7503         }
7504         case 4:  /* Colorize */
7505         {
7506           PixelPacket
7507             target;
7508
7509           (void) GetOneVirtualPixel(image,0,0,&target,exception);
7510           if (attribute_flag[0] != 0)
7511             (void) QueryColorDatabase(argument_list[0].string_reference,&target,
7512               exception);
7513           if (attribute_flag[1] == 0)
7514             argument_list[1].string_reference="100%";
7515           image=ColorizeImage(image,argument_list[1].string_reference,target,
7516             exception);
7517           break;
7518         }
7519         case 5:  /* Border */
7520         {
7521           CompositeOperator
7522             compose;
7523
7524           geometry.width=0;
7525           geometry.height=0;
7526           if (attribute_flag[0] != 0)
7527             {
7528               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7529                 &geometry,exception);
7530               if ((flags & HeightValue) == 0)
7531                 geometry.height=geometry.width;
7532             }
7533           if (attribute_flag[1] != 0)
7534             geometry.width=argument_list[1].integer_reference;
7535           if (attribute_flag[2] != 0)
7536             geometry.height=argument_list[2].integer_reference;
7537           if (attribute_flag[3] != 0)
7538             QueryColorDatabase(argument_list[3].string_reference,
7539               &image->border_color,exception);
7540           if (attribute_flag[4] != 0)
7541             QueryColorDatabase(argument_list[4].string_reference,
7542               &image->border_color,exception);
7543           if (attribute_flag[5] != 0)
7544             QueryColorDatabase(argument_list[5].string_reference,
7545               &image->border_color,exception);
7546           compose=image->compose;
7547           if (attribute_flag[6] != 0)
7548             compose=(CompositeOperator) argument_list[6].integer_reference;
7549           image=BorderImage(image,&geometry,compose,exception);
7550           break;
7551         }
7552         case 6:  /* Blur */
7553         {
7554           if (attribute_flag[0] != 0)
7555             {
7556               flags=ParseGeometry(argument_list[0].string_reference,
7557                 &geometry_info);
7558               if ((flags & SigmaValue) == 0)
7559                 geometry_info.sigma=1.0;
7560             }
7561           if (attribute_flag[1] != 0)
7562             geometry_info.rho=argument_list[1].real_reference;
7563           if (attribute_flag[2] != 0)
7564             geometry_info.sigma=argument_list[2].real_reference;
7565           if (attribute_flag[3] != 0)
7566             geometry_info.xi=argument_list[3].real_reference;
7567           if (attribute_flag[4] != 0)
7568             channel=(ChannelType) argument_list[4].integer_reference;
7569           channel_mask=SetPixelChannelMask(image,channel);
7570           image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
7571             geometry_info.xi,exception);
7572           if (image != (Image *) NULL)
7573             (void) SetPixelChannelMask(image,channel_mask);
7574           break;
7575         }
7576         case 7:  /* Chop */
7577         {
7578           if (attribute_flag[0] != 0)
7579             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7580               &geometry,exception);
7581           if (attribute_flag[1] != 0)
7582             geometry.width=argument_list[1].integer_reference;
7583           if (attribute_flag[2] != 0)
7584             geometry.height=argument_list[2].integer_reference;
7585           if (attribute_flag[3] != 0)
7586             geometry.x=argument_list[3].integer_reference;
7587           if (attribute_flag[4] != 0)
7588             geometry.y=argument_list[4].integer_reference;
7589           image=ChopImage(image,&geometry,exception);
7590           break;
7591         }
7592         case 8:  /* Crop */
7593         {
7594           if (attribute_flag[6] != 0)
7595             image->gravity=(GravityType) argument_list[6].integer_reference;
7596           if (attribute_flag[0] != 0)
7597             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7598               &geometry,exception);
7599           if (attribute_flag[1] != 0)
7600             geometry.width=argument_list[1].integer_reference;
7601           if (attribute_flag[2] != 0)
7602             geometry.height=argument_list[2].integer_reference;
7603           if (attribute_flag[3] != 0)
7604             geometry.x=argument_list[3].integer_reference;
7605           if (attribute_flag[4] != 0)
7606             geometry.y=argument_list[4].integer_reference;
7607           if (attribute_flag[5] != 0)
7608             image->fuzz=
7609               SiPrefixToDouble(argument_list[5].string_reference,QuantumRange);
7610           image=CropImage(image,&geometry,exception);
7611           break;
7612         }
7613         case 9:  /* Despeckle */
7614         {
7615           image=DespeckleImage(image,exception);
7616           break;
7617         }
7618         case 10:  /* Edge */
7619         {
7620           if (attribute_flag[0] != 0)
7621             geometry_info.rho=argument_list[0].real_reference;
7622           image=EdgeImage(image,geometry_info.rho,geometry_info.sigma,
7623             exception);
7624           break;
7625         }
7626         case 11:  /* Emboss */
7627         {
7628           if (attribute_flag[0] != 0)
7629             {
7630               flags=ParseGeometry(argument_list[0].string_reference,
7631                 &geometry_info);
7632               if ((flags & SigmaValue) == 0)
7633                 geometry_info.sigma=1.0;
7634             }
7635           if (attribute_flag[1] != 0)
7636             geometry_info.rho=argument_list[1].real_reference;
7637           if (attribute_flag[2] != 0)
7638             geometry_info.sigma=argument_list[2].real_reference;
7639           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
7640             exception);
7641           break;
7642         }
7643         case 12:  /* Enhance */
7644         {
7645           image=EnhanceImage(image,exception);
7646           break;
7647         }
7648         case 13:  /* Flip */
7649         {
7650           image=FlipImage(image,exception);
7651           break;
7652         }
7653         case 14:  /* Flop */
7654         {
7655           image=FlopImage(image,exception);
7656           break;
7657         }
7658         case 15:  /* Frame */
7659         {
7660           CompositeOperator
7661             compose;
7662
7663           FrameInfo
7664             frame_info;
7665
7666           if (attribute_flag[0] != 0)
7667             {
7668               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7669                 &geometry,exception);
7670               if ((flags & HeightValue) == 0)
7671                 geometry.height=geometry.width;
7672               frame_info.width=geometry.width;
7673               frame_info.height=geometry.height;
7674               frame_info.outer_bevel=geometry.x;
7675               frame_info.inner_bevel=geometry.y;
7676             }
7677           if (attribute_flag[1] != 0)
7678             frame_info.width=argument_list[1].integer_reference;
7679           if (attribute_flag[2] != 0)
7680             frame_info.height=argument_list[2].integer_reference;
7681           if (attribute_flag[3] != 0)
7682             frame_info.inner_bevel=argument_list[3].integer_reference;
7683           if (attribute_flag[4] != 0)
7684             frame_info.outer_bevel=argument_list[4].integer_reference;
7685           if (attribute_flag[5] != 0)
7686             QueryColorDatabase(argument_list[5].string_reference,&fill_color,
7687               exception);
7688           if (attribute_flag[6] != 0)
7689             QueryColorDatabase(argument_list[6].string_reference,&fill_color,
7690               exception);
7691           frame_info.x=(ssize_t) frame_info.width;
7692           frame_info.y=(ssize_t) frame_info.height;
7693           frame_info.width=image->columns+2*frame_info.x;
7694           frame_info.height=image->rows+2*frame_info.y;
7695           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
7696             image->matte_color=fill_color;
7697           compose=image->compose;
7698           if (attribute_flag[7] != 0)
7699             compose=(CompositeOperator) argument_list[7].integer_reference;
7700           image=FrameImage(image,&frame_info,compose,exception);
7701           break;
7702         }
7703         case 16:  /* Implode */
7704         {
7705           PixelInterpolateMethod
7706             method;
7707
7708           if (attribute_flag[0] == 0)
7709             argument_list[0].real_reference=0.5;
7710           method=UndefinedInterpolatePixel;
7711           if (attribute_flag[1] != 0)
7712             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
7713           image=ImplodeImage(image,argument_list[0].real_reference,
7714             method,exception);
7715           break;
7716         }
7717         case 17:  /* Magnify */
7718         {
7719           image=MagnifyImage(image,exception);
7720           break;
7721         }
7722         case 18:  /* MedianFilter */
7723         {
7724           if (attribute_flag[0] != 0)
7725             {
7726               flags=ParseGeometry(argument_list[0].string_reference,
7727                 &geometry_info);
7728               if ((flags & SigmaValue) == 0)
7729                 geometry_info.sigma=geometry_info.rho;
7730             }
7731           if (attribute_flag[1] != 0)
7732             geometry_info.rho=argument_list[1].real_reference;
7733           if (attribute_flag[2] != 0)
7734             geometry_info.sigma=argument_list[2].real_reference;
7735           if (attribute_flag[3] != 0)
7736             channel=(ChannelType) argument_list[3].integer_reference;
7737           channel_mask=SetPixelChannelMask(image,channel);
7738           image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
7739             (size_t) geometry_info.sigma,exception);
7740           if (image != (Image *) NULL)
7741             (void) SetPixelChannelMask(image,channel_mask);
7742           break;
7743         }
7744         case 19:  /* Minify */
7745         {
7746           image=MinifyImage(image,exception);
7747           break;
7748         }
7749         case 20:  /* OilPaint */
7750         {
7751           if (attribute_flag[0] == 0)
7752             argument_list[0].real_reference=0.0;
7753           if (attribute_flag[1] == 0)
7754             argument_list[1].real_reference=1.0;
7755           image=OilPaintImage(image,argument_list[0].real_reference,
7756             argument_list[1].real_reference,exception);
7757           break;
7758         }
7759         case 21:  /* ReduceNoise */
7760         {
7761           if (attribute_flag[0] != 0)
7762             {
7763               flags=ParseGeometry(argument_list[0].string_reference,
7764                 &geometry_info);
7765               if ((flags & SigmaValue) == 0)
7766                 geometry_info.sigma=1.0;
7767             }
7768           if (attribute_flag[1] != 0)
7769             geometry_info.rho=argument_list[1].real_reference;
7770           if (attribute_flag[2] != 0)
7771             geometry_info.sigma=argument_list[2].real_reference;
7772           if (attribute_flag[3] != 0)
7773             channel=(ChannelType) argument_list[3].integer_reference;
7774           channel_mask=SetPixelChannelMask(image,channel);
7775           image=StatisticImage(image,NonpeakStatistic,(size_t)
7776             geometry_info.rho,(size_t) geometry_info.sigma,exception);
7777           if (image != (Image *) NULL)
7778             (void) SetPixelChannelMask(image,channel_mask);
7779           break;
7780         }
7781         case 22:  /* Roll */
7782         {
7783           if (attribute_flag[0] != 0)
7784             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7785               &geometry,exception);
7786           if (attribute_flag[1] != 0)
7787             geometry.x=argument_list[1].integer_reference;
7788           if (attribute_flag[2] != 0)
7789             geometry.y=argument_list[2].integer_reference;
7790           image=RollImage(image,geometry.x,geometry.y,exception);
7791           break;
7792         }
7793         case 23:  /* Rotate */
7794         {
7795           if (attribute_flag[0] == 0)
7796             argument_list[0].real_reference=90.0;
7797           if (attribute_flag[1] != 0)
7798             QueryColorDatabase(argument_list[1].string_reference,
7799               &image->background_color,exception);
7800           if (attribute_flag[2] != 0)
7801             QueryColorDatabase(argument_list[2].string_reference,
7802               &image->background_color,exception);
7803           if (attribute_flag[3] != 0)
7804             QueryColorDatabase(argument_list[3].string_reference,
7805               &image->background_color,exception);
7806           image=RotateImage(image,argument_list[0].real_reference,exception);
7807           break;
7808         }
7809         case 24:  /* Sample */
7810         {
7811           if (attribute_flag[0] != 0)
7812             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7813               &geometry,exception);
7814           if (attribute_flag[1] != 0)
7815             geometry.width=argument_list[1].integer_reference;
7816           if (attribute_flag[2] != 0)
7817             geometry.height=argument_list[2].integer_reference;
7818           image=SampleImage(image,geometry.width,geometry.height,exception);
7819           break;
7820         }
7821         case 25:  /* Scale */
7822         {
7823           if (attribute_flag[0] != 0)
7824             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7825               &geometry,exception);
7826           if (attribute_flag[1] != 0)
7827             geometry.width=argument_list[1].integer_reference;
7828           if (attribute_flag[2] != 0)
7829             geometry.height=argument_list[2].integer_reference;
7830           image=ScaleImage(image,geometry.width,geometry.height,exception);
7831           break;
7832         }
7833         case 26:  /* Shade */
7834         {
7835           if (attribute_flag[0] != 0)
7836             {
7837               flags=ParseGeometry(argument_list[0].string_reference,
7838                 &geometry_info);
7839               if ((flags & SigmaValue) == 0)
7840                 geometry_info.sigma=0.0;
7841             }
7842           if (attribute_flag[1] != 0)
7843             geometry_info.rho=argument_list[1].real_reference;
7844           if (attribute_flag[2] != 0)
7845             geometry_info.sigma=argument_list[2].real_reference;
7846           image=ShadeImage(image,
7847             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
7848             geometry_info.rho,geometry_info.sigma,exception);
7849           break;
7850         }
7851         case 27:  /* Sharpen */
7852         {
7853           if (attribute_flag[0] != 0)
7854             {
7855               flags=ParseGeometry(argument_list[0].string_reference,
7856                 &geometry_info);
7857               if ((flags & SigmaValue) == 0)
7858                 geometry_info.sigma=1.0;
7859             }
7860           if (attribute_flag[1] != 0)
7861             geometry_info.rho=argument_list[1].real_reference;
7862           if (attribute_flag[2] != 0)
7863             geometry_info.sigma=argument_list[2].real_reference;
7864           if (attribute_flag[3] != 0)
7865             geometry_info.xi=argument_list[3].real_reference;
7866           if (attribute_flag[4] != 0)
7867             channel=(ChannelType) argument_list[4].integer_reference;
7868           channel_mask=SetPixelChannelMask(image,channel);
7869           image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
7870             geometry_info.xi,exception);
7871           if (image != (Image *) NULL)
7872             (void) SetPixelChannelMask(image,channel_mask);
7873           break;
7874         }
7875         case 28:  /* Shear */
7876         {
7877           if (attribute_flag[0] != 0)
7878             {
7879               flags=ParseGeometry(argument_list[0].string_reference,
7880                 &geometry_info);
7881               if ((flags & SigmaValue) == 0)
7882                 geometry_info.sigma=geometry_info.rho;
7883             }
7884           if (attribute_flag[1] != 0)
7885             geometry_info.rho=argument_list[1].real_reference;
7886           if (attribute_flag[2] != 0)
7887             geometry_info.sigma=argument_list[2].real_reference;
7888           if (attribute_flag[3] != 0)
7889             QueryColorDatabase(argument_list[3].string_reference,
7890               &image->background_color,exception);
7891           if (attribute_flag[4] != 0)
7892             QueryColorDatabase(argument_list[4].string_reference,
7893               &image->background_color,exception);
7894           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
7895             exception);
7896           break;
7897         }
7898         case 29:  /* Spread */
7899         {
7900           PixelInterpolateMethod
7901             method;
7902
7903           if (attribute_flag[0] == 0)
7904             argument_list[0].real_reference=1.0;
7905           method=UndefinedInterpolatePixel;
7906           if (attribute_flag[1] != 0)
7907             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
7908           image=SpreadImage(image,argument_list[0].real_reference,method,
7909             exception);
7910           break;
7911         }
7912         case 30:  /* Swirl */
7913         {
7914           PixelInterpolateMethod
7915             method;
7916
7917           if (attribute_flag[0] == 0)
7918             argument_list[0].real_reference=50.0;
7919           method=UndefinedInterpolatePixel;
7920           if (attribute_flag[1] != 0)
7921             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
7922           image=SwirlImage(image,argument_list[0].real_reference,
7923             method,exception);
7924           break;
7925         }
7926         case 31:  /* Resize */
7927         case 32:  /* Zoom */
7928         {
7929           if (attribute_flag[0] != 0)
7930             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7931               &geometry,exception);
7932           if (attribute_flag[1] != 0)
7933             geometry.width=argument_list[1].integer_reference;
7934           if (attribute_flag[2] != 0)
7935             geometry.height=argument_list[2].integer_reference;
7936           if (attribute_flag[3] == 0)
7937             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
7938           if (attribute_flag[4] != 0)
7939             SetImageArtifact(image,"filter:support",
7940               argument_list[4].string_reference);
7941           if (attribute_flag[5] == 0)
7942             argument_list[5].real_reference=1.0;
7943           image=ResizeImage(image,geometry.width,geometry.height,
7944             (FilterTypes) argument_list[3].integer_reference,
7945             argument_list[5].real_reference,exception);
7946           break;
7947         }
7948         case 33:  /* Annotate */
7949         {
7950           DrawInfo
7951             *draw_info;
7952
7953           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
7954             (DrawInfo *) NULL);
7955           if (attribute_flag[0] != 0)
7956             {
7957               char
7958                 *text;
7959
7960               text=InterpretImageProperties(info ? info->image_info :
7961                 (ImageInfo *) NULL,image,argument_list[0].string_reference,
7962                 exception);
7963               (void) CloneString(&draw_info->text,text);
7964               text=DestroyString(text);
7965             }
7966           if (attribute_flag[1] != 0)
7967             (void) CloneString(&draw_info->font,
7968               argument_list[1].string_reference);
7969           if (attribute_flag[2] != 0)
7970             draw_info->pointsize=argument_list[2].real_reference;
7971           if (attribute_flag[3] != 0)
7972             (void) CloneString(&draw_info->density,
7973               argument_list[3].string_reference);
7974           if (attribute_flag[4] != 0)
7975             (void) QueryColorDatabase(argument_list[4].string_reference,
7976               &draw_info->undercolor,exception);
7977           if (attribute_flag[5] != 0)
7978             {
7979               (void) QueryColorDatabase(argument_list[5].string_reference,
7980                 &draw_info->stroke,exception);
7981               if (argument_list[5].image_reference != (Image *) NULL)
7982                 draw_info->stroke_pattern=CloneImage(
7983                   argument_list[5].image_reference,0,0,MagickTrue,exception);
7984             }
7985           if (attribute_flag[6] != 0)
7986             {
7987               (void) QueryColorDatabase(argument_list[6].string_reference,
7988                 &draw_info->fill,exception);
7989               if (argument_list[6].image_reference != (Image *) NULL)
7990                 draw_info->fill_pattern=CloneImage(
7991                   argument_list[6].image_reference,0,0,MagickTrue,exception);
7992             }
7993           if (attribute_flag[7] != 0)
7994             {
7995               (void) CloneString(&draw_info->geometry,
7996                 argument_list[7].string_reference);
7997               flags=ParsePageGeometry(image,argument_list[7].string_reference,
7998                 &geometry,exception);
7999               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8000                 geometry_info.sigma=geometry_info.xi;
8001             }
8002           if (attribute_flag[8] != 0)
8003             (void) QueryColorDatabase(argument_list[8].string_reference,
8004               &draw_info->fill,exception);
8005           if (attribute_flag[11] != 0)
8006             draw_info->gravity=(GravityType) argument_list[11].integer_reference;
8007           if (attribute_flag[25] != 0)
8008             {
8009               AV
8010                 *av;
8011
8012               av=(AV *) argument_list[25].array_reference;
8013               if ((av_len(av) != 3) && (av_len(av) != 5))
8014                 {
8015                   ThrowPerlException(exception,OptionError,
8016                     "affine matrix must have 4 or 6 elements",PackageName);
8017                   goto PerlException;
8018                 }
8019               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8020               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8021               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8022               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8023               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8024                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8025                 {
8026                   ThrowPerlException(exception,OptionError,
8027                     "affine matrix is singular",PackageName);
8028                    goto PerlException;
8029                 }
8030               if (av_len(av) == 5)
8031                 {
8032                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8033                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8034                 }
8035             }
8036           for (j=12; j < 17; j++)
8037           {
8038             if (attribute_flag[j] == 0)
8039               continue;
8040             value=argument_list[j].string_reference;
8041             angle=argument_list[j].real_reference;
8042             current=draw_info->affine;
8043             GetAffineMatrix(&affine);
8044             switch (j)
8045             {
8046               case 12:
8047               {
8048                 /*
8049                   Translate.
8050                 */
8051                 flags=ParseGeometry(value,&geometry_info);
8052                 affine.tx=geometry_info.xi;
8053                 affine.ty=geometry_info.psi;
8054                 if ((flags & PsiValue) == 0)
8055                   affine.ty=affine.tx;
8056                 break;
8057               }
8058               case 13:
8059               {
8060                 /*
8061                   Scale.
8062                 */
8063                 flags=ParseGeometry(value,&geometry_info);
8064                 affine.sx=geometry_info.rho;
8065                 affine.sy=geometry_info.sigma;
8066                 if ((flags & SigmaValue) == 0)
8067                   affine.sy=affine.sx;
8068                 break;
8069               }
8070               case 14:
8071               {
8072                 /*
8073                   Rotate.
8074                 */
8075                 if (angle == 0.0)
8076                   break;
8077                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8078                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8079                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8080                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8081                 break;
8082               }
8083               case 15:
8084               {
8085                 /*
8086                   SkewX.
8087                 */
8088                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8089                 break;
8090               }
8091               case 16:
8092               {
8093                 /*
8094                   SkewY.
8095                 */
8096                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8097                 break;
8098               }
8099             }
8100             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8101             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8102             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8103             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8104             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8105               current.tx;
8106             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8107               current.ty;
8108           }
8109           if (attribute_flag[9] == 0)
8110             argument_list[9].real_reference=0.0;
8111           if (attribute_flag[10] == 0)
8112             argument_list[10].real_reference=0.0;
8113           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8114             {
8115               char
8116                 geometry[MaxTextExtent];
8117
8118               (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
8119                 (double) argument_list[9].real_reference+draw_info->affine.tx,
8120                 (double) argument_list[10].real_reference+draw_info->affine.ty);
8121               (void) CloneString(&draw_info->geometry,geometry);
8122             }
8123           if (attribute_flag[17] != 0)
8124             draw_info->stroke_width=argument_list[17].real_reference;
8125           if (attribute_flag[18] != 0)
8126             {
8127               draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8128                 MagickTrue : MagickFalse;
8129               draw_info->stroke_antialias=draw_info->text_antialias;
8130             }
8131           if (attribute_flag[19] != 0)
8132             (void) CloneString(&draw_info->family,
8133               argument_list[19].string_reference);
8134           if (attribute_flag[20] != 0)
8135             draw_info->style=(StyleType) argument_list[20].integer_reference;
8136           if (attribute_flag[21] != 0)
8137             draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8138           if (attribute_flag[22] != 0)
8139             draw_info->weight=argument_list[22].integer_reference;
8140           if (attribute_flag[23] != 0)
8141             draw_info->align=(AlignType) argument_list[23].integer_reference;
8142           if (attribute_flag[24] != 0)
8143             (void) CloneString(&draw_info->encoding,
8144               argument_list[24].string_reference);
8145           if (attribute_flag[25] != 0)
8146             draw_info->fill_pattern=CloneImage(
8147               argument_list[25].image_reference,0,0,MagickTrue,exception);
8148           if (attribute_flag[26] != 0)
8149             draw_info->fill_pattern=CloneImage(
8150               argument_list[26].image_reference,0,0,MagickTrue,exception);
8151           if (attribute_flag[27] != 0)
8152             draw_info->stroke_pattern=CloneImage(
8153               argument_list[27].image_reference,0,0,MagickTrue,exception);
8154           if (attribute_flag[29] != 0)
8155             draw_info->kerning=argument_list[29].real_reference;
8156           if (attribute_flag[30] != 0)
8157             draw_info->interline_spacing=argument_list[30].real_reference;
8158           if (attribute_flag[31] != 0)
8159             draw_info->interword_spacing=argument_list[31].real_reference;
8160           if (attribute_flag[32] != 0)
8161             draw_info->direction=(DirectionType)
8162               argument_list[32].integer_reference;
8163           (void) AnnotateImage(image,draw_info,exception);
8164           draw_info=DestroyDrawInfo(draw_info);
8165           break;
8166         }
8167         case 34:  /* ColorFloodfill */
8168         {
8169           DrawInfo
8170             *draw_info;
8171
8172           MagickBooleanType
8173             invert;
8174
8175           PixelInfo
8176             target;
8177
8178           draw_info=CloneDrawInfo(info ? info->image_info :
8179             (ImageInfo *) NULL,(DrawInfo *) NULL);
8180           if (attribute_flag[0] != 0)
8181             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8182               &geometry,exception);
8183           if (attribute_flag[1] != 0)
8184             geometry.x=argument_list[1].integer_reference;
8185           if (attribute_flag[2] != 0)
8186             geometry.y=argument_list[2].integer_reference;
8187           if (attribute_flag[3] != 0)
8188             (void) QueryColorDatabase(argument_list[3].string_reference,
8189               &draw_info->fill,exception);
8190           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
8191             exception);
8192           invert=MagickFalse;
8193           if (attribute_flag[4] != 0)
8194             {
8195               QueryMagickColor(argument_list[4].string_reference,&target,
8196                 exception);
8197               invert=MagickTrue;
8198             }
8199           if (attribute_flag[5] != 0)
8200             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
8201               QuantumRange);
8202           if (attribute_flag[6] != 0)
8203             invert=(MagickBooleanType) argument_list[6].integer_reference;
8204           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8205             geometry.y,invert,exception);
8206           draw_info=DestroyDrawInfo(draw_info);
8207           break;
8208         }
8209         case 35:  /* Composite */
8210         {
8211           char
8212             composite_geometry[MaxTextExtent];
8213
8214           Image
8215             *composite_image,
8216             *rotate_image;
8217
8218           compose=OverCompositeOp;
8219           if (attribute_flag[0] != 0)
8220             composite_image=argument_list[0].image_reference;
8221           else
8222             {
8223               ThrowPerlException(exception,OptionError,
8224                 "CompositeImageRequired",PackageName);
8225               goto PerlException;
8226             }
8227           /*
8228             Parameter Handling used for BOTH normal and tiled composition.
8229           */
8230           if (attribute_flag[1] != 0) /* compose */
8231             compose=(CompositeOperator) argument_list[1].integer_reference;
8232           if (attribute_flag[6] != 0) /* opacity  */
8233             {
8234               if (compose != DissolveCompositeOp)
8235                 (void) SetImageOpacity(composite_image,(Quantum)
8236                   SiPrefixToDouble(argument_list[6].string_reference,
8237                   QuantumRange));
8238               else
8239                 {
8240                   CacheView
8241                     *composite_view;
8242
8243                   double
8244                     opacity;
8245
8246                   MagickBooleanType
8247                     sync;
8248
8249                   register ssize_t
8250                     x;
8251
8252                   register Quantum
8253                     *q;
8254
8255                   ssize_t
8256                     y;
8257
8258                   /*
8259                     Handle dissolve composite operator (patch by
8260                     Kevin A. McGrail).
8261                   */
8262                   (void) CloneString(&image->geometry,
8263                     argument_list[6].string_reference);
8264                   opacity=(Quantum) SiPrefixToDouble(
8265                     argument_list[6].string_reference,QuantumRange);
8266                   if (composite_image->matte != MagickTrue)
8267                     (void) SetImageOpacity(composite_image,OpaqueAlpha);
8268                   composite_view=AcquireCacheView(composite_image);
8269                   for (y=0; y < (ssize_t) composite_image->rows ; y++)
8270                   {
8271                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8272                       composite_image->columns,1,exception);
8273                     for (x=0; x < (ssize_t) composite_image->columns; x++)
8274                     {
8275                       if (GetPixelAlpha(image,q) == OpaqueAlpha)
8276                         SetPixelAlpha(composite_image,ClampToQuantum(opacity),q);
8277                       q+=GetPixelChannels(composite_image);
8278                     }
8279                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8280                     if (sync == MagickFalse)
8281                       break;
8282                   }
8283                   composite_view=DestroyCacheView(composite_view);
8284                 }
8285             }
8286           if (attribute_flag[9] != 0)    /* "color=>" */
8287             QueryColorDatabase(argument_list[9].string_reference,
8288               &composite_image->background_color,exception);
8289           if (attribute_flag[12] != 0) /* "interpolate=>" */
8290             image->interpolate=(PixelInterpolateMethod)
8291               argument_list[12].integer_reference;
8292           if (attribute_flag[13] != 0)   /* "args=>" */
8293             (void) SetImageArtifact(composite_image,"compose:args",
8294               argument_list[13].string_reference);
8295           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8296             (void) SetImageArtifact(composite_image,"compose:args",
8297               argument_list[14].string_reference);
8298           /*
8299             Tiling Composition (with orthogonal rotate).
8300           */
8301           rotate_image=(Image *) NULL;
8302           if (attribute_flag[8] != 0)   /* "rotate=>" */
8303             {
8304                /*
8305                  Rotate image.
8306                */
8307                rotate_image=RotateImage(composite_image,
8308                  argument_list[8].real_reference,exception);
8309                if (rotate_image == (Image *) NULL)
8310                  break;
8311             }
8312           if (attribute_flag[7] && argument_list[7].integer_reference) /* tile */
8313             {
8314               ssize_t
8315                 x,
8316                 y;
8317
8318               /*
8319                 Tile the composite image.
8320               */
8321              if (attribute_flag[8] != 0)   /* "tile=>" */
8322                (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8323                  "false");
8324              else
8325                (void) SetImageArtifact(composite_image,
8326                  "compose:outside-overlay","false");
8327              for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8328                 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8329                 {
8330                   if (attribute_flag[8] != 0) /* rotate */
8331                     (void) CompositeImage(image,compose,rotate_image,x,y);
8332                   else
8333                     (void) CompositeImage(image,compose,composite_image,x,y);
8334                 }
8335               if (attribute_flag[8] != 0) /* rotate */
8336                 rotate_image=DestroyImage(rotate_image);
8337               break;
8338             }
8339           /*
8340             Parameter Handling used used ONLY for normal composition.
8341           */
8342           if (attribute_flag[5] != 0) /* gravity */
8343             image->gravity=(GravityType) argument_list[5].integer_reference;
8344           if (attribute_flag[2] != 0) /* geometry offset */
8345             {
8346               SetGeometry(image,&geometry);
8347               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8348                 &geometry);
8349               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8350                 &geometry);
8351             }
8352           if (attribute_flag[3] != 0) /* x offset */
8353             geometry.x=argument_list[3].integer_reference;
8354           if (attribute_flag[4] != 0) /* y offset */
8355             geometry.y=argument_list[4].integer_reference;
8356           if (attribute_flag[10] != 0) /* mask */
8357             {
8358               if ((image->compose == DisplaceCompositeOp) ||
8359                   (image->compose == DistortCompositeOp))
8360                 {
8361                   /*
8362                     Merge Y displacement into X displacement image.
8363                   */
8364                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8365                     &image->exception);
8366                   (void) CompositeImage(composite_image,CopyGreenCompositeOp,
8367                     argument_list[10].image_reference,0,0);
8368                 }
8369               else
8370                 {
8371                   /*
8372                     Set a blending mask for the composition.
8373                   */
8374                   image->mask=CloneImage(argument_list[10].image_reference,0,0,
8375                     MagickTrue,&image->exception);
8376                   (void) NegateImage(image->mask,MagickFalse,exception);
8377                 }
8378             }
8379           if (attribute_flag[11] != 0) /* channel */
8380             channel=(ChannelType) argument_list[11].integer_reference;
8381           /*
8382             Composite two images (normal composition).
8383           */
8384           (void) FormatLocaleString(composite_geometry,MaxTextExtent,
8385             "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8386             (double) composite_image->rows,(double) geometry.x,(double)
8387             geometry.y);
8388           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8389             exception);
8390           channel_mask=SetPixelChannelMask(image,channel);
8391           if (attribute_flag[8] == 0) /* no rotate */
8392             CompositeImage(image,compose,composite_image,geometry.x,geometry.y);
8393           else
8394             {
8395               /*
8396                 Position adjust rotated image then composite.
8397               */
8398               geometry.x-=(ssize_t) (rotate_image->columns-
8399                 composite_image->columns)/2;
8400               geometry.y-=(ssize_t) (rotate_image->rows-
8401                 composite_image->rows)/2;
8402               CompositeImage(image,compose,rotate_image,geometry.x,geometry.y);
8403               rotate_image=DestroyImage(rotate_image);
8404             }
8405           if (attribute_flag[10] != 0) /* mask */
8406             {
8407               if ((image->compose == DisplaceCompositeOp) ||
8408                   (image->compose == DistortCompositeOp))
8409                 composite_image=DestroyImage(composite_image);
8410               else
8411                 image->mask=DestroyImage(image->mask);
8412             }
8413           (void) SetPixelChannelMask(image,channel_mask);
8414           break;
8415         }
8416         case 36:  /* Contrast */
8417         {
8418           if (attribute_flag[0] == 0)
8419             argument_list[0].integer_reference=0;
8420           (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8421             MagickTrue : MagickFalse,exception);
8422           break;
8423         }
8424         case 37:  /* CycleColormap */
8425         {
8426           if (attribute_flag[0] == 0)
8427             argument_list[0].integer_reference=6;
8428           (void) CycleColormapImage(image,argument_list[0].integer_reference,
8429             exception);
8430           break;
8431         }
8432         case 38:  /* Draw */
8433         {
8434           DrawInfo
8435             *draw_info;
8436
8437           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8438             (DrawInfo *) NULL);
8439           (void) CloneString(&draw_info->primitive,"point");
8440           if (attribute_flag[0] != 0)
8441             {
8442               if (argument_list[0].integer_reference < 0)
8443                 (void) CloneString(&draw_info->primitive,
8444                   argument_list[0].string_reference);
8445               else
8446                 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8447                   MagickPrimitiveOptions,argument_list[0].integer_reference));
8448             }
8449           if (attribute_flag[1] != 0)
8450             {
8451               if (LocaleCompare(draw_info->primitive,"path") == 0)
8452                 {
8453                   (void) ConcatenateString(&draw_info->primitive," '");
8454                   ConcatenateString(&draw_info->primitive,
8455                     argument_list[1].string_reference);
8456                   (void) ConcatenateString(&draw_info->primitive,"'");
8457                 }
8458               else
8459                 {
8460                   (void) ConcatenateString(&draw_info->primitive," ");
8461                   ConcatenateString(&draw_info->primitive,
8462                     argument_list[1].string_reference);
8463                 }
8464             }
8465           if (attribute_flag[2] != 0)
8466             {
8467               (void) ConcatenateString(&draw_info->primitive," ");
8468               (void) ConcatenateString(&draw_info->primitive,
8469                 CommandOptionToMnemonic(MagickMethodOptions,
8470                 argument_list[2].integer_reference));
8471             }
8472           if (attribute_flag[3] != 0)
8473             {
8474               (void) QueryColorDatabase(argument_list[3].string_reference,
8475                 &draw_info->stroke,exception);
8476               if (argument_list[3].image_reference != (Image *) NULL)
8477                 draw_info->stroke_pattern=CloneImage(
8478                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8479             }
8480           if (attribute_flag[4] != 0)
8481             {
8482               (void) QueryColorDatabase(argument_list[4].string_reference,
8483                 &draw_info->fill,exception);
8484               if (argument_list[4].image_reference != (Image *) NULL)
8485                 draw_info->fill_pattern=CloneImage(
8486                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8487             }
8488           if (attribute_flag[5] != 0)
8489             draw_info->stroke_width=argument_list[5].real_reference;
8490           if (attribute_flag[6] != 0)
8491             (void) CloneString(&draw_info->font,
8492               argument_list[6].string_reference);
8493           if (attribute_flag[7] != 0)
8494             (void) QueryColorDatabase(argument_list[7].string_reference,
8495               &draw_info->border_color,exception);
8496           if (attribute_flag[8] != 0)
8497             draw_info->affine.tx=argument_list[8].real_reference;
8498           if (attribute_flag[9] != 0)
8499             draw_info->affine.ty=argument_list[9].real_reference;
8500           if (attribute_flag[20] != 0)
8501             {
8502               AV
8503                 *av;
8504
8505               av=(AV *) argument_list[20].array_reference;
8506               if ((av_len(av) != 3) && (av_len(av) != 5))
8507                 {
8508                   ThrowPerlException(exception,OptionError,
8509                     "affine matrix must have 4 or 6 elements",PackageName);
8510                   goto PerlException;
8511                 }
8512               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8513               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8514               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8515               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8516               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8517                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8518                 {
8519                   ThrowPerlException(exception,OptionError,
8520                     "affine matrix is singular",PackageName);
8521                    goto PerlException;
8522                 }
8523               if (av_len(av) == 5)
8524                 {
8525                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8526                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8527                 }
8528             }
8529           for (j=10; j < 15; j++)
8530           {
8531             if (attribute_flag[j] == 0)
8532               continue;
8533             value=argument_list[j].string_reference;
8534             angle=argument_list[j].real_reference;
8535             current=draw_info->affine;
8536             GetAffineMatrix(&affine);
8537             switch (j)
8538             {
8539               case 10:
8540               {
8541                 /*
8542                   Translate.
8543                 */
8544                 flags=ParseGeometry(value,&geometry_info);
8545                 affine.tx=geometry_info.xi;
8546                 affine.ty=geometry_info.psi;
8547                 if ((flags & PsiValue) == 0)
8548                   affine.ty=affine.tx;
8549                 break;
8550               }
8551               case 11:
8552               {
8553                 /*
8554                   Scale.
8555                 */
8556                 flags=ParseGeometry(value,&geometry_info);
8557                 affine.sx=geometry_info.rho;
8558                 affine.sy=geometry_info.sigma;
8559                 if ((flags & SigmaValue) == 0)
8560                   affine.sy=affine.sx;
8561                 break;
8562               }
8563               case 12:
8564               {
8565                 /*
8566                   Rotate.
8567                 */
8568                 if (angle == 0.0)
8569                   break;
8570                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8571                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8572                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8573                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8574                 break;
8575               }
8576               case 13:
8577               {
8578                 /*
8579                   SkewX.
8580                 */
8581                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8582                 break;
8583               }
8584               case 14:
8585               {
8586                 /*
8587                   SkewY.
8588                 */
8589                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8590                 break;
8591               }
8592             }
8593             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8594             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8595             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8596             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8597             draw_info->affine.tx=
8598               current.sx*affine.tx+current.ry*affine.ty+current.tx;
8599             draw_info->affine.ty=
8600               current.rx*affine.tx+current.sy*affine.ty+current.ty;
8601           }
8602           if (attribute_flag[15] != 0)
8603             draw_info->fill_pattern=CloneImage(
8604               argument_list[15].image_reference,0,0,MagickTrue,exception);
8605           if (attribute_flag[16] != 0)
8606             draw_info->pointsize=argument_list[16].real_reference;
8607           if (attribute_flag[17] != 0)
8608             {
8609               draw_info->stroke_antialias=argument_list[17].integer_reference != 0
8610                 ? MagickTrue : MagickFalse;
8611               draw_info->text_antialias=draw_info->stroke_antialias;
8612             }
8613           if (attribute_flag[18] != 0)
8614             (void) CloneString(&draw_info->density,
8615               argument_list[18].string_reference);
8616           if (attribute_flag[19] != 0)
8617             draw_info->stroke_width=argument_list[19].real_reference;
8618           if (attribute_flag[21] != 0)
8619             draw_info->dash_offset=argument_list[21].real_reference;
8620           if (attribute_flag[22] != 0)
8621             {
8622               AV
8623                 *av;
8624
8625               av=(AV *) argument_list[22].array_reference;
8626               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
8627                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
8628               if (draw_info->dash_pattern != (double *) NULL)
8629                 {
8630                   for (i=0; i <= av_len(av); i++)
8631                     draw_info->dash_pattern[i]=(double)
8632                       SvNV(*(av_fetch(av,i,0)));
8633                   draw_info->dash_pattern[i]=0.0;
8634                 }
8635             }
8636           if (attribute_flag[23] != 0)
8637             image->interpolate=(PixelInterpolateMethod)
8638               argument_list[23].integer_reference;
8639           if ((attribute_flag[24] != 0) &&
8640               (draw_info->fill_pattern != (Image *) NULL))
8641             flags=ParsePageGeometry(draw_info->fill_pattern,
8642               argument_list[24].string_reference,
8643               &draw_info->fill_pattern->tile_offset,exception);
8644           if (attribute_flag[25] != 0)
8645             {
8646               (void) ConcatenateString(&draw_info->primitive," '");
8647               (void) ConcatenateString(&draw_info->primitive,
8648                 argument_list[25].string_reference);
8649               (void) ConcatenateString(&draw_info->primitive,"'");
8650             }
8651           if (attribute_flag[26] != 0)
8652             draw_info->fill_pattern=CloneImage(
8653               argument_list[26].image_reference,0,0,MagickTrue,exception);
8654           if (attribute_flag[27] != 0)
8655             draw_info->stroke_pattern=CloneImage(
8656               argument_list[27].image_reference,0,0,MagickTrue,exception);
8657           if (attribute_flag[28] != 0)
8658             (void) CloneString(&draw_info->primitive,
8659               argument_list[28].string_reference);
8660           if (attribute_flag[29] != 0)
8661             draw_info->kerning=argument_list[29].real_reference;
8662           if (attribute_flag[30] != 0)
8663             draw_info->interline_spacing=argument_list[30].real_reference;
8664           if (attribute_flag[31] != 0)
8665             draw_info->interword_spacing=argument_list[31].real_reference;
8666           if (attribute_flag[32] != 0)
8667             draw_info->direction=(DirectionType)
8668               argument_list[32].integer_reference;
8669           DrawImage(image,draw_info,exception);
8670           draw_info=DestroyDrawInfo(draw_info);
8671           break;
8672         }
8673         case 39:  /* Equalize */
8674         {
8675           if (attribute_flag[0] != 0)
8676             channel=(ChannelType) argument_list[0].integer_reference;
8677           channel_mask=SetPixelChannelMask(image,channel);
8678           EqualizeImage(image,exception);
8679           (void) SetPixelChannelMask(image,channel_mask);
8680           break;
8681         }
8682         case 40:  /* Gamma */
8683         {
8684           if (attribute_flag[1] != 0)
8685             channel=(ChannelType) argument_list[1].integer_reference;
8686           if (attribute_flag[2] == 0)
8687             argument_list[2].real_reference=1.0;
8688           if (attribute_flag[3] == 0)
8689             argument_list[3].real_reference=1.0;
8690           if (attribute_flag[4] == 0)
8691             argument_list[4].real_reference=1.0;
8692           if (attribute_flag[0] == 0)
8693             {
8694               (void) FormatLocaleString(message,MaxTextExtent,
8695                 "%.15g,%.15g,%.15g",(double) argument_list[2].real_reference,
8696                 (double) argument_list[3].real_reference,
8697                 (double) argument_list[4].real_reference);
8698               argument_list[0].string_reference=message;
8699             }
8700           (void) GammaImage(image,InterpretLocaleValue(
8701             argument_list[0].string_reference,(char **) NULL),exception);
8702           break;
8703         }
8704         case 41:  /* Map */
8705         {
8706           QuantizeInfo
8707             *quantize_info;
8708
8709           if (attribute_flag[0] == 0)
8710             {
8711               ThrowPerlException(exception,OptionError,"MapImageRequired",
8712                 PackageName);
8713               goto PerlException;
8714             }
8715           quantize_info=AcquireQuantizeInfo(info->image_info);
8716           if (attribute_flag[1] != 0)
8717             quantize_info->dither=(MagickBooleanType)
8718               argument_list[1].integer_reference;
8719           if (attribute_flag[2] != 0)
8720             quantize_info->dither_method=(DitherMethod)
8721               argument_list[2].integer_reference;
8722           (void) RemapImages(quantize_info,image,
8723             argument_list[0].image_reference,exception);
8724           quantize_info=DestroyQuantizeInfo(quantize_info);
8725           break;
8726         }
8727         case 42:  /* MatteFloodfill */
8728         {
8729           DrawInfo
8730             *draw_info;
8731
8732           MagickBooleanType
8733             invert;
8734
8735           PixelInfo
8736             target;
8737
8738           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8739             (DrawInfo *) NULL);
8740           if (attribute_flag[0] != 0)
8741             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8742               &geometry,exception);
8743           if (attribute_flag[1] != 0)
8744             geometry.x=argument_list[1].integer_reference;
8745           if (attribute_flag[2] != 0)
8746             geometry.y=argument_list[2].integer_reference;
8747           if (image->matte == MagickFalse)
8748             (void) SetImageOpacity(image,OpaqueAlpha);
8749           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
8750             exception);
8751           if (attribute_flag[4] != 0)
8752             QueryMagickColor(argument_list[4].string_reference,&target,
8753               exception);
8754           if (attribute_flag[3] != 0)
8755             target.alpha=SiPrefixToDouble(argument_list[3].string_reference,
8756               QuantumRange);
8757           if (attribute_flag[5] != 0)
8758             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
8759               QuantumRange);
8760           invert=MagickFalse;
8761           if (attribute_flag[6] != 0)
8762             invert=(MagickBooleanType) argument_list[6].integer_reference;
8763           channel_mask=SetPixelChannelMask(image,AlphaChannel);
8764           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8765             geometry.y,invert,exception);
8766           (void) SetPixelChannelMask(image,channel_mask);
8767           draw_info=DestroyDrawInfo(draw_info);
8768           break;
8769         }
8770         case 43:  /* Modulate */
8771         {
8772           char
8773             modulate[MaxTextExtent];
8774
8775           geometry_info.rho=100.0;
8776           geometry_info.sigma=100.0;
8777           geometry_info.xi=100.0;
8778           if (attribute_flag[0] != 0)
8779             (void)ParseGeometry(argument_list[0].string_reference,
8780               &geometry_info);
8781           if (attribute_flag[1] != 0)
8782             geometry_info.xi=argument_list[1].real_reference;
8783           if (attribute_flag[2] != 0)
8784             geometry_info.sigma=argument_list[2].real_reference;
8785           if (attribute_flag[3] != 0)
8786             {
8787               geometry_info.sigma=argument_list[3].real_reference;
8788               SetImageArtifact(image,"modulate:colorspace","HWB");
8789             }
8790           if (attribute_flag[4] != 0)
8791             {
8792               geometry_info.rho=argument_list[4].real_reference;
8793               SetImageArtifact(image,"modulate:colorspace","HSB");
8794             }
8795           if (attribute_flag[5] != 0)
8796             {
8797               geometry_info.sigma=argument_list[5].real_reference;
8798               SetImageArtifact(image,"modulate:colorspace","HSL");
8799             }
8800           if (attribute_flag[6] != 0)
8801             {
8802               geometry_info.rho=argument_list[6].real_reference;
8803               SetImageArtifact(image,"modulate:colorspace","HWB");
8804             }
8805           (void) FormatLocaleString(modulate,MaxTextExtent,"%.15g,%.15g,%.15g",
8806             geometry_info.rho,geometry_info.sigma,geometry_info.xi);
8807           (void) ModulateImage(image,modulate,exception);
8808           break;
8809         }
8810         case 44:  /* Negate */
8811         {
8812           if (attribute_flag[0] == 0)
8813             argument_list[0].integer_reference=0;
8814           if (attribute_flag[1] != 0)
8815             channel=(ChannelType) argument_list[1].integer_reference;
8816           channel_mask=SetPixelChannelMask(image,channel);
8817           (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
8818             MagickTrue : MagickFalse,exception);
8819           (void) SetPixelChannelMask(image,channel_mask);
8820           break;
8821         }
8822         case 45:  /* Normalize */
8823         {
8824           if (attribute_flag[0] != 0)
8825             channel=(ChannelType) argument_list[0].integer_reference;
8826           channel_mask=SetPixelChannelMask(image,channel);
8827           NormalizeImage(image,exception);
8828           (void) SetPixelChannelMask(image,channel_mask);
8829           break;
8830         }
8831         case 46:  /* NumberColors */
8832           break;
8833         case 47:  /* Opaque */
8834         {
8835           MagickBooleanType
8836             invert;
8837
8838           PixelInfo
8839             fill_color,
8840             target;
8841
8842           (void) QueryMagickColor("none",&target,exception);
8843           (void) QueryMagickColor("none",&fill_color,exception);
8844           if (attribute_flag[0] != 0)
8845             (void) QueryMagickColor(argument_list[0].string_reference,
8846               &target,exception);
8847           if (attribute_flag[1] != 0)
8848             (void) QueryMagickColor(argument_list[1].string_reference,
8849               &fill_color,exception);
8850           if (attribute_flag[2] != 0)
8851             image->fuzz=SiPrefixToDouble(argument_list[2].string_reference,
8852               QuantumRange);
8853           if (attribute_flag[3] != 0)
8854             channel=(ChannelType) argument_list[3].integer_reference;
8855           invert=MagickFalse;
8856           if (attribute_flag[4] != 0)
8857             invert=(MagickBooleanType) argument_list[4].integer_reference;
8858           channel_mask=SetPixelChannelMask(image,channel);
8859           (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
8860           (void) SetPixelChannelMask(image,channel_mask);
8861           break;
8862         }
8863         case 48:  /* Quantize */
8864         {
8865           QuantizeInfo
8866             *quantize_info;
8867
8868           quantize_info=AcquireQuantizeInfo(info->image_info);
8869           if (attribute_flag[0] != 0)
8870             quantize_info->number_colors=(size_t)
8871               argument_list[0].integer_reference;
8872           if (attribute_flag[1] != 0)
8873             quantize_info->tree_depth=(size_t)
8874               argument_list[1].integer_reference;
8875           if (attribute_flag[2] != 0)
8876             quantize_info->colorspace=(ColorspaceType)
8877               argument_list[2].integer_reference;
8878           if (attribute_flag[3] != 0)
8879             quantize_info->dither=argument_list[3].integer_reference != 0 ?
8880               MagickTrue : MagickFalse;
8881           if (attribute_flag[4] != 0)
8882             quantize_info->measure_error=
8883               argument_list[4].integer_reference != 0 ? MagickTrue : MagickFalse;
8884           if (attribute_flag[5] != 0)
8885             (void) QueryColorDatabase(argument_list[5].string_reference,
8886               &image->transparent_color,exception);
8887           if (attribute_flag[5] && argument_list[5].integer_reference)
8888             {
8889               (void) QuantizeImages(quantize_info,image,exception);
8890               goto PerlException;
8891             }
8892           if (attribute_flag[6] != 0)
8893             quantize_info->dither_method=(DitherMethod)
8894               argument_list[6].integer_reference;
8895           if ((image->storage_class == DirectClass) ||
8896               (image->colors > quantize_info->number_colors) ||
8897               (quantize_info->colorspace == GRAYColorspace))
8898             (void) QuantizeImage(quantize_info,image,exception);
8899           else
8900             CompressImageColormap(image,exception);
8901           quantize_info=DestroyQuantizeInfo(quantize_info);
8902           break;
8903         }
8904         case 49:  /* Raise */
8905         {
8906           if (attribute_flag[0] != 0)
8907             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8908               &geometry,exception);
8909           if (attribute_flag[1] != 0)
8910             geometry.width=argument_list[1].integer_reference;
8911           if (attribute_flag[2] != 0)
8912             geometry.height=argument_list[2].integer_reference;
8913           if (attribute_flag[3] == 0)
8914             argument_list[3].integer_reference=1;
8915           (void) RaiseImage(image,&geometry,
8916             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8917             exception);
8918           break;
8919         }
8920         case 50:  /* Segment */
8921         {
8922           ColorspaceType
8923             colorspace;
8924
8925           double
8926             cluster_threshold,
8927             smoothing_threshold;
8928
8929           MagickBooleanType
8930             verbose;
8931
8932           cluster_threshold=1.0;
8933           smoothing_threshold=1.5;
8934           colorspace=RGBColorspace;
8935           verbose=MagickFalse;
8936           if (attribute_flag[0] != 0)
8937             {
8938               flags=ParseGeometry(argument_list[0].string_reference,
8939                 &geometry_info);
8940               cluster_threshold=geometry_info.rho;
8941               if (flags & SigmaValue)
8942                 smoothing_threshold=geometry_info.sigma;
8943             }
8944           if (attribute_flag[1] != 0)
8945             cluster_threshold=argument_list[1].real_reference;
8946           if (attribute_flag[2] != 0)
8947             smoothing_threshold=argument_list[2].real_reference;
8948           if (attribute_flag[3] != 0)
8949             colorspace=(ColorspaceType) argument_list[3].integer_reference;
8950           if (attribute_flag[4] != 0)
8951             verbose=argument_list[4].integer_reference != 0 ?
8952               MagickTrue : MagickFalse;
8953           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
8954             smoothing_threshold,exception);
8955           break;
8956         }
8957         case 51:  /* Signature */
8958         {
8959           (void) SignatureImage(image,exception);
8960           break;
8961         }
8962         case 52:  /* Solarize */
8963         {
8964           geometry_info.rho=QuantumRange/2.0;
8965           if (attribute_flag[0] != 0)
8966             flags=ParseGeometry(argument_list[0].string_reference,
8967               &geometry_info);
8968           if (attribute_flag[1] != 0)
8969             geometry_info.rho=SiPrefixToDouble(
8970              argument_list[1].string_reference,QuantumRange);
8971           (void) SolarizeImage(image,geometry_info.rho,exception);
8972           break;
8973         }
8974         case 53:  /* Sync */
8975         {
8976           (void) SyncImage(image);
8977           break;
8978         }
8979         case 54:  /* Texture */
8980         {
8981           if (attribute_flag[0] == 0)
8982             break;
8983           TextureImage(image,argument_list[0].image_reference);
8984           break;
8985         }
8986         case 55:  /* Evalute */
8987         {
8988           MagickEvaluateOperator
8989             op;
8990
8991           op=SetEvaluateOperator;
8992           if (attribute_flag[0] == MagickFalse)
8993             argument_list[0].real_reference=0.0;
8994           if (attribute_flag[1] != MagickFalse)
8995             op=(MagickEvaluateOperator) argument_list[1].integer_reference;
8996           if (attribute_flag[2] != MagickFalse)
8997             channel=(ChannelType) argument_list[2].integer_reference;
8998           channel_mask=SetPixelChannelMask(image,channel);
8999           (void) EvaluateImage(image,op,argument_list[0].real_reference,
9000             exception);
9001           (void) SetPixelChannelMask(image,channel_mask);
9002           break;
9003         }
9004         case 56:  /* Transparent */
9005         {
9006           double
9007             opacity;
9008
9009           MagickBooleanType
9010             invert;
9011
9012           PixelInfo
9013             target;
9014
9015           (void) QueryMagickColor("none",&target,exception);
9016           if (attribute_flag[0] != 0)
9017             (void) QueryMagickColor(argument_list[0].string_reference,&target,
9018               exception);
9019           opacity=TransparentAlpha;
9020           if (attribute_flag[1] != 0)
9021             opacity=SiPrefixToDouble(argument_list[1].string_reference,
9022               QuantumRange);
9023           if (attribute_flag[2] != 0)
9024             image->fuzz=SiPrefixToDouble(argument_list[2].string_reference,
9025               QuantumRange);
9026           if (attribute_flag[3] == 0)
9027             argument_list[3].integer_reference=0;
9028           invert=MagickFalse;
9029           if (attribute_flag[3] != 0)
9030             invert=(MagickBooleanType) argument_list[3].integer_reference;
9031           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9032             invert,exception);
9033           break;
9034         }
9035         case 57:  /* Threshold */
9036         {
9037           double
9038             threshold;
9039
9040           if (attribute_flag[0] == 0)
9041             argument_list[0].string_reference="50%";
9042           if (attribute_flag[1] != 0)
9043             channel=(ChannelType) argument_list[1].integer_reference;
9044           threshold=SiPrefixToDouble(argument_list[0].string_reference,
9045             QuantumRange);
9046           channel_mask=SetPixelChannelMask(image,channel);
9047           (void) BilevelImage(image,threshold);
9048           (void) SetPixelChannelMask(image,channel_mask);
9049           break;
9050         }
9051         case 58:  /* Charcoal */
9052         {
9053           if (attribute_flag[0] != 0)
9054             {
9055               flags=ParseGeometry(argument_list[0].string_reference,
9056                 &geometry_info);
9057               if ((flags & SigmaValue) == 0)
9058                 geometry_info.sigma=1.0;
9059             }
9060           if (attribute_flag[1] != 0)
9061             geometry_info.rho=argument_list[1].real_reference;
9062           if (attribute_flag[2] != 0)
9063             geometry_info.sigma=argument_list[2].real_reference;
9064           if (attribute_flag[3] != 0)
9065             geometry_info.xi=argument_list[3].real_reference;
9066           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9067             geometry_info.xi,exception);
9068           break;
9069         }
9070         case 59:  /* Trim */
9071         {
9072           if (attribute_flag[0] != 0)
9073             image->fuzz=SiPrefixToDouble(argument_list[0].string_reference,
9074               QuantumRange);
9075           image=TrimImage(image,exception);
9076           break;
9077         }
9078         case 60:  /* Wave */
9079         {
9080           PixelInterpolateMethod
9081             method;
9082
9083           if (attribute_flag[0] != 0)
9084             {
9085               flags=ParseGeometry(argument_list[0].string_reference,
9086                 &geometry_info);
9087               if ((flags & SigmaValue) == 0)
9088                 geometry_info.sigma=1.0;
9089             }
9090           if (attribute_flag[1] != 0)
9091             geometry_info.rho=argument_list[1].real_reference;
9092           if (attribute_flag[2] != 0)
9093             geometry_info.sigma=argument_list[2].real_reference;
9094           method=UndefinedInterpolatePixel;
9095           if (attribute_flag[3] != 0)
9096             method=(PixelInterpolateMethod) argument_list[3].integer_reference;
9097           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9098             method,exception);
9099           break;
9100         }
9101         case 61:  /* Separate */
9102         {
9103           if (attribute_flag[0] != 0)
9104             channel=(ChannelType) argument_list[0].integer_reference;
9105           channel_mask=SetPixelChannelMask(image,channel);
9106           (void) SeparateImage(image);
9107           (void) SetPixelChannelMask(image,channel_mask);
9108           break;
9109         }
9110         case 63:  /* Stereo */
9111         {
9112           if (attribute_flag[0] == 0)
9113             {
9114               ThrowPerlException(exception,OptionError,"StereoImageRequired",
9115                 PackageName);
9116               goto PerlException;
9117             }
9118           if (attribute_flag[1] != 0)
9119             geometry.x=argument_list[1].integer_reference;
9120           if (attribute_flag[2] != 0)
9121             geometry.y=argument_list[2].integer_reference;
9122           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9123             geometry.x,geometry.y,exception);
9124           break;
9125         }
9126         case 64:  /* Stegano */
9127         {
9128           if (attribute_flag[0] == 0)
9129             {
9130               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9131                 PackageName);
9132               goto PerlException;
9133             }
9134           if (attribute_flag[1] == 0)
9135             argument_list[1].integer_reference=0;
9136           image->offset=argument_list[1].integer_reference;
9137           image=SteganoImage(image,argument_list[0].image_reference,exception);
9138           break;
9139         }
9140         case 65:  /* Deconstruct */
9141         {
9142           image=CompareImagesLayers(image,CompareAnyLayer,exception);
9143           break;
9144         }
9145         case 66:  /* GaussianBlur */
9146         {
9147           if (attribute_flag[0] != 0)
9148             {
9149               flags=ParseGeometry(argument_list[0].string_reference,
9150                 &geometry_info);
9151               if ((flags & SigmaValue) == 0)
9152                 geometry_info.sigma=1.0;
9153             }
9154           if (attribute_flag[1] != 0)
9155             geometry_info.rho=argument_list[1].real_reference;
9156           if (attribute_flag[2] != 0)
9157             geometry_info.sigma=argument_list[2].real_reference;
9158           if (attribute_flag[3] != 0)
9159             geometry_info.xi=argument_list[3].real_reference;
9160           if (attribute_flag[4] != 0)
9161             channel=(ChannelType) argument_list[4].integer_reference;
9162           channel_mask=SetPixelChannelMask(image,channel);
9163           image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9164             geometry_info.xi,exception);
9165           if (image != (Image *) NULL)
9166             (void) SetPixelChannelMask(image,channel_mask);
9167           break;
9168         }
9169         case 67:  /* Convolve */
9170         {
9171           KernelInfo
9172             *kernel;
9173
9174           kernel=(KernelInfo *) NULL;
9175           if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9176             break;
9177           if (attribute_flag[0] != 0)
9178             {
9179               AV
9180                 *av;
9181
9182               size_t
9183                 order;
9184
9185               kernel=AcquireKernelInfo((const char *) NULL);
9186               if (kernel == (KernelInfo *) NULL)
9187                 break;
9188               av=(AV *) argument_list[0].array_reference;
9189               order=(size_t) sqrt(av_len(av)+1);
9190               kernel->width=order;
9191               kernel->height=order;
9192               kernel->values=(double *) AcquireAlignedMemory(order,order*
9193                 sizeof(*kernel->values));
9194               if (kernel->values == (double *) NULL)
9195                 {
9196                   kernel=DestroyKernelInfo(kernel);
9197                   ThrowPerlException(exception,ResourceLimitFatalError,
9198                     "MemoryAllocationFailed",PackageName);
9199                   goto PerlException;
9200                 }
9201               for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9202                 kernel->values[j]=(double) SvNV(*(av_fetch(av,j,0)));
9203               for ( ; j < (ssize_t) (order*order); j++)
9204                 kernel->values[j]=0.0;
9205             }
9206           if (attribute_flag[1] != 0)
9207             channel=(ChannelType) argument_list[1].integer_reference;
9208           if (attribute_flag[2] != 0)
9209             image->bias=SiPrefixToDouble(argument_list[2].string_reference,
9210               QuantumRange);
9211           if (attribute_flag[3] != 0)
9212             {
9213               kernel=AcquireKernelInfo(argument_list[3].string_reference);
9214               if (kernel == (KernelInfo *) NULL)
9215                 break;
9216             }
9217           channel_mask=SetPixelChannelMask(image,channel);
9218           kernel->bias=image->bias;
9219           image=ConvolveImage(image,kernel,exception);
9220           if (image != (Image *) NULL)
9221             (void) SetPixelChannelMask(image,channel_mask);
9222           kernel=DestroyKernelInfo(kernel);
9223           break;
9224         }
9225         case 68:  /* Profile */
9226         {
9227           const char
9228             *name;
9229
9230           Image
9231             *profile_image;
9232
9233           ImageInfo
9234             *profile_info;
9235
9236           StringInfo
9237             *profile;
9238
9239           name="*";
9240           if (attribute_flag[0] != 0)
9241             name=argument_list[0].string_reference;
9242           if (attribute_flag[2] != 0)
9243             image->rendering_intent=(RenderingIntent)
9244               argument_list[2].integer_reference;
9245           if (attribute_flag[3] != 0)
9246             image->black_point_compensation=
9247               argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9248           if (attribute_flag[1] != 0)
9249             {
9250               if (argument_list[1].length == 0)
9251                 {
9252                   /*
9253                     Remove a profile from the image.
9254                   */
9255                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9256                     MagickTrue);
9257                   break;
9258                 }
9259               /*
9260                 Associate user supplied profile with the image.
9261               */
9262               profile=AcquireStringInfo(argument_list[1].length);
9263               SetStringInfoDatum(profile,(const unsigned char *)
9264                 argument_list[1].string_reference);
9265               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9266                 (size_t) GetStringInfoLength(profile),MagickFalse);
9267               profile=DestroyStringInfo(profile);
9268               break;
9269             }
9270           /*
9271             Associate a profile with the image.
9272           */
9273           profile_info=
9274             CloneImageInfo(info ? info->image_info : (ImageInfo *) NULL);
9275           (void) CopyMagickString(profile_info->filename,name,MaxTextExtent);
9276           profile_image=ReadImages(profile_info,&image->exception);
9277           if (profile_image == (Image *) NULL)
9278             break;
9279           ResetImageProfileIterator(profile_image);
9280           name=GetNextImageProfile(profile_image);
9281           while (name != (const char *) NULL)
9282           {
9283             const StringInfo
9284               *profile;
9285
9286             profile=GetImageProfile(profile_image,name);
9287             if (profile != (const StringInfo *) NULL)
9288               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9289                 (size_t) GetStringInfoLength(profile),MagickFalse);
9290             name=GetNextImageProfile(profile_image);
9291           }
9292           profile_image=DestroyImage(profile_image);
9293           profile_info=DestroyImageInfo(profile_info);
9294           break;
9295         }
9296         case 69:  /* UnsharpMask */
9297         {
9298           if (attribute_flag[0] != 0)
9299             {
9300               flags=ParseGeometry(argument_list[0].string_reference,
9301                 &geometry_info);
9302               if ((flags & SigmaValue) == 0)
9303                 geometry_info.sigma=1.0;
9304               if ((flags & XiValue) == 0)
9305                 geometry_info.xi=1.0;
9306               if ((flags & PsiValue) == 0)
9307                 geometry_info.psi=0.5;
9308             }
9309           if (attribute_flag[1] != 0)
9310             geometry_info.rho=argument_list[1].real_reference;
9311           if (attribute_flag[2] != 0)
9312             geometry_info.sigma=argument_list[2].real_reference;
9313           if (attribute_flag[3] != 0)
9314             geometry_info.xi=argument_list[3].real_reference;
9315           if (attribute_flag[4] != 0)
9316             geometry_info.psi=argument_list[4].real_reference;
9317           if (attribute_flag[5] != 0)
9318             channel=(ChannelType) argument_list[5].integer_reference;
9319           channel_mask=SetPixelChannelMask(image,channel);
9320           image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9321             geometry_info.xi,geometry_info.psi,exception);
9322           if (image != (Image *) NULL)
9323             (void) SetPixelChannelMask(image,channel_mask);
9324           break;
9325         }
9326         case 70:  /* MotionBlur */
9327         {
9328           if (attribute_flag[0] != 0)
9329             {
9330               flags=ParseGeometry(argument_list[0].string_reference,
9331                 &geometry_info);
9332               if ((flags & SigmaValue) == 0)
9333                 geometry_info.sigma=1.0;
9334               if ((flags & XiValue) == 0)
9335                 geometry_info.xi=1.0;
9336             }
9337           if (attribute_flag[1] != 0)
9338             geometry_info.rho=argument_list[1].real_reference;
9339           if (attribute_flag[2] != 0)
9340             geometry_info.sigma=argument_list[2].real_reference;
9341           if (attribute_flag[3] != 0)
9342             geometry_info.xi=argument_list[3].real_reference;
9343           if (attribute_flag[4] != 0)
9344             geometry_info.psi=argument_list[4].real_reference;
9345           if (attribute_flag[5] != 0)
9346             channel=(ChannelType) argument_list[5].integer_reference;
9347           channel_mask=SetPixelChannelMask(image,channel);
9348           image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9349             geometry_info.xi,geometry_info.psi,exception);
9350           if (image != (Image *) NULL)
9351             (void) SetPixelChannelMask(image,channel_mask);
9352           break;
9353         }
9354         case 71:  /* OrderedDither */
9355         {
9356           if (attribute_flag[0] == 0)
9357             argument_list[0].string_reference="o8x8";
9358           if (attribute_flag[1] != 0)
9359             channel=(ChannelType) argument_list[1].integer_reference;
9360           channel_mask=SetPixelChannelMask(image,channel);
9361           (void) OrderedPosterizeImage(image,argument_list[0].string_reference,
9362             exception);
9363           (void) SetPixelChannelMask(image,channel_mask);
9364           break;
9365         }
9366         case 72:  /* Shave */
9367         {
9368           if (attribute_flag[0] != 0)
9369             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9370               &geometry,exception);
9371           if (attribute_flag[1] != 0)
9372             geometry.width=argument_list[1].integer_reference;
9373           if (attribute_flag[2] != 0)
9374             geometry.height=argument_list[2].integer_reference;
9375           image=ShaveImage(image,&geometry,exception);
9376           break;
9377         }
9378         case 73:  /* Level */
9379         {
9380           double
9381             black_point,
9382             gamma,
9383             white_point;
9384
9385           black_point=0.0;
9386           white_point=(MagickRealType) image->columns*image->rows;
9387           gamma=1.0;
9388           if (attribute_flag[0] != 0)
9389             {
9390               flags=ParseGeometry(argument_list[0].string_reference,
9391                 &geometry_info);
9392               black_point=geometry_info.rho;
9393               if ((flags & SigmaValue) != 0)
9394                 white_point=geometry_info.sigma;
9395               if ((flags & XiValue) != 0)
9396                 gamma=geometry_info.xi;
9397               if ((flags & PercentValue) != 0)
9398                 {
9399                   black_point*=(double) (QuantumRange/100.0);
9400                   white_point*=(double) (QuantumRange/100.0);
9401                 }
9402               if ((flags & SigmaValue) == 0)
9403                 white_point=(double) QuantumRange-black_point;
9404             }
9405           if (attribute_flag[1] != 0)
9406             black_point=argument_list[1].real_reference;
9407           if (attribute_flag[2] != 0)
9408             white_point=argument_list[2].real_reference;
9409           if (attribute_flag[3] != 0)
9410             gamma=argument_list[3].real_reference;
9411           if (attribute_flag[4] != 0)
9412             channel=(ChannelType) argument_list[4].integer_reference;
9413           if (attribute_flag[5] != 0)
9414             {
9415               argument_list[0].real_reference=argument_list[5].real_reference;
9416               attribute_flag[0]=attribute_flag[5];
9417             }
9418           channel_mask=SetPixelChannelMask(image,channel);
9419           (void) LevelImage(image,black_point,white_point,gamma,exception);
9420           (void) SetPixelChannelMask(image,channel_mask);
9421           break;
9422         }
9423         case 74:  /* Clip */
9424         {
9425           if (attribute_flag[0] == 0)
9426             argument_list[0].string_reference="#1";
9427           if (attribute_flag[1] == 0)
9428             argument_list[1].integer_reference=MagickTrue;
9429           (void) ClipImagePath(image,argument_list[0].string_reference,
9430             argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse,
9431             exception);
9432           break;
9433         }
9434         case 75:  /* AffineTransform */
9435         {
9436           DrawInfo
9437             *draw_info;
9438
9439           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9440             (DrawInfo *) NULL);
9441           if (attribute_flag[0] != 0)
9442             {
9443               AV
9444                 *av;
9445
9446               av=(AV *) argument_list[0].array_reference;
9447               if ((av_len(av) != 3) && (av_len(av) != 5))
9448                 {
9449                   ThrowPerlException(exception,OptionError,
9450                     "affine matrix must have 4 or 6 elements",PackageName);
9451                   goto PerlException;
9452                 }
9453               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9454               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9455               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9456               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9457               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9458                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9459                 {
9460                   ThrowPerlException(exception,OptionError,
9461                     "affine matrix is singular",PackageName);
9462                    goto PerlException;
9463                 }
9464               if (av_len(av) == 5)
9465                 {
9466                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9467                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9468                 }
9469             }
9470           for (j=1; j < 6; j++)
9471           {
9472             if (attribute_flag[j] == 0)
9473               continue;
9474             value=argument_list[j].string_reference;
9475             angle=argument_list[j].real_reference;
9476             current=draw_info->affine;
9477             GetAffineMatrix(&affine);
9478             switch (j)
9479             {
9480               case 1:
9481               {
9482                 /*
9483                   Translate.
9484                 */
9485                 flags=ParseGeometry(value,&geometry_info);
9486                 affine.tx=geometry_info.xi;
9487                 affine.ty=geometry_info.psi;
9488                 if ((flags & PsiValue) == 0)
9489                   affine.ty=affine.tx;
9490                 break;
9491               }
9492               case 2:
9493               {
9494                 /*
9495                   Scale.
9496                 */
9497                 flags=ParseGeometry(value,&geometry_info);
9498                 affine.sx=geometry_info.rho;
9499                 affine.sy=geometry_info.sigma;
9500                 if ((flags & SigmaValue) == 0)
9501                   affine.sy=affine.sx;
9502                 break;
9503               }
9504               case 3:
9505               {
9506                 /*
9507                   Rotate.
9508                 */
9509                 if (angle == 0.0)
9510                   break;
9511                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9512                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9513                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9514                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9515                 break;
9516               }
9517               case 4:
9518               {
9519                 /*
9520                   SkewX.
9521                 */
9522                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9523                 break;
9524               }
9525               case 5:
9526               {
9527                 /*
9528                   SkewY.
9529                 */
9530                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9531                 break;
9532               }
9533             }
9534             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9535             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9536             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9537             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9538             draw_info->affine.tx=
9539               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9540             draw_info->affine.ty=
9541               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9542           }
9543           if (attribute_flag[6] != 0)
9544             image->interpolate=(PixelInterpolateMethod)
9545               argument_list[6].integer_reference;
9546           if (attribute_flag[7] != 0)
9547             QueryColorDatabase(argument_list[7].string_reference,
9548               &image->background_color,exception);
9549           image=AffineTransformImage(image,&draw_info->affine,exception);
9550           draw_info=DestroyDrawInfo(draw_info);
9551           break;
9552         }
9553         case 76:  /* Difference */
9554         {
9555           if (attribute_flag[0] == 0)
9556             {
9557               ThrowPerlException(exception,OptionError,
9558                 "ReferenceImageRequired",PackageName);
9559               goto PerlException;
9560             }
9561           if (attribute_flag[1] != 0)
9562             image->fuzz=SiPrefixToDouble(argument_list[1].string_reference,
9563               QuantumRange);
9564           (void) IsImagesEqual(image,argument_list[0].image_reference,
9565             exception);
9566           break;
9567         }
9568         case 77:  /* AdaptiveThreshold */
9569         {
9570           if (attribute_flag[0] != 0)
9571             {
9572               flags=ParseGeometry(argument_list[0].string_reference,
9573                 &geometry_info);
9574               if ((flags & PercentValue) != 0)
9575                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9576             }
9577           if (attribute_flag[1] != 0)
9578             geometry_info.rho=argument_list[1].integer_reference;
9579           if (attribute_flag[2] != 0)
9580             geometry_info.sigma=argument_list[2].integer_reference;
9581           if (attribute_flag[3] != 0)
9582             geometry_info.xi=argument_list[3].integer_reference;;
9583           image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
9584             (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
9585           break;
9586         }
9587         case 78:  /* Resample */
9588         {
9589           size_t
9590             height,
9591             width;
9592
9593           if (attribute_flag[0] != 0)
9594             {
9595               flags=ParseGeometry(argument_list[0].string_reference,
9596                 &geometry_info);
9597               if ((flags & SigmaValue) == 0)
9598                 geometry_info.sigma=geometry_info.rho;
9599             }
9600           if (attribute_flag[1] != 0)
9601             geometry_info.rho=argument_list[1].real_reference;
9602           if (attribute_flag[2] != 0)
9603             geometry_info.sigma=argument_list[2].real_reference;
9604           if (attribute_flag[3] == 0)
9605             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
9606           if (attribute_flag[4] == 0)
9607             SetImageArtifact(image,"filter:support",
9608               argument_list[4].string_reference);
9609           if (attribute_flag[5] != 0)
9610             argument_list[5].real_reference=1.0;
9611           width=(size_t) (geometry_info.rho*image->columns/
9612             (image->x_resolution == 0.0 ? 72.0 : image->x_resolution)+0.5);
9613           height=(size_t) (geometry_info.sigma*image->rows/
9614             (image->y_resolution == 0.0 ? 72.0 : image->y_resolution)+0.5);
9615           image=ResizeImage(image,width,height,(FilterTypes)
9616             argument_list[3].integer_reference,argument_list[5].real_reference,
9617             exception);
9618           if (image != (Image *) NULL)
9619             {
9620               image->x_resolution=geometry_info.rho;
9621               image->y_resolution=geometry_info.sigma;
9622             }
9623           break;
9624         }
9625         case 79:  /* Describe */
9626         {
9627           if (attribute_flag[0] == 0)
9628             argument_list[0].file_reference=(FILE *) NULL;
9629           if (attribute_flag[1] != 0)
9630             (void) SetImageArtifact(image,"identify:features",
9631               argument_list[1].string_reference);
9632           (void) IdentifyImage(image,argument_list[0].file_reference,
9633             MagickTrue,exception);
9634           break;
9635         }
9636         case 80:  /* BlackThreshold */
9637         {
9638           if (attribute_flag[0] == 0)
9639             argument_list[0].string_reference="50%";
9640           if (attribute_flag[2] != 0)
9641             channel=(ChannelType) argument_list[2].integer_reference;
9642           channel_mask=SetPixelChannelMask(image,channel);
9643           BlackThresholdImage(image,argument_list[0].string_reference,
9644             exception);
9645           (void) SetPixelChannelMask(image,channel_mask);
9646           break;
9647         }
9648         case 81:  /* WhiteThreshold */
9649         {
9650           if (attribute_flag[0] == 0)
9651             argument_list[0].string_reference="50%";
9652           if (attribute_flag[2] != 0)
9653             channel=(ChannelType) argument_list[2].integer_reference;
9654           channel_mask=SetPixelChannelMask(image,channel);
9655           WhiteThresholdImage(image,argument_list[0].string_reference,
9656             exception);
9657           (void) SetPixelChannelMask(image,channel_mask);
9658           break;
9659         }
9660         case 82:  /* RadialBlur */
9661         {
9662           if (attribute_flag[0] != 0)
9663             {
9664               flags=ParseGeometry(argument_list[0].string_reference,
9665                 &geometry_info);
9666             }
9667           if (attribute_flag[1] != 0)
9668             geometry_info.rho=argument_list[1].real_reference;
9669           if (attribute_flag[2] != 0)
9670             geometry_info.sigma=argument_list[2].real_reference;
9671           if (attribute_flag[3] != 0)
9672             channel=(ChannelType) argument_list[3].integer_reference;
9673           channel_mask=SetPixelChannelMask(image,channel);
9674           image=RadialBlurImage(image,geometry_info.rho,geometry_info.sigma,
9675             exception);
9676           if (image != (Image *) NULL)
9677             (void) SetPixelChannelMask(image,channel_mask);
9678           break;
9679         }
9680         case 83:  /* Thumbnail */
9681         {
9682           if (attribute_flag[0] != 0)
9683             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
9684               &geometry,exception);
9685           if (attribute_flag[1] != 0)
9686             geometry.width=argument_list[1].integer_reference;
9687           if (attribute_flag[2] != 0)
9688             geometry.height=argument_list[2].integer_reference;
9689           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
9690           break;
9691         }
9692         case 84:  /* Strip */
9693         {
9694           (void) StripImage(image);
9695           break;
9696         }
9697         case 85:  /* Tint */
9698         {
9699           PixelInfo
9700             tint;
9701
9702           GetPixelInfo(image,&tint);
9703           if (attribute_flag[0] != 0)
9704             (void) QueryMagickColor(argument_list[0].string_reference,&tint,
9705               exception);
9706           if (attribute_flag[1] == 0)
9707             argument_list[1].string_reference="100";
9708           image=TintImage(image,argument_list[1].string_reference,&tint,
9709             exception);
9710           break;
9711         }
9712         case 86:  /* Channel */
9713         {
9714           if (attribute_flag[0] != 0)
9715             channel=(ChannelType) argument_list[0].integer_reference;
9716           channel_mask=SetPixelChannelMask(image,channel);
9717           (void) SeparateImage(image);
9718           (void) SetPixelChannelMask(image,channel_mask);
9719           break;
9720         }
9721         case 87:  /* Splice */
9722         {
9723           if (attribute_flag[0] != 0)
9724             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
9725               &geometry,exception);
9726           if (attribute_flag[1] != 0)
9727             geometry.width=argument_list[1].integer_reference;
9728           if (attribute_flag[2] != 0)
9729             geometry.height=argument_list[2].integer_reference;
9730           if (attribute_flag[3] != 0)
9731             geometry.x=argument_list[3].integer_reference;
9732           if (attribute_flag[4] != 0)
9733             geometry.y=argument_list[4].integer_reference;
9734           if (attribute_flag[5] != 0)
9735             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
9736               QuantumRange);
9737           if (attribute_flag[6] != 0)
9738             (void) QueryColorDatabase(argument_list[6].string_reference,
9739               &image->background_color,exception);
9740           if (attribute_flag[7] != 0)
9741             image->gravity=(GravityType) argument_list[7].integer_reference;
9742           image=SpliceImage(image,&geometry,exception);
9743           break;
9744         }
9745         case 88:  /* Posterize */
9746         {
9747           if (attribute_flag[0] == 0)
9748             argument_list[0].integer_reference=3;
9749           if (attribute_flag[1] == 0)
9750             argument_list[1].integer_reference=0;
9751           (void) PosterizeImage(image,argument_list[0].integer_reference,
9752             argument_list[1].integer_reference ? MagickTrue : MagickFalse,
9753             exception);
9754           break;
9755         }
9756         case 89:  /* Shadow */
9757         {
9758           if (attribute_flag[0] != 0)
9759             {
9760               flags=ParseGeometry(argument_list[0].string_reference,
9761                 &geometry_info);
9762               if ((flags & SigmaValue) == 0)
9763                 geometry_info.sigma=1.0;
9764               if ((flags & XiValue) == 0)
9765                 geometry_info.xi=4.0;
9766               if ((flags & PsiValue) == 0)
9767                 geometry_info.psi=4.0;
9768             }
9769           if (attribute_flag[1] != 0)
9770             geometry_info.rho=argument_list[1].real_reference;
9771           if (attribute_flag[2] != 0)
9772             geometry_info.sigma=argument_list[2].real_reference;
9773           if (attribute_flag[3] != 0)
9774             geometry_info.xi=argument_list[3].integer_reference;
9775           if (attribute_flag[4] != 0)
9776             geometry_info.psi=argument_list[4].integer_reference;
9777           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
9778             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-
9779             0.5),exception);
9780           break;
9781         }
9782         case 90:  /* Identify */
9783         {
9784           if (attribute_flag[0] == 0)
9785             argument_list[0].file_reference=(FILE *) NULL;
9786           if (attribute_flag[1] != 0)
9787             (void) SetImageArtifact(image,"identify:features",
9788               argument_list[1].string_reference);
9789           if ((attribute_flag[2] != 0) &&
9790               (argument_list[2].integer_reference != 0))
9791             (void) SetImageArtifact(image,"identify:unique","true");
9792           (void) IdentifyImage(image,argument_list[0].file_reference,
9793             MagickTrue,exception);
9794           break;
9795         }
9796         case 91:  /* SepiaTone */
9797         {
9798           if (attribute_flag[0] == 0)
9799             argument_list[0].real_reference=80.0*QuantumRange/100.0;
9800           image=SepiaToneImage(image,argument_list[0].real_reference,
9801             exception);
9802           break;
9803         }
9804         case 92:  /* SigmoidalContrast */
9805         {
9806           MagickBooleanType
9807             sharpen;
9808
9809           if (attribute_flag[0] != 0)
9810             {
9811               flags=ParseGeometry(argument_list[0].string_reference,
9812                 &geometry_info);
9813               if ((flags & SigmaValue) == 0)
9814                 geometry_info.sigma=QuantumRange/2.0;
9815               if ((flags & PercentValue) != 0)
9816                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
9817             }
9818           if (attribute_flag[1] != 0)
9819             geometry_info.rho=argument_list[1].real_reference;
9820           if (attribute_flag[2] != 0)
9821             geometry_info.sigma=argument_list[2].real_reference;
9822           if (attribute_flag[3] != 0)
9823             channel=(ChannelType) argument_list[3].integer_reference;
9824           sharpen=MagickTrue;
9825           if (attribute_flag[4] != 0)
9826             sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
9827               MagickFalse;
9828           channel_mask=SetPixelChannelMask(image,channel);
9829           (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
9830             geometry_info.sigma,exception);
9831           (void) SetPixelChannelMask(image,channel_mask);
9832           break;
9833         }
9834         case 93:  /* Extent */
9835         {
9836           if (attribute_flag[7] != 0)
9837             image->gravity=(GravityType) argument_list[7].integer_reference;
9838           if (attribute_flag[0] != 0)
9839             {
9840               int
9841                 flags;
9842
9843               flags=ParseGravityGeometry(image,
9844                 argument_list[0].string_reference,&geometry,exception);
9845               (void) flags;
9846               if (geometry.width == 0)
9847                 geometry.width=image->columns;
9848               if (geometry.height == 0)
9849                 geometry.height=image->rows;
9850             }
9851           if (attribute_flag[1] != 0)
9852             geometry.width=argument_list[1].integer_reference;
9853           if (attribute_flag[2] != 0)
9854             geometry.height=argument_list[2].integer_reference;
9855           if (attribute_flag[3] != 0)
9856             geometry.x=argument_list[3].integer_reference;
9857           if (attribute_flag[4] != 0)
9858             geometry.y=argument_list[4].integer_reference;
9859           if (attribute_flag[5] != 0)
9860             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
9861               QuantumRange);
9862           if (attribute_flag[6] != 0)
9863             (void) QueryColorDatabase(argument_list[6].string_reference,
9864               &image->background_color,exception);
9865           image=ExtentImage(image,&geometry,exception);
9866           break;
9867         }
9868         case 94:  /* Vignette */
9869         {
9870           if (attribute_flag[0] != 0)
9871             {
9872               flags=ParseGeometry(argument_list[0].string_reference,
9873                 &geometry_info);
9874               if ((flags & SigmaValue) == 0)
9875                 geometry_info.sigma=1.0;
9876               if ((flags & XiValue) == 0)
9877                 geometry_info.xi=0.1*image->columns;
9878               if ((flags & PsiValue) == 0)
9879                 geometry_info.psi=0.1*image->rows;
9880             }
9881           if (attribute_flag[1] != 0)
9882             geometry_info.rho=argument_list[1].real_reference;
9883           if (attribute_flag[2] != 0)
9884             geometry_info.sigma=argument_list[2].real_reference;
9885           if (attribute_flag[3] != 0)
9886             geometry_info.xi=argument_list[3].integer_reference;
9887           if (attribute_flag[4] != 0)
9888             geometry_info.psi=argument_list[4].integer_reference;
9889           if (attribute_flag[5] != 0)
9890             (void) QueryColorDatabase(argument_list[5].string_reference,
9891               &image->background_color,exception);
9892           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
9893             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-
9894             0.5),exception);
9895           break;
9896         }
9897         case 95:  /* ContrastStretch */
9898         {
9899           double
9900             black_point,
9901             white_point;
9902
9903           black_point=0.0;
9904           white_point=(MagickRealType) image->columns*image->rows;
9905           if (attribute_flag[0] != 0)
9906             {
9907               flags=ParseGeometry(argument_list[0].string_reference,
9908                 &geometry_info);
9909               black_point=geometry_info.rho;
9910               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
9911                 black_point;
9912               if ((flags & PercentValue) != 0)
9913                 {
9914                   black_point*=(double) image->columns*image->rows/100.0;
9915                   white_point*=(double) image->columns*image->rows/100.0;
9916                 }
9917               white_point=(MagickRealType) image->columns*image->rows-
9918                 white_point;
9919             }
9920           if (attribute_flag[1] != 0)
9921             black_point=argument_list[1].real_reference;
9922           if (attribute_flag[2] != 0)
9923             white_point=argument_list[2].real_reference;
9924           if (attribute_flag[4] != 0)
9925             channel=(ChannelType) argument_list[4].integer_reference;
9926           channel_mask=SetPixelChannelMask(image,channel);
9927           (void) ContrastStretchImage(image,black_point,white_point,exception);
9928           (void) SetPixelChannelMask(image,channel_mask);
9929           break;
9930         }
9931         case 96:  /* Sans0 */
9932         {
9933           break;
9934         }
9935         case 97:  /* Sans1 */
9936         {
9937           break;
9938         }
9939         case 98:  /* AdaptiveSharpen */
9940         {
9941           if (attribute_flag[0] != 0)
9942             {
9943               flags=ParseGeometry(argument_list[0].string_reference,
9944                 &geometry_info);
9945               if ((flags & SigmaValue) == 0)
9946                 geometry_info.sigma=1.0;
9947               if ((flags & XiValue) == 0)
9948                 geometry_info.xi=0.0;
9949             }
9950           if (attribute_flag[1] != 0)
9951             geometry_info.rho=argument_list[1].real_reference;
9952           if (attribute_flag[2] != 0)
9953             geometry_info.sigma=argument_list[2].real_reference;
9954           if (attribute_flag[3] != 0)
9955             geometry_info.xi=argument_list[3].real_reference;
9956           if (attribute_flag[4] != 0)
9957             channel=(ChannelType) argument_list[4].integer_reference;
9958           channel_mask=SetPixelChannelMask(image,channel);
9959           image=AdaptiveSharpenImage(image,geometry_info.rho,
9960             geometry_info.sigma,geometry_info.xi,exception);
9961           if (image != (Image *) NULL)
9962             (void) SetPixelChannelMask(image,channel_mask);
9963           break;
9964         }
9965         case 99:  /* Transpose */
9966         {
9967           image=TransposeImage(image,exception);
9968           break;
9969         }
9970         case 100:  /* Tranverse */
9971         {
9972           image=TransverseImage(image,exception);
9973           break;
9974         }
9975         case 101:  /* AutoOrient */
9976         {
9977           switch (image->orientation)
9978           {
9979             case TopRightOrientation:
9980             {
9981               image=FlopImage(image,exception);
9982               break;
9983             }
9984             case BottomRightOrientation:
9985             {
9986               image=RotateImage(image,180.0,exception);
9987               break;
9988             }
9989             case BottomLeftOrientation:
9990             {
9991               image=FlipImage(image,exception);
9992               break;
9993             }
9994             case LeftTopOrientation:
9995             {
9996               image=TransposeImage(image,exception);
9997               break;
9998             }
9999             case RightTopOrientation:
10000             {
10001               image=RotateImage(image,90.0,exception);
10002               break;
10003             }
10004             case RightBottomOrientation:
10005             {
10006               image=TransverseImage(image,exception);
10007               break;
10008             }
10009             case LeftBottomOrientation:
10010             {
10011               image=RotateImage(image,270.0,exception);
10012               break;
10013             }
10014             default:
10015               break;
10016           }
10017           break;
10018         }
10019         case 102:  /* AdaptiveBlur */
10020         {
10021           if (attribute_flag[0] != 0)
10022             {
10023               flags=ParseGeometry(argument_list[0].string_reference,
10024                 &geometry_info);
10025               if ((flags & SigmaValue) == 0)
10026                 geometry_info.sigma=1.0;
10027               if ((flags & XiValue) == 0)
10028                 geometry_info.xi=0.0;
10029             }
10030           if (attribute_flag[1] != 0)
10031             geometry_info.rho=argument_list[1].real_reference;
10032           if (attribute_flag[2] != 0)
10033             geometry_info.sigma=argument_list[2].real_reference;
10034           if (attribute_flag[3] != 0)
10035             geometry_info.xi=argument_list[3].real_reference;
10036           if (attribute_flag[4] != 0)
10037             channel=(ChannelType) argument_list[4].integer_reference;
10038           channel_mask=SetPixelChannelMask(image,channel);
10039           image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10040             geometry_info.xi,exception);
10041           if (image != (Image *) NULL)
10042             (void) SetPixelChannelMask(image,channel_mask);
10043           break;
10044         }
10045         case 103:  /* Sketch */
10046         {
10047           if (attribute_flag[0] != 0)
10048             {
10049               flags=ParseGeometry(argument_list[0].string_reference,
10050                 &geometry_info);
10051               if ((flags & SigmaValue) == 0)
10052                 geometry_info.sigma=1.0;
10053               if ((flags & XiValue) == 0)
10054                 geometry_info.xi=1.0;
10055             }
10056           if (attribute_flag[1] != 0)
10057             geometry_info.rho=argument_list[1].real_reference;
10058           if (attribute_flag[2] != 0)
10059             geometry_info.sigma=argument_list[2].real_reference;
10060           if (attribute_flag[3] != 0)
10061             geometry_info.xi=argument_list[3].real_reference;
10062           if (attribute_flag[4] != 0)
10063             geometry_info.psi=argument_list[4].real_reference;
10064           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10065             geometry_info.xi,geometry_info.psi,exception);
10066           break;
10067         }
10068         case 104:  /* UniqueColors */
10069         {
10070           image=UniqueImageColors(image,exception);
10071           break;
10072         }
10073         case 105:  /* AdaptiveResize */
10074         {
10075           PixelInterpolateMethod
10076             method;
10077
10078           if (attribute_flag[0] != 0)
10079             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10080               &geometry,exception);
10081           if (attribute_flag[1] != 0)
10082             geometry.width=argument_list[1].integer_reference;
10083           if (attribute_flag[2] != 0)
10084             geometry.height=argument_list[2].integer_reference;
10085           if (attribute_flag[3] != 0)
10086             image->filter=(FilterTypes) argument_list[4].integer_reference;
10087           if (attribute_flag[4] != 0)
10088             SetImageArtifact(image,"filter:support",
10089               argument_list[4].string_reference);
10090           if (attribute_flag[5] != 0)
10091             image->blur=argument_list[5].real_reference;
10092           method=UndefinedInterpolatePixel;
10093           if (attribute_flag[6] != 0)
10094             method=(PixelInterpolateMethod) argument_list[6].integer_reference;
10095           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10096             method,exception);
10097           break;
10098         }
10099         case 106:  /* ClipMask */
10100         {
10101           if (attribute_flag[0] == 0)
10102             {
10103               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10104                 PackageName);
10105               goto PerlException;
10106             }
10107           image->clip_mask=CloneImage(argument_list[0].image_reference,0,0,
10108             MagickTrue,exception);
10109           (void) NegateImage(image->clip_mask,MagickFalse,exception);
10110           break;
10111         }
10112         case 107:  /* LinearStretch */
10113         {
10114            double
10115              black_point,
10116              white_point;
10117
10118            black_point=0.0;
10119            white_point=(MagickRealType) image->columns*image->rows;
10120            if (attribute_flag[0] != 0)
10121              {
10122                flags=ParseGeometry(argument_list[0].string_reference,
10123                  &geometry_info);
10124                if ((flags & SigmaValue) != 0)
10125                   white_point=geometry_info.sigma;
10126                if ((flags & PercentValue) != 0)
10127                  {
10128                    black_point*=(double) image->columns*image->rows/100.0;
10129                    white_point*=(double) image->columns*image->rows/100.0;
10130                  }
10131                if ((flags & SigmaValue) == 0)
10132                  white_point=(double) image->columns*image->rows-black_point;
10133              }
10134           if (attribute_flag[1] != 0)
10135             black_point=argument_list[1].real_reference;
10136           if (attribute_flag[2] != 0)
10137             white_point=argument_list[2].real_reference;
10138           (void) LinearStretchImage(image,black_point,white_point,exception);
10139           break;
10140         }
10141         case 109:  /* Mask */
10142         {
10143           if (attribute_flag[0] == 0)
10144             {
10145               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10146                 PackageName);
10147               goto PerlException;
10148             }
10149           image->mask=CloneImage(argument_list[0].image_reference,0,0,
10150             MagickTrue,exception);
10151           (void) NegateImage(image->mask,MagickFalse,exception);
10152           break;
10153         }
10154         case 110:  /* Polaroid */
10155         {
10156           DrawInfo
10157             *draw_info;
10158
10159           double
10160             angle;
10161
10162           PixelInterpolateMethod
10163             method;
10164
10165           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10166             (DrawInfo *) NULL);
10167           if (attribute_flag[0] != 0)
10168             (void) SetImageProperty(image,"caption",InterpretImageProperties(
10169               info ? info->image_info : (ImageInfo *) NULL,image,
10170               argument_list[0].string_reference,exception));
10171           angle=0.0;
10172           if (attribute_flag[1] != 0)
10173             angle=argument_list[1].real_reference;
10174           if (attribute_flag[2] != 0)
10175             (void) CloneString(&draw_info->font,
10176               argument_list[2].string_reference);
10177           if (attribute_flag[3] != 0)
10178             (void) QueryColorDatabase(argument_list[3].string_reference,
10179               &draw_info->stroke,exception);
10180           if (attribute_flag[4] != 0)
10181             (void) QueryColorDatabase(argument_list[4].string_reference,
10182               &draw_info->fill,exception);
10183           if (attribute_flag[5] != 0)
10184             draw_info->stroke_width=argument_list[5].real_reference;
10185           if (attribute_flag[6] != 0)
10186             draw_info->pointsize=argument_list[6].real_reference;
10187           if (attribute_flag[7] != 0)
10188             draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10189           if (attribute_flag[8] != 0)
10190             (void) QueryColorDatabase(argument_list[8].string_reference,
10191               &image->background_color,exception);
10192           method=UndefinedInterpolatePixel;
10193           if (attribute_flag[9] != 0)
10194             method=(PixelInterpolateMethod) argument_list[9].integer_reference;
10195           image=PolaroidImage(image,draw_info,angle,method,exception);
10196           draw_info=DestroyDrawInfo(draw_info);
10197           break;
10198         }
10199         case 111:  /* FloodfillPaint */
10200         {
10201           DrawInfo
10202             *draw_info;
10203
10204           MagickBooleanType
10205             invert;
10206
10207           PixelInfo
10208             target;
10209
10210           draw_info=CloneDrawInfo(info ? info->image_info :
10211             (ImageInfo *) NULL,(DrawInfo *) NULL);
10212           if (attribute_flag[0] != 0)
10213             flags=ParsePageGeometry(image,argument_list[0].string_reference,
10214               &geometry,exception);
10215           if (attribute_flag[1] != 0)
10216             geometry.x=argument_list[1].integer_reference;
10217           if (attribute_flag[2] != 0)
10218             geometry.y=argument_list[2].integer_reference;
10219           if (attribute_flag[3] != 0)
10220             (void) QueryColorDatabase(argument_list[3].string_reference,
10221               &draw_info->fill,exception);
10222           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
10223             exception);
10224           if (attribute_flag[4] != 0)
10225             QueryMagickColor(argument_list[4].string_reference,&target,
10226               exception);
10227           if (attribute_flag[5] != 0)
10228             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
10229               QuantumRange);
10230           if (attribute_flag[6] != 0)
10231             channel=(ChannelType) argument_list[6].integer_reference;
10232           invert=MagickFalse;
10233           if (attribute_flag[7] != 0)
10234             invert=(MagickBooleanType) argument_list[7].integer_reference;
10235           channel_mask=SetPixelChannelMask(image,channel);
10236           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10237             geometry.y,invert,exception);
10238           (void) SetPixelChannelMask(image,channel_mask);
10239           draw_info=DestroyDrawInfo(draw_info);
10240           break;
10241         }
10242         case 112:  /* Distort */
10243         {
10244           AV
10245             *av;
10246
10247           double
10248             *coordinates;
10249
10250           DistortImageMethod
10251             method;
10252
10253           size_t
10254             number_coordinates;
10255
10256           VirtualPixelMethod
10257             virtual_pixel;
10258
10259           if (attribute_flag[0] == 0)
10260             break;
10261           method=UndefinedDistortion;
10262           if (attribute_flag[1] != 0)
10263             method=(DistortImageMethod) argument_list[1].integer_reference;
10264           av=(AV *) argument_list[0].array_reference;
10265           number_coordinates=(size_t) av_len(av)+1;
10266           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10267             sizeof(*coordinates));
10268           if (coordinates == (double *) NULL)
10269             {
10270               ThrowPerlException(exception,ResourceLimitFatalError,
10271                 "MemoryAllocationFailed",PackageName);
10272               goto PerlException;
10273             }
10274           for (j=0; j < (ssize_t) number_coordinates; j++)
10275             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10276           virtual_pixel=UndefinedVirtualPixelMethod;
10277           if (attribute_flag[2] != 0)
10278             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10279               argument_list[2].integer_reference);
10280           image=DistortImage(image,method,number_coordinates,coordinates,
10281             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10282             exception);
10283           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10284             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10285           coordinates=(double *) RelinquishMagickMemory(coordinates);
10286           break;
10287         }
10288         case 113:  /* Clut */
10289         {
10290           PixelInterpolateMethod
10291             method;
10292
10293           if (attribute_flag[0] == 0)
10294             {
10295               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10296                 PackageName);
10297               goto PerlException;
10298             }
10299           method=UndefinedInterpolatePixel;
10300           if (attribute_flag[1] != 0)
10301             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
10302           if (attribute_flag[2] != 0)
10303             channel=(ChannelType) argument_list[2].integer_reference;
10304           channel_mask=SetPixelChannelMask(image,channel);
10305           (void) ClutImage(image,argument_list[0].image_reference,method,
10306             exception);
10307           (void) SetPixelChannelMask(image,channel_mask);
10308           break;
10309         }
10310         case 114:  /* LiquidRescale */
10311         {
10312           if (attribute_flag[0] != 0)
10313             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10314               &geometry,exception);
10315           if (attribute_flag[1] != 0)
10316             geometry.width=argument_list[1].integer_reference;
10317           if (attribute_flag[2] != 0)
10318             geometry.height=argument_list[2].integer_reference;
10319           if (attribute_flag[3] == 0)
10320             argument_list[3].real_reference=1.0;
10321           if (attribute_flag[4] == 0)
10322             argument_list[4].real_reference=0.0;
10323           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10324             argument_list[3].real_reference,argument_list[4].real_reference,
10325             exception);
10326           break;
10327         }
10328         case 115:  /* EncipherImage */
10329         {
10330           (void) EncipherImage(image,argument_list[0].string_reference,
10331             exception);
10332           break;
10333         }
10334         case 116:  /* DecipherImage */
10335         {
10336           (void) DecipherImage(image,argument_list[0].string_reference,
10337             exception);
10338           break;
10339         }
10340         case 117:  /* Deskew */
10341         {
10342           geometry_info.rho=QuantumRange/2.0;
10343           if (attribute_flag[0] != 0)
10344             flags=ParseGeometry(argument_list[0].string_reference,
10345               &geometry_info);
10346           if (attribute_flag[1] != 0)
10347             geometry_info.rho=SiPrefixToDouble(
10348               argument_list[1].string_reference,QuantumRange);
10349           image=DeskewImage(image,geometry_info.rho,exception);
10350           break;
10351         }
10352         case 118:  /* Remap */
10353         {
10354           QuantizeInfo
10355             *quantize_info;
10356
10357           if (attribute_flag[0] == 0)
10358             {
10359               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10360                 PackageName);
10361               goto PerlException;
10362             }
10363           quantize_info=AcquireQuantizeInfo(info->image_info);
10364           if (attribute_flag[1] != 0)
10365             quantize_info->dither=(MagickBooleanType)
10366               argument_list[1].integer_reference;
10367           if (attribute_flag[2] != 0)
10368             quantize_info->dither_method=(DitherMethod)
10369               argument_list[2].integer_reference;
10370           (void) RemapImages(quantize_info,image,
10371             argument_list[0].image_reference,exception);
10372           quantize_info=DestroyQuantizeInfo(quantize_info);
10373           break;
10374         }
10375         case 119:  /* SparseColor */
10376         {
10377           AV
10378             *av;
10379
10380           double
10381             *coordinates;
10382
10383           SparseColorMethod
10384             method;
10385
10386           size_t
10387             number_coordinates;
10388
10389           VirtualPixelMethod
10390             virtual_pixel;
10391
10392           if (attribute_flag[0] == 0)
10393             break;
10394           method=UndefinedColorInterpolate;
10395           if (attribute_flag[1] != 0)
10396             method=(SparseColorMethod) argument_list[1].integer_reference;
10397           av=(AV *) argument_list[0].array_reference;
10398           number_coordinates=(size_t) av_len(av)+1;
10399           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10400             sizeof(*coordinates));
10401           if (coordinates == (double *) NULL)
10402             {
10403               ThrowPerlException(exception,ResourceLimitFatalError,
10404                 "MemoryAllocationFailed",PackageName);
10405               goto PerlException;
10406             }
10407           for (j=0; j < (ssize_t) number_coordinates; j++)
10408             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10409           virtual_pixel=UndefinedVirtualPixelMethod;
10410           if (attribute_flag[2] != 0)
10411             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10412               argument_list[2].integer_reference);
10413           if (attribute_flag[3] != 0)
10414             channel=(ChannelType) argument_list[3].integer_reference;
10415           channel_mask=SetPixelChannelMask(image,channel);
10416           image=SparseColorImage(image,method,number_coordinates,coordinates,
10417             exception);
10418           if (image != (Image *) NULL)
10419             (void) SetPixelChannelMask(image,channel_mask);
10420           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10421             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10422           coordinates=(double *) RelinquishMagickMemory(coordinates);
10423           break;
10424         }
10425         case 120:  /* Function */
10426         {
10427           AV
10428             *av;
10429
10430           double
10431             *parameters;
10432
10433           MagickFunction
10434             function;
10435
10436           size_t
10437             number_parameters;
10438
10439           VirtualPixelMethod
10440             virtual_pixel;
10441
10442           if (attribute_flag[0] == 0)
10443             break;
10444           function=UndefinedFunction;
10445           if (attribute_flag[1] != 0)
10446             function=(MagickFunction) argument_list[1].integer_reference;
10447           av=(AV *) argument_list[0].array_reference;
10448           number_parameters=(size_t) av_len(av)+1;
10449           parameters=(double *) AcquireQuantumMemory(number_parameters,
10450             sizeof(*parameters));
10451           if (parameters == (double *) NULL)
10452             {
10453               ThrowPerlException(exception,ResourceLimitFatalError,
10454                 "MemoryAllocationFailed",PackageName);
10455               goto PerlException;
10456             }
10457           for (j=0; j < (ssize_t) number_parameters; j++)
10458             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10459           virtual_pixel=UndefinedVirtualPixelMethod;
10460           if (attribute_flag[2] != 0)
10461             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10462               argument_list[2].integer_reference);
10463           (void) FunctionImage(image,function,number_parameters,parameters,
10464             exception);
10465           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10466             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10467           parameters=(double *) RelinquishMagickMemory(parameters);
10468           break;
10469         }
10470         case 121:  /* SelectiveBlur */
10471         {
10472           if (attribute_flag[0] != 0)
10473             {
10474               flags=ParseGeometry(argument_list[0].string_reference,
10475                 &geometry_info);
10476               if ((flags & SigmaValue) == 0)
10477                 geometry_info.sigma=1.0;
10478               if ((flags & PercentValue) != 0)
10479                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10480             }
10481           if (attribute_flag[1] != 0)
10482             geometry_info.rho=argument_list[1].real_reference;
10483           if (attribute_flag[2] != 0)
10484             geometry_info.sigma=argument_list[2].real_reference;
10485           if (attribute_flag[3] != 0)
10486             geometry_info.xi=argument_list[3].integer_reference;;
10487           if (attribute_flag[4] != 0)
10488             geometry_info.psi=argument_list[4].integer_reference;;
10489           if (attribute_flag[5] != 0)
10490             channel=(ChannelType) argument_list[5].integer_reference;
10491           channel_mask=SetPixelChannelMask(image,channel);
10492           image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10493             geometry_info.xi,geometry_info.psi,exception);
10494           if (image != (Image *) NULL)
10495             (void) SetPixelChannelMask(image,channel_mask);
10496           break;
10497         }
10498         case 122:  /* HaldClut */
10499         {
10500           if (attribute_flag[0] == 0)
10501             {
10502               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10503                 PackageName);
10504               goto PerlException;
10505             }
10506           if (attribute_flag[1] != 0)
10507             channel=(ChannelType) argument_list[1].integer_reference;
10508           channel_mask=SetPixelChannelMask(image,channel);
10509           (void) HaldClutImage(image,argument_list[0].image_reference,
10510             exception);
10511           (void) SetPixelChannelMask(image,channel_mask);
10512           break;
10513         }
10514         case 123:  /* BlueShift */
10515         {
10516           if (attribute_flag[0] != 0)
10517             (void) ParseGeometry(argument_list[0].string_reference,
10518               &geometry_info);
10519           image=BlueShiftImage(image,geometry_info.rho,exception);
10520           break;
10521         }
10522         case 124:  /* ForwardFourierTransformImage */
10523         {
10524           image=ForwardFourierTransformImage(image,
10525             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10526             exception);
10527           break;
10528         }
10529         case 125:  /* InverseFourierTransformImage */
10530         {
10531           image=InverseFourierTransformImage(image,image->next,
10532             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10533             exception);
10534           break;
10535         }
10536         case 126:  /* ColorDecisionList */
10537         {
10538           if (attribute_flag[0] == 0)
10539             argument_list[0].string_reference=(char *) NULL;
10540           (void) ColorDecisionListImage(image,
10541             argument_list[0].string_reference,exception);
10542           break;
10543         }
10544         case 127:  /* AutoGamma */
10545         {
10546           if (attribute_flag[0] != 0)
10547             channel=(ChannelType) argument_list[0].integer_reference;
10548           channel_mask=SetPixelChannelMask(image,channel);
10549           (void) AutoGammaImage(image,exception);
10550           (void) SetPixelChannelMask(image,channel_mask);
10551           break;
10552         }
10553         case 128:  /* AutoLevel */
10554         {
10555           if (attribute_flag[0] != 0)
10556             channel=(ChannelType) argument_list[0].integer_reference;
10557           channel_mask=SetPixelChannelMask(image,channel);
10558           (void) AutoLevelImage(image,exception);
10559           (void) SetPixelChannelMask(image,channel_mask);
10560           break;
10561         }
10562         case 129:  /* LevelColors */
10563         {
10564           PixelInfo
10565             black_point,
10566             white_point;
10567
10568           (void) QueryMagickColor("#000000",&black_point,exception);
10569           (void) QueryMagickColor("#ffffff",&white_point,exception);
10570           if (attribute_flag[1] != 0)
10571              (void) QueryMagickColor(argument_list[1].string_reference,
10572                &black_point,exception);
10573           if (attribute_flag[2] != 0)
10574              (void) QueryMagickColor(argument_list[2].string_reference,
10575                &white_point,exception);
10576           if (attribute_flag[3] != 0)
10577             channel=(ChannelType) argument_list[3].integer_reference;
10578           channel_mask=SetPixelChannelMask(image,channel);
10579           (void) LevelImageColors(image,&black_point,&white_point,
10580             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10581             exception);
10582           (void) SetPixelChannelMask(image,channel_mask);
10583           break;
10584         }
10585         case 130:  /* Clamp */
10586         {
10587           if (attribute_flag[0] != 0)
10588             channel=(ChannelType) argument_list[0].integer_reference;
10589           channel_mask=SetPixelChannelMask(image,channel);
10590           (void) ClampImage(image);
10591           (void) SetPixelChannelMask(image,channel_mask);
10592           break;
10593         }
10594         case 132:  /* BrightnessContrast */
10595         {
10596           double
10597             brightness,
10598             contrast;
10599
10600           brightness=0.0;
10601           contrast=0.0;
10602           if (attribute_flag[0] != 0)
10603             {
10604               flags=ParseGeometry(argument_list[0].string_reference,
10605                 &geometry_info);
10606               brightness=geometry_info.rho;
10607               if ((flags & SigmaValue) == 0)
10608                 contrast=geometry_info.sigma;
10609             }
10610           if (attribute_flag[1] != 0)
10611             brightness=argument_list[1].real_reference;
10612           if (attribute_flag[2] != 0)
10613             contrast=argument_list[2].real_reference;
10614           if (attribute_flag[4] != 0)
10615             channel=(ChannelType) argument_list[4].integer_reference;
10616           channel_mask=SetPixelChannelMask(image,channel);
10617           (void) BrightnessContrastImage(image,brightness,contrast,exception);
10618           (void) SetPixelChannelMask(image,channel_mask);
10619           break;
10620         }
10621         case 133:  /* Morphology */
10622         {
10623           KernelInfo
10624             *kernel;
10625
10626           MorphologyMethod
10627             method;
10628
10629           ssize_t
10630             iterations;
10631
10632           if (attribute_flag[0] == 0)
10633             break;
10634           kernel=AcquireKernelInfo(argument_list[0].string_reference);
10635           if (kernel == (KernelInfo *) NULL)
10636             break;
10637           if (attribute_flag[1] != 0)
10638             channel=(ChannelType) argument_list[1].integer_reference;
10639           method=UndefinedMorphology;
10640           if (attribute_flag[2] != 0)
10641             method=argument_list[2].integer_reference;
10642           iterations=1;
10643           if (attribute_flag[3] != 0)
10644             iterations=argument_list[4].integer_reference;
10645           channel_mask=SetPixelChannelMask(image,channel);
10646           image=MorphologyImage(image,method,iterations,kernel,exception);
10647           if (image != (Image *) NULL)
10648             (void) SetPixelChannelMask(image,channel_mask);
10649           kernel=DestroyKernelInfo(kernel);
10650           break;
10651         }
10652         case 108:  /* Recolor */
10653         case 134:  /* ColorMatrix */
10654         {
10655           AV
10656             *av;
10657
10658           double
10659             *color_matrix;
10660
10661           KernelInfo
10662             *kernel_info;
10663
10664           size_t
10665             order;
10666
10667           if (attribute_flag[0] == 0)
10668             break;
10669           av=(AV *) argument_list[0].array_reference;
10670           if (av == (AV *) NULL)
10671             break;
10672           order=(size_t) sqrt(av_len(av)+1);
10673           color_matrix=(double *) AcquireQuantumMemory(order,order*
10674             sizeof(*color_matrix));
10675           if (color_matrix == (double *) NULL)
10676             {
10677               ThrowPerlException(exception,ResourceLimitFatalError,
10678                 "MemoryAllocationFailed",PackageName);
10679               goto PerlException;
10680            }
10681           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10682             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10683           for ( ; j < (ssize_t) (order*order); j++)
10684             color_matrix[j]=0.0;
10685           kernel_info=AcquireKernelInfo((const char *) NULL);
10686           if (kernel_info == (KernelInfo *) NULL)
10687             break;
10688           kernel_info->width=order;
10689           kernel_info->height=order;
10690           kernel_info->values=color_matrix;
10691           image=ColorMatrixImage(image,kernel_info,exception);
10692           kernel_info->values=(double *) NULL;
10693           kernel_info=DestroyKernelInfo(kernel_info);
10694           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10695           break;
10696         }
10697         case 135:  /* Color */
10698         {
10699           PixelInfo
10700             color;
10701
10702           (void) QueryMagickColor("none",&color,exception);
10703           if (attribute_flag[0] != 0)
10704             (void) QueryMagickColor(argument_list[0].string_reference,
10705               &color,exception);
10706           (void) SetImageColor(image,&color);
10707           break;
10708         }
10709         case 136:  /* Mode */
10710         {
10711           if (attribute_flag[0] != 0)
10712             {
10713               flags=ParseGeometry(argument_list[0].string_reference,
10714                 &geometry_info);
10715               if ((flags & SigmaValue) == 0)
10716                 geometry_info.sigma=1.0;
10717             }
10718           if (attribute_flag[1] != 0)
10719             geometry_info.rho=argument_list[1].real_reference;
10720           if (attribute_flag[2] != 0)
10721             geometry_info.sigma=argument_list[2].real_reference;
10722           if (attribute_flag[3] != 0)
10723             channel=(ChannelType) argument_list[3].integer_reference;
10724           channel_mask=SetPixelChannelMask(image,channel);
10725           image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
10726             (size_t) geometry_info.sigma,exception);
10727           if (image != (Image *) NULL)
10728             (void) SetPixelChannelMask(image,channel_mask);
10729           break;
10730         }
10731         case 137:  /* Statistic */
10732         {
10733           StatisticType
10734             statistic;
10735
10736           statistic=UndefinedStatistic;
10737           if (attribute_flag[0] != 0)
10738             {
10739               flags=ParseGeometry(argument_list[0].string_reference,
10740                 &geometry_info);
10741               if ((flags & SigmaValue) == 0)
10742                 geometry_info.sigma=1.0;
10743             }
10744           if (attribute_flag[1] != 0)
10745             geometry_info.rho=argument_list[1].real_reference;
10746           if (attribute_flag[2] != 0)
10747             geometry_info.sigma=argument_list[2].real_reference;
10748           if (attribute_flag[3] != 0)
10749             channel=(ChannelType) argument_list[3].integer_reference;
10750           if (attribute_flag[4] != 0)
10751             statistic=(StatisticType) argument_list[4].integer_reference;
10752           channel_mask=SetPixelChannelMask(image,channel);
10753           image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
10754             (size_t) geometry_info.sigma,exception);
10755           if (image != (Image *) NULL)
10756             (void) SetPixelChannelMask(image,channel_mask);
10757           break;
10758         }
10759       }
10760       if (next != (Image *) NULL)
10761         (void) CatchImageException(next);
10762       if (region_image != (Image *) NULL)
10763         {
10764           /*
10765             Composite region.
10766           */ 
10767           status=CompositeImage(region_image,CopyCompositeOp,image,
10768             region_info.x,region_info.y);
10769           (void) status;
10770           (void) CatchImageException(region_image);
10771           image=DestroyImage(image);
10772           image=region_image;
10773         }
10774       if (image != (Image *) NULL)
10775         {
10776           number_images++;
10777           if (next && (next != image))
10778             {
10779               image->next=next->next;
10780               if (image->next != (Image *) NULL)
10781                 image->next->previous=image;
10782               DeleteImageFromRegistry(*pv,next);
10783             }
10784           sv_setiv(*pv,(IV) image);
10785           next=image;
10786         }
10787       if (*pv)
10788         pv++;
10789     }
10790
10791   PerlException:
10792     if (reference_vector)
10793       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
10794     InheritPerlException(exception,perl_exception);
10795     exception=DestroyExceptionInfo(exception);
10796     sv_setiv(perl_exception,(IV) number_images);
10797     SvPOK_on(perl_exception);
10798     ST(0)=sv_2mortal(perl_exception);
10799     XSRETURN(1);
10800   }
10801 \f
10802 #
10803 ###############################################################################
10804 #                                                                             #
10805 #                                                                             #
10806 #                                                                             #
10807 #   M o n t a g e                                                             #
10808 #                                                                             #
10809 #                                                                             #
10810 #                                                                             #
10811 ###############################################################################
10812 #
10813 #
10814 void
10815 Montage(ref,...)
10816   Image::Magick ref=NO_INIT
10817   ALIAS:
10818     MontageImage  = 1
10819     montage       = 2
10820     montageimage  = 3
10821   PPCODE:
10822   {
10823     AV
10824       *av;
10825
10826     char
10827       *attribute;
10828
10829     ExceptionInfo
10830       *exception;
10831
10832     HV
10833       *hv;
10834
10835     Image
10836       *image,
10837       *next;
10838
10839     PixelInfo
10840       transparent_color;
10841
10842     MontageInfo
10843       *montage_info;
10844
10845     register ssize_t
10846       i;
10847
10848     ssize_t
10849       sp;
10850
10851     struct PackageInfo
10852       *info;
10853
10854     SV
10855       *av_reference,
10856       *perl_exception,
10857       *reference,
10858       *rv,
10859       *sv;
10860
10861     PERL_UNUSED_VAR(ref);
10862     PERL_UNUSED_VAR(ix);
10863     exception=AcquireExceptionInfo();
10864     perl_exception=newSVpv("",0);
10865     sv=NULL;
10866     attribute=NULL;
10867     if (sv_isobject(ST(0)) == 0)
10868       {
10869         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
10870           PackageName);
10871         goto PerlException;
10872       }
10873     reference=SvRV(ST(0));
10874     hv=SvSTASH(reference);
10875     av=newAV();
10876     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
10877     SvREFCNT_dec(av);
10878     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
10879     if (image == (Image *) NULL)
10880       {
10881         ThrowPerlException(exception,OptionError,"NoImagesDefined",
10882           PackageName);
10883         goto PerlException;
10884       }
10885     /*
10886       Get options.
10887     */
10888     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
10889     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
10890     (void) QueryMagickColor("none",&transparent_color,exception);
10891     for (i=2; i < items; i+=2)
10892     {
10893       attribute=(char *) SvPV(ST(i-1),na);
10894       switch (*attribute)
10895       {
10896         case 'B':
10897         case 'b':
10898         {
10899           if (LocaleCompare(attribute,"background") == 0)
10900             {
10901               (void) QueryColorDatabase(SvPV(ST(i),na),
10902                 &montage_info->background_color,exception);
10903               for (next=image; next; next=next->next)
10904                 next->background_color=montage_info->background_color;
10905               break;
10906             }
10907           if (LocaleCompare(attribute,"border") == 0)
10908             {
10909               montage_info->border_width=SvIV(ST(i));
10910               break;
10911             }
10912           if (LocaleCompare(attribute,"bordercolor") == 0)
10913             {
10914               (void) QueryColorDatabase(SvPV(ST(i),na),
10915                 &montage_info->border_color,exception);
10916               for (next=image; next; next=next->next)
10917                 next->border_color=montage_info->border_color;
10918               break;
10919             }
10920           if (LocaleCompare(attribute,"borderwidth") == 0)
10921             {
10922               montage_info->border_width=SvIV(ST(i));
10923               break;
10924             }
10925           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10926             attribute);
10927           break;
10928         }
10929         case 'C':
10930         case 'c':
10931         {
10932           if (LocaleCompare(attribute,"compose") == 0)
10933             {
10934               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
10935                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
10936               if (sp < 0)
10937                 {
10938                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
10939                     SvPV(ST(i),na));
10940                   break;
10941                 }
10942               for (next=image; next; next=next->next)
10943                 next->compose=(CompositeOperator) sp;
10944               break;
10945             }
10946           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10947             attribute);
10948           break;
10949         }
10950         case 'F':
10951         case 'f':
10952         {
10953           if (LocaleCompare(attribute,"fill") == 0)
10954             {
10955               (void) QueryColorDatabase(SvPV(ST(i),na),&montage_info->fill,
10956                 exception);
10957               break;
10958             }
10959           if (LocaleCompare(attribute,"font") == 0)
10960             {
10961               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
10962               break;
10963             }
10964           if (LocaleCompare(attribute,"frame") == 0)
10965             {
10966               char
10967                 *p;
10968
10969               p=SvPV(ST(i),na);
10970               if (IsGeometry(p) == MagickFalse)
10971                 {
10972                   ThrowPerlException(exception,OptionError,"MissingGeometry",
10973                     p);
10974                   break;
10975                 }
10976               (void) CloneString(&montage_info->frame,p);
10977               if (*p == '\0')
10978                 montage_info->frame=(char *) NULL;
10979               break;
10980             }
10981           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10982             attribute);
10983           break;
10984         }
10985         case 'G':
10986         case 'g':
10987         {
10988           if (LocaleCompare(attribute,"geometry") == 0)
10989             {
10990               char
10991                 *p;
10992
10993               p=SvPV(ST(i),na);
10994               if (IsGeometry(p) == MagickFalse)
10995                 {
10996                   ThrowPerlException(exception,OptionError,"MissingGeometry",
10997                     p);
10998                   break;
10999                 }
11000              (void) CloneString(&montage_info->geometry,p);
11001              if (*p == '\0')
11002                montage_info->geometry=(char *) NULL;
11003              break;
11004            }
11005          if (LocaleCompare(attribute,"gravity") == 0)
11006            {
11007              ssize_t
11008                in;
11009
11010              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11011                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11012              if (in < 0)
11013                {
11014                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
11015                    SvPV(ST(i),na));
11016                  return;
11017                }
11018              montage_info->gravity=(GravityType) in;
11019              for (next=image; next; next=next->next)
11020                next->gravity=(GravityType) in;
11021              break;
11022            }
11023           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11024             attribute);
11025           break;
11026         }
11027         case 'L':
11028         case 'l':
11029         {
11030           if (LocaleCompare(attribute,"label") == 0)
11031             {
11032               for (next=image; next; next=next->next)
11033                 (void) SetImageProperty(next,"label",InterpretImageProperties(
11034                   info ? info->image_info : (ImageInfo *) NULL,next,
11035                   SvPV(ST(i),na),exception));
11036               break;
11037             }
11038           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11039             attribute);
11040           break;
11041         }
11042         case 'M':
11043         case 'm':
11044         {
11045           if (LocaleCompare(attribute,"mattecolor") == 0)
11046             {
11047               (void) QueryColorDatabase(SvPV(ST(i),na),
11048                 &montage_info->matte_color,exception);
11049               for (next=image; next; next=next->next)
11050                 next->matte_color=montage_info->matte_color;
11051               break;
11052             }
11053           if (LocaleCompare(attribute,"mode") == 0)
11054             {
11055               ssize_t
11056                 in;
11057
11058               in=!SvPOK(ST(i)) ? SvIV(ST(i)) :
11059                 ParseCommandOption(MagickModeOptions,MagickFalse,SvPV(ST(i),na));
11060               switch (in)
11061               {
11062                 default:
11063                 {
11064                   ThrowPerlException(exception,OptionError,
11065                     "UnrecognizedModeType",SvPV(ST(i),na));
11066                   break;
11067                 }
11068                 case FrameMode:
11069                 {
11070                   (void) CloneString(&montage_info->frame,"15x15+3+3");
11071                   montage_info->shadow=MagickTrue;
11072                   break;
11073                 }
11074                 case UnframeMode:
11075                 {
11076                   montage_info->frame=(char *) NULL;
11077                   montage_info->shadow=MagickFalse;
11078                   montage_info->border_width=0;
11079                   break;
11080                 }
11081                 case ConcatenateMode:
11082                 {
11083                   montage_info->frame=(char *) NULL;
11084                   montage_info->shadow=MagickFalse;
11085                   (void) CloneString(&montage_info->geometry,"+0+0");
11086                   montage_info->border_width=0;
11087                 }
11088               }
11089               break;
11090             }
11091           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11092             attribute);
11093           break;
11094         }
11095         case 'P':
11096         case 'p':
11097         {
11098           if (LocaleCompare(attribute,"pointsize") == 0)
11099             {
11100               montage_info->pointsize=SvIV(ST(i));
11101               break;
11102             }
11103           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11104             attribute);
11105           break;
11106         }
11107         case 'S':
11108         case 's':
11109         {
11110           if (LocaleCompare(attribute,"shadow") == 0)
11111             {
11112               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11113                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11114               if (sp < 0)
11115                 {
11116                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11117                     SvPV(ST(i),na));
11118                   break;
11119                 }
11120              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11121              break;
11122             }
11123           if (LocaleCompare(attribute,"stroke") == 0)
11124             {
11125               (void) QueryColorDatabase(SvPV(ST(i),na),&montage_info->stroke,
11126                 exception);
11127               break;
11128             }
11129           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11130             attribute);
11131           break;
11132         }
11133         case 'T':
11134         case 't':
11135         {
11136           if (LocaleCompare(attribute,"texture") == 0)
11137             {
11138               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11139               break;
11140             }
11141           if (LocaleCompare(attribute,"tile") == 0)
11142             {
11143               char *p=SvPV(ST(i),na);
11144               if (IsGeometry(p) == MagickFalse)
11145                 {
11146                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11147                     p);
11148                   break;
11149                 }
11150               (void) CloneString(&montage_info->tile,p);
11151               if (*p == '\0')
11152                 montage_info->tile=(char *) NULL;
11153               break;
11154             }
11155           if (LocaleCompare(attribute,"title") == 0)
11156             {
11157               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11158               break;
11159             }
11160           if (LocaleCompare(attribute,"transparent") == 0)
11161             {
11162               PixelInfo
11163                 transparent_color;
11164
11165               QueryMagickColor(SvPV(ST(i),na),&transparent_color,exception);
11166               for (next=image; next; next=next->next)
11167                 (void) TransparentPaintImage(next,&transparent_color,
11168                   TransparentAlpha,MagickFalse,exception);
11169               break;
11170             }
11171           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11172             attribute);
11173           break;
11174         }
11175         default:
11176         {
11177           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11178             attribute);
11179           break;
11180         }
11181       }
11182     }
11183     image=MontageImageList(info->image_info,montage_info,image,exception);
11184     montage_info=DestroyMontageInfo(montage_info);
11185     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11186       goto PerlException;
11187     if (transparent_color.alpha != TransparentAlpha)
11188       for (next=image; next; next=next->next)
11189         (void) TransparentPaintImage(next,&transparent_color,
11190           TransparentAlpha,MagickFalse,exception);
11191     for (  ; image; image=image->next)
11192     {
11193       AddImageToRegistry(sv,image);
11194       rv=newRV(sv);
11195       av_push(av,sv_bless(rv,hv));
11196       SvREFCNT_dec(sv);
11197     }
11198     exception=DestroyExceptionInfo(exception);
11199     ST(0)=av_reference;
11200     SvREFCNT_dec(perl_exception);
11201     XSRETURN(1);
11202
11203   PerlException:
11204     InheritPerlException(exception,perl_exception);
11205     exception=DestroyExceptionInfo(exception);
11206     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11207     SvPOK_on(perl_exception);
11208     ST(0)=sv_2mortal(perl_exception);
11209     XSRETURN(1);
11210   }
11211 \f
11212 #
11213 ###############################################################################
11214 #                                                                             #
11215 #                                                                             #
11216 #                                                                             #
11217 #   M o r p h                                                                 #
11218 #                                                                             #
11219 #                                                                             #
11220 #                                                                             #
11221 ###############################################################################
11222 #
11223 #
11224 void
11225 Morph(ref,...)
11226   Image::Magick ref=NO_INIT
11227   ALIAS:
11228     MorphImage  = 1
11229     morph       = 2
11230     morphimage  = 3
11231   PPCODE:
11232   {
11233     AV
11234       *av;
11235
11236     char
11237       *attribute;
11238
11239     ExceptionInfo
11240       *exception;
11241
11242     HV
11243       *hv;
11244
11245     Image
11246       *image;
11247
11248     register ssize_t
11249       i;
11250
11251     ssize_t
11252       number_frames;
11253
11254     struct PackageInfo
11255       *info;
11256
11257     SV
11258       *av_reference,
11259       *perl_exception,
11260       *reference,
11261       *rv,
11262       *sv;
11263
11264     PERL_UNUSED_VAR(ref);
11265     PERL_UNUSED_VAR(ix);
11266     exception=AcquireExceptionInfo();
11267     perl_exception=newSVpv("",0);
11268     sv=NULL;
11269     av=NULL;
11270     attribute=NULL;
11271     if (sv_isobject(ST(0)) == 0)
11272       {
11273         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11274           PackageName);
11275         goto PerlException;
11276       }
11277     reference=SvRV(ST(0));
11278     hv=SvSTASH(reference);
11279     av=newAV();
11280     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11281     SvREFCNT_dec(av);
11282     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11283     if (image == (Image *) NULL)
11284       {
11285         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11286           PackageName);
11287         goto PerlException;
11288       }
11289     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11290     /*
11291       Get attribute.
11292     */
11293     number_frames=30;
11294     for (i=2; i < items; i+=2)
11295     {
11296       attribute=(char *) SvPV(ST(i-1),na);
11297       switch (*attribute)
11298       {
11299         case 'F':
11300         case 'f':
11301         {
11302           if (LocaleCompare(attribute,"frames") == 0)
11303             {
11304               number_frames=SvIV(ST(i));
11305               break;
11306             }
11307           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11308             attribute);
11309           break;
11310         }
11311         default:
11312         {
11313           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11314             attribute);
11315           break;
11316         }
11317       }
11318     }
11319     image=MorphImages(image,number_frames,exception);
11320     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11321       goto PerlException;
11322     for ( ; image; image=image->next)
11323     {
11324       AddImageToRegistry(sv,image);
11325       rv=newRV(sv);
11326       av_push(av,sv_bless(rv,hv));
11327       SvREFCNT_dec(sv);
11328     }
11329     exception=DestroyExceptionInfo(exception);
11330     ST(0)=av_reference;
11331     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11332     XSRETURN(1);
11333
11334   PerlException:
11335     InheritPerlException(exception,perl_exception);
11336     exception=DestroyExceptionInfo(exception);
11337     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11338     SvPOK_on(perl_exception);
11339     ST(0)=sv_2mortal(perl_exception);
11340     XSRETURN(1);
11341   }
11342 \f
11343 #
11344 ###############################################################################
11345 #                                                                             #
11346 #                                                                             #
11347 #                                                                             #
11348 #   M o s a i c                                                               #
11349 #                                                                             #
11350 #                                                                             #
11351 #                                                                             #
11352 ###############################################################################
11353 #
11354 #
11355 void
11356 Mosaic(ref)
11357   Image::Magick ref=NO_INIT
11358   ALIAS:
11359     MosaicImage   = 1
11360     mosaic        = 2
11361     mosaicimage   = 3
11362   PPCODE:
11363   {
11364     AV
11365       *av;
11366
11367     ExceptionInfo
11368       *exception;
11369
11370     HV
11371       *hv;
11372
11373     Image
11374       *image;
11375
11376     struct PackageInfo
11377       *info;
11378
11379     SV
11380       *perl_exception,
11381       *reference,
11382       *rv,
11383       *sv;
11384
11385     PERL_UNUSED_VAR(ref);
11386     PERL_UNUSED_VAR(ix);
11387     exception=AcquireExceptionInfo();
11388     perl_exception=newSVpv("",0);
11389     sv=NULL;
11390     if (sv_isobject(ST(0)) == 0)
11391       {
11392         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11393           PackageName);
11394         goto PerlException;
11395       }
11396     reference=SvRV(ST(0));
11397     hv=SvSTASH(reference);
11398     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11399     if (image == (Image *) NULL)
11400       {
11401         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11402           PackageName);
11403         goto PerlException;
11404       }
11405     image=MergeImageLayers(image,MosaicLayer,exception);
11406     /*
11407       Create blessed Perl array for the returned image.
11408     */
11409     av=newAV();
11410     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11411     SvREFCNT_dec(av);
11412     AddImageToRegistry(sv,image);
11413     rv=newRV(sv);
11414     av_push(av,sv_bless(rv,hv));
11415     SvREFCNT_dec(sv);
11416     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11417     (void) CopyMagickString(info->image_info->filename,image->filename,
11418       MaxTextExtent);
11419     SetImageInfo(info->image_info,0,&image->exception);
11420     exception=DestroyExceptionInfo(exception);
11421     SvREFCNT_dec(perl_exception);
11422     XSRETURN(1);
11423
11424   PerlException:
11425     InheritPerlException(exception,perl_exception);
11426     exception=DestroyExceptionInfo(exception);
11427     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11428     SvPOK_on(perl_exception);  /* return messages in string context */
11429     ST(0)=sv_2mortal(perl_exception);
11430     XSRETURN(1);
11431   }
11432 \f
11433 #
11434 ###############################################################################
11435 #                                                                             #
11436 #                                                                             #
11437 #                                                                             #
11438 #   P i n g                                                                   #
11439 #                                                                             #
11440 #                                                                             #
11441 #                                                                             #
11442 ###############################################################################
11443 #
11444 #
11445 void
11446 Ping(ref,...)
11447   Image::Magick ref=NO_INIT
11448   ALIAS:
11449     PingImage  = 1
11450     ping       = 2
11451     pingimage  = 3
11452   PPCODE:
11453   {
11454     AV
11455       *av;
11456
11457     char
11458       **keep,
11459       **list;
11460
11461     ExceptionInfo
11462       *exception;
11463
11464     Image
11465       *image,
11466       *next;
11467
11468     int
11469       n;
11470
11471     MagickBooleanType
11472       status;
11473
11474     register char
11475       **p;
11476
11477     register ssize_t
11478       i;
11479
11480     ssize_t
11481       ac;
11482
11483     STRLEN
11484       *length;
11485
11486     struct PackageInfo
11487       *info,
11488       *package_info;
11489
11490     SV
11491       *perl_exception,
11492       *reference;
11493
11494     size_t
11495       count;
11496
11497     PERL_UNUSED_VAR(ref);
11498     PERL_UNUSED_VAR(ix);
11499     exception=AcquireExceptionInfo();
11500     perl_exception=newSVpv("",0);
11501     package_info=(struct PackageInfo *) NULL;
11502     ac=(items < 2) ? 1 : items-1;
11503     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
11504     keep=list;
11505     length=(STRLEN *) NULL;
11506     if (list == (char **) NULL)
11507       {
11508         ThrowPerlException(exception,ResourceLimitError,
11509           "MemoryAllocationFailed",PackageName);
11510         goto PerlException;
11511       }
11512     keep=list;
11513     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
11514     if (length == (STRLEN *) NULL)
11515       {
11516         ThrowPerlException(exception,ResourceLimitError,
11517           "MemoryAllocationFailed",PackageName);
11518         goto PerlException;
11519       }
11520     if (sv_isobject(ST(0)) == 0)
11521       {
11522         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11523           PackageName);
11524         goto PerlException;
11525       }
11526     reference=SvRV(ST(0));
11527     if (SvTYPE(reference) != SVt_PVAV)
11528       {
11529         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11530           PackageName);
11531         goto PerlException;
11532       }
11533     av=(AV *) reference;
11534     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11535       exception);
11536     package_info=ClonePackageInfo(info,exception);
11537     n=1;
11538     if (items <= 1)
11539       *list=(char *) (*package_info->image_info->filename ?
11540         package_info->image_info->filename : "XC:black");
11541     else
11542       for (n=0, i=0; i < ac; i++)
11543       {
11544         list[n]=(char *) SvPV(ST(i+1),length[n]);
11545         if ((items >= 3) && strEQcase(list[n],"blob"))
11546           {
11547             void
11548               *blob;
11549
11550             i++;
11551             blob=(void *) (SvPV(ST(i+1),length[n]));
11552             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
11553           }
11554         if ((items >= 3) && strEQcase(list[n],"filename"))
11555           continue;
11556         if ((items >= 3) && strEQcase(list[n],"file"))
11557           {
11558             FILE
11559               *file;
11560
11561             PerlIO
11562               *io_info;
11563
11564             i++;
11565             io_info=IoIFP(sv_2io(ST(i+1)));
11566             if (io_info == (PerlIO *) NULL)
11567               {
11568                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11569                   PackageName);
11570                 continue;
11571               }
11572             file=PerlIO_findFILE(io_info);
11573             if (file == (FILE *) NULL)
11574               {
11575                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11576                   PackageName);
11577                 continue;
11578               }
11579             SetImageInfoFile(package_info->image_info,file);
11580           }
11581         if ((items >= 3) && strEQcase(list[n],"magick"))
11582           continue;
11583         n++;
11584       }
11585     list[n]=(char *) NULL;
11586     keep=list;
11587     status=ExpandFilenames(&n,&list);
11588     if (status == MagickFalse)
11589       {
11590         ThrowPerlException(exception,ResourceLimitError,
11591           "MemoryAllocationFailed",PackageName);
11592         goto PerlException;
11593       }
11594     count=0;
11595     for (i=0; i < n; i++)
11596     {
11597       (void) CopyMagickString(package_info->image_info->filename,list[i],
11598         MaxTextExtent);
11599       image=PingImage(package_info->image_info,exception);
11600       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11601         break;
11602       if ((package_info->image_info->file != (FILE *) NULL) ||
11603           (package_info->image_info->blob != (void *) NULL))
11604         DisassociateImageStream(image);
11605       count+=GetImageListLength(image);
11606       EXTEND(sp,4*count);
11607       for (next=image; next; next=next->next)
11608       {
11609         PUSHs(sv_2mortal(newSViv(next->columns)));
11610         PUSHs(sv_2mortal(newSViv(next->rows)));
11611         PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
11612         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
11613       }
11614       image=DestroyImageList(image);
11615     }
11616     /*
11617       Free resources.
11618     */
11619     for (i=0; i < n; i++)
11620       if (list[i] != (char *) NULL)
11621         for (p=keep; list[i] != *p++; )
11622           if (*p == NULL)
11623             {
11624               list[i]=(char *) RelinquishMagickMemory(list[i]);
11625               break;
11626             }
11627
11628   PerlException:
11629     if (package_info != (struct PackageInfo *) NULL)
11630       DestroyPackageInfo(package_info);
11631     if (list && (list != keep))
11632       list=(char **) RelinquishMagickMemory(list);
11633     if (keep)
11634       keep=(char **) RelinquishMagickMemory(keep);
11635     if (length)
11636       length=(STRLEN *) RelinquishMagickMemory(length);
11637     InheritPerlException(exception,perl_exception);
11638     exception=DestroyExceptionInfo(exception);
11639     SvREFCNT_dec(perl_exception);  /* throw away all errors */
11640   }
11641 \f
11642 #
11643 ###############################################################################
11644 #                                                                             #
11645 #                                                                             #
11646 #                                                                             #
11647 #   P r e v i e w                                                             #
11648 #                                                                             #
11649 #                                                                             #
11650 #                                                                             #
11651 ###############################################################################
11652 #
11653 #
11654 void
11655 Preview(ref,...)
11656   Image::Magick ref=NO_INIT
11657   ALIAS:
11658     PreviewImage = 1
11659     preview      = 2
11660     previewimage = 3
11661   PPCODE:
11662   {
11663     AV
11664       *av;
11665
11666     ExceptionInfo
11667       *exception;
11668
11669     HV
11670       *hv;
11671
11672     Image
11673       *image,
11674       *preview_image;
11675
11676     PreviewType
11677       preview_type;
11678
11679     struct PackageInfo
11680       *info;
11681
11682     SV
11683       *av_reference,
11684       *perl_exception,
11685       *reference,
11686       *rv,
11687       *sv;
11688
11689     PERL_UNUSED_VAR(ref);
11690     PERL_UNUSED_VAR(ix);
11691     exception=AcquireExceptionInfo();
11692     perl_exception=newSVpv("",0);
11693     sv=NULL;
11694     av=NULL;
11695     if (sv_isobject(ST(0)) == 0)
11696       {
11697         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11698           PackageName);
11699         goto PerlException;
11700       }
11701     reference=SvRV(ST(0));
11702     hv=SvSTASH(reference);
11703     av=newAV();
11704     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11705     SvREFCNT_dec(av);
11706     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11707     if (image == (Image *) NULL)
11708       {
11709         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11710           PackageName);
11711         goto PerlException;
11712       }
11713     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11714     preview_type=GammaPreview;
11715     if (items > 1)
11716       preview_type=(PreviewType)
11717         ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
11718     for ( ; image; image=image->next)
11719     {
11720       preview_image=PreviewImage(image,preview_type,exception);
11721       if (preview_image == (Image *) NULL)
11722         goto PerlException;
11723       AddImageToRegistry(sv,preview_image);
11724       rv=newRV(sv);
11725       av_push(av,sv_bless(rv,hv));
11726       SvREFCNT_dec(sv);
11727     }
11728     exception=DestroyExceptionInfo(exception);
11729     ST(0)=av_reference;
11730     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11731     XSRETURN(1);
11732
11733   PerlException:
11734     InheritPerlException(exception,perl_exception);
11735     exception=DestroyExceptionInfo(exception);
11736     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11737     SvPOK_on(perl_exception);
11738     ST(0)=sv_2mortal(perl_exception);
11739     XSRETURN(1);
11740   }
11741 \f
11742 #
11743 ###############################################################################
11744 #                                                                             #
11745 #                                                                             #
11746 #                                                                             #
11747 #   Q u e r y C o l o r                                                       #
11748 #                                                                             #
11749 #                                                                             #
11750 #                                                                             #
11751 ###############################################################################
11752 #
11753 #
11754 void
11755 QueryColor(ref,...)
11756   Image::Magick ref=NO_INIT
11757   ALIAS:
11758     querycolor = 1
11759   PPCODE:
11760   {
11761     char
11762       *name;
11763
11764     ExceptionInfo
11765       *exception;
11766
11767     PixelInfo
11768       color;
11769
11770     register ssize_t
11771       i;
11772
11773     SV
11774       *perl_exception;
11775
11776     PERL_UNUSED_VAR(ref);
11777     PERL_UNUSED_VAR(ix);
11778     exception=AcquireExceptionInfo();
11779     perl_exception=newSVpv("",0);
11780     if (items == 1)
11781       {
11782         const ColorInfo
11783           **colorlist;
11784
11785         size_t
11786           colors;
11787
11788         colorlist=GetColorInfoList("*",&colors,exception);
11789         EXTEND(sp,colors);
11790         for (i=0; i < (ssize_t) colors; i++)
11791         {
11792           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
11793         }
11794         colorlist=(const ColorInfo **)
11795           RelinquishMagickMemory((ColorInfo **) colorlist);
11796         goto PerlException;
11797       }
11798     EXTEND(sp,5*items);
11799     for (i=1; i < items; i++)
11800     {
11801       name=(char *) SvPV(ST(i),na);
11802       if (QueryMagickColor(name,&color,exception) == MagickFalse)
11803         {
11804           PUSHs(&sv_undef);
11805           continue;
11806         }
11807       PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
11808       PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
11809       PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
11810       if (color.colorspace == CMYKColorspace)
11811         PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
11812       if (color.matte != MagickFalse)
11813         PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
11814     }
11815
11816   PerlException:
11817     InheritPerlException(exception,perl_exception);
11818     exception=DestroyExceptionInfo(exception);
11819     SvREFCNT_dec(perl_exception);
11820   }
11821 \f
11822 #
11823 ###############################################################################
11824 #                                                                             #
11825 #                                                                             #
11826 #                                                                             #
11827 #   Q u e r y C o l o r N a m e                                               #
11828 #                                                                             #
11829 #                                                                             #
11830 #                                                                             #
11831 ###############################################################################
11832 #
11833 #
11834 void
11835 QueryColorname(ref,...)
11836   Image::Magick ref=NO_INIT
11837   ALIAS:
11838     querycolorname = 1
11839   PPCODE:
11840   {
11841     AV
11842       *av;
11843
11844     char
11845       message[MaxTextExtent];
11846
11847     ExceptionInfo
11848       *exception;
11849
11850     Image
11851       *image;
11852
11853     PixelPacket
11854       target_color;
11855
11856     register ssize_t
11857       i;
11858
11859     struct PackageInfo
11860       *info;
11861
11862     SV
11863       *perl_exception,
11864       *reference;  /* reference is the SV* of ref=SvIV(reference) */
11865
11866     PERL_UNUSED_VAR(ref);
11867     PERL_UNUSED_VAR(ix);
11868     exception=AcquireExceptionInfo();
11869     perl_exception=newSVpv("",0);
11870     reference=SvRV(ST(0));
11871     av=(AV *) reference;
11872     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11873       exception);
11874     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11875     if (image == (Image *) NULL)
11876       {
11877         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11878           PackageName);
11879         goto PerlException;
11880       }
11881     EXTEND(sp,items);
11882     for (i=1; i < items; i++)
11883     {
11884       (void) QueryColorDatabase(SvPV(ST(i),na),&target_color,exception);
11885       (void) QueryColorname(image,&target_color,SVGCompliance,message,
11886         exception);
11887       PUSHs(sv_2mortal(newSVpv(message,0)));
11888     }
11889
11890   PerlException:
11891     InheritPerlException(exception,perl_exception);
11892     exception=DestroyExceptionInfo(exception);
11893     SvREFCNT_dec(perl_exception);
11894   }
11895 \f
11896 #
11897 ###############################################################################
11898 #                                                                             #
11899 #                                                                             #
11900 #                                                                             #
11901 #   Q u e r y F o n t                                                         #
11902 #                                                                             #
11903 #                                                                             #
11904 #                                                                             #
11905 ###############################################################################
11906 #
11907 #
11908 void
11909 QueryFont(ref,...)
11910   Image::Magick ref=NO_INIT
11911   ALIAS:
11912     queryfont = 1
11913   PPCODE:
11914   {
11915     char
11916       *name,
11917       message[MaxTextExtent];
11918
11919     ExceptionInfo
11920       *exception;
11921
11922     register ssize_t
11923       i;
11924
11925     SV
11926       *perl_exception;
11927
11928     volatile const TypeInfo
11929       *type_info;
11930
11931     PERL_UNUSED_VAR(ref);
11932     PERL_UNUSED_VAR(ix);
11933     exception=AcquireExceptionInfo();
11934     perl_exception=newSVpv("",0);
11935     if (items == 1)
11936       {
11937         const TypeInfo
11938           **typelist;
11939
11940         size_t
11941           types;
11942
11943         typelist=GetTypeInfoList("*",&types,exception);
11944         EXTEND(sp,types);
11945         for (i=0; i < (ssize_t) types; i++)
11946         {
11947           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
11948         }
11949         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
11950           typelist);
11951         goto PerlException;
11952       }
11953     EXTEND(sp,10*items);
11954     for (i=1; i < items; i++)
11955     {
11956       name=(char *) SvPV(ST(i),na);
11957       type_info=GetTypeInfo(name,exception);
11958       if (type_info == (TypeInfo *) NULL)
11959         {
11960           PUSHs(&sv_undef);
11961           continue;
11962         }
11963       if (type_info->name == (char *) NULL)
11964         PUSHs(&sv_undef);
11965       else
11966         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
11967       if (type_info->description == (char *) NULL)
11968         PUSHs(&sv_undef);
11969       else
11970         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
11971       if (type_info->family == (char *) NULL)
11972         PUSHs(&sv_undef);
11973       else
11974         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
11975       if (type_info->style == UndefinedStyle)
11976         PUSHs(&sv_undef);
11977       else
11978         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
11979           type_info->style),0)));
11980       if (type_info->stretch == UndefinedStretch)
11981         PUSHs(&sv_undef);
11982       else
11983         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
11984           type_info->stretch),0)));
11985       (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
11986         type_info->weight);
11987       PUSHs(sv_2mortal(newSVpv(message,0)));
11988       if (type_info->encoding == (char *) NULL)
11989         PUSHs(&sv_undef);
11990       else
11991         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
11992       if (type_info->foundry == (char *) NULL)
11993         PUSHs(&sv_undef);
11994       else
11995         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
11996       if (type_info->format == (char *) NULL)
11997         PUSHs(&sv_undef);
11998       else
11999         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
12000       if (type_info->metrics == (char *) NULL)
12001         PUSHs(&sv_undef);
12002       else
12003         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
12004       if (type_info->glyphs == (char *) NULL)
12005         PUSHs(&sv_undef);
12006       else
12007         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
12008     }
12009
12010   PerlException:
12011     InheritPerlException(exception,perl_exception);
12012     exception=DestroyExceptionInfo(exception);
12013     SvREFCNT_dec(perl_exception);
12014   }
12015 \f
12016 #
12017 ###############################################################################
12018 #                                                                             #
12019 #                                                                             #
12020 #                                                                             #
12021 #   Q u e r y F o n t M e t r i c s                                           #
12022 #                                                                             #
12023 #                                                                             #
12024 #                                                                             #
12025 ###############################################################################
12026 #
12027 #
12028 void
12029 QueryFontMetrics(ref,...)
12030   Image::Magick ref=NO_INIT
12031   ALIAS:
12032     queryfontmetrics = 1
12033   PPCODE:
12034   {
12035     AffineMatrix
12036       affine,
12037       current;
12038
12039     AV
12040       *av;
12041
12042     char
12043       *attribute;
12044
12045     double
12046       x,
12047       y;
12048
12049     DrawInfo
12050       *draw_info;
12051
12052     ExceptionInfo
12053       *exception;
12054
12055     GeometryInfo
12056       geometry_info;
12057
12058     Image
12059       *image;
12060
12061     MagickBooleanType
12062       status;
12063
12064     MagickStatusType
12065       flags;
12066
12067     register ssize_t
12068       i;
12069
12070     ssize_t
12071       type;
12072
12073     struct PackageInfo
12074       *info,
12075       *package_info;
12076
12077     SV
12078       *perl_exception,
12079       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12080
12081     TypeMetric
12082       metrics;
12083
12084     PERL_UNUSED_VAR(ref);
12085     PERL_UNUSED_VAR(ix);
12086     exception=AcquireExceptionInfo();
12087     package_info=(struct PackageInfo *) NULL;
12088     perl_exception=newSVpv("",0);
12089     reference=SvRV(ST(0));
12090     av=(AV *) reference;
12091     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12092       exception);
12093     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12094     if (image == (Image *) NULL)
12095       {
12096         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12097           PackageName);
12098         goto PerlException;
12099       }
12100     package_info=ClonePackageInfo(info,exception);
12101     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12102     CloneString(&draw_info->text,"");
12103     current=draw_info->affine;
12104     GetAffineMatrix(&affine);
12105     x=0.0;
12106     y=0.0;
12107     EXTEND(sp,7*items);
12108     for (i=2; i < items; i+=2)
12109     {
12110       attribute=(char *) SvPV(ST(i-1),na);
12111       switch (*attribute)
12112       {
12113         case 'A':
12114         case 'a':
12115         {
12116           if (LocaleCompare(attribute,"antialias") == 0)
12117             {
12118               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12119                 SvPV(ST(i),na));
12120               if (type < 0)
12121                 {
12122                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12123                     SvPV(ST(i),na));
12124                   break;
12125                 }
12126               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12127               break;
12128             }
12129           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12130             attribute);
12131           break;
12132         }
12133         case 'd':
12134         case 'D':
12135         {
12136           if (LocaleCompare(attribute,"density") == 0)
12137             {
12138               CloneString(&draw_info->density,SvPV(ST(i),na));
12139               break;
12140             }
12141           if (LocaleCompare(attribute,"direction") == 0)
12142             {
12143               draw_info->direction=(DirectionType) ParseCommandOption(
12144                 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12145               break;
12146             }
12147           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12148             attribute);
12149           break;
12150         }
12151         case 'e':
12152         case 'E':
12153         {
12154           if (LocaleCompare(attribute,"encoding") == 0)
12155             {
12156               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12157               break;
12158             }
12159           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12160             attribute);
12161           break;
12162         }
12163         case 'f':
12164         case 'F':
12165         {
12166           if (LocaleCompare(attribute,"family") == 0)
12167             {
12168               CloneString(&draw_info->family,SvPV(ST(i),na));
12169               break;
12170             }
12171           if (LocaleCompare(attribute,"fill") == 0)
12172             {
12173               if (info)
12174                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->fill,
12175                   &image->exception);
12176               break;
12177             }
12178           if (LocaleCompare(attribute,"font") == 0)
12179             {
12180               CloneString(&draw_info->font,SvPV(ST(i),na));
12181               break;
12182             }
12183           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12184             attribute);
12185           break;
12186         }
12187         case 'g':
12188         case 'G':
12189         {
12190           if (LocaleCompare(attribute,"geometry") == 0)
12191             {
12192               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12193               break;
12194             }
12195           if (LocaleCompare(attribute,"gravity") == 0)
12196             {
12197               draw_info->gravity=(GravityType) ParseCommandOption(
12198                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12199               break;
12200             }
12201           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12202             attribute);
12203           break;
12204         }
12205         case 'i':
12206         case 'I':
12207         {
12208           if (LocaleCompare(attribute,"interline-spacing") == 0)
12209             {
12210               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12211               draw_info->interline_spacing=geometry_info.rho;
12212               break;
12213             }
12214           if (LocaleCompare(attribute,"interword-spacing") == 0)
12215             {
12216               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12217               draw_info->interword_spacing=geometry_info.rho;
12218               break;
12219             }
12220           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12221             attribute);
12222           break;
12223         }
12224         case 'k':
12225         case 'K':
12226         {
12227           if (LocaleCompare(attribute,"kerning") == 0)
12228             {
12229               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12230               draw_info->kerning=geometry_info.rho;
12231               break;
12232             }
12233           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12234             attribute);
12235           break;
12236         }
12237         case 'p':
12238         case 'P':
12239         {
12240           if (LocaleCompare(attribute,"pointsize") == 0)
12241             {
12242               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12243               draw_info->pointsize=geometry_info.rho;
12244               break;
12245             }
12246           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12247             attribute);
12248           break;
12249         }
12250         case 'r':
12251         case 'R':
12252         {
12253           if (LocaleCompare(attribute,"rotate") == 0)
12254             {
12255               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12256               affine.rx=geometry_info.rho;
12257               affine.ry=geometry_info.sigma;
12258               if ((flags & SigmaValue) == 0)
12259                 affine.ry=affine.rx;
12260               break;
12261             }
12262           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12263             attribute);
12264           break;
12265         }
12266         case 's':
12267         case 'S':
12268         {
12269           if (LocaleCompare(attribute,"scale") == 0)
12270             {
12271               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12272               affine.sx=geometry_info.rho;
12273               affine.sy=geometry_info.sigma;
12274               if ((flags & SigmaValue) == 0)
12275                 affine.sy=affine.sx;
12276               break;
12277             }
12278           if (LocaleCompare(attribute,"skew") == 0)
12279             {
12280               double
12281                 x_angle,
12282                 y_angle;
12283
12284               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12285               x_angle=geometry_info.rho;
12286               y_angle=geometry_info.sigma;
12287               if ((flags & SigmaValue) == 0)
12288                 y_angle=x_angle;
12289               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12290               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12291               break;
12292             }
12293           if (LocaleCompare(attribute,"stroke") == 0)
12294             {
12295               if (info)
12296                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->stroke,
12297                   &image->exception);
12298               break;
12299             }
12300           if (LocaleCompare(attribute,"style") == 0)
12301             {
12302               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12303                 SvPV(ST(i),na));
12304               if (type < 0)
12305                 {
12306                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12307                     SvPV(ST(i),na));
12308                   break;
12309                 }
12310               draw_info->style=(StyleType) type;
12311               break;
12312             }
12313           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12314             attribute);
12315           break;
12316         }
12317         case 't':
12318         case 'T':
12319         {
12320           if (LocaleCompare(attribute,"text") == 0)
12321             {
12322               CloneString(&draw_info->text,SvPV(ST(i),na));
12323               break;
12324             }
12325           if (LocaleCompare(attribute,"translate") == 0)
12326             {
12327               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12328               affine.tx=geometry_info.rho;
12329               affine.ty=geometry_info.sigma;
12330               if ((flags & SigmaValue) == 0)
12331                 affine.ty=affine.tx;
12332               break;
12333             }
12334           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12335             attribute);
12336           break;
12337         }
12338         case 'w':
12339         case 'W':
12340         {
12341           if (LocaleCompare(attribute,"weight") == 0)
12342             {
12343               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12344               draw_info->weight=(size_t) geometry_info.rho;
12345               break;
12346             }
12347           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12348             attribute);
12349           break;
12350         }
12351         case 'x':
12352         case 'X':
12353         {
12354           if (LocaleCompare(attribute,"x") == 0)
12355             {
12356               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12357               x=geometry_info.rho;
12358               break;
12359             }
12360           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12361             attribute);
12362           break;
12363         }
12364         case 'y':
12365         case 'Y':
12366         {
12367           if (LocaleCompare(attribute,"y") == 0)
12368             {
12369               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12370               y=geometry_info.rho;
12371               break;
12372             }
12373           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12374             attribute);
12375           break;
12376         }
12377         default:
12378         {
12379           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12380             attribute);
12381           break;
12382         }
12383       }
12384     }
12385     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12386     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12387     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12388     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12389     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12390     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12391     if (draw_info->geometry == (char *) NULL)
12392       {
12393         draw_info->geometry=AcquireString((char *) NULL);
12394         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12395           "%.15g,%.15g",x,y);
12396       }
12397     status=GetTypeMetrics(image,draw_info,&metrics,exception);
12398     (void) CatchImageException(image);
12399     if (status == MagickFalse)
12400       PUSHs(&sv_undef);
12401     else
12402       {
12403         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12404         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12405         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12406         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12407         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12408         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12409         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12410         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12411         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12412         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12413         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12414         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12415         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12416       }
12417     draw_info=DestroyDrawInfo(draw_info);
12418
12419   PerlException:
12420     if (package_info != (struct PackageInfo *) NULL)
12421       DestroyPackageInfo(package_info);
12422     InheritPerlException(exception,perl_exception);
12423     exception=DestroyExceptionInfo(exception);
12424     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12425   }
12426 \f
12427 #
12428 ###############################################################################
12429 #                                                                             #
12430 #                                                                             #
12431 #                                                                             #
12432 #   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                         #
12433 #                                                                             #
12434 #                                                                             #
12435 #                                                                             #
12436 ###############################################################################
12437 #
12438 #
12439 void
12440 QueryMultilineFontMetrics(ref,...)
12441   Image::Magick ref=NO_INIT
12442   ALIAS:
12443     querymultilinefontmetrics = 1
12444   PPCODE:
12445   {
12446     AffineMatrix
12447       affine,
12448       current;
12449
12450     AV
12451       *av;
12452
12453     char
12454       *attribute;
12455
12456     double
12457       x,
12458       y;
12459
12460     DrawInfo
12461       *draw_info;
12462
12463     ExceptionInfo
12464       *exception;
12465
12466     GeometryInfo
12467       geometry_info;
12468
12469     Image
12470       *image;
12471
12472     MagickBooleanType
12473       status;
12474
12475     MagickStatusType
12476       flags;
12477
12478     register ssize_t
12479       i;
12480
12481     ssize_t
12482       type;
12483
12484     struct PackageInfo
12485       *info,
12486       *package_info;
12487
12488     SV
12489       *perl_exception,
12490       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12491
12492     TypeMetric
12493       metrics;
12494
12495     PERL_UNUSED_VAR(ref);
12496     PERL_UNUSED_VAR(ix);
12497     exception=AcquireExceptionInfo();
12498     package_info=(struct PackageInfo *) NULL;
12499     perl_exception=newSVpv("",0);
12500     reference=SvRV(ST(0));
12501     av=(AV *) reference;
12502     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12503       exception);
12504     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12505     if (image == (Image *) NULL)
12506       {
12507         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12508           PackageName);
12509         goto PerlException;
12510       }
12511     package_info=ClonePackageInfo(info,exception);
12512     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12513     CloneString(&draw_info->text,"");
12514     current=draw_info->affine;
12515     GetAffineMatrix(&affine);
12516     x=0.0;
12517     y=0.0;
12518     EXTEND(sp,7*items);
12519     for (i=2; i < items; i+=2)
12520     {
12521       attribute=(char *) SvPV(ST(i-1),na);
12522       switch (*attribute)
12523       {
12524         case 'A':
12525         case 'a':
12526         {
12527           if (LocaleCompare(attribute,"antialias") == 0)
12528             {
12529               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12530                 SvPV(ST(i),na));
12531               if (type < 0)
12532                 {
12533                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12534                     SvPV(ST(i),na));
12535                   break;
12536                 }
12537               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12538               break;
12539             }
12540           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12541             attribute);
12542           break;
12543         }
12544         case 'd':
12545         case 'D':
12546         {
12547           if (LocaleCompare(attribute,"density") == 0)
12548             {
12549               CloneString(&draw_info->density,SvPV(ST(i),na));
12550               break;
12551             }
12552           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12553             attribute);
12554           break;
12555         }
12556         case 'e':
12557         case 'E':
12558         {
12559           if (LocaleCompare(attribute,"encoding") == 0)
12560             {
12561               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12562               break;
12563             }
12564           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12565             attribute);
12566           break;
12567         }
12568         case 'f':
12569         case 'F':
12570         {
12571           if (LocaleCompare(attribute,"family") == 0)
12572             {
12573               CloneString(&draw_info->family,SvPV(ST(i),na));
12574               break;
12575             }
12576           if (LocaleCompare(attribute,"fill") == 0)
12577             {
12578               if (info)
12579                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->fill,
12580                   &image->exception);
12581               break;
12582             }
12583           if (LocaleCompare(attribute,"font") == 0)
12584             {
12585               CloneString(&draw_info->font,SvPV(ST(i),na));
12586               break;
12587             }
12588           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12589             attribute);
12590           break;
12591         }
12592         case 'g':
12593         case 'G':
12594         {
12595           if (LocaleCompare(attribute,"geometry") == 0)
12596             {
12597               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12598               break;
12599             }
12600           if (LocaleCompare(attribute,"gravity") == 0)
12601             {
12602               draw_info->gravity=(GravityType) ParseCommandOption(
12603                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12604               break;
12605             }
12606           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12607             attribute);
12608           break;
12609         }
12610         case 'p':
12611         case 'P':
12612         {
12613           if (LocaleCompare(attribute,"pointsize") == 0)
12614             {
12615               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12616               draw_info->pointsize=geometry_info.rho;
12617               break;
12618             }
12619           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12620             attribute);
12621           break;
12622         }
12623         case 'r':
12624         case 'R':
12625         {
12626           if (LocaleCompare(attribute,"rotate") == 0)
12627             {
12628               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12629               affine.rx=geometry_info.rho;
12630               affine.ry=geometry_info.sigma;
12631               if ((flags & SigmaValue) == 0)
12632                 affine.ry=affine.rx;
12633               break;
12634             }
12635           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12636             attribute);
12637           break;
12638         }
12639         case 's':
12640         case 'S':
12641         {
12642           if (LocaleCompare(attribute,"scale") == 0)
12643             {
12644               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12645               affine.sx=geometry_info.rho;
12646               affine.sy=geometry_info.sigma;
12647               if ((flags & SigmaValue) == 0)
12648                 affine.sy=affine.sx;
12649               break;
12650             }
12651           if (LocaleCompare(attribute,"skew") == 0)
12652             {
12653               double
12654                 x_angle,
12655                 y_angle;
12656
12657               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12658               x_angle=geometry_info.rho;
12659               y_angle=geometry_info.sigma;
12660               if ((flags & SigmaValue) == 0)
12661                 y_angle=x_angle;
12662               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12663               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12664               break;
12665             }
12666           if (LocaleCompare(attribute,"stroke") == 0)
12667             {
12668               if (info)
12669                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->stroke,
12670                   &image->exception);
12671               break;
12672             }
12673           if (LocaleCompare(attribute,"style") == 0)
12674             {
12675               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12676                 SvPV(ST(i),na));
12677               if (type < 0)
12678                 {
12679                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12680                     SvPV(ST(i),na));
12681                   break;
12682                 }
12683               draw_info->style=(StyleType) type;
12684               break;
12685             }
12686           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12687             attribute);
12688           break;
12689         }
12690         case 't':
12691         case 'T':
12692         {
12693           if (LocaleCompare(attribute,"text") == 0)
12694             {
12695               CloneString(&draw_info->text,SvPV(ST(i),na));
12696               break;
12697             }
12698           if (LocaleCompare(attribute,"translate") == 0)
12699             {
12700               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12701               affine.tx=geometry_info.rho;
12702               affine.ty=geometry_info.sigma;
12703               if ((flags & SigmaValue) == 0)
12704                 affine.ty=affine.tx;
12705               break;
12706             }
12707           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12708             attribute);
12709           break;
12710         }
12711         case 'w':
12712         case 'W':
12713         {
12714           if (LocaleCompare(attribute,"weight") == 0)
12715             {
12716               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12717               draw_info->weight=(size_t) geometry_info.rho;
12718               break;
12719             }
12720           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12721             attribute);
12722           break;
12723         }
12724         case 'x':
12725         case 'X':
12726         {
12727           if (LocaleCompare(attribute,"x") == 0)
12728             {
12729               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12730               x=geometry_info.rho;
12731               break;
12732             }
12733           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12734             attribute);
12735           break;
12736         }
12737         case 'y':
12738         case 'Y':
12739         {
12740           if (LocaleCompare(attribute,"y") == 0)
12741             {
12742               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12743               y=geometry_info.rho;
12744               break;
12745             }
12746           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12747             attribute);
12748           break;
12749         }
12750         default:
12751         {
12752           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12753             attribute);
12754           break;
12755         }
12756       }
12757     }
12758     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12759     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12760     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12761     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12762     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12763     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12764     if (draw_info->geometry == (char *) NULL)
12765       {
12766         draw_info->geometry=AcquireString((char *) NULL);
12767         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12768           "%.15g,%.15g",x,y);
12769       }
12770     status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
12771     (void) CatchException(exception);
12772     if (status == MagickFalse)
12773       PUSHs(&sv_undef);
12774     else
12775       {
12776         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12777         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12778         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12779         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12780         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12781         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12782         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12783         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12784         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12785         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12786         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12787         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12788         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12789       }
12790     draw_info=DestroyDrawInfo(draw_info);
12791
12792   PerlException:
12793     if (package_info != (struct PackageInfo *) NULL)
12794       DestroyPackageInfo(package_info);
12795     InheritPerlException(exception,perl_exception);
12796     exception=DestroyExceptionInfo(exception);
12797     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12798   }
12799 \f
12800 #
12801 ###############################################################################
12802 #                                                                             #
12803 #                                                                             #
12804 #                                                                             #
12805 #   Q u e r y F o r m a t                                                     #
12806 #                                                                             #
12807 #                                                                             #
12808 #                                                                             #
12809 ###############################################################################
12810 #
12811 #
12812 void
12813 QueryFormat(ref,...)
12814   Image::Magick ref=NO_INIT
12815   ALIAS:
12816     queryformat = 1
12817   PPCODE:
12818   {
12819     char
12820       *name;
12821
12822     ExceptionInfo
12823       *exception;
12824
12825     register ssize_t
12826       i;
12827
12828     SV
12829       *perl_exception;
12830
12831     volatile const MagickInfo
12832       *magick_info;
12833
12834     PERL_UNUSED_VAR(ref);
12835     PERL_UNUSED_VAR(ix);
12836     exception=AcquireExceptionInfo();
12837     perl_exception=newSVpv("",0);
12838     if (items == 1)
12839       {
12840         char
12841           format[MaxTextExtent];
12842
12843         const MagickInfo
12844           **format_list;
12845
12846         size_t
12847           types;
12848
12849         format_list=GetMagickInfoList("*",&types,exception);
12850         EXTEND(sp,types);
12851         for (i=0; i < (ssize_t) types; i++)
12852         {
12853           (void) CopyMagickString(format,format_list[i]->name,MaxTextExtent);
12854           LocaleLower(format);
12855           PUSHs(sv_2mortal(newSVpv(format,0)));
12856         }
12857         format_list=(const MagickInfo **)
12858           RelinquishMagickMemory((MagickInfo *) format_list);
12859         goto PerlException;
12860       }
12861     EXTEND(sp,8*items);
12862     for (i=1; i < items; i++)
12863     {
12864       name=(char *) SvPV(ST(i),na);
12865       magick_info=GetMagickInfo(name,exception);
12866       if (magick_info == (const MagickInfo *) NULL)
12867         {
12868           PUSHs(&sv_undef);
12869           continue;
12870         }
12871       PUSHs(sv_2mortal(newSViv(magick_info->adjoin)));
12872       PUSHs(sv_2mortal(newSViv(magick_info->blob_support)));
12873       PUSHs(sv_2mortal(newSViv(magick_info->raw)));
12874       PUSHs(sv_2mortal(newSViv((long) magick_info->decoder)));
12875       PUSHs(sv_2mortal(newSViv((long) magick_info->encoder)));
12876       if (magick_info->description == (char *) NULL)
12877         PUSHs(&sv_undef);
12878       else
12879         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
12880       if (magick_info->module == (char *) NULL)
12881         PUSHs(&sv_undef);
12882       else
12883         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
12884     }
12885
12886   PerlException:
12887     InheritPerlException(exception,perl_exception);
12888     exception=DestroyExceptionInfo(exception);
12889     SvREFCNT_dec(perl_exception);
12890   }
12891 \f
12892 #
12893 ###############################################################################
12894 #                                                                             #
12895 #                                                                             #
12896 #                                                                             #
12897 #   Q u e r y O p t i o n                                                     #
12898 #                                                                             #
12899 #                                                                             #
12900 #                                                                             #
12901 ###############################################################################
12902 #
12903 #
12904 void
12905 QueryOption(ref,...)
12906   Image::Magick ref=NO_INIT
12907   ALIAS:
12908     queryoption = 1
12909   PPCODE:
12910   {
12911     char
12912       **options;
12913
12914     ExceptionInfo
12915       *exception;
12916
12917     register ssize_t
12918       i;
12919
12920     ssize_t
12921       j,
12922       option;
12923
12924     SV
12925       *perl_exception;
12926
12927     PERL_UNUSED_VAR(ref);
12928     PERL_UNUSED_VAR(ix);
12929     exception=AcquireExceptionInfo();
12930     perl_exception=newSVpv("",0);
12931     EXTEND(sp,8*items);
12932     for (i=1; i < items; i++)
12933     {
12934       option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
12935         SvPV(ST(i),na));
12936       options=GetCommandOptions((CommandOption) option);
12937       if (options == (char **) NULL)
12938         PUSHs(&sv_undef);
12939       else
12940         {
12941           for (j=0; options[j] != (char *) NULL; j++)
12942             PUSHs(sv_2mortal(newSVpv(options[j],0)));
12943           options=DestroyStringList(options);
12944         }
12945     }
12946
12947     InheritPerlException(exception,perl_exception);
12948     exception=DestroyExceptionInfo(exception);
12949     SvREFCNT_dec(perl_exception);
12950   }
12951 \f
12952 #
12953 ###############################################################################
12954 #                                                                             #
12955 #                                                                             #
12956 #                                                                             #
12957 #   R e a d                                                                   #
12958 #                                                                             #
12959 #                                                                             #
12960 #                                                                             #
12961 ###############################################################################
12962 #
12963 #
12964 void
12965 Read(ref,...)
12966   Image::Magick ref=NO_INIT
12967   ALIAS:
12968     ReadImage  = 1
12969     read       = 2
12970     readimage  = 3
12971   PPCODE:
12972   {
12973     AV
12974       *av;
12975
12976     char
12977       **keep,
12978       **list;
12979
12980     ExceptionInfo
12981       *exception;
12982
12983     HV
12984       *hv;
12985
12986     Image
12987       *image;
12988
12989     int
12990       n;
12991
12992     MagickBooleanType
12993       status;
12994
12995     register char
12996       **p;
12997
12998     register ssize_t
12999       i;
13000
13001     ssize_t
13002       ac,
13003       number_images;
13004
13005     STRLEN
13006       *length;
13007
13008     struct PackageInfo
13009       *info,
13010       *package_info;
13011
13012     SV
13013       *perl_exception,  /* Perl variable for storing messages */
13014       *reference,
13015       *rv,
13016       *sv;
13017
13018     PERL_UNUSED_VAR(ref);
13019     PERL_UNUSED_VAR(ix);
13020     exception=AcquireExceptionInfo();
13021     perl_exception=newSVpv("",0);
13022     sv=NULL;
13023     package_info=(struct PackageInfo *) NULL;
13024     number_images=0;
13025     ac=(items < 2) ? 1 : items-1;
13026     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
13027     keep=list;
13028     length=(STRLEN *) NULL;
13029     if (list == (char **) NULL)
13030       {
13031         ThrowPerlException(exception,ResourceLimitError,
13032           "MemoryAllocationFailed",PackageName);
13033         goto PerlException;
13034       }
13035     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
13036     if (length == (STRLEN *) NULL)
13037       {
13038         ThrowPerlException(exception,ResourceLimitError,
13039           "MemoryAllocationFailed",PackageName);
13040         goto PerlException;
13041       }
13042     if (sv_isobject(ST(0)) == 0)
13043       {
13044         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13045           PackageName);
13046         goto PerlException;
13047       }
13048     reference=SvRV(ST(0));
13049     hv=SvSTASH(reference);
13050     if (SvTYPE(reference) != SVt_PVAV)
13051       {
13052         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13053           PackageName);
13054         goto PerlException;
13055       }
13056     av=(AV *) reference;
13057     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13058       exception);
13059     package_info=ClonePackageInfo(info,exception);
13060     n=1;
13061     if (items <= 1)
13062       *list=(char *) (*package_info->image_info->filename ?
13063         package_info->image_info->filename : "XC:black");
13064     else
13065       for (n=0, i=0; i < ac; i++)
13066       {
13067         list[n]=(char *) SvPV(ST(i+1),length[n]);
13068         if ((items >= 3) && strEQcase(list[n],"blob"))
13069           {
13070             void
13071               *blob;
13072
13073             i++;
13074             blob=(void *) (SvPV(ST(i+1),length[n]));
13075             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13076           }
13077         if ((items >= 3) && strEQcase(list[n],"filename"))
13078           continue;
13079         if ((items >= 3) && strEQcase(list[n],"file"))
13080           {
13081             FILE
13082               *file;
13083
13084             PerlIO
13085               *io_info;
13086
13087             i++;
13088             io_info=IoIFP(sv_2io(ST(i+1)));
13089             if (io_info == (PerlIO *) NULL)
13090               {
13091                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13092                   PackageName);
13093                 continue;
13094               }
13095             file=PerlIO_findFILE(io_info);
13096             if (file == (FILE *) NULL)
13097               {
13098                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13099                   PackageName);
13100                 continue;
13101               }
13102             SetImageInfoFile(package_info->image_info,file);
13103           }
13104         if ((items >= 3) && strEQcase(list[n],"magick"))
13105           continue;
13106         n++;
13107       }
13108     list[n]=(char *) NULL;
13109     keep=list;
13110     status=ExpandFilenames(&n,&list);
13111     if (status == MagickFalse)
13112       {
13113         ThrowPerlException(exception,ResourceLimitError,
13114           "MemoryAllocationFailed",PackageName);
13115         goto PerlException;
13116       }
13117     number_images=0;
13118     for (i=0; i < n; i++)
13119     {
13120       if ((package_info->image_info->file != (FILE *) NULL) ||
13121           (package_info->image_info->blob != (void *) NULL))
13122         {
13123           image=ReadImages(package_info->image_info,exception);
13124           if (image != (Image *) NULL)
13125             DisassociateImageStream(image);
13126         }
13127       else
13128         {
13129           (void) CopyMagickString(package_info->image_info->filename,list[i],
13130             MaxTextExtent);
13131           image=ReadImages(package_info->image_info,exception);
13132         }
13133       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
13134         break;
13135       for ( ; image; image=image->next)
13136       {
13137         AddImageToRegistry(sv,image);
13138         rv=newRV(sv);
13139         av_push(av,sv_bless(rv,hv));
13140         SvREFCNT_dec(sv);
13141         number_images++;
13142       }
13143     }
13144     /*
13145       Free resources.
13146     */
13147     for (i=0; i < n; i++)
13148       if (list[i] != (char *) NULL)
13149         for (p=keep; list[i] != *p++; )
13150           if (*p == (char *) NULL)
13151             {
13152               list[i]=(char *) RelinquishMagickMemory(list[i]);
13153               break;
13154             }
13155
13156   PerlException:
13157     if (package_info != (struct PackageInfo *) NULL)
13158       DestroyPackageInfo(package_info);
13159     if (list && (list != keep))
13160       list=(char **) RelinquishMagickMemory(list);
13161     if (keep)
13162       keep=(char **) RelinquishMagickMemory(keep);
13163     if (length)
13164       length=(STRLEN *) RelinquishMagickMemory(length);
13165     InheritPerlException(exception,perl_exception);
13166     exception=DestroyExceptionInfo(exception);
13167     sv_setiv(perl_exception,(IV) number_images);
13168     SvPOK_on(perl_exception);
13169     ST(0)=sv_2mortal(perl_exception);
13170     XSRETURN(1);
13171   }
13172 \f
13173 #
13174 ###############################################################################
13175 #                                                                             #
13176 #                                                                             #
13177 #                                                                             #
13178 #   R e m o t e                                                               #
13179 #                                                                             #
13180 #                                                                             #
13181 #                                                                             #
13182 ###############################################################################
13183 #
13184 #
13185 void
13186 Remote(ref,...)
13187   Image::Magick ref=NO_INIT
13188   ALIAS:
13189     RemoteCommand  = 1
13190     remote         = 2
13191     remoteCommand  = 3
13192   PPCODE:
13193   {
13194     AV
13195       *av;
13196
13197     ExceptionInfo
13198       *exception;
13199
13200     register ssize_t
13201       i;
13202
13203     SV
13204       *perl_exception,
13205       *reference;
13206
13207     struct PackageInfo
13208       *info;
13209
13210     PERL_UNUSED_VAR(ref);
13211     PERL_UNUSED_VAR(ix);
13212     exception=AcquireExceptionInfo();
13213     perl_exception=newSVpv("",0);
13214     reference=SvRV(ST(0));
13215     av=(AV *) reference;
13216     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13217       exception);
13218     for (i=1; i < items; i++)
13219       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13220         SvPV(ST(i),na),exception);
13221     InheritPerlException(exception,perl_exception);
13222     exception=DestroyExceptionInfo(exception);
13223     SvREFCNT_dec(perl_exception);    /* throw away all errors */
13224   }
13225 \f
13226 #
13227 ###############################################################################
13228 #                                                                             #
13229 #                                                                             #
13230 #                                                                             #
13231 #   S e t                                                                     #
13232 #                                                                             #
13233 #                                                                             #
13234 #                                                                             #
13235 ###############################################################################
13236 #
13237 #
13238 void
13239 Set(ref,...)
13240   Image::Magick ref=NO_INIT
13241   ALIAS:
13242     SetAttributes  = 1
13243     SetAttribute   = 2
13244     set            = 3
13245     setattributes  = 4
13246     setattribute   = 5
13247   PPCODE:
13248   {
13249     ExceptionInfo
13250       *exception;
13251
13252     Image
13253       *image;
13254
13255     register ssize_t
13256       i;
13257
13258     struct PackageInfo
13259       *info;
13260
13261     SV
13262       *perl_exception,
13263       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13264
13265     PERL_UNUSED_VAR(ref);
13266     PERL_UNUSED_VAR(ix);
13267     exception=AcquireExceptionInfo();
13268     perl_exception=newSVpv("",0);
13269     if (sv_isobject(ST(0)) == 0)
13270       {
13271         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13272           PackageName);
13273         goto PerlException;
13274       }
13275     reference=SvRV(ST(0));
13276     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13277     if (items == 2)
13278       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13279     else
13280       for (i=2; i < items; i+=2)
13281         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13282
13283   PerlException:
13284     InheritPerlException(exception,perl_exception);
13285     exception=DestroyExceptionInfo(exception);
13286     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13287     SvPOK_on(perl_exception);
13288     ST(0)=sv_2mortal(perl_exception);
13289     XSRETURN(1);
13290   }
13291 \f
13292 #
13293 ###############################################################################
13294 #                                                                             #
13295 #                                                                             #
13296 #                                                                             #
13297 #   S e t P i x e l                                                           #
13298 #                                                                             #
13299 #                                                                             #
13300 #                                                                             #
13301 ###############################################################################
13302 #
13303 #
13304 void
13305 SetPixel(ref,...)
13306   Image::Magick ref=NO_INIT
13307   ALIAS:
13308     setpixel = 1
13309     setPixel = 2
13310   PPCODE:
13311   {
13312     AV
13313       *av;
13314
13315     char
13316       *attribute;
13317
13318     ChannelType
13319       channel,
13320       channel_mask;
13321
13322     ExceptionInfo
13323       *exception;
13324
13325     Image
13326       *image;
13327
13328     MagickBooleanType
13329       normalize;
13330
13331     RectangleInfo
13332       region;
13333
13334     register ssize_t
13335       i;
13336
13337     register Quantum
13338       *q;
13339
13340     ssize_t
13341       option;
13342
13343     struct PackageInfo
13344       *info;
13345
13346     SV
13347       *perl_exception,
13348       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13349
13350     PERL_UNUSED_VAR(ref);
13351     PERL_UNUSED_VAR(ix);
13352     exception=AcquireExceptionInfo();
13353     perl_exception=newSVpv("",0);
13354     reference=SvRV(ST(0));
13355     av=(AV *) reference;
13356     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13357       exception);
13358     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13359     if (image == (Image *) NULL)
13360       {
13361         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13362           PackageName);
13363         goto PerlException;
13364       }
13365     av=(AV *) NULL;
13366     normalize=MagickTrue;
13367     region.x=0;
13368     region.y=0;
13369     region.width=image->columns;
13370     region.height=1;
13371     if (items == 1)
13372       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13373     channel=DefaultChannels;
13374     for (i=2; i < items; i+=2)
13375     {
13376       attribute=(char *) SvPV(ST(i-1),na);
13377       switch (*attribute)
13378       {
13379         case 'C':
13380         case 'c':
13381         {
13382           if (LocaleCompare(attribute,"channel") == 0)
13383             {
13384               ssize_t
13385                 option;
13386
13387               option=ParseChannelOption(SvPV(ST(i),na));
13388               if (option < 0)
13389                 {
13390                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13391                     SvPV(ST(i),na));
13392                   return;
13393                 }
13394               channel=(ChannelType) option;
13395               break;
13396             }
13397           if (LocaleCompare(attribute,"color") == 0)
13398             {
13399               if (SvTYPE(ST(i)) != SVt_RV)
13400                 {
13401                   char
13402                     message[MaxTextExtent];
13403
13404                   (void) FormatLocaleString(message,MaxTextExtent,
13405                     "invalid %.60s value",attribute);
13406                   ThrowPerlException(exception,OptionError,message,
13407                     SvPV(ST(i),na));
13408                 }
13409               av=(AV *) SvRV(ST(i));
13410               break;
13411             }
13412           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13413             attribute);
13414           break;
13415         }
13416         case 'g':
13417         case 'G':
13418         {
13419           if (LocaleCompare(attribute,"geometry") == 0)
13420             {
13421               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
13422               break;
13423             }
13424           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13425             attribute);
13426           break;
13427         }
13428         case 'N':
13429         case 'n':
13430         {
13431           if (LocaleCompare(attribute,"normalize") == 0)
13432             {
13433               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13434                 SvPV(ST(i),na));
13435               if (option < 0)
13436                 {
13437                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13438                     SvPV(ST(i),na));
13439                   break;
13440                 }
13441              normalize=option != 0 ? MagickTrue : MagickFalse;
13442              break;
13443             }
13444           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13445             attribute);
13446           break;
13447         }
13448         case 'x':
13449         case 'X':
13450         {
13451           if (LocaleCompare(attribute,"x") == 0)
13452             {
13453               region.x=SvIV(ST(i));
13454               break;
13455             }
13456           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13457             attribute);
13458           break;
13459         }
13460         case 'y':
13461         case 'Y':
13462         {
13463           if (LocaleCompare(attribute,"y") == 0)
13464             {
13465               region.y=SvIV(ST(i));
13466               break;
13467             }
13468           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13469             attribute);
13470           break;
13471         }
13472         default:
13473         {
13474           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13475             attribute);
13476           break;
13477         }
13478       }
13479     }
13480     (void) SetImageStorageClass(image,DirectClass,exception);
13481     channel_mask=SetPixelChannelMask(image,channel);
13482     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
13483     if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
13484         (SvTYPE(av) != SVt_PVAV))
13485       PUSHs(&sv_undef);
13486     else
13487       {
13488         double
13489           scale;
13490
13491         register ssize_t
13492           i;
13493
13494         i=0;
13495         scale=1.0;
13496         if (normalize != MagickFalse)
13497           scale=QuantumRange;
13498         if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
13499             (i <= av_len(av)))
13500           {
13501             SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
13502               av_fetch(av,i,0)))),q);
13503             i++;
13504           }
13505         if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
13506             (i <= av_len(av)))
13507           {
13508             SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
13509               av_fetch(av,i,0)))),q);
13510             i++;
13511           }
13512         if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
13513             (i <= av_len(av)))
13514           {
13515             SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
13516               av_fetch(av,i,0)))),q);
13517             i++;
13518           }
13519         if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
13520             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
13521           {
13522             SetPixelBlack(image,ClampToQuantum(scale*
13523               SvNV(*(av_fetch(av,i,0)))),q);
13524             i++;
13525           }
13526         if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
13527             (i <= av_len(av)))
13528           {
13529             SetPixelAlpha(image,ClampToQuantum(scale*
13530               SvNV(*(av_fetch(av,i,0)))),q);
13531             i++;
13532           }
13533         (void) SyncAuthenticPixels(image,exception);
13534       }
13535     (void) SetPixelChannelMask(image,channel_mask);
13536
13537   PerlException:
13538     InheritPerlException(exception,perl_exception);
13539     exception=DestroyExceptionInfo(exception);
13540     SvREFCNT_dec(perl_exception);
13541   }
13542 \f
13543 #
13544 ###############################################################################
13545 #                                                                             #
13546 #                                                                             #
13547 #                                                                             #
13548 #   S m u s h                                                                 #
13549 #                                                                             #
13550 #                                                                             #
13551 #                                                                             #
13552 ###############################################################################
13553 #
13554 #
13555 void
13556 Smush(ref,...)
13557   Image::Magick ref=NO_INIT
13558   ALIAS:
13559     SmushImage  = 1
13560     smush       = 2
13561     smushimage  = 3
13562   PPCODE:
13563   {
13564     AV
13565       *av;
13566
13567     char
13568       *attribute;
13569
13570     ExceptionInfo
13571       *exception;
13572
13573     HV
13574       *hv;
13575
13576     Image
13577       *image;
13578
13579     register ssize_t
13580       i;
13581
13582     ssize_t
13583       offset,
13584       stack;
13585
13586     struct PackageInfo
13587       *info;
13588
13589     SV
13590       *av_reference,
13591       *perl_exception,
13592       *reference,
13593       *rv,
13594       *sv;
13595
13596     PERL_UNUSED_VAR(ref);
13597     PERL_UNUSED_VAR(ix);
13598     exception=AcquireExceptionInfo();
13599     perl_exception=newSVpv("",0);
13600     sv=NULL;
13601     attribute=NULL;
13602     av=NULL;
13603     if (sv_isobject(ST(0)) == 0)
13604       {
13605         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13606           PackageName);
13607         goto PerlException;
13608       }
13609     reference=SvRV(ST(0));
13610     hv=SvSTASH(reference);
13611     av=newAV();
13612     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13613     SvREFCNT_dec(av);
13614     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13615     if (image == (Image *) NULL)
13616       {
13617         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13618           PackageName);
13619         goto PerlException;
13620       }
13621     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13622     /*
13623       Get options.
13624     */
13625     offset=0;
13626     stack=MagickTrue;
13627     for (i=2; i < items; i+=2)
13628     {
13629       attribute=(char *) SvPV(ST(i-1),na);
13630       switch (*attribute)
13631       {
13632         case 'O':
13633         case 'o':
13634         {
13635           if (LocaleCompare(attribute,"offset") == 0)
13636             {
13637               offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
13638               break;
13639             }
13640           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13641             attribute);
13642           break;
13643         }
13644         case 'S':
13645         case 's':
13646         {
13647           if (LocaleCompare(attribute,"stack") == 0)
13648             {
13649               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13650                 SvPV(ST(i),na));
13651               if (stack < 0)
13652                 {
13653                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13654                     SvPV(ST(i),na));
13655                   return;
13656                 }
13657               break;
13658             }
13659           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13660             attribute);
13661           break;
13662         }
13663         default:
13664         {
13665           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13666             attribute);
13667           break;
13668         }
13669       }
13670     }
13671     image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
13672       exception);
13673     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
13674       goto PerlException;
13675     for ( ; image; image=image->next)
13676     {
13677       AddImageToRegistry(sv,image);
13678       rv=newRV(sv);
13679       av_push(av,sv_bless(rv,hv));
13680       SvREFCNT_dec(sv);
13681     }
13682     exception=DestroyExceptionInfo(exception);
13683     ST(0)=av_reference;
13684     SvREFCNT_dec(perl_exception);
13685     XSRETURN(1);
13686
13687   PerlException:
13688     InheritPerlException(exception,perl_exception);
13689     exception=DestroyExceptionInfo(exception);
13690     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
13691     SvPOK_on(perl_exception);
13692     ST(0)=sv_2mortal(perl_exception);
13693     XSRETURN(1);
13694   }
13695 \f
13696 #
13697 ###############################################################################
13698 #                                                                             #
13699 #                                                                             #
13700 #                                                                             #
13701 #   S t a t i s t i c s                                                       #
13702 #                                                                             #
13703 #                                                                             #
13704 #                                                                             #
13705 ###############################################################################
13706 #
13707 #
13708 void
13709 Statistics(ref,...)
13710   Image::Magick ref=NO_INIT
13711   ALIAS:
13712     StatisticsImage = 1
13713     statistics      = 2
13714     statisticsimage = 3
13715   PPCODE:
13716   {
13717 #define ChannelStatistics(channel) \
13718 { \
13719   (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
13720     (double) channel_statistics[channel].depth); \
13721   PUSHs(sv_2mortal(newSVpv(message,0))); \
13722   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13723     channel_statistics[channel].minima/scale); \
13724   PUSHs(sv_2mortal(newSVpv(message,0))); \
13725   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13726     channel_statistics[channel].maxima/scale); \
13727   PUSHs(sv_2mortal(newSVpv(message,0))); \
13728   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13729     channel_statistics[channel].mean/scale); \
13730   PUSHs(sv_2mortal(newSVpv(message,0))); \
13731   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13732     channel_statistics[channel].standard_deviation/scale); \
13733   PUSHs(sv_2mortal(newSVpv(message,0))); \
13734   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13735     channel_statistics[channel].kurtosis); \
13736   PUSHs(sv_2mortal(newSVpv(message,0))); \
13737   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13738     channel_statistics[channel].skewness); \
13739   PUSHs(sv_2mortal(newSVpv(message,0))); \
13740 }
13741
13742     AV
13743       *av;
13744
13745     char
13746       message[MaxTextExtent];
13747
13748     ChannelStatistics
13749       *channel_statistics;
13750
13751     double
13752       scale;
13753
13754     ExceptionInfo
13755       *exception;
13756
13757     Image
13758       *image;
13759
13760     ssize_t
13761       count;
13762
13763     struct PackageInfo
13764       *info;
13765
13766     SV
13767       *perl_exception,
13768       *reference;
13769
13770     PERL_UNUSED_VAR(ref);
13771     PERL_UNUSED_VAR(ix);
13772     exception=AcquireExceptionInfo();
13773     perl_exception=newSVpv("",0);
13774     av=NULL;
13775     if (sv_isobject(ST(0)) == 0)
13776       {
13777         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13778           PackageName);
13779         goto PerlException;
13780       }
13781     reference=SvRV(ST(0));
13782     av=newAV();
13783     SvREFCNT_dec(av);
13784     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13785     if (image == (Image *) NULL)
13786       {
13787         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13788           PackageName);
13789         goto PerlException;
13790       }
13791     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13792     count=0;
13793     for ( ; image; image=image->next)
13794     {
13795       channel_statistics=GetImageStatistics(image,&image->exception);
13796       if (channel_statistics == (ChannelStatistics *) NULL)
13797         continue;
13798       count++;
13799       EXTEND(sp,35*count);
13800       scale=(double) QuantumRange;
13801       ChannelStatistics(RedChannel);
13802       ChannelStatistics(GreenChannel);
13803       ChannelStatistics(BlueChannel);
13804       if (image->colorspace == CMYKColorspace)
13805         ChannelStatistics(BlackChannel);
13806       if (image->matte != MagickFalse)
13807         ChannelStatistics(AlphaChannel);
13808       channel_statistics=(ChannelStatistics *)
13809         RelinquishMagickMemory(channel_statistics);
13810     }
13811
13812   PerlException:
13813     InheritPerlException(exception,perl_exception);
13814     exception=DestroyExceptionInfo(exception);
13815     SvREFCNT_dec(perl_exception);
13816   }
13817 \f
13818 #
13819 ###############################################################################
13820 #                                                                             #
13821 #                                                                             #
13822 #                                                                             #
13823 #   S y n c A u t h e n t i c P i x e l s                                     #
13824 #                                                                             #
13825 #                                                                             #
13826 #                                                                             #
13827 ###############################################################################
13828 #
13829 #
13830 void
13831 SyncAuthenticPixels(ref,...)
13832   Image::Magick ref = NO_INIT
13833   ALIAS:
13834     Syncauthenticpixels = 1
13835     SyncImagePixels = 2
13836     syncimagepixels = 3
13837   CODE:
13838   {
13839     ExceptionInfo
13840       *exception;
13841
13842     Image
13843       *image;
13844
13845     MagickBooleanType
13846       status;
13847
13848     struct PackageInfo
13849       *info;
13850
13851     SV
13852       *perl_exception,
13853       *reference;
13854
13855     PERL_UNUSED_VAR(ref);
13856     PERL_UNUSED_VAR(ix);
13857     exception=AcquireExceptionInfo();
13858     perl_exception=newSVpv("",0);
13859     if (sv_isobject(ST(0)) == 0)
13860       {
13861         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13862           PackageName);
13863         goto PerlException;
13864       }
13865
13866     reference=SvRV(ST(0));
13867     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13868     if (image == (Image *) NULL)
13869       {
13870         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13871           PackageName);
13872         goto PerlException;
13873       }
13874
13875     status=SyncAuthenticPixels(image,exception);
13876     if (status != MagickFalse)
13877       return;
13878     InheritException(exception,&image->exception);
13879
13880   PerlException:
13881     InheritPerlException(exception,perl_exception);
13882     exception=DestroyExceptionInfo(exception);
13883     SvREFCNT_dec(perl_exception);  /* throw away all errors */
13884   }
13885 \f
13886 #
13887 ###############################################################################
13888 #                                                                             #
13889 #                                                                             #
13890 #                                                                             #
13891 #   T r a n s f o r m                                                         #
13892 #                                                                             #
13893 #                                                                             #
13894 #                                                                             #
13895 ###############################################################################
13896 #
13897 #
13898 void
13899 Transform(ref,...)
13900   Image::Magick ref=NO_INIT
13901   ALIAS:
13902     TransformImage = 1
13903     transform      = 2
13904     transformimage = 3
13905   PPCODE:
13906   {
13907     AV
13908       *av;
13909
13910     char
13911       *attribute,
13912       *crop_geometry,
13913       *geometry;
13914
13915     ExceptionInfo
13916       *exception;
13917
13918     HV
13919       *hv;
13920
13921     Image
13922       *clone,
13923       *image;
13924
13925     register ssize_t
13926       i;
13927
13928     struct PackageInfo
13929       *info;
13930
13931     SV
13932       *av_reference,
13933       *perl_exception,
13934       *reference,
13935       *rv,
13936       *sv;
13937
13938     PERL_UNUSED_VAR(ref);
13939     PERL_UNUSED_VAR(ix);
13940     exception=AcquireExceptionInfo();
13941     perl_exception=newSVpv("",0);
13942     sv=NULL;
13943     av=NULL;
13944     attribute=NULL;
13945     if (sv_isobject(ST(0)) == 0)
13946       {
13947         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13948           PackageName);
13949         goto PerlException;
13950       }
13951     reference=SvRV(ST(0));
13952     hv=SvSTASH(reference);
13953     av=newAV();
13954     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13955     SvREFCNT_dec(av);
13956     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13957     if (image == (Image *) NULL)
13958       {
13959         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13960           PackageName);
13961         goto PerlException;
13962       }
13963     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13964     /*
13965       Get attribute.
13966     */
13967     crop_geometry=(char *) NULL;
13968     geometry=(char *) NULL;
13969     for (i=2; i < items; i+=2)
13970     {
13971       attribute=(char *) SvPV(ST(i-1),na);
13972       switch (*attribute)
13973       {
13974         case 'c':
13975         case 'C':
13976         {
13977           if (LocaleCompare(attribute,"crop") == 0)
13978             {
13979               crop_geometry=SvPV(ST(i),na);
13980               break;
13981             }
13982           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13983             attribute);
13984           break;
13985         }
13986         case 'g':
13987         case 'G':
13988         {
13989           if (LocaleCompare(attribute,"geometry") == 0)
13990             {
13991               geometry=SvPV(ST(i),na);
13992               break;
13993             }
13994          if (LocaleCompare(attribute,"gravity") == 0)
13995            {
13996              Image
13997                *next;
13998
13999              ssize_t
14000                in;
14001
14002              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
14003                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
14004              if (in < 0)
14005                {
14006                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
14007                    SvPV(ST(i),na));
14008                  return;
14009                }
14010              for (next=image; next; next=next->next)
14011                next->gravity=(GravityType) in;
14012              break;
14013            }
14014           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14015             attribute);
14016           break;
14017         }
14018         default:
14019         {
14020           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14021             attribute);
14022           break;
14023         }
14024       }
14025     }
14026     for ( ; image; image=image->next)
14027     {
14028       clone=CloneImage(image,0,0,MagickTrue,exception);
14029       if ((clone == (Image *) NULL) || (exception->severity >= ErrorException))
14030         goto PerlException;
14031       TransformImage(&clone,crop_geometry,geometry);
14032       for ( ; clone; clone=clone->next)
14033       {
14034         AddImageToRegistry(sv,clone);
14035         rv=newRV(sv);
14036         av_push(av,sv_bless(rv,hv));
14037         SvREFCNT_dec(sv);
14038       }
14039     }
14040     exception=DestroyExceptionInfo(exception);
14041     ST(0)=av_reference;
14042     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
14043     XSRETURN(1);
14044
14045   PerlException:
14046     InheritPerlException(exception,perl_exception);
14047     exception=DestroyExceptionInfo(exception);
14048     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14049     SvPOK_on(perl_exception);
14050     ST(0)=sv_2mortal(perl_exception);
14051     XSRETURN(1);
14052   }
14053 \f
14054 #
14055 ###############################################################################
14056 #                                                                             #
14057 #                                                                             #
14058 #                                                                             #
14059 #   W r i t e                                                                 #
14060 #                                                                             #
14061 #                                                                             #
14062 #                                                                             #
14063 ###############################################################################
14064 #
14065 #
14066 void
14067 Write(ref,...)
14068   Image::Magick ref=NO_INIT
14069   ALIAS:
14070     WriteImage    = 1
14071     write         = 2
14072     writeimage    = 3
14073   PPCODE:
14074   {
14075     char
14076       filename[MaxTextExtent];
14077
14078     ExceptionInfo
14079       *exception;
14080
14081     Image
14082       *image,
14083       *next;
14084
14085     register ssize_t
14086       i;
14087
14088     ssize_t
14089       number_images,
14090       scene;
14091
14092     struct PackageInfo
14093       *info,
14094       *package_info;
14095
14096     SV
14097       *perl_exception,
14098       *reference;
14099
14100     PERL_UNUSED_VAR(ref);
14101     PERL_UNUSED_VAR(ix);
14102     exception=AcquireExceptionInfo();
14103     perl_exception=newSVpv("",0);
14104     number_images=0;
14105     package_info=(struct PackageInfo *) NULL;
14106     if (sv_isobject(ST(0)) == 0)
14107       {
14108         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14109           PackageName);
14110         goto PerlException;
14111       }
14112     reference=SvRV(ST(0));
14113     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14114     if (image == (Image *) NULL)
14115       {
14116         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14117           PackageName);
14118         goto PerlException;
14119       }
14120     package_info=ClonePackageInfo(info,exception);
14121     if (items == 2)
14122       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14123     else
14124       if (items > 2)
14125         for (i=2; i < items; i+=2)
14126           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14127             exception);
14128     (void) CopyMagickString(filename,package_info->image_info->filename,
14129       MaxTextExtent);
14130     scene=0;
14131     for (next=image; next; next=next->next)
14132     {
14133       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
14134       next->scene=scene++;
14135     }
14136     SetImageInfo(package_info->image_info,(unsigned int)
14137       GetImageListLength(image),&image->exception);
14138     for (next=image; next; next=next->next)
14139     {
14140       (void) WriteImage(package_info->image_info,next,exception);
14141       number_images++;
14142       if (package_info->image_info->adjoin)
14143         break;
14144     }
14145
14146   PerlException:
14147     if (package_info != (struct PackageInfo *) NULL)
14148       DestroyPackageInfo(package_info);
14149     InheritPerlException(exception,perl_exception);
14150     exception=DestroyExceptionInfo(exception);
14151     sv_setiv(perl_exception,(IV) number_images);
14152     SvPOK_on(perl_exception);
14153     ST(0)=sv_2mortal(perl_exception);
14154     XSRETURN(1);
14155   }