]> 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-2013 ImageMagick Studio LLC, a non-profit organization      %
27 %  dedicated to making software imaging solutions freely available.           %
28 %                                                                             %
29 %  You may not use this file except in compliance with the License.  You may  %
30 %  obtain a copy of the License at                                            %
31 %                                                                             %
32 %    http://www.imagemagick.org/script/license.php                            %
33 %                                                                             %
34 %  Unless required by applicable law or agreed to in writing, software        %
35 %  distributed under the License is distributed on an "AS IS" BASIS,          %
36 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
37 %  See the License for the specific language governing permissions and        %
38 %  limitations under the License.                                             %
39 %                                                                             %
40 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
41 %
42 %  PerlMagick is an objected-oriented Perl interface to ImageMagick.  Use
43 %  the module to read, manipulate, or write an image or image sequence from
44 %  within a Perl script.  This makes PerlMagick suitable for Web CGI scripts.
45 %
46 */
47 \f
48 /*
49   Include declarations.
50 */
51 #if defined(__cplusplus) || defined(c_plusplus)
52 extern "C" {
53 #endif
54
55 #define PERL_NO_GET_CONTEXT
56 #include "EXTERN.h"
57 #include "perl.h"
58 #include "XSUB.h"
59 #include <math.h>
60 #include <MagickCore/MagickCore.h>
61 #undef tainted
62
63 #if defined(__cplusplus) || defined(c_plusplus)
64 }
65 #endif
66 \f
67 /*
68   Define declarations.
69 */
70 #ifndef aTHX_
71 #define aTHX_
72 #define pTHX_
73 #define dTHX
74 #endif
75 #define DegreesToRadians(x)  (MagickPI*(x)/180.0)
76 #define EndOf(array)  (&array[NumberOf(array)])
77 #define MaxArguments  33
78 #ifndef na
79 #define na  PL_na
80 #endif
81 #define NumberOf(array)  (sizeof(array)/sizeof(*array))
82 #define PackageName   "Image::Magick"
83 #if PERL_VERSION <= 6
84 #define PerlIO  FILE
85 #define PerlIO_importFILE(f, fl)  (f)
86 #define PerlIO_findFILE(f)  NULL
87 #endif
88 #ifndef sv_undef
89 #define sv_undef  PL_sv_undef
90 #endif
91
92 #define AddImageToRegistry(sv,image) \
93 { \
94   if (magick_registry != (SplayTreeInfo *) NULL) \
95     { \
96       (void) AddValueToSplayTree(magick_registry,image,image); \
97       (sv)=newSViv(PTR2IV(image)); \
98     } \
99 }
100
101 #define DeleteImageFromRegistry(reference,image) \
102 { \
103   if (magick_registry != (SplayTreeInfo *) NULL) \
104     { \
105       if (GetImageReferenceCount(image) == 1) \
106        (void) DeleteNodeByValueFromSplayTree(magick_registry,image); \
107       image=DestroyImage(image); \
108       sv_setiv(reference,0); \
109     } \
110 }
111
112 #define InheritPerlException(exception,perl_exception) \
113 { \
114   char \
115     message[MaxTextExtent]; \
116  \
117   if ((exception)->severity != UndefinedException) \
118     { \
119       (void) FormatLocaleString(message,MaxTextExtent,"Exception %d: %s%s%s%s",\
120         (exception)->severity, (exception)->reason ? \
121         GetLocaleExceptionMessage((exception)->severity,(exception)->reason) : \
122         "Unknown", (exception)->description ? " (" : "", \
123         (exception)->description ? GetLocaleExceptionMessage( \
124         (exception)->severity,(exception)->description) : "", \
125         (exception)->description ? ")" : ""); \
126       if ((perl_exception) != (SV *) NULL) \
127         { \
128           if (SvCUR(perl_exception)) \
129             sv_catpv(perl_exception,"\n"); \
130           sv_catpv(perl_exception,message); \
131         } \
132     } \
133 }
134
135 #define ThrowPerlException(exception,severity,tag,reason) \
136   (void) ThrowMagickException(exception,GetMagickModule(),severity, \
137     tag,"`%s'",reason); \
138 \f
139 /*
140   Typedef and structure declarations.
141 */
142 typedef enum
143 {
144   ArrayReference = (~0),
145   RealReference = (~0)-1,
146   FileReference = (~0)-2,
147   ImageReference = (~0)-3,
148   IntegerReference = (~0)-4,
149   StringReference = (~0)-5
150 } MagickReference;
151
152 typedef struct _Arguments
153 {
154   const char
155     *method;
156
157   ssize_t
158     type;
159 } Arguments;
160
161 struct ArgumentList
162 {
163   ssize_t
164     integer_reference;
165
166   double
167     real_reference;
168
169   const char
170     *string_reference;
171
172   Image
173     *image_reference;
174
175   SV
176     *array_reference;
177
178   FILE
179     *file_reference;
180
181   size_t
182     length;
183 };
184
185 struct PackageInfo
186 {
187   ImageInfo
188     *image_info;
189 };
190
191 typedef void
192   *Image__Magick;  /* data type for the Image::Magick package */
193 \f
194 /*
195   Static declarations.
196 */
197 static struct
198   Methods
199   {
200     const char
201       *name;
202
203     Arguments
204       arguments[MaxArguments];
205   } Methods[] =
206   {
207     { "Comment", { {"comment", StringReference} } },
208     { "Label", { {"label", StringReference} } },
209     { "AddNoise", { {"noise", MagickNoiseOptions}, {"attenuate", RealReference},
210       {"channel", MagickChannelOptions} } },
211     { "Colorize", { {"fill", StringReference}, {"blend", StringReference} } },
212     { "Border", { {"geometry", StringReference}, {"width", IntegerReference},
213       {"height", IntegerReference}, {"fill", StringReference},
214       {"bordercolor", StringReference}, {"color", StringReference},
215       {"compose", MagickComposeOptions} } },
216     { "Blur", { {"geometry", StringReference}, {"radius", RealReference},
217       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
218     { "Chop", { {"geometry", StringReference}, {"width", IntegerReference},
219       {"height", IntegerReference}, {"x", IntegerReference},
220       {"y", IntegerReference} } },
221     { "Crop", { {"geometry", StringReference}, {"width", IntegerReference},
222       {"height", IntegerReference}, {"x", IntegerReference},
223       {"y", IntegerReference}, {"fuzz", StringReference},
224       {"gravity", MagickGravityOptions} } },
225     { "Despeckle", },
226     { "Edge", { {"radius", RealReference} } },
227     { "Emboss", { {"geometry", StringReference}, {"radius", RealReference},
228       {"sigma", RealReference} } },
229     { "Enhance", },
230     { "Flip", },
231     { "Flop", },
232     { "Frame", { {"geometry", StringReference}, {"width", IntegerReference},
233       {"height", IntegerReference}, {"inner", IntegerReference},
234       {"outer", IntegerReference}, {"fill", StringReference},
235       {"color", StringReference}, {"compose", MagickComposeOptions} } },
236     { "Implode", { {"amount", RealReference},
237       {"interpolate", MagickInterpolateOptions} } },
238     { "Magnify", },
239     { "MedianFilter", { {"geometry", StringReference},
240       {"width", IntegerReference}, {"height", IntegerReference},
241       {"channel", MagickChannelOptions} } },
242     { "Minify", },
243     { "OilPaint", { {"radius", RealReference}, {"sigma", RealReference} } },
244     { "ReduceNoise", { {"geometry", StringReference},
245       {"width", IntegerReference},{"height", IntegerReference},
246       {"channel", MagickChannelOptions} } },
247     { "Roll", { {"geometry", StringReference}, {"x", IntegerReference},
248       {"y", IntegerReference} } },
249     { "Rotate", { {"degrees", RealReference}, 
250       {"background", StringReference} } },
251     { "Sample", { {"geometry", StringReference}, {"width", IntegerReference},
252       {"height", IntegerReference} } },
253     { "Scale", { {"geometry", StringReference}, {"width", IntegerReference},
254       {"height", IntegerReference} } },
255     { "Shade", { {"geometry", StringReference}, {"azimuth", RealReference},
256       {"elevation", RealReference}, {"gray", MagickBooleanOptions} } },
257     { "Sharpen", { {"geometry", StringReference}, {"radius", RealReference},
258       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
259     { "Shear", { {"geometry", StringReference}, {"x", RealReference},
260       {"y", RealReference}, { "fill", StringReference},
261       {"color", StringReference} } },
262     { "Spread", { {"radius", RealReference},
263       {"interpolate", MagickInterpolateOptions} } },
264     { "Swirl", { {"degrees", RealReference},
265       {"interpolate", MagickInterpolateOptions} } },
266     { "Resize", { {"geometry", StringReference}, {"width", IntegerReference},
267       {"height", IntegerReference}, {"filter", MagickFilterOptions},
268       {"support", StringReference } } },
269     { "Zoom", { {"geometry", StringReference}, {"width", IntegerReference},
270       {"height", IntegerReference}, {"filter", MagickFilterOptions},
271       {"support", RealReference } } },
272     { "Annotate", { {"text", StringReference}, {"font", StringReference},
273       {"pointsize", RealReference}, {"density", StringReference},
274       {"undercolor", StringReference}, {"stroke", StringReference},
275       {"fill", StringReference}, {"geometry", StringReference},
276       {"sans", StringReference}, {"x", RealReference},
277       {"y", RealReference}, {"gravity", MagickGravityOptions},
278       {"translate", StringReference}, {"scale", StringReference},
279       {"rotate", RealReference}, {"skewX", RealReference},
280       {"skewY", RealReference}, {"strokewidth", RealReference},
281       {"antialias", MagickBooleanOptions}, {"family", StringReference},
282       {"style", MagickStyleOptions}, {"stretch", MagickStretchOptions},
283       {"weight", IntegerReference}, {"align", MagickAlignOptions},
284       {"encoding", StringReference}, {"affine", ArrayReference},
285       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
286       {"tile", ImageReference}, {"kerning", RealReference},
287       {"interline-spacing", RealReference},
288       {"interword-spacing", RealReference},
289       {"direction", MagickDirectionOptions} } },
290     { "ColorFloodfill", { {"geometry", StringReference},
291       {"x", IntegerReference}, {"y", IntegerReference},
292       {"fill", StringReference}, {"bordercolor", StringReference},
293       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
294     { "Composite", { {"image", ImageReference},
295       {"compose", MagickComposeOptions}, {"geometry", StringReference},
296       {"x", IntegerReference}, {"y", IntegerReference},
297       {"gravity", MagickGravityOptions}, {"opacity", StringReference},
298       {"tile", MagickBooleanOptions}, {"rotate", RealReference},
299       {"color", StringReference}, {"mask", ImageReference},
300       {"channel", MagickChannelOptions},
301       {"interpolate", MagickInterpolateOptions}, {"args", StringReference},
302       {"blend", StringReference}, {"crop-to-self", MagickBooleanOptions} } },
303     { "Contrast", { {"sharpen", MagickBooleanOptions} } },
304     { "CycleColormap", { {"display", IntegerReference} } },
305     { "Draw", { {"primitive", MagickPrimitiveOptions},
306       {"points", StringReference}, {"method", MagickMethodOptions},
307       {"stroke", StringReference}, {"fill", StringReference},
308       {"strokewidth", RealReference}, {"font", StringReference},
309       {"bordercolor", StringReference}, {"x", RealReference},
310       {"y", RealReference}, {"translate", StringReference},
311       {"scale", StringReference}, {"rotate", RealReference},
312       {"skewX", RealReference}, {"skewY", RealReference},
313       {"tile", ImageReference}, {"pointsize", RealReference},
314       {"antialias", MagickBooleanOptions}, {"density", StringReference},
315       {"linewidth", RealReference}, {"affine", ArrayReference},
316       {"stroke-dashoffset", RealReference},
317       {"stroke-dasharray", ArrayReference},
318       {"interpolate", MagickInterpolateOptions},
319       {"origin", StringReference}, {"text", StringReference},
320       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
321       {"vector-graphics", StringReference}, {"kerning", RealReference},
322       {"interline-spacing", RealReference},
323       {"interword-spacing", RealReference},
324       {"direction", MagickDirectionOptions} } },
325     { "Equalize", { {"channel", MagickChannelOptions} } },
326     { "Gamma", { {"gamma", StringReference}, {"channel", MagickChannelOptions},
327       {"red", RealReference}, {"green", RealReference},
328       {"blue", RealReference} } },
329     { "Map", { {"image", ImageReference},
330       {"dither-method", MagickDitherOptions} } },
331     { "MatteFloodfill", { {"geometry", StringReference},
332       {"x", IntegerReference}, {"y", IntegerReference},
333       {"opacity", StringReference}, {"bordercolor", StringReference},
334       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
335     { "Modulate", { {"factor", StringReference}, {"hue", RealReference},
336       {"saturation", RealReference}, {"whiteness", RealReference},
337       {"brightness", RealReference}, {"lightness", RealReference},
338       {"blackness", RealReference} } },
339     { "Negate", { {"gray", MagickBooleanOptions},
340       {"channel", MagickChannelOptions} } },
341     { "Normalize", { {"channel", MagickChannelOptions} } },
342     { "NumberColors", },
343     { "Opaque", { {"color", StringReference}, {"fill", StringReference},
344       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
345       {"invert", MagickBooleanOptions} } },
346     { "Quantize", { {"colors", IntegerReference},
347       {"treedepth", IntegerReference}, {"colorspace", MagickColorspaceOptions},
348       {"dither", MagickDitherOptions}, {"measure", MagickBooleanOptions},
349       {"global", MagickBooleanOptions}, {"transparent-color", StringReference},
350       {"dither-method", MagickDitherOptions} } },
351     { "Raise", { {"geometry", StringReference}, {"width", IntegerReference},
352       {"height", IntegerReference}, {"raise", MagickBooleanOptions} } },
353     { "Segment", { {"geometry", StringReference},
354       {"cluster-threshold", RealReference},
355       {"smoothing-threshold", RealReference},
356       {"colorspace", MagickColorspaceOptions},
357       {"verbose", MagickBooleanOptions} } },
358     { "Signature", },
359     { "Solarize", { {"geometry", StringReference},
360       {"threshold", StringReference} } },
361     { "Sync", },
362     { "Texture", { {"texture", ImageReference} } },
363     { "Evaluate", { {"value", RealReference},
364       {"operator", MagickEvaluateOptions},
365       {"channel", MagickChannelOptions} } },
366     { "Transparent", { {"color", StringReference}, {"opacity", StringReference},
367       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
368     { "Threshold", { {"threshold", StringReference},
369       {"channel", MagickChannelOptions} } },
370     { "Charcoal", { {"geometry", StringReference}, {"radius", RealReference},
371       {"sigma", RealReference} } },
372     { "Trim", { {"fuzz", StringReference} } },
373     { "Wave", { {"geometry", StringReference}, {"amplitude", RealReference},
374       {"wavelength", RealReference},
375       {"interpolate", MagickInterpolateOptions} } },
376     { "Separate", { {"channel", MagickChannelOptions} } },
377     { "Condense", },
378     { "Stereo", { {"image", ImageReference}, {"x", IntegerReference},
379       {"y", IntegerReference} } },
380     { "Stegano", { {"image", ImageReference}, {"offset", IntegerReference} } },
381     { "Deconstruct", },
382     { "GaussianBlur", { {"geometry", StringReference},
383       {"radius", RealReference}, {"sigma", RealReference},
384       {"channel", MagickChannelOptions} } },
385     { "Convolve", { {"coefficients", ArrayReference},
386       {"channel", MagickChannelOptions}, {"bias", StringReference},
387       {"kernel", StringReference} } },
388     { "Profile", { {"name", StringReference}, {"profile", StringReference},
389       { "rendering-intent", MagickIntentOptions},
390       { "black-point-compensation", MagickBooleanOptions} } },
391     { "UnsharpMask", { {"geometry", StringReference},
392       {"radius", RealReference}, {"sigma", RealReference},
393       {"amount", RealReference}, {"threshold", RealReference},
394       {"channel", MagickChannelOptions} } },
395     { "MotionBlur", { {"geometry", StringReference},
396       {"radius", RealReference}, {"sigma", RealReference},
397       {"angle", RealReference}, {"channel", MagickChannelOptions} } },
398     { "OrderedDither", { {"threshold", StringReference},
399       {"channel", MagickChannelOptions} } },
400     { "Shave", { {"geometry", StringReference}, {"width", IntegerReference},
401       {"height", IntegerReference} } },
402     { "Level", { {"levels", StringReference}, {"black-point", RealReference},
403       {"white-point", RealReference}, {"gamma", RealReference},
404       {"channel", MagickChannelOptions}, {"level", StringReference} } },
405     { "Clip", { {"id", StringReference}, {"inside", MagickBooleanOptions} } },
406     { "AffineTransform", { {"affine", ArrayReference},
407       {"translate", StringReference}, {"scale", StringReference},
408       {"rotate", RealReference}, {"skewX", RealReference},
409       {"skewY", RealReference}, {"interpolate", MagickInterpolateOptions},
410       {"background", StringReference} } },
411     { "Difference", { {"image", ImageReference}, {"fuzz", StringReference} } },
412     { "AdaptiveThreshold", { {"geometry", StringReference},
413       {"width", IntegerReference}, {"height", IntegerReference} } },
414     { "Resample", { {"density", StringReference}, {"x", RealReference},
415       {"y", RealReference}, {"filter", MagickFilterOptions},
416       {"support", RealReference } } },
417     { "Describe", { {"file", FileReference} } },
418     { "BlackThreshold", { {"threshold", StringReference},
419       {"channel", MagickChannelOptions} } },
420     { "WhiteThreshold", { {"threshold", StringReference},
421       {"channel", MagickChannelOptions} } },
422     { "RadialBlur", { {"geometry", StringReference}, {"angle", RealReference},
423       {"channel", MagickChannelOptions} } },
424     { "Thumbnail", { {"geometry", StringReference}, {"width", IntegerReference},
425       {"height", IntegerReference} } },
426     { "Strip", },
427     { "Tint", { {"fill", StringReference}, {"blend", StringReference} } },
428     { "Channel", { {"channel", MagickChannelOptions} } },
429     { "Splice", { {"geometry", StringReference}, {"width", IntegerReference},
430       {"height", IntegerReference}, {"x", IntegerReference},
431       {"y", IntegerReference}, {"fuzz", StringReference},
432       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
433     { "Posterize", { {"levels", IntegerReference},
434       {"dither", MagickBooleanOptions} } },
435     { "Shadow", { {"geometry", StringReference}, {"alpha", RealReference},
436       {"sigma", RealReference}, {"x", IntegerReference},
437       {"y", IntegerReference} } },
438     { "Identify", { {"file", FileReference}, {"features", StringReference},
439       {"unique", MagickBooleanOptions} } },
440     { "SepiaTone", { {"threshold", RealReference} } },
441     { "SigmoidalContrast", { {"geometry", StringReference},
442       {"contrast", RealReference}, {"mid-point", RealReference},
443       {"channel", MagickChannelOptions}, {"sharpen", MagickBooleanOptions} } },
444     { "Extent", { {"geometry", StringReference}, {"width", IntegerReference},
445       {"height", IntegerReference}, {"x", IntegerReference},
446       {"y", IntegerReference}, {"fuzz", StringReference},
447       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
448     { "Vignette", { {"geometry", StringReference}, {"radius", RealReference},
449       {"sigma", RealReference}, {"x", IntegerReference},
450       {"y", IntegerReference}, {"background", StringReference} } },
451     { "ContrastStretch", { {"levels", StringReference},
452       {"black-point", RealReference},{"white-point", RealReference},
453       {"channel", MagickChannelOptions} } },
454     { "Sans0", },
455     { "Sans1", },
456     { "AdaptiveSharpen", { {"geometry", StringReference},
457       {"radius", RealReference}, {"sigma", RealReference},
458       {"bias", RealReference}, {"channel", MagickChannelOptions} } },
459     { "Transpose", },
460     { "Transverse", },
461     { "AutoOrient", },
462     { "AdaptiveBlur", { {"geometry", StringReference},
463       {"radius", RealReference}, {"sigma", RealReference},
464       {"channel", MagickChannelOptions} } },
465     { "Sketch", { {"geometry", StringReference},
466       {"radius", RealReference}, {"sigma", RealReference},
467       {"angle", RealReference} } },
468     { "UniqueColors", },
469     { "AdaptiveResize", { {"geometry", StringReference},
470       {"width", IntegerReference}, {"height", IntegerReference},
471       {"filter", MagickFilterOptions}, {"support", StringReference },
472       {"blur", RealReference } } },
473     { "ClipMask", { {"mask", ImageReference} } },
474     { "LinearStretch", { {"levels", StringReference},
475       {"black-point", RealReference},{"white-point", RealReference} } },
476     { "ColorMatrix", { {"matrix", ArrayReference} } },
477     { "Mask", { {"mask", ImageReference} } },
478     { "Polaroid", { {"caption", StringReference}, {"angle", RealReference},
479       {"font", StringReference}, {"stroke", StringReference},
480       {"fill", StringReference}, {"strokewidth", RealReference},
481       {"pointsize", RealReference}, {"gravity", MagickGravityOptions},
482       {"background", StringReference},
483       {"interpolate", MagickInterpolateOptions} } },
484     { "FloodfillPaint", { {"geometry", StringReference},
485       {"x", IntegerReference}, {"y", IntegerReference},
486       {"fill", StringReference}, {"bordercolor", StringReference},
487       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
488       {"invert", MagickBooleanOptions} } },
489     { "Distort", { {"points", ArrayReference}, {"method", MagickDistortOptions},
490       {"virtual-pixel", MagickVirtualPixelOptions},
491       {"best-fit", MagickBooleanOptions} } },
492     { "Clut", { {"image", ImageReference},
493       {"interpolate", MagickInterpolateOptions},
494       {"channel", MagickChannelOptions} } },
495     { "LiquidRescale", { {"geometry", StringReference},
496       {"width", IntegerReference}, {"height", IntegerReference},
497       {"delta-x", RealReference}, {"rigidity", RealReference } } },
498     { "Encipher", { {"passphrase", StringReference} } },
499     { "Decipher", { {"passphrase", StringReference} } },
500     { "Deskew", { {"geometry", StringReference},
501       {"threshold", StringReference} } },
502     { "Remap", { {"image", ImageReference},
503       {"dither-method", MagickDitherOptions} } },
504     { "SparseColor", { {"points", ArrayReference},
505       {"method", MagickSparseColorOptions},
506       {"virtual-pixel", MagickVirtualPixelOptions},
507       {"channel", MagickChannelOptions} } },
508     { "Function", { {"parameters", ArrayReference},
509       {"function", MagickFunctionOptions},
510       {"virtual-pixel", MagickVirtualPixelOptions} } },
511     { "SelectiveBlur", { {"geometry", StringReference},
512       {"radius", RealReference}, {"sigma", RealReference},
513       {"threshold", RealReference}, {"channel", MagickChannelOptions} } },
514     { "HaldClut", { {"image", ImageReference},
515       {"channel", MagickChannelOptions} } },
516     { "BlueShift", { {"factor", StringReference} } },
517     { "ForwardFourierTransform", { {"magnitude", MagickBooleanOptions} } },
518     { "InverseFourierTransform", { {"magnitude", MagickBooleanOptions} } },
519     { "ColorDecisionList", {
520       {"color-correction-collection", StringReference} } },
521     { "AutoGamma", { {"channel", MagickChannelOptions} } },
522     { "AutoLevel", { {"channel", MagickChannelOptions} } },
523     { "LevelColors", { {"invert", MagickBooleanOptions},
524       {"black-point", StringReference}, {"white-point", StringReference},
525       {"channel", MagickChannelOptions}, {"invert", MagickBooleanOptions} } },
526     { "Clamp", { {"channel", MagickChannelOptions} } },
527     { "BrightnessContrast", { {"levels", StringReference},
528       {"brightness", RealReference},{"contrast", RealReference},
529       {"channel", MagickChannelOptions} } },
530     { "Morphology", { {"kernel", StringReference},
531       {"channel", MagickChannelOptions}, {"method", MagickMorphologyOptions},
532       {"iterations", IntegerReference} } },
533     { "Sans", { {"matrix", ArrayReference} } },
534     { "Color", { {"color", StringReference} } },
535     { "Mode", { {"geometry", StringReference},
536       {"width", IntegerReference},{"height", IntegerReference},
537       {"channel", MagickChannelOptions} } },
538     { "Statistic", { {"geometry", StringReference},
539       {"width", IntegerReference},{"height", IntegerReference},
540       {"channel", MagickChannelOptions}, {"type", MagickStatisticOptions} } },
541     { "Perceptible", { {"epsilon", RealReference},
542       {"channel", MagickChannelOptions} } },
543     { "Poly", { {"terms", ArrayReference},
544       {"channel", MagickChannelOptions} } }
545   };
546
547 static SplayTreeInfo
548   *magick_registry = (SplayTreeInfo *) NULL;
549 \f
550 /*
551   Forward declarations.
552 */
553 static Image
554   *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
555
556 static ssize_t
557   strEQcase(const char *,const char *);
558 \f
559 /*
560 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
561 %                                                                             %
562 %                                                                             %
563 %                                                                             %
564 %   C l o n e P a c k a g e I n f o                                           %
565 %                                                                             %
566 %                                                                             %
567 %                                                                             %
568 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
569 %
570 %  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
571 %  a new one.
572 %
573 %  The format of the ClonePackageInfo routine is:
574 %
575 %      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
576 %        exception)
577 %
578 %  A description of each parameter follows:
579 %
580 %    o info: a structure of type info.
581 %
582 %    o exception: Return any errors or warnings in this structure.
583 %
584 */
585 static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
586   ExceptionInfo *exception)
587 {
588   struct PackageInfo
589     *clone_info;
590
591   clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
592   if (clone_info == (struct PackageInfo *) NULL)
593     {
594       ThrowPerlException(exception,ResourceLimitError,
595         "UnableToClonePackageInfo",PackageName);
596       return((struct PackageInfo *) NULL);
597     }
598   if (info == (struct PackageInfo *) NULL)
599     {
600       clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
601       return(clone_info);
602     }
603   *clone_info=(*info);
604   clone_info->image_info=CloneImageInfo(info->image_info);
605   return(clone_info);
606 }
607 \f
608 /*
609 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
610 %                                                                             %
611 %                                                                             %
612 %                                                                             %
613 %   c o n s t a n t                                                           %
614 %                                                                             %
615 %                                                                             %
616 %                                                                             %
617 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
618 %
619 %  constant() returns a double value for the specified name.
620 %
621 %  The format of the constant routine is:
622 %
623 %      double constant(char *name,ssize_t sans)
624 %
625 %  A description of each parameter follows:
626 %
627 %    o value: Method constant returns a double value for the specified name.
628 %
629 %    o name: The name of the constant.
630 %
631 %    o sans: This integer value is not used.
632 %
633 */
634 static double constant(char *name,ssize_t sans)
635 {
636   (void) sans;
637   errno=0;
638   switch (*name)
639   {
640     case 'B':
641     {
642       if (strEQ(name,"BlobError"))
643         return(BlobError);
644       if (strEQ(name,"BlobWarning"))
645         return(BlobWarning);
646       break;
647     }
648     case 'C':
649     {
650       if (strEQ(name,"CacheError"))
651         return(CacheError);
652       if (strEQ(name,"CacheWarning"))
653         return(CacheWarning);
654       if (strEQ(name,"CoderError"))
655         return(CoderError);
656       if (strEQ(name,"CoderWarning"))
657         return(CoderWarning);
658       if (strEQ(name,"ConfigureError"))
659         return(ConfigureError);
660       if (strEQ(name,"ConfigureWarning"))
661         return(ConfigureWarning);
662       if (strEQ(name,"CorruptImageError"))
663         return(CorruptImageError);
664       if (strEQ(name,"CorruptImageWarning"))
665         return(CorruptImageWarning);
666       break;
667     }
668     case 'D':
669     {
670       if (strEQ(name,"DelegateError"))
671         return(DelegateError);
672       if (strEQ(name,"DelegateWarning"))
673         return(DelegateWarning);
674       if (strEQ(name,"DrawError"))
675         return(DrawError);
676       if (strEQ(name,"DrawWarning"))
677         return(DrawWarning);
678       break;
679     }
680     case 'E':
681     {
682       if (strEQ(name,"ErrorException"))
683         return(ErrorException);
684       if (strEQ(name,"ExceptionError"))
685         return(CoderError);
686       if (strEQ(name,"ExceptionWarning"))
687         return(CoderWarning);
688       break;
689     }
690     case 'F':
691     {
692       if (strEQ(name,"FatalErrorException"))
693         return(FatalErrorException);
694       if (strEQ(name,"FileOpenError"))
695         return(FileOpenError);
696       if (strEQ(name,"FileOpenWarning"))
697         return(FileOpenWarning);
698       break;
699     }
700     case 'I':
701     {
702       if (strEQ(name,"ImageError"))
703         return(ImageError);
704       if (strEQ(name,"ImageWarning"))
705         return(ImageWarning);
706       break;
707     }
708     case 'M':
709     {
710       if (strEQ(name,"MaxRGB"))
711         return(QuantumRange);
712       if (strEQ(name,"MissingDelegateError"))
713         return(MissingDelegateError);
714       if (strEQ(name,"MissingDelegateWarning"))
715         return(MissingDelegateWarning);
716       if (strEQ(name,"ModuleError"))
717         return(ModuleError);
718       if (strEQ(name,"ModuleWarning"))
719         return(ModuleWarning);
720       break;
721     }
722     case 'O':
723     {
724       if (strEQ(name,"Opaque"))
725         return(OpaqueAlpha);
726       if (strEQ(name,"OptionError"))
727         return(OptionError);
728       if (strEQ(name,"OptionWarning"))
729         return(OptionWarning);
730       break;
731     }
732     case 'Q':
733     {
734       if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
735         return(MAGICKCORE_QUANTUM_DEPTH);
736       if (strEQ(name,"QuantumDepth"))
737         return(MAGICKCORE_QUANTUM_DEPTH);
738       if (strEQ(name,"QuantumRange"))
739         return(QuantumRange);
740       break;
741     }
742     case 'R':
743     {
744       if (strEQ(name,"ResourceLimitError"))
745         return(ResourceLimitError);
746       if (strEQ(name,"ResourceLimitWarning"))
747         return(ResourceLimitWarning);
748       if (strEQ(name,"RegistryError"))
749         return(RegistryError);
750       if (strEQ(name,"RegistryWarning"))
751         return(RegistryWarning);
752       break;
753     }
754     case 'S':
755     {
756       if (strEQ(name,"StreamError"))
757         return(StreamError);
758       if (strEQ(name,"StreamWarning"))
759         return(StreamWarning);
760       if (strEQ(name,"Success"))
761         return(0);
762       break;
763     }
764     case 'T':
765     {
766       if (strEQ(name,"Transparent"))
767         return(TransparentAlpha);
768       if (strEQ(name,"TypeError"))
769         return(TypeError);
770       if (strEQ(name,"TypeWarning"))
771         return(TypeWarning);
772       break;
773     }
774     case 'W':
775     {
776       if (strEQ(name,"WarningException"))
777         return(WarningException);
778       break;
779     }
780     case 'X':
781     {
782       if (strEQ(name,"XServerError"))
783         return(XServerError);
784       if (strEQ(name,"XServerWarning"))
785         return(XServerWarning);
786       break;
787     }
788   }
789   errno=EINVAL;
790   return(0);
791 }
792 \f
793 /*
794 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
795 %                                                                             %
796 %                                                                             %
797 %                                                                             %
798 %   D e s t r o y P a c k a g e I n f o                                       %
799 %                                                                             %
800 %                                                                             %
801 %                                                                             %
802 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
803 %
804 %  Method DestroyPackageInfo frees a previously created info structure.
805 %
806 %  The format of the DestroyPackageInfo routine is:
807 %
808 %      DestroyPackageInfo(struct PackageInfo *info)
809 %
810 %  A description of each parameter follows:
811 %
812 %    o info: a structure of type info.
813 %
814 */
815 static void DestroyPackageInfo(struct PackageInfo *info)
816 {
817   info->image_info=DestroyImageInfo(info->image_info);
818   info=(struct PackageInfo *) RelinquishMagickMemory(info);
819 }
820 \f
821 /*
822 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
823 %                                                                             %
824 %                                                                             %
825 %                                                                             %
826 %   G e t L i s t                                                             %
827 %                                                                             %
828 %                                                                             %
829 %                                                                             %
830 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
831 %
832 %  Method GetList is recursively called by SetupList to traverse the
833 %  Image__Magick reference.  If building an reference_vector (see SetupList),
834 %  *current is the current position in *reference_vector and *last is the final
835 %  entry in *reference_vector.
836 %
837 %  The format of the GetList routine is:
838 %
839 %      GetList(info)
840 %
841 %  A description of each parameter follows:
842 %
843 %    o info: a structure of type info.
844 %
845 */
846 static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
847   ssize_t *current,ssize_t *last,ExceptionInfo *exception)
848 {
849   Image
850     *image;
851
852   if (reference == (SV *) NULL)
853     return(NULL);
854   switch (SvTYPE(reference))
855   {
856     case SVt_PVAV:
857     {
858       AV
859         *av;
860
861       Image
862         *head,
863         *previous;
864
865       register ssize_t
866         i;
867
868       ssize_t
869         n;
870
871       /*
872         Array of images.
873       */
874       previous=(Image *) NULL;
875       head=(Image *) NULL;
876       av=(AV *) reference;
877       n=av_len(av);
878       for (i=0; i <= n; i++)
879       {
880         SV
881           **rv;
882
883         rv=av_fetch(av,i,0);
884         if (rv && *rv && sv_isobject(*rv))
885           {
886             image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
887               exception);
888             if (image == (Image *) NULL)
889               continue;
890             if (image == previous)
891               {
892                 image=CloneImage(image,0,0,MagickTrue,exception);
893                 if (image == (Image *) NULL)
894                   return(NULL);
895               }
896             image->previous=previous;
897             *(previous ? &previous->next : &head)=image;
898             for (previous=image; previous->next; previous=previous->next) ;
899           }
900       }
901       return(head);
902     }
903     case SVt_PVMG:
904     {
905       /*
906         Blessed scalar, one image.
907       */
908       image=INT2PTR(Image *,SvIV(reference));
909       if (image == (Image *) NULL)
910         return(NULL);
911       image->previous=(Image *) NULL;
912       image->next=(Image *) NULL;
913       if (reference_vector)
914         {
915           if (*current == *last)
916             {
917               *last+=256;
918               if (*reference_vector == (SV **) NULL)
919                 *reference_vector=(SV **) AcquireQuantumMemory(*last,
920                   sizeof(*reference_vector));
921               else
922                 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
923                   *last,sizeof(*reference_vector));
924             }
925           if (*reference_vector == (SV **) NULL)
926             {
927               ThrowPerlException(exception,ResourceLimitError,
928                 "MemoryAllocationFailed",PackageName);
929               return((Image *) NULL);
930             }
931           (*reference_vector)[*current]=reference;
932           (*reference_vector)[++(*current)]=NULL;
933         }
934       return(image);
935     }
936     default:
937       break;
938   }
939   (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
940     (double) SvTYPE(reference));
941   return((Image *) NULL);
942 }
943 \f
944 /*
945 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
946 %                                                                             %
947 %                                                                             %
948 %                                                                             %
949 %   G e t P a c k a g e I n f o                                               %
950 %                                                                             %
951 %                                                                             %
952 %                                                                             %
953 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
954 %
955 %  Method GetPackageInfo looks up or creates an info structure for the given
956 %  Image__Magick reference.  If it does create a new one, the information in
957 %  package_info is used to initialize it.
958 %
959 %  The format of the GetPackageInfo routine is:
960 %
961 %      struct PackageInfo *GetPackageInfo(void *reference,
962 %        struct PackageInfo *package_info,ExceptionInfo *exception)
963 %
964 %  A description of each parameter follows:
965 %
966 %    o info: a structure of type info.
967 %
968 %    o exception: Return any errors or warnings in this structure.
969 %
970 */
971 static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
972   struct PackageInfo *package_info,ExceptionInfo *exception)
973 {
974   char
975     message[MaxTextExtent];
976
977   struct PackageInfo
978     *clone_info;
979
980   SV
981     *sv;
982
983   (void) FormatLocaleString(message,MaxTextExtent,"%s::package%s%p",
984     PackageName,XS_VERSION,reference);
985   sv=perl_get_sv(message,(TRUE | 0x02));
986   if (sv == (SV *) NULL)
987     {
988       ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
989         message);
990       return(package_info);
991     }
992   if (SvREFCNT(sv) == 0)
993     (void) SvREFCNT_inc(sv);
994   if (SvIOKp(sv) && (clone_info=INT2PTR(struct PackageInfo *,SvIV(sv))))
995     return(clone_info);
996   clone_info=ClonePackageInfo(package_info,exception);
997   sv_setiv(sv,PTR2IV(clone_info));
998   return(clone_info);
999 }
1000 \f
1001 /*
1002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1003 %                                                                             %
1004 %                                                                             %
1005 %                                                                             %
1006 %   S e t A t t r i b u t e                                                   %
1007 %                                                                             %
1008 %                                                                             %
1009 %                                                                             %
1010 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1011 %
1012 %  SetAttribute() sets the attribute to the value in sval.  This can change
1013 %  either or both of image or info.
1014 %
1015 %  The format of the SetAttribute routine is:
1016 %
1017 %      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1018 %        SV *sval,ExceptionInfo *exception)
1019 %
1020 %  A description of each parameter follows:
1021 %
1022 %    o list: a list of strings.
1023 %
1024 %    o string: a character string.
1025 %
1026 */
1027
1028 static double SiPrefixToDoubleInterval(const char *string,const double interval)
1029 {
1030   char
1031     *q;
1032
1033   double
1034     value;
1035
1036   value=InterpretSiPrefixValue(string,&q);
1037   if (*q == '%')
1038     value*=interval/100.0;
1039   return(value);
1040 }
1041
1042 static inline double StringToDouble(const char *string,char **sentinal)
1043 {
1044   return(InterpretLocaleValue(string,sentinal));
1045 }
1046
1047 static double StringToDoubleInterval(const char *string,const double interval)
1048 {
1049   char
1050     *q;
1051
1052   double
1053     value;
1054
1055   value=InterpretLocaleValue(string,&q);
1056   if (*q == '%')
1057     value*=interval/100.0;
1058   return(value);
1059 }
1060
1061 static inline ssize_t StringToLong(const char *value)
1062 {
1063   return(strtol(value,(char **) NULL,10));
1064 }
1065
1066 static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1067   const char *attribute,SV *sval,ExceptionInfo *exception)
1068 {
1069   GeometryInfo
1070     geometry_info;
1071
1072   long
1073     x,
1074     y;
1075
1076   PixelInfo
1077     pixel;
1078
1079   MagickStatusType
1080     flags;
1081
1082   PixelInfo
1083     *color,
1084     target_color;
1085
1086   ssize_t
1087     sp;
1088
1089   switch (*attribute)
1090   {
1091     case 'A':
1092     case 'a':
1093     {
1094       if (LocaleCompare(attribute,"adjoin") == 0)
1095         {
1096           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1097             SvPV(sval,na)) : SvIV(sval);
1098           if (sp < 0)
1099             {
1100               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1101                 SvPV(sval,na));
1102               break;
1103             }
1104           if (info)
1105             info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1106           break;
1107         }
1108       if (LocaleCompare(attribute,"alpha") == 0)
1109         {
1110           sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaChannelOptions,MagickFalse,
1111             SvPV(sval,na)) : SvIV(sval);
1112           if (sp < 0)
1113             {
1114               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1115                 SvPV(sval,na));
1116               break;
1117             }
1118           for ( ; image; image=image->next)
1119             (void) SetImageAlphaChannel(image,(AlphaChannelOption) sp,exception);
1120           break;
1121         }
1122       if (LocaleCompare(attribute,"antialias") == 0)
1123         {
1124           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1125             SvPV(sval,na)) : SvIV(sval);
1126           if (sp < 0)
1127             {
1128               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1129                 SvPV(sval,na));
1130               break;
1131             }
1132           if (info)
1133             info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1134           break;
1135         }
1136       if (LocaleCompare(attribute,"area-limit") == 0)
1137         {
1138           MagickSizeType
1139             limit;
1140
1141           limit=MagickResourceInfinity;
1142           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1143             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1144               100.0);
1145           (void) SetMagickResourceLimit(AreaResource,limit);
1146           break;
1147         }
1148       if (LocaleCompare(attribute,"attenuate") == 0)
1149         {
1150           if (info)
1151             (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1152           break;
1153         }
1154       if (LocaleCompare(attribute,"authenticate") == 0)
1155         {
1156           if (info)
1157             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1158           break;
1159         }
1160       if (info)
1161         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1162       for ( ; image; image=image->next)
1163         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1164       break;
1165     }
1166     case 'B':
1167     case 'b':
1168     {
1169       if (LocaleCompare(attribute,"background") == 0)
1170         {
1171           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1172             exception);
1173           if (info)
1174             info->image_info->background_color=target_color;
1175           for ( ; image; image=image->next)
1176             image->background_color=target_color;
1177           break;
1178         }
1179       if (LocaleCompare(attribute,"blue-primary") == 0)
1180         {
1181           for ( ; image; image=image->next)
1182           {
1183             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1184             image->chromaticity.blue_primary.x=geometry_info.rho;
1185             image->chromaticity.blue_primary.y=geometry_info.sigma;
1186             if ((flags & SigmaValue) == 0)
1187               image->chromaticity.blue_primary.y=
1188                 image->chromaticity.blue_primary.x;
1189           }
1190           break;
1191         }
1192       if (LocaleCompare(attribute,"bordercolor") == 0)
1193         {
1194           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1195             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),exception);
1206       break;
1207     }
1208     case 'C':
1209     case 'c':
1210     {
1211       if (LocaleCompare(attribute,"cache-threshold") == 0)
1212         {
1213           (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1214             SiPrefixToDoubleInterval(SvPV(sval,na),100.0));
1215           (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1216             (2.0*SiPrefixToDoubleInterval(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             SetImageMask(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               QueryColorCompliance(SvPV(sval,na),AllCompliance,
1251                 image->colormap+i,exception);
1252             else
1253               {
1254                 color=image->colormap+i;
1255                 pixel.red=color->red;
1256                 pixel.green=color->green;
1257                 pixel.blue=color->blue;
1258                 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1259                 pixel.red=geometry_info.rho;
1260                 pixel.green=geometry_info.sigma;
1261                 pixel.blue=geometry_info.xi;
1262                 color->red=ClampToQuantum(pixel.red);
1263                 color->green=ClampToQuantum(pixel.green);
1264                 color->blue=ClampToQuantum(pixel.blue);
1265               }
1266           }
1267           break;
1268         }
1269       if (LocaleCompare(attribute,"colorspace") == 0)
1270         {
1271           sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1272             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1273           if (sp < 0)
1274             {
1275               ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1276                 SvPV(sval,na));
1277               break;
1278             }
1279           for ( ; image; image=image->next)
1280             (void) TransformImageColorspace(image,(ColorspaceType) sp,
1281               exception);
1282           break;
1283         }
1284       if (LocaleCompare(attribute,"comment") == 0)
1285         {
1286           for ( ; image; image=image->next)
1287             (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1288               info ? info->image_info : (ImageInfo *) NULL,image,
1289               SvPV(sval,na),exception),exception);
1290           break;
1291         }
1292       if (LocaleCompare(attribute,"compression") == 0)
1293         {
1294           sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1295             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1296           if (sp < 0)
1297             {
1298               ThrowPerlException(exception,OptionError,
1299                 "UnrecognizedImageCompression",SvPV(sval,na));
1300               break;
1301             }
1302           if (info)
1303             info->image_info->compression=(CompressionType) sp;
1304           for ( ; image; image=image->next)
1305             image->compression=(CompressionType) sp;
1306           break;
1307         }
1308       if (info)
1309         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1310       for ( ; image; image=image->next)
1311         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1312       break;
1313     }
1314     case 'D':
1315     case 'd':
1316     {
1317       if (LocaleCompare(attribute,"debug") == 0)
1318         {
1319           SetLogEventMask(SvPV(sval,na));
1320           break;
1321         }
1322       if (LocaleCompare(attribute,"delay") == 0)
1323         {
1324           flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1325           for ( ; image; image=image->next)
1326           {
1327             image->delay=(size_t) floor(geometry_info.rho+0.5);
1328             if ((flags & SigmaValue) != 0)
1329               image->ticks_per_second=(ssize_t)
1330                 floor(geometry_info.sigma+0.5);
1331           }
1332           break;
1333         }
1334       if (LocaleCompare(attribute,"disk-limit") == 0)
1335         {
1336           MagickSizeType
1337             limit;
1338
1339           limit=MagickResourceInfinity;
1340           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1341             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1342               100.0);
1343           (void) SetMagickResourceLimit(DiskResource,limit);
1344           break;
1345         }
1346       if (LocaleCompare(attribute,"density") == 0)
1347         {
1348           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1349             {
1350               ThrowPerlException(exception,OptionError,"MissingGeometry",
1351                 SvPV(sval,na));
1352               break;
1353             }
1354           if (info)
1355             (void) CloneString(&info->image_info->density,SvPV(sval,na));
1356           for ( ; image; image=image->next)
1357           {
1358             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1359             image->resolution.x=geometry_info.rho;
1360             image->resolution.y=geometry_info.sigma;
1361             if ((flags & SigmaValue) == 0)
1362               image->resolution.y=image->resolution.x;
1363           }
1364           break;
1365         }
1366       if (LocaleCompare(attribute,"depth") == 0)
1367         {
1368           if (info)
1369             info->image_info->depth=SvIV(sval);
1370           for ( ; image; image=image->next)
1371             (void) SetImageDepth(image,SvIV(sval),exception);
1372           break;
1373         }
1374       if (LocaleCompare(attribute,"dispose") == 0)
1375         {
1376           sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1377             SvPV(sval,na)) : SvIV(sval);
1378           if (sp < 0)
1379             {
1380               ThrowPerlException(exception,OptionError,
1381                 "UnrecognizedDisposeMethod",SvPV(sval,na));
1382               break;
1383             }
1384           for ( ; image; image=image->next)
1385             image->dispose=(DisposeType) sp;
1386           break;
1387         }
1388       if (LocaleCompare(attribute,"dither") == 0)
1389         {
1390           if (info)
1391             {
1392               sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1393                 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1394               if (sp < 0)
1395                 {
1396                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
1397                     SvPV(sval,na));
1398                   break;
1399                 }
1400               info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1401             }
1402           break;
1403         }
1404       if (LocaleCompare(attribute,"display") == 0)
1405         {
1406           display:
1407           if (info)
1408             (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1409           break;
1410         }
1411       if (info)
1412         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1413       for ( ; image; image=image->next)
1414         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1415       break;
1416     }
1417     case 'E':
1418     case 'e':
1419     {
1420       if (LocaleCompare(attribute,"endian") == 0)
1421         {
1422           sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1423             SvPV(sval,na)) : SvIV(sval);
1424           if (sp < 0)
1425             {
1426               ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1427                 SvPV(sval,na));
1428               break;
1429             }
1430           if (info)
1431             info->image_info->endian=(EndianType) sp;
1432           for ( ; image; image=image->next)
1433             image->endian=(EndianType) sp;
1434           break;
1435         }
1436       if (LocaleCompare(attribute,"extract") == 0)
1437         {
1438           /*
1439             Set image extract geometry.
1440           */
1441           (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1442           break;
1443         }
1444       if (info)
1445         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1446       for ( ; image; image=image->next)
1447         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1448       break;
1449     }
1450     case 'F':
1451     case 'f':
1452     {
1453       if (LocaleCompare(attribute,"filename") == 0)
1454         {
1455           if (info)
1456             (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1457               MaxTextExtent);
1458           for ( ; image; image=image->next)
1459             (void) CopyMagickString(image->filename,SvPV(sval,na),
1460               MaxTextExtent);
1461           break;
1462         }
1463       if (LocaleCompare(attribute,"file") == 0)
1464         {
1465           FILE
1466             *file;
1467
1468           PerlIO
1469             *io_info;
1470
1471           if (info == (struct PackageInfo *) NULL)
1472             break;
1473           io_info=IoIFP(sv_2io(sval));
1474           if (io_info == (PerlIO *) NULL)
1475             {
1476               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1477                 PackageName);
1478               break;
1479             }
1480           file=PerlIO_findFILE(io_info);
1481           if (file == (FILE *) NULL)
1482             {
1483               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1484                 PackageName);
1485               break;
1486             }
1487           SetImageInfoFile(info->image_info,file);
1488           break;
1489         }
1490       if (LocaleCompare(attribute,"fill") == 0)
1491         {
1492           if (info)
1493             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1494           break;
1495         }
1496       if (LocaleCompare(attribute,"font") == 0)
1497         {
1498           if (info)
1499             (void) CloneString(&info->image_info->font,SvPV(sval,na));
1500           break;
1501         }
1502       if (LocaleCompare(attribute,"foreground") == 0)
1503         break;
1504       if (LocaleCompare(attribute,"fuzz") == 0)
1505         {
1506           if (info)
1507             info->image_info->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1508               QuantumRange+1.0);
1509           for ( ; image; image=image->next)
1510             image->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1511               QuantumRange+1.0);
1512           break;
1513         }
1514       if (info)
1515         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1516       for ( ; image; image=image->next)
1517         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1518       break;
1519     }
1520     case 'G':
1521     case 'g':
1522     {
1523       if (LocaleCompare(attribute,"gamma") == 0)
1524         {
1525           for ( ; image; image=image->next)
1526             image->gamma=SvNV(sval);
1527           break;
1528         }
1529       if (LocaleCompare(attribute,"gravity") == 0)
1530         {
1531           sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1532             SvPV(sval,na)) : SvIV(sval);
1533           if (sp < 0)
1534             {
1535               ThrowPerlException(exception,OptionError,
1536                 "UnrecognizedGravityType",SvPV(sval,na));
1537               break;
1538             }
1539           if (info)
1540             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1541           for ( ; image; image=image->next)
1542             image->gravity=(GravityType) sp;
1543           break;
1544         }
1545       if (LocaleCompare(attribute,"green-primary") == 0)
1546         {
1547           for ( ; image; image=image->next)
1548           {
1549             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1550             image->chromaticity.green_primary.x=geometry_info.rho;
1551             image->chromaticity.green_primary.y=geometry_info.sigma;
1552             if ((flags & SigmaValue) == 0)
1553               image->chromaticity.green_primary.y=
1554                 image->chromaticity.green_primary.x;
1555           }
1556           break;
1557         }
1558       if (info)
1559         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1560       for ( ; image; image=image->next)
1561         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1562       break;
1563     }
1564     case 'I':
1565     case 'i':
1566     {
1567       if (LocaleNCompare(attribute,"index",5) == 0)
1568         {
1569           int
1570             items;
1571
1572           long
1573             index;
1574
1575           register Quantum
1576             *q;
1577
1578           CacheView
1579             *image_view;
1580
1581           for ( ; image; image=image->next)
1582           {
1583             if (image->storage_class != PseudoClass)
1584               continue;
1585             x=0;
1586             y=0;
1587             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1588             (void) items;
1589             image_view=AcquireAuthenticCacheView(image,exception);
1590             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1591             if (q != (Quantum *) NULL)
1592               {
1593                 items=sscanf(SvPV(sval,na),"%ld",&index);
1594                 if ((index >= 0) && (index < (ssize_t) image->colors))
1595                   SetPixelIndex(image,index,q);
1596                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1597               }
1598             image_view=DestroyCacheView(image_view);
1599           }
1600           break;
1601         }
1602       if (LocaleCompare(attribute,"iterations") == 0)
1603         {
1604   iterations:
1605           for ( ; image; image=image->next)
1606             image->iterations=SvIV(sval);
1607           break;
1608         }
1609       if (LocaleCompare(attribute,"interlace") == 0)
1610         {
1611           sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1612             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1613           if (sp < 0)
1614             {
1615               ThrowPerlException(exception,OptionError,
1616                 "UnrecognizedInterlaceType",SvPV(sval,na));
1617               break;
1618             }
1619           if (info)
1620             info->image_info->interlace=(InterlaceType) sp;
1621           for ( ; image; image=image->next)
1622             image->interlace=(InterlaceType) sp;
1623           break;
1624         }
1625       if (info)
1626         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1627       for ( ; image; image=image->next)
1628         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1629       break;
1630     }
1631     case 'L':
1632     case 'l':
1633     {
1634       if (LocaleCompare(attribute,"label") == 0)
1635         {
1636           for ( ; image; image=image->next)
1637             (void) SetImageProperty(image,"label",InterpretImageProperties(
1638               info ? info->image_info : (ImageInfo *) NULL,image,
1639               SvPV(sval,na),exception),exception);
1640           break;
1641         }
1642       if (LocaleCompare(attribute,"loop") == 0)
1643         goto iterations;
1644       if (info)
1645         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1646       for ( ; image; image=image->next)
1647         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1648       break;
1649     }
1650     case 'M':
1651     case 'm':
1652     {
1653       if (LocaleCompare(attribute,"magick") == 0)
1654         {
1655           if (info)
1656             (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
1657               "%s:",SvPV(sval,na));
1658           for ( ; image; image=image->next)
1659             (void) CopyMagickString(image->magick,SvPV(sval,na),MaxTextExtent);
1660           break;
1661         }
1662       if (LocaleCompare(attribute,"map-limit") == 0)
1663         {
1664           MagickSizeType
1665             limit;
1666
1667           limit=MagickResourceInfinity;
1668           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1669             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1670               100.0);
1671           (void) SetMagickResourceLimit(MapResource,limit);
1672           break;
1673         }
1674       if (LocaleCompare(attribute,"mask") == 0)
1675         {
1676           Image
1677             *mask;
1678
1679           mask=(Image *) NULL;
1680           if (SvPOK(sval))
1681             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1682           for ( ; image; image=image->next)
1683             SetImageMask(image,mask,exception);
1684           break;
1685         }
1686       if (LocaleCompare(attribute,"mattecolor") == 0)
1687         {
1688           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1689             exception);
1690           if (info)
1691             info->image_info->matte_color=target_color;
1692           for ( ; image; image=image->next)
1693             image->matte_color=target_color;
1694           break;
1695         }
1696       if (LocaleCompare(attribute,"matte") == 0)
1697         {
1698           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1699             SvPV(sval,na)) : SvIV(sval);
1700           if (sp < 0)
1701             {
1702               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1703                 SvPV(sval,na));
1704               break;
1705             }
1706           for ( ; image; image=image->next)
1707             image->alpha_trait=sp != 0 ? BlendPixelTrait : UndefinedPixelTrait;
1708           break;
1709         }
1710       if (LocaleCompare(attribute,"memory-limit") == 0)
1711         {
1712           MagickSizeType
1713             limit;
1714
1715           limit=MagickResourceInfinity;
1716           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1717             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1718               100.0);
1719           (void) SetMagickResourceLimit(MemoryResource,limit);
1720           break;
1721         }
1722       if (LocaleCompare(attribute,"monochrome") == 0)
1723         {
1724           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1725             SvPV(sval,na)) : SvIV(sval);
1726           if (sp < 0)
1727             {
1728               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1729                 SvPV(sval,na));
1730               break;
1731             }
1732           if (info)
1733             info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1734           for ( ; image; image=image->next)
1735             (void) SetImageType(image,BilevelType,exception);
1736           break;
1737         }
1738       if (info)
1739         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1740       for ( ; image; image=image->next)
1741         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1742       break;
1743     }
1744     case 'O':
1745     case 'o':
1746     {
1747       if (LocaleCompare(attribute,"option") == 0)
1748         {
1749           if (info)
1750             DefineImageOption(info->image_info,SvPV(sval,na));
1751           break;
1752         }
1753       if (LocaleCompare(attribute,"orientation") == 0)
1754         {
1755           sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1756             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1757           if (sp < 0)
1758             {
1759               ThrowPerlException(exception,OptionError,
1760                 "UnrecognizedOrientationType",SvPV(sval,na));
1761               break;
1762             }
1763           if (info)
1764             info->image_info->orientation=(OrientationType) sp;
1765           for ( ; image; image=image->next)
1766             image->orientation=(OrientationType) sp;
1767           break;
1768         }
1769       if (info)
1770         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1771       for ( ; image; image=image->next)
1772         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1773       break;
1774     }
1775     case 'P':
1776     case 'p':
1777     {
1778       if (LocaleCompare(attribute,"page") == 0)
1779         {
1780           char
1781             *geometry;
1782
1783           geometry=GetPageGeometry(SvPV(sval,na));
1784           if (info)
1785             (void) CloneString(&info->image_info->page,geometry);
1786           for ( ; image; image=image->next)
1787             (void) ParsePageGeometry(image,geometry,&image->page,exception);
1788           geometry=(char *) RelinquishMagickMemory(geometry);
1789           break;
1790         }
1791       if (LocaleNCompare(attribute,"pixel",5) == 0)
1792         {
1793           int
1794             items;
1795
1796           PixelInfo
1797             pixel;
1798
1799           register Quantum
1800             *q;
1801
1802           CacheView
1803             *image_view;
1804
1805           for ( ; image; image=image->next)
1806           {
1807             if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1808               break;
1809             x=0;
1810             y=0;
1811             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1812             (void) items;
1813             image_view=AcquireVirtualCacheView(image,exception);
1814             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1815             if (q != (Quantum *) NULL)
1816               {
1817                 if ((strchr(SvPV(sval,na),',') == 0) ||
1818                     (strchr(SvPV(sval,na),')') != 0))
1819                   QueryColorCompliance(SvPV(sval,na),AllCompliance,
1820                     &pixel,exception);
1821                 else
1822                   {
1823                     GetPixelInfo(image,&pixel);
1824                     flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1825                     pixel.red=geometry_info.rho;
1826                     if ((flags & SigmaValue) != 0)
1827                       pixel.green=geometry_info.sigma;
1828                     if ((flags & XiValue) != 0)
1829                       pixel.blue=geometry_info.xi;
1830                     if ((flags & PsiValue) != 0)
1831                       pixel.alpha=geometry_info.psi;
1832                     if ((flags & ChiValue) != 0)
1833                       pixel.black=geometry_info.chi;
1834                   }
1835                 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1836                 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1837                 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1838                 if (image->colorspace == CMYKColorspace)
1839                   SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1840                 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1841                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1842               }
1843             image_view=DestroyCacheView(image_view);
1844           }
1845           break;
1846         }
1847       if (LocaleCompare(attribute,"pointsize") == 0)
1848         {
1849           if (info)
1850             {
1851               (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1852               info->image_info->pointsize=geometry_info.rho;
1853             }
1854           break;
1855         }
1856       if (LocaleCompare(attribute,"preview") == 0)
1857         {
1858           sp=SvPOK(sval) ? ParseCommandOption(MagickPreviewOptions,MagickFalse,
1859             SvPV(sval,na)) : SvIV(sval);
1860           if (sp < 0)
1861             {
1862               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1863                 SvPV(sval,na));
1864               break;
1865             }
1866           if (info)
1867             info->image_info->preview_type=(PreviewType) sp;
1868           break;
1869         }
1870       if (info)
1871         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1872       for ( ; image; image=image->next)
1873         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1874       break;
1875     }
1876     case 'Q':
1877     case 'q':
1878     {
1879       if (LocaleCompare(attribute,"quality") == 0)
1880         {
1881           if (info)
1882             info->image_info->quality=SvIV(sval);
1883           for ( ; image; image=image->next)
1884             image->quality=SvIV(sval);
1885           break;
1886         }
1887       if (info)
1888         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1889       for ( ; image; image=image->next)
1890         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1891       break;
1892     }
1893     case 'R':
1894     case 'r':
1895     {
1896       if (LocaleCompare(attribute,"red-primary") == 0)
1897         {
1898           for ( ; image; image=image->next)
1899           {
1900             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1901             image->chromaticity.red_primary.x=geometry_info.rho;
1902             image->chromaticity.red_primary.y=geometry_info.sigma;
1903             if ((flags & SigmaValue) == 0)
1904               image->chromaticity.red_primary.y=
1905                 image->chromaticity.red_primary.x;
1906           }
1907           break;
1908         }
1909       if (LocaleCompare(attribute,"render") == 0)
1910         {
1911           sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1912             SvPV(sval,na)) : SvIV(sval);
1913           if (sp < 0)
1914             {
1915               ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1916                 SvPV(sval,na));
1917               break;
1918             }
1919          for ( ; image; image=image->next)
1920            image->rendering_intent=(RenderingIntent) sp;
1921          break;
1922        }
1923       if (LocaleCompare(attribute,"repage") == 0)
1924         {
1925           RectangleInfo
1926             geometry;
1927
1928           for ( ; image; image=image->next)
1929           {
1930             flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
1931             if ((flags & WidthValue) != 0)
1932               {
1933                 if ((flags & HeightValue) == 0)
1934                   geometry.height=geometry.width;
1935                 image->page.width=geometry.width;
1936                 image->page.height=geometry.height;
1937               }
1938             if ((flags & AspectValue) != 0)
1939               {
1940                 if ((flags & XValue) != 0)
1941                   image->page.x+=geometry.x;
1942                 if ((flags & YValue) != 0)
1943                   image->page.y+=geometry.y;
1944               }
1945             else
1946               {
1947                 if ((flags & XValue) != 0)
1948                   {
1949                     image->page.x=geometry.x;
1950                     if (((flags & WidthValue) != 0) && (geometry.x > 0))
1951                       image->page.width=image->columns+geometry.x;
1952                   }
1953                 if ((flags & YValue) != 0)
1954                   {
1955                     image->page.y=geometry.y;
1956                     if (((flags & HeightValue) != 0) && (geometry.y > 0))
1957                       image->page.height=image->rows+geometry.y;
1958                   }
1959               }
1960           }
1961           break;
1962         }
1963       if (info)
1964         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1965       for ( ; image; image=image->next)
1966         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1967       break;
1968     }
1969     case 'S':
1970     case 's':
1971     {
1972       if (LocaleCompare(attribute,"sampling-factor") == 0)
1973         {
1974           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1975             {
1976               ThrowPerlException(exception,OptionError,"MissingGeometry",
1977                 SvPV(sval,na));
1978               break;
1979             }
1980           if (info)
1981             (void) CloneString(&info->image_info->sampling_factor,
1982               SvPV(sval,na));
1983           break;
1984         }
1985       if (LocaleCompare(attribute,"scene") == 0)
1986         {
1987           for ( ; image; image=image->next)
1988             image->scene=SvIV(sval);
1989           break;
1990         }
1991       if (LocaleCompare(attribute,"server") == 0)
1992         goto display;
1993       if (LocaleCompare(attribute,"size") == 0)
1994         {
1995           if (info)
1996             {
1997               if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1998                 {
1999                   ThrowPerlException(exception,OptionError,"MissingGeometry",
2000                     SvPV(sval,na));
2001                   break;
2002                 }
2003               (void) CloneString(&info->image_info->size,SvPV(sval,na));
2004             }
2005           break;
2006         }
2007       if (LocaleCompare(attribute,"stroke") == 0)
2008         {
2009           if (info)
2010             (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2011           break;
2012         }
2013       if (info)
2014         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2015       for ( ; image; image=image->next)
2016         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2017       break;
2018     }
2019     case 'T':
2020     case 't':
2021     {
2022       if (LocaleCompare(attribute,"texture") == 0)
2023         {
2024           if (info)
2025             (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2026           break;
2027         }
2028       if (LocaleCompare(attribute,"thread-limit") == 0)
2029         {
2030           MagickSizeType
2031             limit;
2032
2033           limit=MagickResourceInfinity;
2034           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2035             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2036               100.0);
2037           (void) SetMagickResourceLimit(ThreadResource,limit);
2038           break;
2039         }
2040       if (LocaleCompare(attribute,"tile-offset") == 0)
2041         {
2042           char
2043             *geometry;
2044
2045           geometry=GetPageGeometry(SvPV(sval,na));
2046           if (info)
2047             (void) CloneString(&info->image_info->page,geometry);
2048           for ( ; image; image=image->next)
2049             (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2050               exception);
2051           geometry=(char *) RelinquishMagickMemory(geometry);
2052           break;
2053         }
2054       if (LocaleCompare(attribute,"time-limit") == 0)
2055         {
2056           MagickSizeType
2057             limit;
2058
2059           limit=MagickResourceInfinity;
2060           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2061             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2062               100.0);
2063           (void) SetMagickResourceLimit(TimeResource,limit);
2064           break;
2065         }
2066       if (LocaleCompare(attribute,"transparent-color") == 0)
2067         {
2068           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
2069             exception);
2070           if (info)
2071             info->image_info->transparent_color=target_color;
2072           for ( ; image; image=image->next)
2073             image->transparent_color=target_color;
2074           break;
2075         }
2076       if (LocaleCompare(attribute,"type") == 0)
2077         {
2078           sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2079             SvPV(sval,na)) : SvIV(sval);
2080           if (sp < 0)
2081             {
2082               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2083                 SvPV(sval,na));
2084               break;
2085             }
2086           if (info)
2087             info->image_info->type=(ImageType) sp;
2088           for ( ; image; image=image->next)
2089             SetImageType(image,(ImageType) sp,exception);
2090           break;
2091         }
2092       if (info)
2093         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2094       for ( ; image; image=image->next)
2095         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2096       break;
2097     }
2098     case 'U':
2099     case 'u':
2100     {
2101       if (LocaleCompare(attribute,"units") == 0)
2102         {
2103           sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2104             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2105           if (sp < 0)
2106             {
2107               ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2108                 SvPV(sval,na));
2109               break;
2110             }
2111           if (info)
2112             info->image_info->units=(ResolutionType) sp;
2113           for ( ; image; image=image->next)
2114           {
2115             ResolutionType
2116               units;
2117
2118             units=(ResolutionType) sp;
2119             if (image->units != units)
2120               switch (image->units)
2121               {
2122                 case UndefinedResolution:
2123                 case PixelsPerInchResolution:
2124                 {
2125                   if (units == PixelsPerCentimeterResolution)
2126                     {
2127                       image->resolution.x*=2.54;
2128                       image->resolution.y*=2.54;
2129                     }
2130                   break;
2131                 }
2132                 case PixelsPerCentimeterResolution:
2133                 {
2134                   if (units == PixelsPerInchResolution)
2135                     {
2136                       image->resolution.x/=2.54;
2137                       image->resolution.y/=2.54;
2138                     }
2139                   break;
2140                 }
2141               }
2142             image->units=units;
2143           }
2144           break;
2145         }
2146       if (info)
2147         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2148       for ( ; image; image=image->next)
2149         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2150       break;
2151     }
2152     case 'V':
2153     case 'v':
2154     {
2155       if (LocaleCompare(attribute,"verbose") == 0)
2156         {
2157           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2158             SvPV(sval,na)) : SvIV(sval);
2159           if (sp < 0)
2160             {
2161               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2162                 SvPV(sval,na));
2163               break;
2164             }
2165           if (info)
2166             info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2167           break;
2168         }
2169       if (LocaleCompare(attribute,"view") == 0)
2170         {
2171           if (info)
2172             (void) CloneString(&info->image_info->view,SvPV(sval,na));
2173           break;
2174         }
2175       if (LocaleCompare(attribute,"virtual-pixel") == 0)
2176         {
2177           sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2178             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2179           if (sp < 0)
2180             {
2181               ThrowPerlException(exception,OptionError,
2182                 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2183               break;
2184             }
2185           for ( ; image; image=image->next)
2186             SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp,exception);
2187           break;
2188         }
2189       if (info)
2190         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2191       for ( ; image; image=image->next)
2192         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2193       break;
2194     }
2195     case 'W':
2196     case 'w':
2197     {
2198       if (LocaleCompare(attribute,"white-point") == 0)
2199         {
2200           for ( ; image; image=image->next)
2201           {
2202             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2203             image->chromaticity.white_point.x=geometry_info.rho;
2204             image->chromaticity.white_point.y=geometry_info.sigma;
2205             if ((flags & SigmaValue) == 0)
2206               image->chromaticity.white_point.y=
2207                 image->chromaticity.white_point.x;
2208           }
2209           break;
2210         }
2211       if (info)
2212         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2213       for ( ; image; image=image->next)
2214         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2215       break;
2216     }
2217     default:
2218     {
2219       if (info)
2220         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2221       for ( ; image; image=image->next)
2222         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2223       break;
2224     }
2225   }
2226 }
2227 \f
2228 /*
2229 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2230 %                                                                             %
2231 %                                                                             %
2232 %                                                                             %
2233 %   S e t u p L i s t                                                         %
2234 %                                                                             %
2235 %                                                                             %
2236 %                                                                             %
2237 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2238 %
2239 %  Method SetupList returns the list of all the images linked by their
2240 %  image->next and image->previous link lists for use with ImageMagick.  If
2241 %  info is non-NULL, an info structure is returned in *info.  If
2242 %  reference_vector is non-NULL,an array of SV* are returned in
2243 %  *reference_vector.  Reference_vector is used when the images are going to be
2244 %  replaced with new Image*'s.
2245 %
2246 %  The format of the SetupList routine is:
2247 %
2248 %      Image *SetupList(SV *reference,struct PackageInfo **info,
2249 %        SV ***reference_vector,ExceptionInfo *exception)
2250 %
2251 %  A description of each parameter follows:
2252 %
2253 %    o list: a list of strings.
2254 %
2255 %    o string: a character string.
2256 %
2257 %    o exception: Return any errors or warnings in this structure.
2258 %
2259 */
2260 static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2261   SV ***reference_vector,ExceptionInfo *exception)
2262 {
2263   Image
2264     *image;
2265
2266   ssize_t
2267     current,
2268     last;
2269
2270   if (reference_vector)
2271     *reference_vector=NULL;
2272   if (info)
2273     *info=NULL;
2274   current=0;
2275   last=0;
2276   image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2277   if (info && (SvTYPE(reference) == SVt_PVAV))
2278     *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2279       exception);
2280   return(image);
2281 }
2282 \f
2283 /*
2284 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2285 %                                                                             %
2286 %                                                                             %
2287 %                                                                             %
2288 %   s t r E Q c a s e                                                         %
2289 %                                                                             %
2290 %                                                                             %
2291 %                                                                             %
2292 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2293 %
2294 %  strEQcase() compares two strings and returns 0 if they are the
2295 %  same or if the second string runs out first.  The comparison is case
2296 %  insensitive.
2297 %
2298 %  The format of the strEQcase routine is:
2299 %
2300 %      ssize_t strEQcase(const char *p,const char *q)
2301 %
2302 %  A description of each parameter follows:
2303 %
2304 %    o p: a character string.
2305 %
2306 %    o q: a character string.
2307 %
2308 %
2309 */
2310 static ssize_t strEQcase(const char *p,const char *q)
2311 {
2312   char
2313     c;
2314
2315   register ssize_t
2316     i;
2317
2318   for (i=0 ; (c=(*q)) != 0; i++)
2319   {
2320     if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2321         (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2322       return(0);
2323     p++;
2324     q++;
2325   }
2326   return(((*q == 0) && (*p == 0)) ? i : 0);
2327 }
2328 \f
2329 /*
2330 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2331 %                                                                             %
2332 %                                                                             %
2333 %                                                                             %
2334 %   I m a g e : : M a g i c k                                                 %
2335 %                                                                             %
2336 %                                                                             %
2337 %                                                                             %
2338 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2339 %
2340 %
2341 */
2342 MODULE = Image::Magick PACKAGE = Image::Magick
2343
2344 PROTOTYPES: ENABLE
2345
2346 BOOT:
2347   MagickCoreGenesis("PerlMagick",MagickFalse);
2348   SetWarningHandler(NULL);
2349   SetErrorHandler(NULL);
2350   magick_registry=NewSplayTree((int (*)(const void *,const void *))
2351     NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2352
2353 void
2354 UNLOAD()
2355   PPCODE:
2356   {
2357     if (magick_registry != (SplayTreeInfo *) NULL)
2358       magick_registry=DestroySplayTree(magick_registry);
2359     MagickCoreTerminus();
2360   }
2361
2362 double
2363 constant(name,argument)
2364   char *name
2365   ssize_t argument
2366 \f
2367 #
2368 ###############################################################################
2369 #                                                                             #
2370 #                                                                             #
2371 #                                                                             #
2372 #   A n i m a t e                                                             #
2373 #                                                                             #
2374 #                                                                             #
2375 #                                                                             #
2376 ###############################################################################
2377 #
2378 #
2379 void
2380 Animate(ref,...)
2381   Image::Magick ref=NO_INIT
2382   ALIAS:
2383     AnimateImage  = 1
2384     animate       = 2
2385     animateimage  = 3
2386   PPCODE:
2387   {
2388     ExceptionInfo
2389       *exception;
2390
2391     Image
2392       *image;
2393
2394     register ssize_t
2395       i;
2396
2397     struct PackageInfo
2398       *info,
2399       *package_info;
2400
2401     SV
2402       *perl_exception,
2403       *reference;
2404
2405     PERL_UNUSED_VAR(ref);
2406     PERL_UNUSED_VAR(ix);
2407     exception=AcquireExceptionInfo();
2408     perl_exception=newSVpv("",0);
2409     package_info=(struct PackageInfo *) NULL;
2410     if (sv_isobject(ST(0)) == 0)
2411       {
2412         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2413           PackageName);
2414         goto PerlException;
2415       }
2416     reference=SvRV(ST(0));
2417     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2418     if (image == (Image *) NULL)
2419       {
2420         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2421           PackageName);
2422         goto PerlException;
2423       }
2424     package_info=ClonePackageInfo(info,exception);
2425     if (items == 2)
2426       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2427     else
2428       if (items > 2)
2429         for (i=2; i < items; i+=2)
2430           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2431             exception);
2432     (void) AnimateImages(package_info->image_info,image,exception);
2433     (void) CatchImageException(image);
2434
2435   PerlException:
2436     if (package_info != (struct PackageInfo *) NULL)
2437       DestroyPackageInfo(package_info);
2438     InheritPerlException(exception,perl_exception);
2439     exception=DestroyExceptionInfo(exception);
2440     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2441     SvPOK_on(perl_exception);
2442     ST(0)=sv_2mortal(perl_exception);
2443     XSRETURN(1);
2444   }
2445 \f
2446 #
2447 ###############################################################################
2448 #                                                                             #
2449 #                                                                             #
2450 #                                                                             #
2451 #   A p p e n d                                                               #
2452 #                                                                             #
2453 #                                                                             #
2454 #                                                                             #
2455 ###############################################################################
2456 #
2457 #
2458 void
2459 Append(ref,...)
2460   Image::Magick ref=NO_INIT
2461   ALIAS:
2462     AppendImage  = 1
2463     append       = 2
2464     appendimage  = 3
2465   PPCODE:
2466   {
2467     AV
2468       *av;
2469
2470     char
2471       *attribute;
2472
2473     ExceptionInfo
2474       *exception;
2475
2476     HV
2477       *hv;
2478
2479     Image
2480       *image;
2481
2482     register ssize_t
2483       i;
2484
2485     ssize_t
2486       stack;
2487
2488     struct PackageInfo
2489       *info;
2490
2491     SV
2492       *av_reference,
2493       *perl_exception,
2494       *reference,
2495       *rv,
2496       *sv;
2497
2498     PERL_UNUSED_VAR(ref);
2499     PERL_UNUSED_VAR(ix);
2500     exception=AcquireExceptionInfo();
2501     perl_exception=newSVpv("",0);
2502     sv=NULL;
2503     attribute=NULL;
2504     av=NULL;
2505     if (sv_isobject(ST(0)) == 0)
2506       {
2507         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2508           PackageName);
2509         goto PerlException;
2510       }
2511     reference=SvRV(ST(0));
2512     hv=SvSTASH(reference);
2513     av=newAV();
2514     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2515     SvREFCNT_dec(av);
2516     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2517     if (image == (Image *) NULL)
2518       {
2519         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2520           PackageName);
2521         goto PerlException;
2522       }
2523     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2524     /*
2525       Get options.
2526     */
2527     stack=MagickTrue;
2528     for (i=2; i < items; i+=2)
2529     {
2530       attribute=(char *) SvPV(ST(i-1),na);
2531       switch (*attribute)
2532       {
2533         case 'S':
2534         case 's':
2535         {
2536           if (LocaleCompare(attribute,"stack") == 0)
2537             {
2538               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2539                 SvPV(ST(i),na));
2540               if (stack < 0)
2541                 {
2542                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
2543                     SvPV(ST(i),na));
2544                   return;
2545                 }
2546               break;
2547             }
2548           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2549             attribute);
2550           break;
2551         }
2552         default:
2553         {
2554           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2555             attribute);
2556           break;
2557         }
2558       }
2559     }
2560     image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2561     if (image == (Image *) NULL)
2562       goto PerlException;
2563     for ( ; image; image=image->next)
2564     {
2565       AddImageToRegistry(sv,image);
2566       rv=newRV(sv);
2567       av_push(av,sv_bless(rv,hv));
2568       SvREFCNT_dec(sv);
2569     }
2570     exception=DestroyExceptionInfo(exception);
2571     ST(0)=av_reference;
2572     SvREFCNT_dec(perl_exception);
2573     XSRETURN(1);
2574
2575   PerlException:
2576     InheritPerlException(exception,perl_exception);
2577     exception=DestroyExceptionInfo(exception);
2578     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2579     SvPOK_on(perl_exception);
2580     ST(0)=sv_2mortal(perl_exception);
2581     XSRETURN(1);
2582   }
2583 \f
2584 #
2585 ###############################################################################
2586 #                                                                             #
2587 #                                                                             #
2588 #                                                                             #
2589 #   A v e r a g e                                                             #
2590 #                                                                             #
2591 #                                                                             #
2592 #                                                                             #
2593 ###############################################################################
2594 #
2595 #
2596 void
2597 Average(ref)
2598   Image::Magick ref=NO_INIT
2599   ALIAS:
2600     AverageImage   = 1
2601     average        = 2
2602     averageimage   = 3
2603   PPCODE:
2604   {
2605     AV
2606       *av;
2607
2608     char
2609       *p;
2610
2611     ExceptionInfo
2612       *exception;
2613
2614     HV
2615       *hv;
2616
2617     Image
2618       *image;
2619
2620     struct PackageInfo
2621       *info;
2622
2623     SV
2624       *perl_exception,
2625       *reference,
2626       *rv,
2627       *sv;
2628
2629     PERL_UNUSED_VAR(ref);
2630     PERL_UNUSED_VAR(ix);
2631     exception=AcquireExceptionInfo();
2632     perl_exception=newSVpv("",0);
2633     sv=NULL;
2634     if (sv_isobject(ST(0)) == 0)
2635       {
2636         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2637           PackageName);
2638         goto PerlException;
2639       }
2640     reference=SvRV(ST(0));
2641     hv=SvSTASH(reference);
2642     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2643     if (image == (Image *) NULL)
2644       {
2645         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2646           PackageName);
2647         goto PerlException;
2648       }
2649     image=EvaluateImages(image,MeanEvaluateOperator,exception);
2650     if (image == (Image *) NULL)
2651       goto PerlException;
2652     /*
2653       Create blessed Perl array for the returned image.
2654     */
2655     av=newAV();
2656     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2657     SvREFCNT_dec(av);
2658     AddImageToRegistry(sv,image);
2659     rv=newRV(sv);
2660     av_push(av,sv_bless(rv,hv));
2661     SvREFCNT_dec(sv);
2662     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2663     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
2664       "average-%.*s",(int) (MaxTextExtent-9),
2665       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2666     (void) CopyMagickString(image->filename,info->image_info->filename,
2667       MaxTextExtent);
2668     SetImageInfo(info->image_info,0,exception);
2669     exception=DestroyExceptionInfo(exception);
2670     SvREFCNT_dec(perl_exception);
2671     XSRETURN(1);
2672
2673   PerlException:
2674     InheritPerlException(exception,perl_exception);
2675     exception=DestroyExceptionInfo(exception);
2676     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2677     SvPOK_on(perl_exception);
2678     ST(0)=sv_2mortal(perl_exception);
2679     XSRETURN(1);
2680   }
2681 \f
2682 #
2683 ###############################################################################
2684 #                                                                             #
2685 #                                                                             #
2686 #                                                                             #
2687 #   B l o b T o I m a g e                                                     #
2688 #                                                                             #
2689 #                                                                             #
2690 #                                                                             #
2691 ###############################################################################
2692 #
2693 #
2694 void
2695 BlobToImage(ref,...)
2696   Image::Magick ref=NO_INIT
2697   ALIAS:
2698     BlobToImage  = 1
2699     blobtoimage  = 2
2700     blobto       = 3
2701   PPCODE:
2702   {
2703     AV
2704       *av;
2705
2706     char
2707       **keep,
2708       **list;
2709
2710     ExceptionInfo
2711       *exception;
2712
2713     HV
2714       *hv;
2715
2716     Image
2717       *image;
2718
2719     register char
2720       **p;
2721
2722     register ssize_t
2723       i;
2724
2725     ssize_t
2726       ac,
2727       n,
2728       number_images;
2729
2730     STRLEN
2731       *length;
2732
2733     struct PackageInfo
2734       *info;
2735
2736     SV
2737       *perl_exception,
2738       *reference,
2739       *rv,
2740       *sv;
2741
2742     PERL_UNUSED_VAR(ref);
2743     PERL_UNUSED_VAR(ix);
2744     exception=AcquireExceptionInfo();
2745     perl_exception=newSVpv("",0);
2746     sv=NULL;
2747     number_images=0;
2748     ac=(items < 2) ? 1 : items-1;
2749     length=(STRLEN *) NULL;
2750     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2751     if (list == (char **) NULL)
2752       {
2753         ThrowPerlException(exception,ResourceLimitError,
2754           "MemoryAllocationFailed",PackageName);
2755         goto PerlException;
2756       }
2757     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2758     if (length == (STRLEN *) NULL)
2759       {
2760         ThrowPerlException(exception,ResourceLimitError,
2761           "MemoryAllocationFailed",PackageName);
2762         goto PerlException;
2763       }
2764     if (sv_isobject(ST(0)) == 0)
2765       {
2766         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2767           PackageName);
2768         goto PerlException;
2769       }
2770     reference=SvRV(ST(0));
2771     hv=SvSTASH(reference);
2772     if (SvTYPE(reference) != SVt_PVAV)
2773       {
2774         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2775           PackageName);
2776         goto PerlException;
2777       }
2778     av=(AV *) reference;
2779     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2780       exception);
2781     n=1;
2782     if (items <= 1)
2783       {
2784         ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2785         goto PerlException;
2786       }
2787     for (n=0, i=0; i < ac; i++)
2788     {
2789       list[n]=(char *) (SvPV(ST(i+1),length[n]));
2790       if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2791         {
2792           list[n]=(char *) (SvPV(ST(i+2),length[n]));
2793           continue;
2794         }
2795       n++;
2796     }
2797     list[n]=(char *) NULL;
2798     keep=list;
2799     for (i=number_images=0; i < n; i++)
2800     {
2801       image=BlobToImage(info->image_info,list[i],length[i],exception);
2802       if (image == (Image *) NULL)
2803         break;
2804       for ( ; image; image=image->next)
2805       {
2806         AddImageToRegistry(sv,image);
2807         rv=newRV(sv);
2808         av_push(av,sv_bless(rv,hv));
2809         SvREFCNT_dec(sv);
2810         number_images++;
2811       }
2812     }
2813     /*
2814       Free resources.
2815     */
2816     for (i=0; i < n; i++)
2817       if (list[i] != (char *) NULL)
2818         for (p=keep; list[i] != *p++; )
2819           if (*p == (char *) NULL)
2820             {
2821               list[i]=(char *) RelinquishMagickMemory(list[i]);
2822               break;
2823             }
2824
2825   PerlException:
2826     if (list)
2827       list=(char **) RelinquishMagickMemory(list);
2828     if (length)
2829       length=(STRLEN *) RelinquishMagickMemory(length);
2830     InheritPerlException(exception,perl_exception);
2831     exception=DestroyExceptionInfo(exception);
2832     sv_setiv(perl_exception,(IV) number_images);
2833     SvPOK_on(perl_exception);
2834     ST(0)=sv_2mortal(perl_exception);
2835     XSRETURN(1);
2836   }
2837 \f
2838 #
2839 ###############################################################################
2840 #                                                                             #
2841 #                                                                             #
2842 #                                                                             #
2843 #   C h a n n e l F x                                                         #
2844 #                                                                             #
2845 #                                                                             #
2846 #                                                                             #
2847 ###############################################################################
2848 #
2849 #
2850 void
2851 ChannelFx(ref,...)
2852   Image::Magick ref=NO_INIT
2853   ALIAS:
2854     ChannelFxImage  = 1
2855     channelfx       = 2
2856     channelfximage  = 3
2857   PPCODE:
2858   {
2859     AV
2860       *av;
2861
2862     char
2863       *attribute,
2864       expression[MaxTextExtent];
2865
2866     ChannelType
2867       channel,
2868       channel_mask;
2869
2870     ExceptionInfo
2871       *exception;
2872
2873     HV
2874       *hv;
2875
2876     Image
2877       *image;
2878
2879     register ssize_t
2880       i;
2881
2882     struct PackageInfo
2883       *info;
2884
2885     SV
2886       *av_reference,
2887       *perl_exception,
2888       *reference,
2889       *rv,
2890       *sv;
2891
2892     PERL_UNUSED_VAR(ref);
2893     PERL_UNUSED_VAR(ix);
2894     exception=AcquireExceptionInfo();
2895     perl_exception=newSVpv("",0);
2896     sv=NULL;
2897     attribute=NULL;
2898     av=NULL;
2899     if (sv_isobject(ST(0)) == 0)
2900       {
2901         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2902           PackageName);
2903         goto PerlException;
2904       }
2905     reference=SvRV(ST(0));
2906     hv=SvSTASH(reference);
2907     av=newAV();
2908     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2909     SvREFCNT_dec(av);
2910     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2911     if (image == (Image *) NULL)
2912       {
2913         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2914           PackageName);
2915         goto PerlException;
2916       }
2917     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2918     /*
2919       Get options.
2920     */
2921     channel=DefaultChannels;
2922     (void) CopyMagickString(expression,"u",MaxTextExtent);
2923     if (items == 2)
2924       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MaxTextExtent);
2925     else
2926       for (i=2; i < items; i+=2)
2927       {
2928         attribute=(char *) SvPV(ST(i-1),na);
2929         switch (*attribute)
2930         {
2931           case 'C':
2932           case 'c':
2933           {
2934             if (LocaleCompare(attribute,"channel") == 0)
2935               {
2936                 ssize_t
2937                   option;
2938
2939                 option=ParseChannelOption(SvPV(ST(i),na));
2940                 if (option < 0)
2941                   {
2942                     ThrowPerlException(exception,OptionError,
2943                       "UnrecognizedType",SvPV(ST(i),na));
2944                     return;
2945                   }
2946                 channel=(ChannelType) option;
2947                 break;
2948               }
2949             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2950               attribute);
2951             break;
2952           }
2953           case 'E':
2954           case 'e':
2955           {
2956             if (LocaleCompare(attribute,"expression") == 0)
2957               {
2958                 (void) CopyMagickString(expression,SvPV(ST(i),na),
2959                   MaxTextExtent);
2960                 break;
2961               }
2962             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2963               attribute);
2964             break;
2965           }
2966           default:
2967           {
2968             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2969               attribute);
2970             break;
2971           }
2972         }
2973       }
2974     channel_mask=SetImageChannelMask(image,channel);
2975     image=ChannelFxImage(image,expression,exception);
2976     if (image != (Image *) NULL)
2977       (void) SetImageChannelMask(image,channel_mask);
2978     if (image == (Image *) NULL)
2979       goto PerlException;
2980     for ( ; image; image=image->next)
2981     {
2982       AddImageToRegistry(sv,image);
2983       rv=newRV(sv);
2984       av_push(av,sv_bless(rv,hv));
2985       SvREFCNT_dec(sv);
2986     }
2987     exception=DestroyExceptionInfo(exception);
2988     ST(0)=av_reference;
2989     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
2990     XSRETURN(1);
2991
2992   PerlException:
2993     InheritPerlException(exception,perl_exception);
2994     exception=DestroyExceptionInfo(exception);
2995     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2996     SvPOK_on(perl_exception);
2997     ST(0)=sv_2mortal(perl_exception);
2998     XSRETURN(1);
2999   }
3000 \f
3001 #
3002 ###############################################################################
3003 #                                                                             #
3004 #                                                                             #
3005 #                                                                             #
3006 #   C l o n e                                                                 #
3007 #                                                                             #
3008 #                                                                             #
3009 #                                                                             #
3010 ###############################################################################
3011 #
3012 #
3013 void
3014 Clone(ref)
3015   Image::Magick ref=NO_INIT
3016   ALIAS:
3017     CopyImage   = 1
3018     copy        = 2
3019     copyimage   = 3
3020     CloneImage  = 4
3021     clone       = 5
3022     cloneimage  = 6
3023     Clone       = 7
3024   PPCODE:
3025   {
3026     AV
3027       *av;
3028
3029     ExceptionInfo
3030       *exception;
3031
3032     HV
3033       *hv;
3034
3035     Image
3036       *clone,
3037       *image;
3038
3039     struct PackageInfo
3040       *info;
3041
3042     SV
3043       *perl_exception,
3044       *reference,
3045       *rv,
3046       *sv;
3047
3048     PERL_UNUSED_VAR(ref);
3049     PERL_UNUSED_VAR(ix);
3050     exception=AcquireExceptionInfo();
3051     perl_exception=newSVpv("",0);
3052     sv=NULL;
3053     if (sv_isobject(ST(0)) == 0)
3054       {
3055         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3056           PackageName);
3057         goto PerlException;
3058       }
3059     reference=SvRV(ST(0));
3060     hv=SvSTASH(reference);
3061     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3062     if (image == (Image *) NULL)
3063       {
3064         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3065           PackageName);
3066         goto PerlException;
3067       }
3068     /*
3069       Create blessed Perl array for the returned image.
3070     */
3071     av=newAV();
3072     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3073     SvREFCNT_dec(av);
3074     for ( ; image; image=image->next)
3075     {
3076       clone=CloneImage(image,0,0,MagickTrue,exception);
3077       if (clone == (Image *) NULL)
3078         break;
3079       AddImageToRegistry(sv,clone);
3080       rv=newRV(sv);
3081       av_push(av,sv_bless(rv,hv));
3082       SvREFCNT_dec(sv);
3083     }
3084     exception=DestroyExceptionInfo(exception);
3085     SvREFCNT_dec(perl_exception);
3086     XSRETURN(1);
3087
3088   PerlException:
3089     InheritPerlException(exception,perl_exception);
3090     exception=DestroyExceptionInfo(exception);
3091     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3092     SvPOK_on(perl_exception);
3093     ST(0)=sv_2mortal(perl_exception);
3094     XSRETURN(1);
3095   }
3096 \f
3097 #
3098 ###############################################################################
3099 #                                                                             #
3100 #                                                                             #
3101 #                                                                             #
3102 #   C L O N E                                                                 #
3103 #                                                                             #
3104 #                                                                             #
3105 #                                                                             #
3106 ###############################################################################
3107 #
3108 #
3109 void
3110 CLONE(ref,...)
3111   SV *ref;
3112   CODE:
3113   {
3114     PERL_UNUSED_VAR(ref);
3115     if (magick_registry != (SplayTreeInfo *) NULL)
3116       {
3117         register Image
3118           *p;
3119
3120         ResetSplayTreeIterator(magick_registry);
3121         p=(Image *) GetNextKeyInSplayTree(magick_registry);
3122         while (p != (Image *) NULL)
3123         {
3124           ReferenceImage(p);
3125           p=(Image *) GetNextKeyInSplayTree(magick_registry);
3126         }
3127       }
3128   }
3129 \f
3130 #
3131 ###############################################################################
3132 #                                                                             #
3133 #                                                                             #
3134 #                                                                             #
3135 #   C o a l e s c e                                                           #
3136 #                                                                             #
3137 #                                                                             #
3138 #                                                                             #
3139 ###############################################################################
3140 #
3141 #
3142 void
3143 Coalesce(ref)
3144   Image::Magick ref=NO_INIT
3145   ALIAS:
3146     CoalesceImage   = 1
3147     coalesce        = 2
3148     coalesceimage   = 3
3149   PPCODE:
3150   {
3151     AV
3152       *av;
3153
3154     ExceptionInfo
3155       *exception;
3156
3157     HV
3158       *hv;
3159
3160     Image
3161       *image;
3162
3163     struct PackageInfo
3164       *info;
3165
3166     SV
3167       *av_reference,
3168       *perl_exception,
3169       *reference,
3170       *rv,
3171       *sv;
3172
3173     PERL_UNUSED_VAR(ref);
3174     PERL_UNUSED_VAR(ix);
3175     exception=AcquireExceptionInfo();
3176     perl_exception=newSVpv("",0);
3177     sv=NULL;
3178     if (sv_isobject(ST(0)) == 0)
3179       {
3180         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3181           PackageName);
3182         goto PerlException;
3183       }
3184     reference=SvRV(ST(0));
3185     hv=SvSTASH(reference);
3186     av=newAV();
3187     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3188     SvREFCNT_dec(av);
3189     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3190     if (image == (Image *) NULL)
3191       {
3192         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3193           PackageName);
3194         goto PerlException;
3195       }
3196     image=CoalesceImages(image,exception);
3197     if (image == (Image *) NULL)
3198       goto PerlException;
3199     for ( ; image; image=image->next)
3200     {
3201       AddImageToRegistry(sv,image);
3202       rv=newRV(sv);
3203       av_push(av,sv_bless(rv,hv));
3204       SvREFCNT_dec(sv);
3205     }
3206     exception=DestroyExceptionInfo(exception);
3207     ST(0)=av_reference;
3208     SvREFCNT_dec(perl_exception);
3209     XSRETURN(1);
3210
3211   PerlException:
3212     InheritPerlException(exception,perl_exception);
3213     exception=DestroyExceptionInfo(exception);
3214     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3215     SvPOK_on(perl_exception);
3216     ST(0)=sv_2mortal(perl_exception);
3217     XSRETURN(1);
3218   }
3219 \f
3220 #
3221 ###############################################################################
3222 #                                                                             #
3223 #                                                                             #
3224 #                                                                             #
3225 #   C o m p a r e                                                             #
3226 #                                                                             #
3227 #                                                                             #
3228 #                                                                             #
3229 ###############################################################################
3230 #
3231 #
3232 void
3233 Compare(ref,...)
3234   Image::Magick ref=NO_INIT
3235   ALIAS:
3236     CompareImages = 1
3237     compare      = 2
3238     compareimage = 3
3239   PPCODE:
3240   {
3241     AV
3242       *av;
3243
3244     char
3245       *attribute;
3246
3247     double
3248       distortion;
3249
3250     ExceptionInfo
3251       *exception;
3252
3253     HV
3254       *hv;
3255
3256     Image
3257       *difference_image,
3258       *image,
3259       *reconstruct_image;
3260
3261     MetricType
3262       metric;
3263
3264     register ssize_t
3265       i;
3266
3267     ssize_t
3268       option;
3269
3270     struct PackageInfo
3271       *info;
3272
3273     SV
3274       *av_reference,
3275       *perl_exception,
3276       *reference,
3277       *rv,
3278       *sv;
3279
3280     PERL_UNUSED_VAR(ref);
3281     PERL_UNUSED_VAR(ix);
3282     exception=AcquireExceptionInfo();
3283     perl_exception=newSVpv("",0);
3284     sv=NULL;
3285     av=NULL;
3286     attribute=NULL;
3287     if (sv_isobject(ST(0)) == 0)
3288       {
3289         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3290           PackageName);
3291         goto PerlException;
3292       }
3293     reference=SvRV(ST(0));
3294     hv=SvSTASH(reference);
3295     av=newAV();
3296     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3297     SvREFCNT_dec(av);
3298     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3299     if (image == (Image *) NULL)
3300       {
3301         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3302           PackageName);
3303         goto PerlException;
3304       }
3305     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3306     /*
3307       Get attribute.
3308     */
3309     reconstruct_image=image;
3310     metric=RootMeanSquaredErrorMetric;
3311     for (i=2; i < items; i+=2)
3312     {
3313       attribute=(char *) SvPV(ST(i-1),na);
3314       switch (*attribute)
3315       {
3316         case 'C':
3317         case 'c':
3318         {
3319           if (LocaleCompare(attribute,"channel") == 0)
3320             {
3321               ssize_t
3322                 option;
3323
3324               option=ParseChannelOption(SvPV(ST(i),na));
3325               if (option < 0)
3326                 {
3327                   ThrowPerlException(exception,OptionError,
3328                     "UnrecognizedType",SvPV(ST(i),na));
3329                   return;
3330                 }
3331               SetPixelChannelMask(image,(ChannelType) option);
3332               break;
3333             }
3334           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3335             attribute);
3336           break;
3337         }
3338         case 'F':
3339         case 'f':
3340         {
3341           if (LocaleCompare(attribute,"fuzz") == 0)
3342             {
3343               image->fuzz=StringToDoubleInterval(SvPV(ST(i),na),100.0);
3344               break;
3345             }
3346           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3347             attribute);
3348           break;
3349         }
3350         case 'I':
3351         case 'i':
3352         {
3353           if (LocaleCompare(attribute,"image") == 0)
3354             {
3355               reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3356                 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3357               break;
3358             }
3359           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3360             attribute);
3361           break;
3362         }
3363         case 'M':
3364         case 'm':
3365         {
3366           if (LocaleCompare(attribute,"metric") == 0)
3367             {
3368               option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3369                 SvPV(ST(i),na));
3370               if (option < 0)
3371                 {
3372                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3373                     SvPV(ST(i),na));
3374                   break;
3375                 }
3376               metric=(MetricType) option;
3377               break;
3378             }
3379           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3380             attribute);
3381           break;
3382         }
3383         default:
3384         {
3385           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3386             attribute);
3387           break;
3388         }
3389       }
3390     }
3391     difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3392       exception);
3393     if (difference_image != (Image *) NULL)
3394       {
3395         difference_image->error.mean_error_per_pixel=distortion;
3396         AddImageToRegistry(sv,difference_image);
3397         rv=newRV(sv);
3398         av_push(av,sv_bless(rv,hv));
3399         SvREFCNT_dec(sv);
3400       }
3401     exception=DestroyExceptionInfo(exception);
3402     ST(0)=av_reference;
3403     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3404     XSRETURN(1);
3405
3406   PerlException:
3407     InheritPerlException(exception,perl_exception);
3408     exception=DestroyExceptionInfo(exception);
3409     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3410     SvPOK_on(perl_exception);
3411     ST(0)=sv_2mortal(perl_exception);
3412     XSRETURN(1);
3413   }
3414 \f
3415 #
3416 ###############################################################################
3417 #                                                                             #
3418 #                                                                             #
3419 #                                                                             #
3420 #   C o m p a r e L a y e r s                                                 #
3421 #                                                                             #
3422 #                                                                             #
3423 #                                                                             #
3424 ###############################################################################
3425 #
3426 #
3427 void
3428 CompareLayers(ref)
3429   Image::Magick ref=NO_INIT
3430   ALIAS:
3431     CompareImagesLayers   = 1
3432     comparelayers        = 2
3433     compareimagelayers   = 3
3434   PPCODE:
3435   {
3436     AV
3437       *av;
3438
3439     char
3440       *attribute;
3441
3442     ExceptionInfo
3443       *exception;
3444
3445     HV
3446       *hv;
3447
3448     Image
3449       *image;
3450
3451     LayerMethod
3452       method;
3453
3454     register ssize_t
3455       i;
3456
3457     ssize_t
3458       option;
3459
3460     struct PackageInfo
3461       *info;
3462
3463     SV
3464       *av_reference,
3465       *perl_exception,
3466       *reference,
3467       *rv,
3468       *sv;
3469
3470     PERL_UNUSED_VAR(ref);
3471     PERL_UNUSED_VAR(ix);
3472     exception=AcquireExceptionInfo();
3473     perl_exception=newSVpv("",0);
3474     sv=NULL;
3475     if (sv_isobject(ST(0)) == 0)
3476       {
3477         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3478           PackageName);
3479         goto PerlException;
3480       }
3481     reference=SvRV(ST(0));
3482     hv=SvSTASH(reference);
3483     av=newAV();
3484     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3485     SvREFCNT_dec(av);
3486     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3487     if (image == (Image *) NULL)
3488       {
3489         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3490           PackageName);
3491         goto PerlException;
3492       }
3493     method=CompareAnyLayer;
3494     for (i=2; i < items; i+=2)
3495     {
3496       attribute=(char *) SvPV(ST(i-1),na);
3497       switch (*attribute)
3498       {
3499         case 'M':
3500         case 'm':
3501         {
3502           if (LocaleCompare(attribute,"method") == 0)
3503             {
3504               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3505                 SvPV(ST(i),na));
3506               if (option < 0)
3507                 {
3508                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3509                     SvPV(ST(i),na));
3510                   break;
3511                 }
3512                method=(LayerMethod) option;
3513               break;
3514             }
3515           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3516             attribute);
3517           break;
3518         }
3519         default:
3520         {
3521           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3522             attribute);
3523           break;
3524         }
3525       }
3526     }
3527     image=CompareImagesLayers(image,method,exception);
3528     if (image == (Image *) NULL)
3529       goto PerlException;
3530     for ( ; image; image=image->next)
3531     {
3532       AddImageToRegistry(sv,image);
3533       rv=newRV(sv);
3534       av_push(av,sv_bless(rv,hv));
3535       SvREFCNT_dec(sv);
3536     }
3537     exception=DestroyExceptionInfo(exception);
3538     ST(0)=av_reference;
3539     SvREFCNT_dec(perl_exception);
3540     XSRETURN(1);
3541
3542   PerlException:
3543     InheritPerlException(exception,perl_exception);
3544     exception=DestroyExceptionInfo(exception);
3545     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3546     SvPOK_on(perl_exception);
3547     ST(0)=sv_2mortal(perl_exception);
3548     XSRETURN(1);
3549   }
3550 \f
3551 #
3552 ###############################################################################
3553 #                                                                             #
3554 #                                                                             #
3555 #                                                                             #
3556 #   D e s t r o y                                                             #
3557 #                                                                             #
3558 #                                                                             #
3559 #                                                                             #
3560 ###############################################################################
3561 #
3562 #
3563 void
3564 DESTROY(ref)
3565   Image::Magick ref=NO_INIT
3566   PPCODE:
3567   {
3568     SV
3569       *reference;
3570
3571     PERL_UNUSED_VAR(ref);
3572     if (sv_isobject(ST(0)) == 0)
3573       croak("ReferenceIsNotMyType");
3574     reference=SvRV(ST(0));
3575     switch (SvTYPE(reference))
3576     {
3577       case SVt_PVAV:
3578       {
3579         char
3580           message[MaxTextExtent];
3581
3582         const SV
3583           *key;
3584
3585         HV
3586           *hv;
3587
3588         GV
3589           **gvp;
3590
3591         struct PackageInfo
3592           *info;
3593
3594         SV
3595           *sv;
3596
3597         /*
3598           Array (AV *) reference
3599         */
3600         (void) FormatLocaleString(message,MaxTextExtent,"package%s%p",
3601           XS_VERSION,reference);
3602         hv=gv_stashpv(PackageName, FALSE);
3603         if (!hv)
3604           break;
3605         gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3606         if (!gvp)
3607           break;
3608         sv=GvSV(*gvp);
3609         if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3610           {
3611             info=INT2PTR(struct PackageInfo *,SvIV(sv));
3612             DestroyPackageInfo(info);
3613           }
3614         key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3615         (void) key;
3616         break;
3617       }
3618       case SVt_PVMG:
3619       {
3620         Image
3621           *image;
3622
3623         /*
3624           Blessed scalar = (Image *) SvIV(reference)
3625         */
3626         image=INT2PTR(Image *,SvIV(reference));
3627         if (image != (Image *) NULL)
3628           DeleteImageFromRegistry(reference,image);
3629         break;
3630       }
3631       default:
3632         break;
3633     }
3634   }
3635 \f
3636 #
3637 ###############################################################################
3638 #                                                                             #
3639 #                                                                             #
3640 #                                                                             #
3641 #   D i s p l a y                                                             #
3642 #                                                                             #
3643 #                                                                             #
3644 #                                                                             #
3645 ###############################################################################
3646 #
3647 #
3648 void
3649 Display(ref,...)
3650   Image::Magick ref=NO_INIT
3651   ALIAS:
3652     DisplayImage  = 1
3653     display       = 2
3654     displayimage  = 3
3655   PPCODE:
3656   {
3657     ExceptionInfo
3658       *exception;
3659
3660     Image
3661       *image;
3662
3663     register ssize_t
3664       i;
3665
3666     struct PackageInfo
3667       *info,
3668       *package_info;
3669
3670     SV
3671       *perl_exception,
3672       *reference;
3673
3674     PERL_UNUSED_VAR(ref);
3675     PERL_UNUSED_VAR(ix);
3676     exception=AcquireExceptionInfo();
3677     perl_exception=newSVpv("",0);
3678     package_info=(struct PackageInfo *) NULL;
3679     if (sv_isobject(ST(0)) == 0)
3680       {
3681         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3682           PackageName);
3683         goto PerlException;
3684       }
3685     reference=SvRV(ST(0));
3686     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3687     if (image == (Image *) NULL)
3688       {
3689         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3690           PackageName);
3691         goto PerlException;
3692       }
3693     package_info=ClonePackageInfo(info,exception);
3694     if (items == 2)
3695       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3696     else
3697       if (items > 2)
3698         for (i=2; i < items; i+=2)
3699           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3700             exception);
3701     (void) DisplayImages(package_info->image_info,image,exception);
3702     (void) CatchImageException(image);
3703
3704   PerlException:
3705     if (package_info != (struct PackageInfo *) NULL)
3706       DestroyPackageInfo(package_info);
3707     InheritPerlException(exception,perl_exception);
3708     exception=DestroyExceptionInfo(exception);
3709     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3710     SvPOK_on(perl_exception);
3711     ST(0)=sv_2mortal(perl_exception);
3712     XSRETURN(1);
3713   }
3714 \f
3715 #
3716 ###############################################################################
3717 #                                                                             #
3718 #                                                                             #
3719 #                                                                             #
3720 #   E v a l u a t e I m a g e s                                               #
3721 #                                                                             #
3722 #                                                                             #
3723 #                                                                             #
3724 ###############################################################################
3725 #
3726 #
3727 void
3728 EvaluateImages(ref)
3729   Image::Magick ref=NO_INIT
3730   ALIAS:
3731     EvaluateImages   = 1
3732     evaluateimages   = 2
3733   PPCODE:
3734   {
3735     AV
3736       *av;
3737
3738     char
3739       *attribute,
3740       *p;
3741
3742     ExceptionInfo
3743       *exception;
3744
3745     HV
3746       *hv;
3747
3748     Image
3749       *image;
3750
3751     MagickEvaluateOperator
3752       op;
3753
3754     register ssize_t
3755       i;
3756
3757     struct PackageInfo
3758       *info;
3759
3760     SV
3761       *perl_exception,
3762       *reference,
3763       *rv,
3764       *sv;
3765
3766     PERL_UNUSED_VAR(ref);
3767     PERL_UNUSED_VAR(ix);
3768     exception=AcquireExceptionInfo();
3769     perl_exception=newSVpv("",0);
3770     sv=NULL;
3771     if (sv_isobject(ST(0)) == 0)
3772       {
3773         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3774           PackageName);
3775         goto PerlException;
3776       }
3777     reference=SvRV(ST(0));
3778     hv=SvSTASH(reference);
3779     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3780     if (image == (Image *) NULL)
3781       {
3782         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3783           PackageName);
3784         goto PerlException;
3785       }
3786     op=MeanEvaluateOperator;
3787     if (items == 2)
3788       {
3789         ssize_t
3790           in;
3791
3792         in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
3793           SvPV(ST(1),na));
3794         if (in < 0)
3795           {
3796             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3797               SvPV(ST(1),na));
3798             return;
3799           }
3800         op=(MagickEvaluateOperator) in;
3801       }
3802     else
3803       for (i=2; i < items; i+=2)
3804       {
3805         attribute=(char *) SvPV(ST(i-1),na);
3806         switch (*attribute)
3807         {
3808           case 'O':
3809           case 'o':
3810           {
3811             if (LocaleCompare(attribute,"operator") == 0)
3812               {
3813                 ssize_t
3814                   in;
3815
3816                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3817                   MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
3818                 if (in < 0)
3819                   {
3820                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3821                       SvPV(ST(i),na));
3822                     return;
3823                   }
3824                 op=(MagickEvaluateOperator) in;
3825                 break;
3826               }
3827             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3828               attribute);
3829             break;
3830           }
3831           default:
3832           {
3833             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3834               attribute);
3835             break;
3836           }
3837         }
3838       }
3839     image=EvaluateImages(image,op,exception);
3840     if (image == (Image *) NULL)
3841       goto PerlException;
3842     /*
3843       Create blessed Perl array for the returned image.
3844     */
3845     av=newAV();
3846     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3847     SvREFCNT_dec(av);
3848     AddImageToRegistry(sv,image);
3849     rv=newRV(sv);
3850     av_push(av,sv_bless(rv,hv));
3851     SvREFCNT_dec(sv);
3852     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3853     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
3854       "evaluate-%.*s",(int) (MaxTextExtent-9),
3855       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3856     (void) CopyMagickString(image->filename,info->image_info->filename,
3857       MaxTextExtent);
3858     SetImageInfo(info->image_info,0,exception);
3859     exception=DestroyExceptionInfo(exception);
3860     SvREFCNT_dec(perl_exception);
3861     XSRETURN(1);
3862
3863   PerlException:
3864     InheritPerlException(exception,perl_exception);
3865     exception=DestroyExceptionInfo(exception);
3866     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3867     SvPOK_on(perl_exception);
3868     ST(0)=sv_2mortal(perl_exception);
3869     XSRETURN(1);
3870   }
3871 \f
3872 #
3873 ###############################################################################
3874 #                                                                             #
3875 #                                                                             #
3876 #                                                                             #
3877 #   F e a t u r e s                                                           #
3878 #                                                                             #
3879 #                                                                             #
3880 #                                                                             #
3881 ###############################################################################
3882 #
3883 #
3884 void
3885 Features(ref,...)
3886   Image::Magick ref=NO_INIT
3887   ALIAS:
3888     FeaturesImage = 1
3889     features      = 2
3890     featuresimage = 3
3891   PPCODE:
3892   {
3893 #define ChannelFeatures(channel,direction) \
3894 { \
3895   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3896     channel_features[channel].angular_second_moment[direction]); \
3897   PUSHs(sv_2mortal(newSVpv(message,0))); \
3898   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3899     channel_features[channel].contrast[direction]); \
3900   PUSHs(sv_2mortal(newSVpv(message,0))); \
3901   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3902     channel_features[channel].contrast[direction]); \
3903   PUSHs(sv_2mortal(newSVpv(message,0))); \
3904   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3905     channel_features[channel].variance_sum_of_squares[direction]); \
3906   PUSHs(sv_2mortal(newSVpv(message,0))); \
3907   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3908     channel_features[channel].inverse_difference_moment[direction]); \
3909   PUSHs(sv_2mortal(newSVpv(message,0))); \
3910   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3911     channel_features[channel].sum_average[direction]); \
3912   PUSHs(sv_2mortal(newSVpv(message,0))); \
3913   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3914     channel_features[channel].sum_variance[direction]); \
3915   PUSHs(sv_2mortal(newSVpv(message,0))); \
3916   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3917     channel_features[channel].sum_entropy[direction]); \
3918   PUSHs(sv_2mortal(newSVpv(message,0))); \
3919   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3920     channel_features[channel].entropy[direction]); \
3921   PUSHs(sv_2mortal(newSVpv(message,0))); \
3922   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3923     channel_features[channel].difference_variance[direction]); \
3924   PUSHs(sv_2mortal(newSVpv(message,0))); \
3925   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3926     channel_features[channel].difference_entropy[direction]); \
3927   PUSHs(sv_2mortal(newSVpv(message,0))); \
3928   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3929     channel_features[channel].measure_of_correlation_1[direction]); \
3930   PUSHs(sv_2mortal(newSVpv(message,0))); \
3931   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3932     channel_features[channel].measure_of_correlation_2[direction]); \
3933   PUSHs(sv_2mortal(newSVpv(message,0))); \
3934   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3935     channel_features[channel].maximum_correlation_coefficient[direction]); \
3936   PUSHs(sv_2mortal(newSVpv(message,0))); \
3937 }
3938
3939     AV
3940       *av;
3941
3942     char
3943       *attribute,
3944       message[MaxTextExtent];
3945
3946     ChannelFeatures
3947       *channel_features;
3948
3949     double
3950       distance;
3951
3952     ExceptionInfo
3953       *exception;
3954
3955     Image
3956       *image;
3957
3958     register ssize_t
3959       i;
3960
3961     ssize_t
3962       count;
3963
3964     struct PackageInfo
3965       *info;
3966
3967     SV
3968       *perl_exception,
3969       *reference;
3970
3971     PERL_UNUSED_VAR(ref);
3972     PERL_UNUSED_VAR(ix);
3973     exception=AcquireExceptionInfo();
3974     perl_exception=newSVpv("",0);
3975     av=NULL;
3976     if (sv_isobject(ST(0)) == 0)
3977       {
3978         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3979           PackageName);
3980         goto PerlException;
3981       }
3982     reference=SvRV(ST(0));
3983     av=newAV();
3984     SvREFCNT_dec(av);
3985     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3986     if (image == (Image *) NULL)
3987       {
3988         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3989           PackageName);
3990         goto PerlException;
3991       }
3992     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3993     distance=1;
3994     for (i=2; i < items; i+=2)
3995     {
3996       attribute=(char *) SvPV(ST(i-1),na);
3997       switch (*attribute)
3998       {
3999         case 'D':
4000         case 'd':
4001         {
4002           if (LocaleCompare(attribute,"distance") == 0)
4003             {
4004               distance=StringToLong((char *) SvPV(ST(1),na));
4005               break;
4006             }
4007           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4008             attribute);
4009           break;
4010         }
4011         default:
4012         {
4013           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4014             attribute);
4015           break;
4016         }
4017       }
4018     }
4019     count=0;
4020     for ( ; image; image=image->next)
4021     {
4022       channel_features=GetImageFeatures(image,distance,exception);
4023       if (channel_features == (ChannelFeatures *) NULL)
4024         continue;
4025       count++;
4026       EXTEND(sp,75*count);
4027       for (i=0; i < 4; i++)
4028       {
4029         ChannelFeatures(RedChannel,i);
4030         ChannelFeatures(GreenChannel,i);
4031         ChannelFeatures(BlueChannel,i);
4032         if (image->colorspace == CMYKColorspace)
4033           ChannelFeatures(BlackChannel,i);
4034         if (image->alpha_trait == BlendPixelTrait)
4035           ChannelFeatures(AlphaChannel,i);
4036       }
4037       channel_features=(ChannelFeatures *)
4038         RelinquishMagickMemory(channel_features);
4039     }
4040
4041   PerlException:
4042     InheritPerlException(exception,perl_exception);
4043     exception=DestroyExceptionInfo(exception);
4044     SvREFCNT_dec(perl_exception);
4045   }
4046 \f
4047 #
4048 ###############################################################################
4049 #                                                                             #
4050 #                                                                             #
4051 #                                                                             #
4052 #   F l a t t e n                                                             #
4053 #                                                                             #
4054 #                                                                             #
4055 #                                                                             #
4056 ###############################################################################
4057 #
4058 #
4059 void
4060 Flatten(ref)
4061   Image::Magick ref=NO_INIT
4062   ALIAS:
4063     FlattenImage   = 1
4064     flatten        = 2
4065     flattenimage   = 3
4066   PPCODE:
4067   {
4068     AV
4069       *av;
4070
4071     char
4072       *attribute,
4073       *p;
4074
4075     ExceptionInfo
4076       *exception;
4077
4078     HV
4079       *hv;
4080
4081     Image
4082       *image;
4083
4084     PixelInfo
4085       background_color;
4086
4087     register ssize_t
4088       i;
4089
4090     struct PackageInfo
4091       *info;
4092
4093     SV
4094       *perl_exception,
4095       *reference,
4096       *rv,
4097       *sv;
4098
4099     PERL_UNUSED_VAR(ref);
4100     PERL_UNUSED_VAR(ix);
4101     exception=AcquireExceptionInfo();
4102     perl_exception=newSVpv("",0);
4103     sv=NULL;
4104     if (sv_isobject(ST(0)) == 0)
4105       {
4106         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4107           PackageName);
4108         goto PerlException;
4109       }
4110     reference=SvRV(ST(0));
4111     hv=SvSTASH(reference);
4112     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4113     if (image == (Image *) NULL)
4114       {
4115         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4116           PackageName);
4117         goto PerlException;
4118       }
4119     background_color=image->background_color;
4120     if (items == 2)
4121       (void) QueryColorCompliance((char *) SvPV(ST(1),na),AllCompliance,
4122         &background_color,exception);
4123     else
4124       for (i=2; i < items; i+=2)
4125       {
4126         attribute=(char *) SvPV(ST(i-1),na);
4127         switch (*attribute)
4128         {
4129           case 'B':
4130           case 'b':
4131           {
4132             if (LocaleCompare(attribute,"background") == 0)
4133               {
4134                 (void) QueryColorCompliance((char *) SvPV(ST(1),na),
4135                   AllCompliance,&background_color,exception);
4136                 break;
4137               }
4138             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4139               attribute);
4140             break;
4141           }
4142           default:
4143           {
4144             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4145               attribute);
4146             break;
4147           }
4148         }
4149       }
4150     image->background_color=background_color;
4151     image=MergeImageLayers(image,FlattenLayer,exception);
4152     if (image == (Image *) NULL)
4153       goto PerlException;
4154     /*
4155       Create blessed Perl array for the returned image.
4156     */
4157     av=newAV();
4158     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4159     SvREFCNT_dec(av);
4160     AddImageToRegistry(sv,image);
4161     rv=newRV(sv);
4162     av_push(av,sv_bless(rv,hv));
4163     SvREFCNT_dec(sv);
4164     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4165     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
4166       "flatten-%.*s",(int) (MaxTextExtent-9),
4167       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4168     (void) CopyMagickString(image->filename,info->image_info->filename,
4169       MaxTextExtent);
4170     SetImageInfo(info->image_info,0,exception);
4171     exception=DestroyExceptionInfo(exception);
4172     SvREFCNT_dec(perl_exception);
4173     XSRETURN(1);
4174
4175   PerlException:
4176     InheritPerlException(exception,perl_exception);
4177     exception=DestroyExceptionInfo(exception);
4178     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4179     SvPOK_on(perl_exception);  /* return messages in string context */
4180     ST(0)=sv_2mortal(perl_exception);
4181     XSRETURN(1);
4182   }
4183 \f
4184 #
4185 ###############################################################################
4186 #                                                                             #
4187 #                                                                             #
4188 #                                                                             #
4189 #   F x                                                                       #
4190 #                                                                             #
4191 #                                                                             #
4192 #                                                                             #
4193 ###############################################################################
4194 #
4195 #
4196 void
4197 Fx(ref,...)
4198   Image::Magick ref=NO_INIT
4199   ALIAS:
4200     FxImage  = 1
4201     fx       = 2
4202     fximage  = 3
4203   PPCODE:
4204   {
4205     AV
4206       *av;
4207
4208     char
4209       *attribute,
4210       expression[MaxTextExtent];
4211
4212     ChannelType
4213       channel,
4214       channel_mask;
4215
4216     ExceptionInfo
4217       *exception;
4218
4219     HV
4220       *hv;
4221
4222     Image
4223       *image;
4224
4225     register ssize_t
4226       i;
4227
4228     struct PackageInfo
4229       *info;
4230
4231     SV
4232       *av_reference,
4233       *perl_exception,
4234       *reference,
4235       *rv,
4236       *sv;
4237
4238     PERL_UNUSED_VAR(ref);
4239     PERL_UNUSED_VAR(ix);
4240     exception=AcquireExceptionInfo();
4241     perl_exception=newSVpv("",0);
4242     sv=NULL;
4243     attribute=NULL;
4244     av=NULL;
4245     if (sv_isobject(ST(0)) == 0)
4246       {
4247         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4248           PackageName);
4249         goto PerlException;
4250       }
4251     reference=SvRV(ST(0));
4252     hv=SvSTASH(reference);
4253     av=newAV();
4254     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4255     SvREFCNT_dec(av);
4256     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4257     if (image == (Image *) NULL)
4258       {
4259         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4260           PackageName);
4261         goto PerlException;
4262       }
4263     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4264     /*
4265       Get options.
4266     */
4267     channel=DefaultChannels;
4268     (void) CopyMagickString(expression,"u",MaxTextExtent);
4269     if (items == 2)
4270       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MaxTextExtent);
4271     else
4272       for (i=2; i < items; i+=2)
4273       {
4274         attribute=(char *) SvPV(ST(i-1),na);
4275         switch (*attribute)
4276         {
4277           case 'C':
4278           case 'c':
4279           {
4280             if (LocaleCompare(attribute,"channel") == 0)
4281               {
4282                 ssize_t
4283                   option;
4284
4285                 option=ParseChannelOption(SvPV(ST(i),na));
4286                 if (option < 0)
4287                   {
4288                     ThrowPerlException(exception,OptionError,
4289                       "UnrecognizedType",SvPV(ST(i),na));
4290                     return;
4291                   }
4292                 channel=(ChannelType) option;
4293                 break;
4294               }
4295             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4296               attribute);
4297             break;
4298           }
4299           case 'E':
4300           case 'e':
4301           {
4302             if (LocaleCompare(attribute,"expression") == 0)
4303               {
4304                 (void) CopyMagickString(expression,SvPV(ST(i),na),
4305                   MaxTextExtent);
4306                 break;
4307               }
4308             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4309               attribute);
4310             break;
4311           }
4312           default:
4313           {
4314             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4315               attribute);
4316             break;
4317           }
4318         }
4319       }
4320     channel_mask=SetImageChannelMask(image,channel);
4321     image=FxImage(image,expression,exception);
4322     if (image != (Image *) NULL)
4323       (void) SetImageChannelMask(image,channel_mask);
4324     if (image == (Image *) NULL)
4325       goto PerlException;
4326     for ( ; image; image=image->next)
4327     {
4328       AddImageToRegistry(sv,image);
4329       rv=newRV(sv);
4330       av_push(av,sv_bless(rv,hv));
4331       SvREFCNT_dec(sv);
4332     }
4333     exception=DestroyExceptionInfo(exception);
4334     ST(0)=av_reference;
4335     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4336     XSRETURN(1);
4337
4338   PerlException:
4339     InheritPerlException(exception,perl_exception);
4340     exception=DestroyExceptionInfo(exception);
4341     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4342     SvPOK_on(perl_exception);
4343     ST(0)=sv_2mortal(perl_exception);
4344     XSRETURN(1);
4345   }
4346 \f
4347 #
4348 ###############################################################################
4349 #                                                                             #
4350 #                                                                             #
4351 #                                                                             #
4352 #   G e t                                                                     #
4353 #                                                                             #
4354 #                                                                             #
4355 #                                                                             #
4356 ###############################################################################
4357 #
4358 #
4359 void
4360 Get(ref,...)
4361   Image::Magick ref=NO_INIT
4362   ALIAS:
4363     GetAttributes = 1
4364     GetAttribute  = 2
4365     get           = 3
4366     getattributes = 4
4367     getattribute  = 5
4368   PPCODE:
4369   {
4370     char
4371       *attribute,
4372       color[MaxTextExtent];
4373
4374     const char
4375       *value;
4376
4377     ExceptionInfo
4378       *exception;
4379
4380     Image
4381       *image;
4382
4383     long
4384       j;
4385
4386     register ssize_t
4387       i;
4388
4389     struct PackageInfo
4390       *info;
4391
4392     SV
4393       *perl_exception,
4394       *reference,
4395       *s;
4396
4397     PERL_UNUSED_VAR(ref);
4398     PERL_UNUSED_VAR(ix);
4399     exception=AcquireExceptionInfo();
4400     perl_exception=newSVpv("",0);
4401     if (sv_isobject(ST(0)) == 0)
4402       {
4403         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4404           PackageName);
4405         XSRETURN_EMPTY;
4406       }
4407     reference=SvRV(ST(0));
4408     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4409     if (image == (Image *) NULL && !info)
4410       XSRETURN_EMPTY;
4411     EXTEND(sp,items);
4412     for (i=1; i < items; i++)
4413     {
4414       attribute=(char *) SvPV(ST(i),na);
4415       s=NULL;
4416       switch (*attribute)
4417       {
4418         case 'A':
4419         case 'a':
4420         {
4421           if (LocaleCompare(attribute,"adjoin") == 0)
4422             {
4423               if (info)
4424                 s=newSViv((ssize_t) info->image_info->adjoin);
4425               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4426               continue;
4427             }
4428           if (LocaleCompare(attribute,"antialias") == 0)
4429             {
4430               if (info)
4431                 s=newSViv((ssize_t) info->image_info->antialias);
4432               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4433               continue;
4434             }
4435           if (LocaleCompare(attribute,"area") == 0)
4436             {
4437               s=newSViv(GetMagickResource(AreaResource));
4438               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4439               continue;
4440             }
4441           if (LocaleCompare(attribute,"attenuate") == 0)
4442             {
4443               const char
4444                 *value;
4445
4446               value=GetImageProperty(image,attribute,exception);
4447               if (value != (const char *) NULL)
4448                 s=newSVpv(value,0);
4449               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4450               continue;
4451             }
4452           if (LocaleCompare(attribute,"authenticate") == 0)
4453             {
4454               if (info)
4455                 {
4456                   const char
4457                     *option;
4458
4459                   option=GetImageOption(info->image_info,attribute);
4460                   if (option != (const char *) NULL)
4461                     s=newSVpv(option,0);
4462                 }
4463               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4464               continue;
4465             }
4466           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4467             attribute);
4468           break;
4469         }
4470         case 'B':
4471         case 'b':
4472         {
4473           if (LocaleCompare(attribute,"background") == 0)
4474             {
4475               if (image == (Image *) NULL)
4476                 break;
4477               (void) FormatLocaleString(color,MaxTextExtent,
4478                 "%.20g,%.20g,%.20g,%.20g",image->background_color.red,
4479                 image->background_color.green,image->background_color.blue,
4480                 image->background_color.alpha);
4481               s=newSVpv(color,0);
4482               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4483               continue;
4484             }
4485           if (LocaleCompare(attribute,"base-columns") == 0)
4486             {
4487               if (image != (Image *) NULL)
4488                 s=newSViv((ssize_t) image->magick_columns);
4489               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4490               continue;
4491             }
4492           if (LocaleCompare(attribute,"base-filename") == 0)
4493             {
4494               if (image != (Image *) NULL)
4495                 s=newSVpv(image->magick_filename,0);
4496               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4497               continue;
4498             }
4499           if (LocaleCompare(attribute,"base-height") == 0)
4500             {
4501               if (image != (Image *) NULL)
4502                 s=newSViv((ssize_t) image->magick_rows);
4503               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4504               continue;
4505             }
4506           if (LocaleCompare(attribute,"base-rows") == 0)
4507             {
4508               if (image != (Image *) NULL)
4509                 s=newSViv((ssize_t) image->magick_rows);
4510               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4511               continue;
4512             }
4513           if (LocaleCompare(attribute,"base-width") == 0)
4514             {
4515               if (image != (Image *) NULL)
4516                 s=newSViv((ssize_t) image->magick_columns);
4517               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4518               continue;
4519             }
4520           if (LocaleCompare(attribute,"blue-primary") == 0)
4521             {
4522               if (image == (Image *) NULL)
4523                 break;
4524               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4525                 image->chromaticity.blue_primary.x,
4526                 image->chromaticity.blue_primary.y);
4527               s=newSVpv(color,0);
4528               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4529               continue;
4530             }
4531           if (LocaleCompare(attribute,"bordercolor") == 0)
4532             {
4533               if (image == (Image *) NULL)
4534                 break;
4535               (void) FormatLocaleString(color,MaxTextExtent,
4536                 "%.20g,%.20g,%.20g,%.20g",image->border_color.red,
4537                 image->border_color.green,image->border_color.blue,
4538                 image->border_color.alpha);
4539               s=newSVpv(color,0);
4540               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4541               continue;
4542             }
4543           if (LocaleCompare(attribute,"bounding-box") == 0)
4544             {
4545               char
4546                 geometry[MaxTextExtent];
4547
4548               RectangleInfo
4549                 page;
4550
4551               if (image == (Image *) NULL)
4552                 break;
4553               page=GetImageBoundingBox(image,exception);
4554               (void) FormatLocaleString(geometry,MaxTextExtent,
4555                 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4556                 page.height,(double) page.x,(double) page.y);
4557               s=newSVpv(geometry,0);
4558               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4559               continue;
4560             }
4561           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4562             attribute);
4563           break;
4564         }
4565         case 'C':
4566         case 'c':
4567         {
4568           if (LocaleCompare(attribute,"class") == 0)
4569             {
4570               if (image == (Image *) NULL)
4571                 break;
4572               s=newSViv(image->storage_class);
4573               (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4574                 image->storage_class));
4575               SvIOK_on(s);
4576               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4577               continue;
4578             }
4579           if (LocaleCompare(attribute,"clip-mask") == 0)
4580             {
4581               if (image != (Image *) NULL)
4582                 {
4583                   Image
4584                     *mask_image;
4585
4586                   SV
4587                     *sv;
4588
4589                   sv=NULL;
4590                   if (image->mask == MagickFalse)
4591                     ClipImage(image,exception);
4592                   mask_image=GetImageMask(image,exception);
4593                   if (mask_image != (Image *) NULL)
4594                     {
4595                       AddImageToRegistry(sv,mask_image);
4596                       s=sv_bless(newRV(sv),SvSTASH(reference));
4597                     }
4598                 }
4599               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4600               continue;
4601             }
4602           if (LocaleCompare(attribute,"clip-path") == 0)
4603             {
4604               if (image != (Image *) NULL)
4605                 {
4606                   Image
4607                     *mask_image;
4608
4609                   SV
4610                     *sv;
4611
4612                   sv=NULL;
4613                   if (image->mask != MagickFalse)
4614                     ClipImage(image,exception);
4615                   mask_image=GetImageMask(image,exception);
4616                   if (mask_image != (Image *) NULL)
4617                     {
4618                       AddImageToRegistry(sv,mask_image);
4619                       s=sv_bless(newRV(sv),SvSTASH(reference));
4620                     }
4621                 }
4622               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4623               continue;
4624             }
4625           if (LocaleCompare(attribute,"compression") == 0)
4626             {
4627               j=info ? info->image_info->compression : image ?
4628                 image->compression : UndefinedCompression;
4629               if (info)
4630                 if (info->image_info->compression == UndefinedCompression)
4631                   j=image->compression;
4632               s=newSViv(j);
4633               (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4634                 j));
4635               SvIOK_on(s);
4636               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4637               continue;
4638             }
4639           if (LocaleCompare(attribute,"colorspace") == 0)
4640             {
4641               j=image ? image->colorspace : RGBColorspace;
4642               s=newSViv(j);
4643               (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4644                 j));
4645               SvIOK_on(s);
4646               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4647               continue;
4648             }
4649           if (LocaleCompare(attribute,"colors") == 0)
4650             {
4651               if (image != (Image *) NULL)
4652                 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4653                   exception));
4654               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4655               continue;
4656             }
4657           if (LocaleNCompare(attribute,"colormap",8) == 0)
4658             {
4659               int
4660                 items;
4661
4662               if (image == (Image *) NULL || !image->colormap)
4663                 break;
4664               j=0;
4665               items=sscanf(attribute,"%*[^[][%ld",&j);
4666               (void) items;
4667               if (j > (ssize_t) image->colors)
4668                 j%=image->colors;
4669               (void) FormatLocaleString(color,MaxTextExtent,
4670                 "%.20g,%.20g,%.20g,%.20g",image->colormap[j].red,
4671                 image->colormap[j].green,image->colormap[j].blue,
4672                 image->colormap[j].alpha);
4673               s=newSVpv(color,0);
4674               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4675               continue;
4676             }
4677           if (LocaleCompare(attribute,"columns") == 0)
4678             {
4679               if (image != (Image *) NULL)
4680                 s=newSViv((ssize_t) image->columns);
4681               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4682               continue;
4683             }
4684           if (LocaleCompare(attribute,"comment") == 0)
4685             {
4686               const char
4687                 *value;
4688
4689               value=GetImageProperty(image,attribute,exception);
4690               if (value != (const char *) NULL)
4691                 s=newSVpv(value,0);
4692               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4693               continue;
4694             }
4695           if (LocaleCompare(attribute,"copyright") == 0)
4696             {
4697               s=newSVpv(GetMagickCopyright(),0);
4698               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4699               continue;
4700             }
4701           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4702             attribute);
4703           break;
4704         }
4705         case 'D':
4706         case 'd':
4707         {
4708           if (LocaleCompare(attribute,"density") == 0)
4709             {
4710               char
4711                 geometry[MaxTextExtent];
4712
4713               if (image == (Image *) NULL)
4714                 break;
4715               (void) FormatLocaleString(geometry,MaxTextExtent,"%.15gx%.15g",
4716                 image->resolution.x,image->resolution.y);
4717               s=newSVpv(geometry,0);
4718               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4719               continue;
4720             }
4721           if (LocaleCompare(attribute,"delay") == 0)
4722             {
4723               if (image != (Image *) NULL)
4724                 s=newSViv((ssize_t) image->delay);
4725               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4726               continue;
4727             }
4728           if (LocaleCompare(attribute,"depth") == 0)
4729             {
4730               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4731               if (image != (Image *) NULL)
4732                 s=newSViv((ssize_t) GetImageDepth(image,exception));
4733               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4734               continue;
4735             }
4736           if (LocaleCompare(attribute,"directory") == 0)
4737             {
4738               if (image && image->directory)
4739                 s=newSVpv(image->directory,0);
4740               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4741               continue;
4742             }
4743           if (LocaleCompare(attribute,"dispose") == 0)
4744             {
4745               if (image == (Image *) NULL)
4746                 break;
4747
4748               s=newSViv(image->dispose);
4749               (void) sv_setpv(s,
4750                 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
4751               SvIOK_on(s);
4752               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4753               continue;
4754             }
4755           if (LocaleCompare(attribute,"disk") == 0)
4756             {
4757               s=newSViv(GetMagickResource(DiskResource));
4758               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4759               continue;
4760             }
4761           if (LocaleCompare(attribute,"dither") == 0)
4762             {
4763               if (info)
4764                 s=newSViv((ssize_t) info->image_info->dither);
4765               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4766               continue;
4767             }
4768           if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4769             {
4770               if (info && info->image_info->server_name)
4771                 s=newSVpv(info->image_info->server_name,0);
4772               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4773               continue;
4774             }
4775           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4776             attribute);
4777           break;
4778         }
4779         case 'E':
4780         case 'e':
4781         {
4782           if (LocaleCompare(attribute,"elapsed-time") == 0)
4783             {
4784               if (image != (Image *) NULL)
4785                 s=newSVnv(GetElapsedTime(&image->timer));
4786               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4787               continue;
4788             }
4789           if (LocaleCompare(attribute,"endian") == 0)
4790             {
4791               j=info ? info->image_info->endian : image ? image->endian :
4792                 UndefinedEndian;
4793               s=newSViv(j);
4794               (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
4795               SvIOK_on(s);
4796               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4797               continue;
4798             }
4799           if (LocaleCompare(attribute,"error") == 0)
4800             {
4801               if (image != (Image *) NULL)
4802                 s=newSVnv(image->error.mean_error_per_pixel);
4803               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4804               continue;
4805             }
4806           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4807             attribute);
4808           break;
4809         }
4810         case 'F':
4811         case 'f':
4812         {
4813           if (LocaleCompare(attribute,"filesize") == 0)
4814             {
4815               if (image != (Image *) NULL)
4816                 s=newSViv((ssize_t) GetBlobSize(image));
4817               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4818               continue;
4819             }
4820           if (LocaleCompare(attribute,"filename") == 0)
4821             {
4822               if (info && info->image_info->filename &&
4823                   *info->image_info->filename)
4824                 s=newSVpv(info->image_info->filename,0);
4825               if (image != (Image *) NULL)
4826                 s=newSVpv(image->filename,0);
4827               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4828               continue;
4829             }
4830           if (LocaleCompare(attribute,"filter") == 0)
4831             {
4832               s=image ? newSViv(image->filter) : newSViv(0);
4833               (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
4834                 image->filter));
4835               SvIOK_on(s);
4836               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4837               continue;
4838             }
4839           if (LocaleCompare(attribute,"font") == 0)
4840             {
4841               if (info && info->image_info->font)
4842                 s=newSVpv(info->image_info->font,0);
4843               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4844               continue;
4845             }
4846           if (LocaleCompare(attribute,"foreground") == 0)
4847             continue;
4848           if (LocaleCompare(attribute,"format") == 0)
4849             {
4850               const MagickInfo
4851                 *magick_info;
4852
4853               magick_info=(const MagickInfo *) NULL;
4854               if (info && (*info->image_info->magick != '\0'))
4855                 magick_info=GetMagickInfo(info->image_info->magick,exception);
4856               if (image != (Image *) NULL)
4857                 magick_info=GetMagickInfo(image->magick,exception);
4858               if ((magick_info != (const MagickInfo *) NULL) &&
4859                   (*magick_info->description != '\0'))
4860                 s=newSVpv((char *) magick_info->description,0);
4861               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4862               continue;
4863             }
4864           if (LocaleCompare(attribute,"fuzz") == 0)
4865             {
4866               if (info)
4867                 s=newSVnv(info->image_info->fuzz);
4868               if (image != (Image *) NULL)
4869                 s=newSVnv(image->fuzz);
4870               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4871               continue;
4872             }
4873           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4874             attribute);
4875           break;
4876         }
4877         case 'G':
4878         case 'g':
4879         {
4880           if (LocaleCompare(attribute,"gamma") == 0)
4881             {
4882               if (image != (Image *) NULL)
4883                 s=newSVnv(image->gamma);
4884               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4885               continue;
4886             }
4887           if (LocaleCompare(attribute,"geometry") == 0)
4888             {
4889               if (image && image->geometry)
4890                 s=newSVpv(image->geometry,0);
4891               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4892               continue;
4893             }
4894           if (LocaleCompare(attribute,"gravity") == 0)
4895             {
4896               s=image ? newSViv(image->gravity) : newSViv(0);
4897               (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
4898                 image->gravity));
4899               SvIOK_on(s);
4900               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4901               continue;
4902             }
4903           if (LocaleCompare(attribute,"green-primary") == 0)
4904             {
4905               if (image == (Image *) NULL)
4906                 break;
4907               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4908                 image->chromaticity.green_primary.x,
4909                 image->chromaticity.green_primary.y);
4910               s=newSVpv(color,0);
4911               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4912               continue;
4913             }
4914           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4915             attribute);
4916           break;
4917         }
4918         case 'H':
4919         case 'h':
4920         {
4921           if (LocaleCompare(attribute,"height") == 0)
4922             {
4923               if (image != (Image *) NULL)
4924                 s=newSViv((ssize_t) image->rows);
4925               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4926               continue;
4927             }
4928           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4929             attribute);
4930           break;
4931         }
4932         case 'I':
4933         case 'i':
4934         {
4935           if (LocaleCompare(attribute,"icc") == 0)
4936             {
4937               if (image != (Image *) NULL)
4938                 {
4939                   const StringInfo
4940                     *profile;
4941
4942                   profile=GetImageProfile(image,"icc");
4943                   if (profile != (StringInfo *) NULL)
4944                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4945                       GetStringInfoLength(profile));
4946                 }
4947               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4948               continue;
4949             }
4950           if (LocaleCompare(attribute,"icm") == 0)
4951             {
4952               if (image != (Image *) NULL)
4953                 {
4954                   const StringInfo
4955                     *profile;
4956
4957                   profile=GetImageProfile(image,"icm");
4958                   if (profile != (const StringInfo *) NULL)
4959                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4960                       GetStringInfoLength(profile));
4961                 }
4962               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4963               continue;
4964             }
4965           if (LocaleCompare(attribute,"id") == 0)
4966             {
4967               if (image != (Image *) NULL)
4968                 {
4969                   char
4970                     key[MaxTextExtent];
4971
4972                   MagickBooleanType
4973                     status;
4974
4975                   static ssize_t
4976                     id = 0;
4977
4978                   (void) FormatLocaleString(key,MaxTextExtent,"%.20g\n",(double)
4979                     id);
4980                   status=SetImageRegistry(ImageRegistryType,key,image,
4981                     exception);
4982                   (void) status;
4983                   s=newSViv(id++);
4984                 }
4985               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4986               continue;
4987             }
4988           if (LocaleNCompare(attribute,"index",5) == 0)
4989             {
4990               char
4991                 name[MaxTextExtent];
4992
4993               int
4994                 items;
4995
4996               long
4997                 x,
4998                 y;
4999
5000               register const Quantum
5001                 *p;
5002
5003               CacheView
5004                 *image_view;
5005
5006               if (image == (Image *) NULL)
5007                 break;
5008               if (image->storage_class != PseudoClass)
5009                 break;
5010               x=0;
5011               y=0;
5012               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5013               (void) items;
5014               image_view=AcquireVirtualCacheView(image,exception);
5015               p=GetCacheViewVirtualPixels(image_view,x,y,1,1,exception);
5016               if (p != (const Quantum *) NULL)
5017                 {
5018                   (void) FormatLocaleString(name,MaxTextExtent,QuantumFormat,
5019                     GetPixelIndex(image,p));
5020                   s=newSVpv(name,0);
5021                   PUSHs(s ? sv_2mortal(s) : &sv_undef);
5022                 }
5023               image_view=DestroyCacheView(image_view);
5024               continue;
5025             }
5026           if (LocaleCompare(attribute,"iptc") == 0)
5027             {
5028               if (image != (Image *) NULL)
5029                 {
5030                   const StringInfo
5031                     *profile;
5032
5033                   profile=GetImageProfile(image,"iptc");
5034                   if (profile != (const StringInfo *) NULL)
5035                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5036                       GetStringInfoLength(profile));
5037                 }
5038               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5039               continue;
5040             }
5041           if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
5042             {
5043               if (image != (Image *) NULL)
5044                 s=newSViv((ssize_t) image->iterations);
5045               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5046               continue;
5047             }
5048           if (LocaleCompare(attribute,"interlace") == 0)
5049             {
5050               j=info ? info->image_info->interlace : image ? image->interlace :
5051                 UndefinedInterlace;
5052               s=newSViv(j);
5053               (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
5054                 j));
5055               SvIOK_on(s);
5056               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5057               continue;
5058             }
5059           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5060             attribute);
5061           break;
5062         }
5063         case 'L':
5064         case 'l':
5065         {
5066           if (LocaleCompare(attribute,"label") == 0)
5067             {
5068               const char
5069                 *value;
5070
5071               if (image == (Image *) NULL)
5072                 break;
5073               value=GetImageProperty(image,"Label",exception);
5074               if (value != (const char *) NULL)
5075                 s=newSVpv(value,0);
5076               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5077               continue;
5078             }
5079           if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
5080             {
5081               if (image != (Image *) NULL)
5082                 s=newSViv((ssize_t) image->iterations);
5083               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5084               continue;
5085             }
5086           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5087             attribute);
5088           break;
5089         }
5090         case 'M':
5091         case 'm':
5092         {
5093           if (LocaleCompare(attribute,"magick") == 0)
5094             {
5095               if (info && *info->image_info->magick)
5096                 s=newSVpv(info->image_info->magick,0);
5097               if (image != (Image *) NULL)
5098                 s=newSVpv(image->magick,0);
5099               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5100               continue;
5101             }
5102           if (LocaleCompare(attribute,"map") == 0)
5103             {
5104               s=newSViv(GetMagickResource(MapResource));
5105               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5106               continue;
5107             }
5108           if (LocaleCompare(attribute,"maximum-error") == 0)
5109             {
5110               if (image != (Image *) NULL)
5111                 s=newSVnv(image->error.normalized_maximum_error);
5112               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5113               continue;
5114             }
5115           if (LocaleCompare(attribute,"memory") == 0)
5116             {
5117               s=newSViv(GetMagickResource(MemoryResource));
5118               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5119               continue;
5120             }
5121           if (LocaleCompare(attribute,"mean-error") == 0)
5122             {
5123               if (image != (Image *) NULL)
5124                 s=newSVnv(image->error.normalized_mean_error);
5125               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5126               continue;
5127             }
5128           if (LocaleCompare(attribute,"mime") == 0)
5129             {
5130               if (info && *info->image_info->magick)
5131                 s=newSVpv(MagickToMime(info->image_info->magick),0);
5132               if (image != (Image *) NULL)
5133                 s=newSVpv(MagickToMime(image->magick),0);
5134               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5135               continue;
5136             }
5137           if (LocaleCompare(attribute,"mattecolor") == 0)
5138             {
5139               if (image == (Image *) NULL)
5140                 break;
5141               (void) FormatLocaleString(color,MaxTextExtent,
5142                 "%.20g,%.20g,%.20g,%.20g",image->matte_color.red,
5143                 image->matte_color.green,image->matte_color.blue,
5144                 image->matte_color.alpha);
5145               s=newSVpv(color,0);
5146               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5147               continue;
5148             }
5149           if (LocaleCompare(attribute,"matte") == 0)
5150             {
5151               if (image != (Image *) NULL)
5152                 s=newSViv((ssize_t) image->alpha_trait == BlendPixelTrait ?
5153                   1 : 0);
5154               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5155               continue;
5156             }
5157           if (LocaleCompare(attribute,"mime") == 0)
5158             {
5159               const char
5160                 *magick;
5161
5162               magick=NULL;
5163               if (info && *info->image_info->magick)
5164                 magick=info->image_info->magick;
5165               if (image != (Image *) NULL)
5166                 magick=image->magick;
5167               if (magick)
5168                 {
5169                   char
5170                     *mime;
5171
5172                   mime=MagickToMime(magick);
5173                   s=newSVpv(mime,0);
5174                   mime=(char *) RelinquishMagickMemory(mime);
5175                 }
5176               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5177               continue;
5178             }
5179           if (LocaleCompare(attribute,"monochrome") == 0)
5180             {
5181               if (image == (Image *) NULL)
5182                 continue;
5183               j=info ? info->image_info->monochrome :
5184                 IsImageMonochrome(image,exception);
5185               s=newSViv(j);
5186               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5187               continue;
5188             }
5189           if (LocaleCompare(attribute,"montage") == 0)
5190             {
5191               if (image && image->montage)
5192                 s=newSVpv(image->montage,0);
5193               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5194               continue;
5195             }
5196           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5197             attribute);
5198           break;
5199         }
5200         case 'O':
5201         case 'o':
5202         {
5203           if (LocaleCompare(attribute,"orientation") == 0)
5204             {
5205               j=info ? info->image_info->orientation : image ?
5206                 image->orientation : UndefinedOrientation;
5207               s=newSViv(j);
5208               (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5209                 j));
5210               SvIOK_on(s);
5211               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5212               continue;
5213             }
5214           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5215             attribute);
5216           break;
5217         }
5218         case 'P':
5219         case 'p':
5220         {
5221           if (LocaleCompare(attribute,"page") == 0)
5222             {
5223               if (info && info->image_info->page)
5224                 s=newSVpv(info->image_info->page,0);
5225               if (image != (Image *) NULL)
5226                 {
5227                   char
5228                     geometry[MaxTextExtent];
5229
5230                   (void) FormatLocaleString(geometry,MaxTextExtent,
5231                     "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5232                     (double) image->page.height,(double) image->page.x,(double)
5233                     image->page.y);
5234                   s=newSVpv(geometry,0);
5235                 }
5236               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5237               continue;
5238             }
5239           if (LocaleCompare(attribute,"page.x") == 0)
5240             {
5241               if (image != (Image *) NULL)
5242                 s=newSViv((ssize_t) image->page.x);
5243               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5244               continue;
5245             }
5246           if (LocaleCompare(attribute,"page.y") == 0)
5247             {
5248               if (image != (Image *) NULL)
5249                 s=newSViv((ssize_t) image->page.y);
5250               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5251               continue;
5252             }
5253           if (LocaleNCompare(attribute,"pixel",5) == 0)
5254             {
5255               char
5256                 tuple[MaxTextExtent];
5257
5258               int
5259                 items;
5260
5261               long
5262                 x,
5263                 y;
5264
5265               register const Quantum
5266                 *p;
5267
5268               if (image == (Image *) NULL)
5269                 break;
5270               x=0;
5271               y=0;
5272               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5273               (void) items;
5274               p=GetVirtualPixels(image,x,y,1,1,exception);
5275               if (image->colorspace != CMYKColorspace)
5276                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5277                   QuantumFormat "," QuantumFormat "," QuantumFormat,
5278                   GetPixelRed(image,p),GetPixelGreen(image,p),
5279                   GetPixelBlue(image,p),GetPixelAlpha(image,p));
5280               else
5281                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5282                   QuantumFormat "," QuantumFormat "," QuantumFormat ","
5283                   QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5284                   GetPixelBlue(image,p),GetPixelBlack(image,p),
5285                   GetPixelAlpha(image,p));
5286               s=newSVpv(tuple,0);
5287               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5288               continue;
5289             }
5290           if (LocaleCompare(attribute,"pointsize") == 0)
5291             {
5292               if (info)
5293                 s=newSViv((ssize_t) info->image_info->pointsize);
5294               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5295               continue;
5296             }
5297           if (LocaleCompare(attribute,"preview") == 0)
5298             {
5299               s=newSViv(info->image_info->preview_type);
5300               (void) sv_setpv(s,CommandOptionToMnemonic(MagickPreviewOptions,
5301                 info->image_info->preview_type));
5302               SvIOK_on(s);
5303               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5304               continue;
5305             }
5306           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5307             attribute);
5308           break;
5309         }
5310         case 'Q':
5311         case 'q':
5312         {
5313           if (LocaleCompare(attribute,"quality") == 0)
5314             {
5315               if (info)
5316                 s=newSViv((ssize_t) info->image_info->quality);
5317               if (image != (Image *) NULL)
5318                 s=newSViv((ssize_t) image->quality);
5319               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5320               continue;
5321             }
5322           if (LocaleCompare(attribute,"quantum") == 0)
5323             {
5324               if (info)
5325                 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5326               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5327               continue;
5328             }
5329           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5330             attribute);
5331           break;
5332         }
5333         case 'R':
5334         case 'r':
5335         {
5336           if (LocaleCompare(attribute,"rendering-intent") == 0)
5337             {
5338               s=newSViv(image->rendering_intent);
5339               (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5340                 image->rendering_intent));
5341               SvIOK_on(s);
5342               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5343               continue;
5344             }
5345           if (LocaleCompare(attribute,"red-primary") == 0)
5346             {
5347               if (image == (Image *) NULL)
5348                 break;
5349               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5350                 image->chromaticity.red_primary.x,
5351                 image->chromaticity.red_primary.y);
5352               s=newSVpv(color,0);
5353               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5354               continue;
5355             }
5356           if (LocaleCompare(attribute,"rows") == 0)
5357             {
5358               if (image != (Image *) NULL)
5359                 s=newSViv((ssize_t) image->rows);
5360               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5361               continue;
5362             }
5363           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5364             attribute);
5365           break;
5366         }
5367         case 'S':
5368         case 's':
5369         {
5370           if (LocaleCompare(attribute,"sampling-factor") == 0)
5371             {
5372               if (info && info->image_info->sampling_factor)
5373                 s=newSVpv(info->image_info->sampling_factor,0);
5374               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5375               continue;
5376             }
5377           if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5378             {
5379               if (info && info->image_info->server_name)
5380                 s=newSVpv(info->image_info->server_name,0);
5381               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5382               continue;
5383             }
5384           if (LocaleCompare(attribute,"size") == 0)
5385             {
5386               if (info && info->image_info->size)
5387                 s=newSVpv(info->image_info->size,0);
5388               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5389               continue;
5390             }
5391           if (LocaleCompare(attribute,"scene") == 0)
5392             {
5393               if (image != (Image *) NULL)
5394                 s=newSViv((ssize_t) image->scene);
5395               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5396               continue;
5397             }
5398           if (LocaleCompare(attribute,"scenes") == 0)
5399             {
5400               if (image != (Image *) NULL)
5401                 s=newSViv((ssize_t) info->image_info->number_scenes);
5402               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5403               continue;
5404             }
5405           if (LocaleCompare(attribute,"signature") == 0)
5406             {
5407               const char
5408                 *value;
5409
5410               if (image == (Image *) NULL)
5411                 break;
5412               (void) SignatureImage(image,exception);
5413               value=GetImageProperty(image,"Signature",exception);
5414               if (value != (const char *) NULL)
5415                 s=newSVpv(value,0);
5416               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5417               continue;
5418             }
5419           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5420             attribute);
5421           break;
5422         }
5423         case 'T':
5424         case 't':
5425         {
5426           if (LocaleCompare(attribute,"taint") == 0)
5427             {
5428               if (image != (Image *) NULL)
5429                 s=newSViv((ssize_t) IsTaintImage(image));
5430               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5431               continue;
5432             }
5433           if (LocaleCompare(attribute,"texture") == 0)
5434             {
5435               if (info && info->image_info->texture)
5436                 s=newSVpv(info->image_info->texture,0);
5437               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5438               continue;
5439             }
5440           if (LocaleCompare(attribute,"total-ink-density") == 0)
5441             {
5442               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5443               if (image != (Image *) NULL)
5444                 s=newSVnv(GetImageTotalInkDensity(image,exception));
5445               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5446               continue;
5447             }
5448           if (LocaleCompare(attribute,"transparent-color") == 0)
5449             {
5450               if (image == (Image *) NULL)
5451                 break;
5452               (void) FormatLocaleString(color,MaxTextExtent,
5453                 "%.20g,%.20g,%.20g,%.20g",image->transparent_color.red,
5454                 image->transparent_color.green,image->transparent_color.blue,
5455                 image->transparent_color.alpha);
5456               s=newSVpv(color,0);
5457               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5458               continue;
5459             }
5460           if (LocaleCompare(attribute,"type") == 0)
5461             {
5462               if (image == (Image *) NULL)
5463                 break;
5464               j=(ssize_t) GetImageType(image,exception);
5465               s=newSViv(j);
5466               (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5467               SvIOK_on(s);
5468               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5469               continue;
5470             }
5471           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5472             attribute);
5473           break;
5474         }
5475         case 'U':
5476         case 'u':
5477         {
5478           if (LocaleCompare(attribute,"units") == 0)
5479             {
5480               j=info ? info->image_info->units : image ? image->units :
5481                 UndefinedResolution;
5482               if (info && (info->image_info->units == UndefinedResolution))
5483                 if (image)
5484                   j=image->units;
5485               if (j == UndefinedResolution)
5486                 s=newSVpv("undefined units",0);
5487               else
5488                 if (j == PixelsPerInchResolution)
5489                   s=newSVpv("pixels / inch",0);
5490                 else
5491                   s=newSVpv("pixels / centimeter",0);
5492               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5493               continue;
5494             }
5495           if (LocaleCompare(attribute,"user-time") == 0)
5496             {
5497               if (image != (Image *) NULL)
5498                 s=newSVnv(GetUserTime(&image->timer));
5499               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5500               continue;
5501             }
5502           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5503             attribute);
5504           break;
5505         }
5506         case 'V':
5507         case 'v':
5508         {
5509           if (LocaleCompare(attribute,"verbose") == 0)
5510             {
5511               if (info)
5512                 s=newSViv((ssize_t) info->image_info->verbose);
5513               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5514               continue;
5515             }
5516           if (LocaleCompare(attribute,"version") == 0)
5517             {
5518               s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5519               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5520               continue;
5521             }
5522           if (LocaleCompare(attribute,"view") == 0)
5523             {
5524               if (info && info->image_info->view)
5525                 s=newSVpv(info->image_info->view,0);
5526               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5527               continue;
5528             }
5529           if (LocaleCompare(attribute,"virtual-pixel") == 0)
5530             {
5531               if (image == (Image *) NULL)
5532                 break;
5533               j=(ssize_t) GetImageVirtualPixelMethod(image);
5534               s=newSViv(j);
5535               (void) sv_setpv(s,CommandOptionToMnemonic(
5536                 MagickVirtualPixelOptions,j));
5537               SvIOK_on(s);
5538               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5539               continue;
5540             }
5541           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5542             attribute);
5543           break;
5544         }
5545         case 'W':
5546         case 'w':
5547         {
5548           if (LocaleCompare(attribute,"white-point") == 0)
5549             {
5550               if (image == (Image *) NULL)
5551                 break;
5552               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5553                 image->chromaticity.white_point.x,
5554                 image->chromaticity.white_point.y);
5555               s=newSVpv(color,0);
5556               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5557               continue;
5558             }
5559           if (LocaleCompare(attribute,"width") == 0)
5560             {
5561               if (image != (Image *) NULL)
5562                 s=newSViv((ssize_t) image->columns);
5563               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5564               continue;
5565             }
5566           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5567              attribute);
5568           break;
5569         }
5570         case 'X':
5571         case 'x':
5572         {
5573           if (LocaleCompare(attribute,"x-resolution") == 0)
5574             {
5575               if (image != (Image *) NULL)
5576                 s=newSVnv(image->resolution.x);
5577               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5578               continue;
5579             }
5580           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5581             attribute);
5582           break;
5583         }
5584         case 'Y':
5585         case 'y':
5586         {
5587           if (LocaleCompare(attribute,"y-resolution") == 0)
5588             {
5589               if (image != (Image *) NULL)
5590                 s=newSVnv(image->resolution.y);
5591               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5592               continue;
5593             }
5594           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5595             attribute);
5596           break;
5597         }
5598         default:
5599           break;
5600       }
5601       if (image == (Image *) NULL)
5602         ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5603           attribute)
5604       else
5605         {
5606           value=GetImageProperty(image,attribute,exception);
5607           if (value != (const char *) NULL)
5608             {
5609               s=newSVpv(value,0);
5610               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5611             }
5612           else
5613             if (*attribute != '%')
5614               ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5615                 attribute)
5616             else
5617               {
5618                  char
5619                    *meta;
5620
5621                  meta=InterpretImageProperties(info ? info->image_info :
5622                    (ImageInfo *) NULL,image,attribute,exception);
5623                  s=newSVpv(meta,0);
5624                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5625                  meta=(char *) RelinquishMagickMemory(meta);
5626               }
5627         }
5628     }
5629     exception=DestroyExceptionInfo(exception);
5630     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5631   }
5632 \f
5633 #
5634 ###############################################################################
5635 #                                                                             #
5636 #                                                                             #
5637 #                                                                             #
5638 #   G e t A u t h e n t i c P i x e l s                                       #
5639 #                                                                             #
5640 #                                                                             #
5641 #                                                                             #
5642 ###############################################################################
5643 #
5644 #
5645 void *
5646 GetAuthenticPixels(ref,...)
5647   Image::Magick ref = NO_INIT
5648   ALIAS:
5649     getauthenticpixels = 1
5650     GetImagePixels = 2
5651     getimagepixels = 3
5652   CODE:
5653   {
5654     char
5655       *attribute;
5656
5657     ExceptionInfo
5658       *exception;
5659
5660     Image
5661       *image;
5662
5663     RectangleInfo
5664       region;
5665
5666     ssize_t
5667       i;
5668
5669     struct PackageInfo
5670       *info;
5671
5672     SV
5673       *perl_exception,
5674       *reference;
5675
5676     void
5677       *blob = NULL;
5678
5679     PERL_UNUSED_VAR(ref);
5680     PERL_UNUSED_VAR(ix);
5681     exception=AcquireExceptionInfo();
5682     perl_exception=newSVpv("",0);
5683     if (sv_isobject(ST(0)) == 0)
5684       {
5685         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5686           PackageName);
5687         goto PerlException;
5688       }
5689     reference=SvRV(ST(0));
5690
5691     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5692     if (image == (Image *) NULL)
5693       {
5694         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5695           PackageName);
5696         goto PerlException;
5697       }
5698
5699     region.x=0;
5700     region.y=0;
5701     region.width=image->columns;
5702     region.height=1;
5703     if (items == 1)
5704       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5705     for (i=2; i < items; i+=2)
5706     {
5707       attribute=(char *) SvPV(ST(i-1),na);
5708       switch (*attribute)
5709       {
5710         case 'g':
5711         case 'G':
5712         {
5713           if (LocaleCompare(attribute,"geometry") == 0)
5714             {
5715               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5716               break;
5717             }
5718           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5719             attribute);
5720           break;
5721         }
5722         case 'H':
5723         case 'h':
5724         {
5725           if (LocaleCompare(attribute,"height") == 0)
5726             {
5727               region.height=SvIV(ST(i));
5728               continue;
5729             }
5730           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5731             attribute);
5732           break;
5733         }
5734         case 'X':
5735         case 'x':
5736         {
5737           if (LocaleCompare(attribute,"x") == 0)
5738             {
5739               region.x=SvIV(ST(i));
5740               continue;
5741             }
5742           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5743             attribute);
5744           break;
5745         }
5746         case 'Y':
5747         case 'y':
5748         {
5749           if (LocaleCompare(attribute,"y") == 0)
5750             {
5751               region.y=SvIV(ST(i));
5752               continue;
5753             }
5754           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5755             attribute);
5756           break;
5757         }
5758         case 'W':
5759         case 'w':
5760         {
5761           if (LocaleCompare(attribute,"width") == 0)
5762             {
5763               region.width=SvIV(ST(i));
5764               continue;
5765             }
5766           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5767             attribute);
5768           break;
5769         }
5770       }
5771     }
5772     blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5773       region.height,exception);
5774     if (blob != (void *) NULL)
5775       goto PerlEnd;
5776
5777   PerlException:
5778     InheritPerlException(exception,perl_exception);
5779     exception=DestroyExceptionInfo(exception);
5780     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5781
5782   PerlEnd:
5783     RETVAL = blob;
5784   }
5785   OUTPUT:
5786     RETVAL
5787 \f
5788 #
5789 ###############################################################################
5790 #                                                                             #
5791 #                                                                             #
5792 #                                                                             #
5793 #   G e t V i r t u a l P i x e l s                                           #
5794 #                                                                             #
5795 #                                                                             #
5796 #                                                                             #
5797 ###############################################################################
5798 #
5799 #
5800 void *
5801 GetVirtualPixels(ref,...)
5802   Image::Magick ref = NO_INIT
5803   ALIAS:
5804     getvirtualpixels = 1
5805     AcquireImagePixels = 2
5806     acquireimagepixels = 3
5807   CODE:
5808   {
5809     char
5810       *attribute;
5811
5812     const void
5813       *blob = NULL;
5814
5815     ExceptionInfo
5816       *exception;
5817
5818     Image
5819       *image;
5820
5821     RectangleInfo
5822       region;
5823
5824     ssize_t
5825       i;
5826
5827     struct PackageInfo
5828       *info;
5829
5830     SV
5831       *perl_exception,
5832       *reference;
5833
5834     PERL_UNUSED_VAR(ref);
5835     PERL_UNUSED_VAR(ix);
5836     exception=AcquireExceptionInfo();
5837     perl_exception=newSVpv("",0);
5838     if (sv_isobject(ST(0)) == 0)
5839       {
5840         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5841           PackageName);
5842         goto PerlException;
5843       }
5844     reference=SvRV(ST(0));
5845
5846     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5847     if (image == (Image *) NULL)
5848       {
5849         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5850           PackageName);
5851         goto PerlException;
5852       }
5853
5854     region.x=0;
5855     region.y=0;
5856     region.width=image->columns;
5857     region.height=1;
5858     if (items == 1)
5859       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5860     for (i=2; i < items; i+=2)
5861     {
5862       attribute=(char *) SvPV(ST(i-1),na);
5863       switch (*attribute)
5864       {
5865         case 'g':
5866         case 'G':
5867         {
5868           if (LocaleCompare(attribute,"geometry") == 0)
5869             {
5870               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5871               break;
5872             }
5873           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5874             attribute);
5875           break;
5876         }
5877         case 'H':
5878         case 'h':
5879         {
5880           if (LocaleCompare(attribute,"height") == 0)
5881             {
5882               region.height=SvIV(ST(i));
5883               continue;
5884             }
5885           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5886             attribute);
5887           break;
5888         }
5889         case 'X':
5890         case 'x':
5891         {
5892           if (LocaleCompare(attribute,"x") == 0)
5893             {
5894               region.x=SvIV(ST(i));
5895               continue;
5896             }
5897           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5898             attribute);
5899           break;
5900         }
5901         case 'Y':
5902         case 'y':
5903         {
5904           if (LocaleCompare(attribute,"y") == 0)
5905             {
5906               region.y=SvIV(ST(i));
5907               continue;
5908             }
5909           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5910             attribute);
5911           break;
5912         }
5913         case 'W':
5914         case 'w':
5915         {
5916           if (LocaleCompare(attribute,"width") == 0)
5917             {
5918               region.width=SvIV(ST(i));
5919               continue;
5920             }
5921           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5922             attribute);
5923           break;
5924         }
5925       }
5926     }
5927     blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
5928       region.height,exception);
5929     if (blob != (void *) NULL)
5930       goto PerlEnd;
5931
5932   PerlException:
5933     InheritPerlException(exception,perl_exception);
5934     exception=DestroyExceptionInfo(exception);
5935     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5936
5937   PerlEnd:
5938     RETVAL = (void *) blob;
5939   }
5940   OUTPUT:
5941     RETVAL
5942 \f
5943 #
5944 ###############################################################################
5945 #                                                                             #
5946 #                                                                             #
5947 #                                                                             #
5948 #   G e t A u t h e n t i c M e t a c o n t e n t                             #
5949 #                                                                             #
5950 #                                                                             #
5951 #                                                                             #
5952 ###############################################################################
5953 #
5954 #
5955 void *
5956 GetAuthenticMetacontent(ref,...)
5957   Image::Magick ref = NO_INIT
5958   ALIAS:
5959     getauthenticmetacontent = 1
5960     GetMetacontent = 2
5961     getmetacontent = 3
5962   CODE:
5963   {
5964     ExceptionInfo
5965       *exception;
5966
5967     Image
5968       *image;
5969
5970     struct PackageInfo
5971       *info;
5972
5973     SV
5974       *perl_exception,
5975       *reference;
5976
5977     void
5978       *blob = NULL;
5979
5980     PERL_UNUSED_VAR(ref);
5981     PERL_UNUSED_VAR(ix);
5982     exception=AcquireExceptionInfo();
5983     perl_exception=newSVpv("",0);
5984     if (sv_isobject(ST(0)) == 0)
5985       {
5986         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5987           PackageName);
5988         goto PerlException;
5989       }
5990     reference=SvRV(ST(0));
5991
5992     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5993     if (image == (Image *) NULL)
5994       {
5995         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5996           PackageName);
5997         goto PerlException;
5998       }
5999
6000     blob=(void *) GetAuthenticMetacontent(image);
6001     if (blob != (void *) NULL)
6002       goto PerlEnd;
6003
6004   PerlException:
6005     InheritPerlException(exception,perl_exception);
6006     exception=DestroyExceptionInfo(exception);
6007     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6008
6009   PerlEnd:
6010     RETVAL = blob;
6011   }
6012   OUTPUT:
6013     RETVAL
6014 \f
6015 #
6016 ###############################################################################
6017 #                                                                             #
6018 #                                                                             #
6019 #                                                                             #
6020 #   G e t V i r t u a l M e t a c o n t e n t                                 #
6021 #                                                                             #
6022 #                                                                             #
6023 #                                                                             #
6024 ###############################################################################
6025 #
6026 #
6027 void *
6028 GetVirtualMetacontent(ref,...)
6029   Image::Magick ref = NO_INIT
6030   ALIAS:
6031     getvirtualmetacontent = 1
6032   CODE:
6033   {
6034     ExceptionInfo
6035       *exception;
6036
6037     Image
6038       *image;
6039
6040     struct PackageInfo
6041       *info;
6042
6043     SV
6044       *perl_exception,
6045       *reference;
6046
6047     void
6048       *blob = NULL;
6049
6050     PERL_UNUSED_VAR(ref);
6051     PERL_UNUSED_VAR(ix);
6052     exception=AcquireExceptionInfo();
6053     perl_exception=newSVpv("",0);
6054     if (sv_isobject(ST(0)) == 0)
6055       {
6056         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6057           PackageName);
6058         goto PerlException;
6059       }
6060     reference=SvRV(ST(0));
6061
6062     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6063     if (image == (Image *) NULL)
6064       {
6065         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6066           PackageName);
6067         goto PerlException;
6068       }
6069
6070     blob=(void *) GetVirtualMetacontent(image);
6071     if (blob != (void *) NULL)
6072       goto PerlEnd;
6073
6074   PerlException:
6075     InheritPerlException(exception,perl_exception);
6076     exception=DestroyExceptionInfo(exception);
6077     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6078
6079   PerlEnd:
6080     RETVAL = blob;
6081   }
6082   OUTPUT:
6083     RETVAL
6084 \f
6085 #
6086 ###############################################################################
6087 #                                                                             #
6088 #                                                                             #
6089 #                                                                             #
6090 #   H i s t o g r a m                                                         #
6091 #                                                                             #
6092 #                                                                             #
6093 #                                                                             #
6094 ###############################################################################
6095 #
6096 #
6097 void
6098 Histogram(ref,...)
6099   Image::Magick ref=NO_INIT
6100   ALIAS:
6101     HistogramImage = 1
6102     histogram      = 2
6103     histogramimage = 3
6104   PPCODE:
6105   {
6106     AV
6107       *av;
6108
6109     char
6110       message[MaxTextExtent];
6111
6112     PixelInfo
6113       *histogram;
6114
6115     ExceptionInfo
6116       *exception;
6117
6118     Image
6119       *image;
6120
6121     register ssize_t
6122       i;
6123
6124     ssize_t
6125       count;
6126
6127     struct PackageInfo
6128       *info;
6129
6130     SV
6131       *perl_exception,
6132       *reference;
6133
6134     size_t
6135       number_colors;
6136
6137     PERL_UNUSED_VAR(ref);
6138     PERL_UNUSED_VAR(ix);
6139     exception=AcquireExceptionInfo();
6140     perl_exception=newSVpv("",0);
6141     av=NULL;
6142     if (sv_isobject(ST(0)) == 0)
6143       {
6144         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6145           PackageName);
6146         goto PerlException;
6147       }
6148     reference=SvRV(ST(0));
6149     av=newAV();
6150     SvREFCNT_dec(av);
6151     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6152     if (image == (Image *) NULL)
6153       {
6154         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6155           PackageName);
6156         goto PerlException;
6157       }
6158     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
6159     count=0;
6160     for ( ; image; image=image->next)
6161     {
6162       histogram=GetImageHistogram(image,&number_colors,exception);
6163       if (histogram == (PixelInfo *) NULL)
6164         continue;
6165       count+=(ssize_t) number_colors;
6166       EXTEND(sp,6*count);
6167       for (i=0; i < (ssize_t) number_colors; i++)
6168       {
6169         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6170           histogram[i].red);
6171         PUSHs(sv_2mortal(newSVpv(message,0)));
6172         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6173           histogram[i].green);
6174         PUSHs(sv_2mortal(newSVpv(message,0)));
6175         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6176           histogram[i].blue);
6177         PUSHs(sv_2mortal(newSVpv(message,0)));
6178         if (image->colorspace == CMYKColorspace)
6179           {
6180             (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6181               histogram[i].black);
6182             PUSHs(sv_2mortal(newSVpv(message,0)));
6183           }
6184         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6185           histogram[i].alpha);
6186         PUSHs(sv_2mortal(newSVpv(message,0)));
6187         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
6188           histogram[i].count);
6189         PUSHs(sv_2mortal(newSVpv(message,0)));
6190       }
6191       histogram=(PixelInfo *) RelinquishMagickMemory(histogram);
6192     }
6193
6194   PerlException:
6195     InheritPerlException(exception,perl_exception);
6196     exception=DestroyExceptionInfo(exception);
6197     SvREFCNT_dec(perl_exception);
6198   }
6199 \f
6200 #
6201 ###############################################################################
6202 #                                                                             #
6203 #                                                                             #
6204 #                                                                             #
6205 #   G e t P i x e l                                                           #
6206 #                                                                             #
6207 #                                                                             #
6208 #                                                                             #
6209 ###############################################################################
6210 #
6211 #
6212 void
6213 GetPixel(ref,...)
6214   Image::Magick ref=NO_INIT
6215   ALIAS:
6216     getpixel = 1
6217     getPixel = 2
6218   PPCODE:
6219   {
6220     AV
6221       *av;
6222
6223     char
6224       *attribute;
6225
6226     ExceptionInfo
6227       *exception;
6228
6229     Image
6230       *image;
6231
6232     MagickBooleanType
6233       normalize;
6234
6235     RectangleInfo
6236       region;
6237
6238     register const Quantum
6239       *p;
6240
6241     register ssize_t
6242       i;
6243
6244     ssize_t
6245       option;
6246
6247     struct PackageInfo
6248       *info;
6249
6250     SV
6251       *perl_exception,
6252       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6253
6254     PERL_UNUSED_VAR(ref);
6255     PERL_UNUSED_VAR(ix);
6256     exception=AcquireExceptionInfo();
6257     perl_exception=newSVpv("",0);
6258     reference=SvRV(ST(0));
6259     av=(AV *) reference;
6260     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6261       exception);
6262     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6263     if (image == (Image *) NULL)
6264       {
6265         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6266           PackageName);
6267         goto PerlException;
6268       }
6269     normalize=MagickTrue;
6270     region.x=0;
6271     region.y=0;
6272     region.width=image->columns;
6273     region.height=1;
6274     if (items == 1)
6275       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6276     for (i=2; i < items; i+=2)
6277     {
6278       attribute=(char *) SvPV(ST(i-1),na);
6279       switch (*attribute)
6280       {
6281         case 'C':
6282         case 'c':
6283         {
6284           if (LocaleCompare(attribute,"channel") == 0)
6285             {
6286               ssize_t
6287                 option;
6288
6289               option=ParseChannelOption(SvPV(ST(i),na));
6290               if (option < 0)
6291                 {
6292                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6293                     SvPV(ST(i),na));
6294                   return;
6295                 }
6296               SetPixelChannelMask(image,(ChannelType) option);
6297               break;
6298             }
6299           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6300             attribute);
6301           break;
6302         }
6303         case 'g':
6304         case 'G':
6305         {
6306           if (LocaleCompare(attribute,"geometry") == 0)
6307             {
6308               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6309               break;
6310             }
6311           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6312             attribute);
6313           break;
6314         }
6315         case 'N':
6316         case 'n':
6317         {
6318           if (LocaleCompare(attribute,"normalize") == 0)
6319             {
6320               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6321                 SvPV(ST(i),na));
6322               if (option < 0)
6323                 {
6324                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6325                     SvPV(ST(i),na));
6326                   break;
6327                 }
6328              normalize=option != 0 ? MagickTrue : MagickFalse;
6329              break;
6330             }
6331           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6332             attribute);
6333           break;
6334         }
6335         case 'x':
6336         case 'X':
6337         {
6338           if (LocaleCompare(attribute,"x") == 0)
6339             {
6340               region.x=SvIV(ST(i));
6341               break;
6342             }
6343           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6344             attribute);
6345           break;
6346         }
6347         case 'y':
6348         case 'Y':
6349         {
6350           if (LocaleCompare(attribute,"y") == 0)
6351             {
6352               region.y=SvIV(ST(i));
6353               break;
6354             }
6355           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6356             attribute);
6357           break;
6358         }
6359         default:
6360         {
6361           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6362             attribute);
6363           break;
6364         }
6365       }
6366     }
6367     p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6368     if (p == (const Quantum *) NULL)
6369       PUSHs(&sv_undef);
6370     else
6371       {
6372         double
6373           scale;
6374
6375         scale=1.0;
6376         if (normalize != MagickFalse)
6377           scale=1.0/QuantumRange;
6378         if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
6379           PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6380         if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6381           PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6382         if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6383           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6384         if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6385             (image->colorspace == CMYKColorspace))
6386           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6387         if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
6388           PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6389       }
6390
6391   PerlException:
6392     InheritPerlException(exception,perl_exception);
6393     exception=DestroyExceptionInfo(exception);
6394     SvREFCNT_dec(perl_exception);
6395   }
6396 \f
6397 #
6398 ###############################################################################
6399 #                                                                             #
6400 #                                                                             #
6401 #                                                                             #
6402 #   G e t P i x e l s                                                         #
6403 #                                                                             #
6404 #                                                                             #
6405 #                                                                             #
6406 ###############################################################################
6407 #
6408 #
6409 void
6410 GetPixels(ref,...)
6411   Image::Magick ref=NO_INIT
6412   ALIAS:
6413     getpixels = 1
6414     getPixels = 2
6415   PPCODE:
6416   {
6417     AV
6418       *av;
6419
6420     char
6421       *attribute;
6422
6423     const char
6424       *map;
6425
6426     ExceptionInfo
6427       *exception;
6428
6429     Image
6430       *image;
6431
6432     MagickBooleanType
6433       normalize,
6434       status;
6435
6436     RectangleInfo
6437       region;
6438
6439     register ssize_t
6440       i;
6441
6442     ssize_t
6443       option;
6444
6445     struct PackageInfo
6446       *info;
6447
6448     SV
6449       *perl_exception,
6450       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6451
6452     PERL_UNUSED_VAR(ref);
6453     PERL_UNUSED_VAR(ix);
6454     exception=AcquireExceptionInfo();
6455     perl_exception=newSVpv("",0);
6456     reference=SvRV(ST(0));
6457     av=(AV *) reference;
6458     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6459       exception);
6460     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6461     if (image == (Image *) NULL)
6462       {
6463         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6464           PackageName);
6465         goto PerlException;
6466       }
6467     map="RGB";
6468     if (image->alpha_trait == BlendPixelTrait)
6469       map="RGBA";
6470     if (image->colorspace == CMYKColorspace)
6471       {
6472         map="CMYK";
6473         if (image->alpha_trait == BlendPixelTrait)
6474           map="CMYKA";
6475       }
6476     normalize=MagickFalse;
6477     region.x=0;
6478     region.y=0;
6479     region.width=image->columns;
6480     region.height=1;
6481     if (items == 1)
6482       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6483     for (i=2; i < items; i+=2)
6484     {
6485       attribute=(char *) SvPV(ST(i-1),na);
6486       switch (*attribute)
6487       {
6488         case 'g':
6489         case 'G':
6490         {
6491           if (LocaleCompare(attribute,"geometry") == 0)
6492             {
6493               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6494               break;
6495             }
6496           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6497             attribute);
6498           break;
6499         }
6500         case 'H':
6501         case 'h':
6502         {
6503           if (LocaleCompare(attribute,"height") == 0)
6504             {
6505               region.height=SvIV(ST(i));
6506               break;
6507             }
6508           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6509             attribute);
6510           break;
6511         }
6512         case 'M':
6513         case 'm':
6514         {
6515           if (LocaleCompare(attribute,"map") == 0)
6516             {
6517               map=SvPV(ST(i),na);
6518               break;
6519             }
6520           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6521             attribute);
6522           break;
6523         }
6524         case 'N':
6525         case 'n':
6526         {
6527           if (LocaleCompare(attribute,"normalize") == 0)
6528             {
6529               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6530                 SvPV(ST(i),na));
6531               if (option < 0)
6532                 {
6533                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6534                     SvPV(ST(i),na));
6535                   break;
6536                 }
6537              normalize=option != 0 ? MagickTrue : MagickFalse;
6538              break;
6539             }
6540           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6541             attribute);
6542           break;
6543         }
6544         case 'W':
6545         case 'w':
6546         {
6547           if (LocaleCompare(attribute,"width") == 0)
6548             {
6549               region.width=SvIV(ST(i));
6550               break;
6551             }
6552           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6553             attribute);
6554           break;
6555         }
6556         case 'x':
6557         case 'X':
6558         {
6559           if (LocaleCompare(attribute,"x") == 0)
6560             {
6561               region.x=SvIV(ST(i));
6562               break;
6563             }
6564           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6565             attribute);
6566           break;
6567         }
6568         case 'y':
6569         case 'Y':
6570         {
6571           if (LocaleCompare(attribute,"y") == 0)
6572             {
6573               region.y=SvIV(ST(i));
6574               break;
6575             }
6576           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6577             attribute);
6578           break;
6579         }
6580         default:
6581         {
6582           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6583             attribute);
6584           break;
6585         }
6586       }
6587     }
6588     if (normalize != MagickFalse)
6589       {
6590         float
6591           *pixels;
6592
6593         pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6594           region.height*sizeof(*pixels));
6595         if (pixels == (float *) NULL)
6596           {
6597             ThrowPerlException(exception,ResourceLimitError,
6598               "MemoryAllocationFailed",PackageName);
6599             goto PerlException;
6600           }
6601         status=ExportImagePixels(image,region.x,region.y,region.width,
6602           region.height,map,FloatPixel,pixels,exception);
6603         if (status == MagickFalse)
6604           PUSHs(&sv_undef);
6605         else
6606           {
6607             EXTEND(sp,strlen(map)*region.width*region.height);
6608             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6609               PUSHs(sv_2mortal(newSVnv(pixels[i])));
6610           }
6611         pixels=(float *) RelinquishMagickMemory(pixels);
6612       }
6613     else
6614       {
6615         Quantum
6616           *pixels;
6617
6618         pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6619           region.height*sizeof(*pixels));
6620         if (pixels == (Quantum *) NULL)
6621           {
6622             ThrowPerlException(exception,ResourceLimitError,
6623               "MemoryAllocationFailed",PackageName);
6624             goto PerlException;
6625           }
6626         status=ExportImagePixels(image,region.x,region.y,region.width,
6627           region.height,map,QuantumPixel,pixels,exception);
6628         if (status == MagickFalse)
6629           PUSHs(&sv_undef);
6630         else
6631           {
6632             EXTEND(sp,strlen(map)*region.width*region.height);
6633             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6634               PUSHs(sv_2mortal(newSViv(pixels[i])));
6635           }
6636         pixels=(Quantum *) RelinquishMagickMemory(pixels);
6637       }
6638
6639   PerlException:
6640     InheritPerlException(exception,perl_exception);
6641     exception=DestroyExceptionInfo(exception);
6642     SvREFCNT_dec(perl_exception);
6643   }
6644 \f
6645 #
6646 ###############################################################################
6647 #                                                                             #
6648 #                                                                             #
6649 #                                                                             #
6650 #   I m a g e T o B l o b                                                     #
6651 #                                                                             #
6652 #                                                                             #
6653 #                                                                             #
6654 ###############################################################################
6655 #
6656 #
6657 void
6658 ImageToBlob(ref,...)
6659   Image::Magick ref=NO_INIT
6660   ALIAS:
6661     ImageToBlob  = 1
6662     imagetoblob  = 2
6663     toblob       = 3
6664     blob         = 4
6665   PPCODE:
6666   {
6667     char
6668       filename[MaxTextExtent];
6669
6670     ExceptionInfo
6671       *exception;
6672
6673     Image
6674       *image,
6675       *next;
6676
6677     register ssize_t
6678       i;
6679
6680     struct PackageInfo
6681       *info,
6682       *package_info;
6683
6684     size_t
6685       length;
6686
6687     ssize_t
6688       scene;
6689
6690     SV
6691       *perl_exception,
6692       *reference;
6693
6694     void
6695       *blob;
6696
6697     PERL_UNUSED_VAR(ref);
6698     PERL_UNUSED_VAR(ix);
6699     exception=AcquireExceptionInfo();
6700     perl_exception=newSVpv("",0);
6701     package_info=(struct PackageInfo *) NULL;
6702     if (sv_isobject(ST(0)) == 0)
6703       {
6704         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6705           PackageName);
6706         goto PerlException;
6707       }
6708     reference=SvRV(ST(0));
6709     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6710     if (image == (Image *) NULL)
6711       {
6712         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6713           PackageName);
6714         goto PerlException;
6715       }
6716     package_info=ClonePackageInfo(info,exception);
6717     for (i=2; i < items; i+=2)
6718       SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6719     (void) CopyMagickString(filename,package_info->image_info->filename,
6720       MaxTextExtent);
6721     scene=0;
6722     for (next=image; next; next=next->next)
6723     {
6724       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
6725       next->scene=scene++;
6726     }
6727     SetImageInfo(package_info->image_info,(unsigned int)
6728       GetImageListLength(image),exception);
6729     EXTEND(sp,(ssize_t) GetImageListLength(image));
6730     for ( ; image; image=image->next)
6731     {
6732       length=0;
6733       blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6734       if (blob != (char *) NULL)
6735         {
6736           PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6737           blob=(unsigned char *) RelinquishMagickMemory(blob);
6738         }
6739       if (package_info->image_info->adjoin)
6740         break;
6741     }
6742
6743   PerlException:
6744     if (package_info != (struct PackageInfo *) NULL)
6745       DestroyPackageInfo(package_info);
6746     InheritPerlException(exception,perl_exception);
6747     exception=DestroyExceptionInfo(exception);
6748     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6749   }
6750 \f
6751 #
6752 ###############################################################################
6753 #                                                                             #
6754 #                                                                             #
6755 #                                                                             #
6756 #   L a y e r s                                                               #
6757 #                                                                             #
6758 #                                                                             #
6759 #                                                                             #
6760 ###############################################################################
6761 #
6762 #
6763 void
6764 Layers(ref,...)
6765   Image::Magick ref=NO_INIT
6766   ALIAS:
6767     Layers                = 1
6768     layers           = 2
6769     OptimizeImageLayers   = 3
6770     optimizelayers        = 4
6771     optimizeimagelayers   = 5
6772   PPCODE:
6773   {
6774     AV
6775       *av;
6776
6777     char
6778       *attribute;
6779
6780     CompositeOperator
6781       compose;
6782
6783     ExceptionInfo
6784       *exception;
6785
6786     HV
6787       *hv;
6788
6789     Image
6790       *image,
6791       *layers;
6792
6793     LayerMethod
6794       method;
6795
6796     register ssize_t
6797       i;
6798
6799     ssize_t
6800       option,
6801       sp;
6802
6803     struct PackageInfo
6804       *info;
6805
6806     SV
6807       *av_reference,
6808       *perl_exception,
6809       *reference,
6810       *rv,
6811       *sv;
6812
6813     PERL_UNUSED_VAR(ref);
6814     PERL_UNUSED_VAR(ix);
6815     exception=AcquireExceptionInfo();
6816     perl_exception=newSVpv("",0);
6817     sv=NULL;
6818     if (sv_isobject(ST(0)) == 0)
6819       {
6820         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6821           PackageName);
6822         goto PerlException;
6823       }
6824     reference=SvRV(ST(0));
6825     hv=SvSTASH(reference);
6826     av=newAV();
6827     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
6828     SvREFCNT_dec(av);
6829     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6830     if (image == (Image *) NULL)
6831       {
6832         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6833           PackageName);
6834         goto PerlException;
6835       }
6836     compose=image->compose;
6837     method=OptimizeLayer;
6838     for (i=2; i < items; i+=2)
6839     {
6840       attribute=(char *) SvPV(ST(i-1),na);
6841       switch (*attribute)
6842       {
6843         case 'C':
6844         case 'c':
6845         {
6846           if (LocaleCompare(attribute,"compose") == 0)
6847             {
6848               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
6849                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
6850               if (sp < 0)
6851                 {
6852                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6853                     SvPV(ST(i),na));
6854                   break;
6855                 }
6856               compose=(CompositeOperator) sp;
6857               break;
6858             }
6859           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6860             attribute);
6861           break;
6862         }
6863         case 'M':
6864         case 'm':
6865         {
6866           if (LocaleCompare(attribute,"method") == 0)
6867             {
6868               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
6869                 SvPV(ST(i),na));
6870               if (option < 0)
6871                 {
6872                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6873                     SvPV(ST(i),na));
6874                   break;
6875                 }
6876               method=(LayerMethod) option;
6877               break;
6878             }
6879           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6880             attribute);
6881           break;
6882         }
6883         default:
6884         {
6885           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6886             attribute);
6887           break;
6888         }
6889       }
6890     }
6891     layers=(Image *) NULL;
6892     switch (method)
6893     {
6894       case CompareAnyLayer:
6895       case CompareClearLayer:
6896       case CompareOverlayLayer:
6897       default:
6898       {
6899         layers=CompareImagesLayers(image,method,exception);
6900         break;
6901       }
6902       case MergeLayer:
6903       case FlattenLayer:
6904       case MosaicLayer:
6905       {
6906         layers=MergeImageLayers(image,method,exception);
6907         break;
6908       }
6909       case DisposeLayer:
6910       {
6911         layers=DisposeImages(image,exception);
6912         break;
6913       }
6914       case OptimizeImageLayer:
6915       {
6916         layers=OptimizeImageLayers(image,exception);
6917         break;
6918       }
6919       case OptimizePlusLayer:
6920       {
6921         layers=OptimizePlusImageLayers(image,exception);
6922         break;
6923       }
6924       case OptimizeTransLayer:
6925       {
6926         OptimizeImageTransparency(image,exception);
6927         break;
6928       }
6929       case RemoveDupsLayer:
6930       {
6931         RemoveDuplicateLayers(&image,exception);
6932         break;
6933       }
6934       case RemoveZeroLayer:
6935       {
6936         RemoveZeroDelayLayers(&image,exception);
6937         break;
6938       }
6939       case OptimizeLayer:
6940       {
6941         QuantizeInfo
6942           *quantize_info;
6943
6944         /*
6945           General Purpose, GIF Animation Optimizer.
6946         */
6947         layers=CoalesceImages(image,exception);
6948         if (layers == (Image *) NULL)
6949           break;
6950         image=layers;
6951         layers=OptimizeImageLayers(image,exception);
6952         if (layers == (Image *) NULL)
6953           break;
6954         image=DestroyImageList(image);
6955         image=layers;
6956         layers=(Image *) NULL;
6957         OptimizeImageTransparency(image,exception);
6958         quantize_info=AcquireQuantizeInfo(info->image_info);
6959         (void) RemapImages(quantize_info,image,(Image *) NULL,exception);
6960         quantize_info=DestroyQuantizeInfo(quantize_info);
6961         break;
6962       }
6963       case CompositeLayer:
6964       {
6965         Image
6966           *source;
6967
6968         RectangleInfo
6969           geometry;
6970
6971         /*
6972           Split image sequence at the first 'NULL:' image.
6973         */
6974         source=image;
6975         while (source != (Image *) NULL)
6976         {
6977           source=GetNextImageInList(source);
6978           if ((source != (Image *) NULL) &&
6979               (LocaleCompare(source->magick,"NULL") == 0))
6980             break;
6981         }
6982         if (source != (Image *) NULL)
6983           {
6984             if ((GetPreviousImageInList(source) == (Image *) NULL) ||
6985                 (GetNextImageInList(source) == (Image *) NULL))
6986               source=(Image *) NULL;
6987             else
6988               {
6989                 /*
6990                   Separate the two lists, junk the null: image.
6991                 */
6992                 source=SplitImageList(source->previous);
6993                 DeleteImageFromList(&source);
6994               }
6995           }
6996         if (source == (Image *) NULL)
6997           {
6998             (void) ThrowMagickException(exception,GetMagickModule(),
6999               OptionError,"MissingNullSeparator","layers Composite");
7000             break;
7001           }
7002         /*
7003           Adjust offset with gravity and virtual canvas.
7004         */
7005         SetGeometry(image,&geometry);
7006         (void) ParseAbsoluteGeometry(image->geometry,&geometry);
7007         geometry.width=source->page.width != 0 ? source->page.width :
7008           source->columns;
7009         geometry.height=source->page.height != 0 ? source->page.height :
7010           source->rows;
7011         GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
7012           image->columns,image->page.height != 0 ? image->page.height :
7013           image->rows,image->gravity,&geometry);
7014         CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
7015         source=DestroyImageList(source);
7016         break;
7017       }
7018     }
7019     if (layers != (Image *) NULL)
7020       image=layers;
7021     if (image == (Image *) NULL)
7022       goto PerlException;
7023     for ( ; image; image=image->next)
7024     {
7025       AddImageToRegistry(sv,image);
7026       rv=newRV(sv);
7027       av_push(av,sv_bless(rv,hv));
7028       SvREFCNT_dec(sv);
7029     }
7030     exception=DestroyExceptionInfo(exception);
7031     ST(0)=av_reference;
7032     SvREFCNT_dec(perl_exception);
7033     XSRETURN(1);
7034
7035   PerlException:
7036     InheritPerlException(exception,perl_exception);
7037     exception=DestroyExceptionInfo(exception);
7038     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
7039     SvPOK_on(perl_exception);
7040     ST(0)=sv_2mortal(perl_exception);
7041     XSRETURN(1);
7042   }
7043 \f
7044 #
7045 ###############################################################################
7046 #                                                                             #
7047 #                                                                             #
7048 #                                                                             #
7049 #   M a g i c k T o M i m e                                                   #
7050 #                                                                             #
7051 #                                                                             #
7052 #                                                                             #
7053 ###############################################################################
7054 #
7055 #
7056 SV *
7057 MagickToMime(ref,name)
7058   Image::Magick ref=NO_INIT
7059   char *name
7060   ALIAS:
7061     magicktomime = 1
7062   CODE:
7063   {
7064     char
7065       *mime;
7066
7067     PERL_UNUSED_VAR(ref);
7068     PERL_UNUSED_VAR(ix);
7069     mime=MagickToMime(name);
7070     RETVAL=newSVpv(mime,0);
7071     mime=(char *) RelinquishMagickMemory(mime);
7072   }
7073   OUTPUT:
7074     RETVAL
7075 \f
7076 #
7077 ###############################################################################
7078 #                                                                             #
7079 #                                                                             #
7080 #                                                                             #
7081 #   M o g r i f y                                                             #
7082 #                                                                             #
7083 #                                                                             #
7084 #                                                                             #
7085 ###############################################################################
7086 #
7087 #
7088 void
7089 Mogrify(ref,...)
7090   Image::Magick ref=NO_INIT
7091   ALIAS:
7092     Comment            =   1
7093     CommentImage       =   2
7094     Label              =   3
7095     LabelImage         =   4
7096     AddNoise           =   5
7097     AddNoiseImage      =   6
7098     Colorize           =   7
7099     ColorizeImage      =   8
7100     Border             =   9
7101     BorderImage        =  10
7102     Blur               =  11
7103     BlurImage          =  12
7104     Chop               =  13
7105     ChopImage          =  14
7106     Crop               =  15
7107     CropImage          =  16
7108     Despeckle          =  17
7109     DespeckleImage     =  18
7110     Edge               =  19
7111     EdgeImage          =  20
7112     Emboss             =  21
7113     EmbossImage        =  22
7114     Enhance            =  23
7115     EnhanceImage       =  24
7116     Flip               =  25
7117     FlipImage          =  26
7118     Flop               =  27
7119     FlopImage          =  28
7120     Frame              =  29
7121     FrameImage         =  30
7122     Implode            =  31
7123     ImplodeImage       =  32
7124     Magnify            =  33
7125     MagnifyImage       =  34
7126     MedianFilter       =  35
7127     MedianConvolveImage  =  36
7128     Minify             =  37
7129     MinifyImage        =  38
7130     OilPaint           =  39
7131     OilPaintImage      =  40
7132     ReduceNoise        =  41
7133     ReduceNoiseImage   =  42
7134     Roll               =  43
7135     RollImage          =  44
7136     Rotate             =  45
7137     RotateImage        =  46
7138     Sample             =  47
7139     SampleImage        =  48
7140     Scale              =  49
7141     ScaleImage         =  50
7142     Shade              =  51
7143     ShadeImage         =  52
7144     Sharpen            =  53
7145     SharpenImage       =  54
7146     Shear              =  55
7147     ShearImage         =  56
7148     Spread             =  57
7149     SpreadImage        =  58
7150     Swirl              =  59
7151     SwirlImage         =  60
7152     Resize             =  61
7153     ResizeImage        =  62
7154     Zoom               =  63
7155     ZoomImage          =  64
7156     Annotate           =  65
7157     AnnotateImage      =  66
7158     ColorFloodfill     =  67
7159     ColorFloodfillImage=  68
7160     Composite          =  69
7161     CompositeImage     =  70
7162     Contrast           =  71
7163     ContrastImage      =  72
7164     CycleColormap      =  73
7165     CycleColormapImage =  74
7166     Draw               =  75
7167     DrawImage          =  76
7168     Equalize           =  77
7169     EqualizeImage      =  78
7170     Gamma              =  79
7171     GammaImage         =  80
7172     Map                =  81
7173     MapImage           =  82
7174     MatteFloodfill     =  83
7175     MatteFloodfillImage=  84
7176     Modulate           =  85
7177     ModulateImage      =  86
7178     Negate             =  87
7179     NegateImage        =  88
7180     Normalize          =  89
7181     NormalizeImage     =  90
7182     NumberColors       =  91
7183     NumberColorsImage  =  92
7184     Opaque             =  93
7185     OpaqueImage        =  94
7186     Quantize           =  95
7187     QuantizeImage      =  96
7188     Raise              =  97
7189     RaiseImage         =  98
7190     Segment            =  99
7191     SegmentImage       = 100
7192     Signature          = 101
7193     SignatureImage     = 102
7194     Solarize           = 103
7195     SolarizeImage      = 104
7196     Sync               = 105
7197     SyncImage          = 106
7198     Texture            = 107
7199     TextureImage       = 108
7200     Evaluate           = 109
7201     EvaluateImage      = 110
7202     Transparent        = 111
7203     TransparentImage   = 112
7204     Threshold          = 113
7205     ThresholdImage     = 114
7206     Charcoal           = 115
7207     CharcoalImage      = 116
7208     Trim               = 117
7209     TrimImage          = 118
7210     Wave               = 119
7211     WaveImage          = 120
7212     Separate           = 121
7213     SeparateImage      = 122
7214     Stereo             = 125
7215     StereoImage        = 126
7216     Stegano            = 127
7217     SteganoImage       = 128
7218     Deconstruct        = 129
7219     DeconstructImage   = 130
7220     GaussianBlur       = 131
7221     GaussianBlurImage  = 132
7222     Convolve           = 133
7223     ConvolveImage      = 134
7224     Profile            = 135
7225     ProfileImage       = 136
7226     UnsharpMask        = 137
7227     UnsharpMaskImage   = 138
7228     MotionBlur         = 139
7229     MotionBlurImage    = 140
7230     OrderedDither      = 141
7231     OrderedDitherImage = 142
7232     Shave              = 143
7233     ShaveImage         = 144
7234     Level              = 145
7235     LevelImage         = 146
7236     Clip               = 147
7237     ClipImage          = 148
7238     AffineTransform    = 149
7239     AffineTransformImage = 150
7240     Difference         = 151
7241     DifferenceImage    = 152
7242     AdaptiveThreshold  = 153
7243     AdaptiveThresholdImage = 154
7244     Resample           = 155
7245     ResampleImage      = 156
7246     Describe           = 157
7247     DescribeImage      = 158
7248     BlackThreshold     = 159
7249     BlackThresholdImage= 160
7250     WhiteThreshold     = 161
7251     WhiteThresholdImage= 162
7252     RadialBlur         = 163
7253     RadialBlurImage    = 164
7254     Thumbnail          = 165
7255     ThumbnailImage     = 166
7256     Strip              = 167
7257     StripImage         = 168
7258     Tint               = 169
7259     TintImage          = 170
7260     Channel            = 171
7261     ChannelImage       = 172
7262     Splice             = 173
7263     SpliceImage        = 174
7264     Posterize          = 175
7265     PosterizeImage     = 176
7266     Shadow             = 177
7267     ShadowImage        = 178
7268     Identify           = 179
7269     IdentifyImage      = 180
7270     SepiaTone          = 181
7271     SepiaToneImage     = 182
7272     SigmoidalContrast  = 183
7273     SigmoidalContrastImage = 184
7274     Extent             = 185
7275     ExtentImage        = 186
7276     Vignette           = 187
7277     VignetteImage      = 188
7278     ContrastStretch    = 189
7279     ContrastStretchImage = 190
7280     Sans0              = 191
7281     Sans0Image         = 192
7282     Sans1              = 193
7283     Sans1Image         = 194
7284     AdaptiveSharpen    = 195
7285     AdaptiveSharpenImage = 196
7286     Transpose          = 197
7287     TransposeImage     = 198
7288     Transverse         = 199
7289     TransverseImage    = 200
7290     AutoOrient         = 201
7291     AutoOrientImage    = 202
7292     AdaptiveBlur       = 203
7293     AdaptiveBlurImage  = 204
7294     Sketch             = 205
7295     SketchImage        = 206
7296     UniqueColors       = 207
7297     UniqueColorsImage  = 208
7298     AdaptiveResize     = 209
7299     AdaptiveResizeImage= 210
7300     ClipMask           = 211
7301     ClipMaskImage      = 212
7302     LinearStretch      = 213
7303     LinearStretchImage = 214
7304     ColorMatrix        = 215
7305     ColorMatrixImage   = 216
7306     Mask               = 217
7307     MaskImage          = 218
7308     Polaroid           = 219
7309     PolaroidImage      = 220
7310     FloodfillPaint     = 221
7311     FloodfillPaintImage= 222
7312     Distort            = 223
7313     DistortImage       = 224
7314     Clut               = 225
7315     ClutImage          = 226
7316     LiquidRescale      = 227
7317     LiquidRescaleImage = 228
7318     Encipher           = 229
7319     EncipherImage      = 230
7320     Decipher           = 231
7321     DecipherImage      = 232
7322     Deskew             = 233
7323     DeskewImage        = 234
7324     Remap              = 235
7325     RemapImage         = 236
7326     SparseColor        = 237
7327     SparseColorImage   = 238
7328     Function           = 239
7329     FunctionImage      = 240
7330     SelectiveBlur      = 241
7331     SelectiveBlurImage = 242
7332     HaldClut           = 243
7333     HaldClutImage      = 244
7334     BlueShift          = 245
7335     BlueShiftImage     = 246
7336     ForwardFourierTransform  = 247
7337     ForwardFourierTransformImage = 248
7338     InverseFourierTransform = 249
7339     InverseFourierTransformImage = 250
7340     ColorDecisionList  = 251
7341     ColorDecisionListImage = 252
7342     AutoGamma          = 253
7343     AutoGammaImage     = 254
7344     AutoLevel          = 255
7345     AutoLevelImage     = 256
7346     LevelColors        = 257
7347     LevelImageColors   = 258
7348     Clamp              = 259
7349     ClampImage         = 260
7350     BrightnessContrast = 261
7351     BrightnessContrastImage = 262
7352     Morphology         = 263
7353     MorphologyImage    = 264
7354     Color              = 265
7355     ColorImage         = 266
7356     Mode               = 267
7357     ModeImage          = 268
7358     Statistic          = 269
7359     StatisticImage     = 270
7360     Perceptible        = 271
7361     PerceptibleImage   = 272
7362     Poly               = 273
7363     PolyImage          = 274
7364     MogrifyRegion      = 666
7365   PPCODE:
7366   {
7367     AffineMatrix
7368       affine,
7369       current;
7370
7371     char
7372       attribute_flag[MaxArguments],
7373       message[MaxTextExtent];
7374
7375     ChannelType
7376       channel,
7377       channel_mask;
7378
7379     CompositeOperator
7380       compose;
7381
7382     const char
7383       *attribute,
7384       *value;
7385
7386     double
7387       angle;
7388
7389     ExceptionInfo
7390       *exception;
7391
7392     GeometryInfo
7393       geometry_info;
7394
7395     Image
7396       *image,
7397       *next,
7398       *region_image;
7399
7400     MagickBooleanType
7401       status;
7402
7403     MagickStatusType
7404       flags;
7405
7406     PixelInfo
7407       fill_color;
7408
7409     RectangleInfo
7410       geometry,
7411       region_info;
7412
7413     register ssize_t
7414       i;
7415
7416     ssize_t
7417       base,
7418       j,
7419       number_images;
7420
7421     struct Methods
7422       *rp;
7423
7424     struct PackageInfo
7425       *info;
7426
7427     SV
7428       *perl_exception,
7429       **pv,
7430       *reference,
7431       **reference_vector;
7432
7433     struct ArgumentList
7434       argument_list[MaxArguments];
7435
7436     PERL_UNUSED_VAR(ref);
7437     PERL_UNUSED_VAR(ix);
7438     exception=AcquireExceptionInfo();
7439     perl_exception=newSVpv("",0);
7440     reference_vector=NULL;
7441     region_image=NULL;
7442     number_images=0;
7443     base=2;
7444     if (sv_isobject(ST(0)) == 0)
7445       {
7446         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7447           PackageName);
7448         goto PerlException;
7449       }
7450     reference=SvRV(ST(0));
7451     region_info.width=0;
7452     region_info.height=0;
7453     region_info.x=0;
7454     region_info.y=0;
7455     region_image=(Image *) NULL;
7456     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7457     if (ix && (ix != 666))
7458       {
7459         /*
7460           Called as Method(...)
7461         */
7462         ix=(ix+1)/2;
7463         rp=(&Methods[ix-1]);
7464         attribute=rp->name;
7465       }
7466     else
7467       {
7468         /*
7469           Called as Mogrify("Method",...)
7470         */
7471         attribute=(char *) SvPV(ST(1),na);
7472         if (ix)
7473           {
7474             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7475             attribute=(char *) SvPV(ST(2),na);
7476             base++;
7477           }
7478         for (rp=Methods; ; rp++)
7479         {
7480           if (rp >= EndOf(Methods))
7481             {
7482               ThrowPerlException(exception,OptionError,
7483                 "UnrecognizedPerlMagickMethod",attribute);
7484               goto PerlException;
7485             }
7486           if (strEQcase(attribute,rp->name))
7487             break;
7488         }
7489         ix=rp-Methods+1;
7490         base++;
7491       }
7492     if (image == (Image *) NULL)
7493       {
7494         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7495         goto PerlException;
7496       }
7497     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7498     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7499     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7500     {
7501       Arguments
7502         *pp,
7503         *qq;
7504
7505       ssize_t
7506         ssize_test;
7507
7508       struct ArgumentList
7509         *al;
7510
7511       SV
7512         *sv;
7513
7514       sv=NULL;
7515       ssize_test=0;
7516       pp=(Arguments *) NULL;
7517       qq=rp->arguments;
7518       if (i == items)
7519         {
7520           pp=rp->arguments,
7521           sv=ST(i-1);
7522         }
7523       else
7524         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7525         {
7526           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7527             break;
7528           if (strEQcase(attribute,qq->method) > ssize_test)
7529             {
7530               pp=qq;
7531               ssize_test=strEQcase(attribute,qq->method);
7532             }
7533         }
7534       if (pp == (Arguments *) NULL)
7535         {
7536           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7537             attribute);
7538           goto continue_outer_loop;
7539         }
7540       al=(&argument_list[pp-rp->arguments]);
7541       switch (pp->type)
7542       {
7543         case ArrayReference:
7544         {
7545           if (SvTYPE(sv) != SVt_RV)
7546             {
7547               (void) FormatLocaleString(message,MaxTextExtent,
7548                 "invalid %.60s value",pp->method);
7549               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7550               goto continue_outer_loop;
7551             }
7552           al->array_reference=SvRV(sv);
7553           break;
7554         }
7555         case RealReference:
7556         {
7557           al->real_reference=SvNV(sv);
7558           break;
7559         }
7560         case FileReference:
7561         {
7562           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7563           break;
7564         }
7565         case ImageReference:
7566         {
7567           if (!sv_isobject(sv) ||
7568               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7569                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7570             {
7571               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7572                 PackageName);
7573               goto PerlException;
7574             }
7575           break;
7576         }
7577         case IntegerReference:
7578         {
7579           al->integer_reference=SvIV(sv);
7580           break;
7581         }
7582         case StringReference:
7583         {
7584           al->string_reference=(char *) SvPV(sv,al->length);
7585           if (sv_isobject(sv))
7586             al->image_reference=SetupList(aTHX_ SvRV(sv),
7587               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7588           break;
7589         }
7590         default:
7591         {
7592           /*
7593             Is a string; look up name.
7594           */
7595           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7596             {
7597               al->string_reference=(char *) SvPV(sv,al->length);
7598               al->integer_reference=(-1);
7599               break;
7600             }
7601           al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7602             MagickFalse,SvPV(sv,na));
7603           if (pp->type == MagickChannelOptions)
7604             al->integer_reference=ParseChannelOption(SvPV(sv,na));
7605           if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7606             {
7607               (void) FormatLocaleString(message,MaxTextExtent,
7608                 "invalid %.60s value",pp->method);
7609               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7610               goto continue_outer_loop;
7611             }
7612           break;
7613         }
7614       }
7615       attribute_flag[pp-rp->arguments]++;
7616       continue_outer_loop: ;
7617     }
7618     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7619     pv=reference_vector;
7620     SetGeometryInfo(&geometry_info);
7621     channel=DefaultChannels;
7622     for (next=image; next; next=next->next)
7623     {
7624       image=next;
7625       SetGeometry(image,&geometry);
7626       if ((region_info.width*region_info.height) != 0)
7627         {
7628           region_image=image;
7629           image=CropImage(image,&region_info,exception);
7630         }
7631       switch (ix)
7632       {
7633         default:
7634         {
7635           (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double) ix);
7636           ThrowPerlException(exception,OptionError,
7637             "UnrecognizedPerlMagickMethod",message);
7638           goto PerlException;
7639         }
7640         case 1:  /* Comment */
7641         {
7642           if (attribute_flag[0] == 0)
7643             argument_list[0].string_reference=(char *) NULL;
7644           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7645             info ? info->image_info : (ImageInfo *) NULL,image,
7646             argument_list[0].string_reference,exception),exception);
7647           break;
7648         }
7649         case 2:  /* Label */
7650         {
7651           if (attribute_flag[0] == 0)
7652             argument_list[0].string_reference=(char *) NULL;
7653           (void) SetImageProperty(image,"label",InterpretImageProperties(
7654             info ? info->image_info : (ImageInfo *) NULL,image,
7655             argument_list[0].string_reference,exception),exception);
7656           break;
7657         }
7658         case 3:  /* AddNoise */
7659         {
7660           double
7661             attenuate;
7662
7663           if (attribute_flag[0] == 0)
7664             argument_list[0].integer_reference=UniformNoise;
7665           attenuate=1.0;
7666           if (attribute_flag[1] != 0)
7667             attenuate=argument_list[1].real_reference;
7668           if (attribute_flag[2] != 0)
7669             channel=(ChannelType) argument_list[2].integer_reference;
7670           channel_mask=SetImageChannelMask(image,channel);
7671           image=AddNoiseImage(image,(NoiseType)
7672             argument_list[0].integer_reference,attenuate,exception);
7673           if (image != (Image *) NULL)
7674             (void) SetImageChannelMask(image,channel_mask);
7675           break;
7676         }
7677         case 4:  /* Colorize */
7678         {
7679           PixelInfo
7680             target;
7681
7682           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
7683             0,0,&target,exception);
7684           if (attribute_flag[0] != 0)
7685             (void) QueryColorCompliance(argument_list[0].string_reference,
7686               AllCompliance,&target,exception);
7687           if (attribute_flag[1] == 0)
7688             argument_list[1].string_reference="100%";
7689           image=ColorizeImage(image,argument_list[1].string_reference,&target,
7690             exception);
7691           break;
7692         }
7693         case 5:  /* Border */
7694         {
7695           CompositeOperator
7696             compose;
7697
7698           geometry.width=0;
7699           geometry.height=0;
7700           if (attribute_flag[0] != 0)
7701             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7702               &geometry,exception);
7703           if (attribute_flag[1] != 0)
7704             geometry.width=argument_list[1].integer_reference;
7705           if (attribute_flag[2] != 0)
7706             geometry.height=argument_list[2].integer_reference;
7707           if (attribute_flag[3] != 0)
7708             QueryColorCompliance(argument_list[3].string_reference,
7709               AllCompliance,&image->border_color,exception);
7710           if (attribute_flag[4] != 0)
7711             QueryColorCompliance(argument_list[4].string_reference,
7712               AllCompliance,&image->border_color,exception);
7713           if (attribute_flag[5] != 0)
7714             QueryColorCompliance(argument_list[5].string_reference,
7715               AllCompliance,&image->border_color,exception);
7716           compose=image->compose;
7717           if (attribute_flag[6] != 0)
7718             compose=(CompositeOperator) argument_list[6].integer_reference;
7719           image=BorderImage(image,&geometry,compose,exception);
7720           break;
7721         }
7722         case 6:  /* Blur */
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=1.0;
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=SetImageChannelMask(image,channel);
7738           image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
7739             exception);
7740           if (image != (Image *) NULL)
7741             (void) SetImageChannelMask(image,channel_mask);
7742           break;
7743         }
7744         case 7:  /* Chop */
7745         {
7746           if (attribute_flag[0] != 0)
7747             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7748               &geometry,exception);
7749           if (attribute_flag[1] != 0)
7750             geometry.width=argument_list[1].integer_reference;
7751           if (attribute_flag[2] != 0)
7752             geometry.height=argument_list[2].integer_reference;
7753           if (attribute_flag[3] != 0)
7754             geometry.x=argument_list[3].integer_reference;
7755           if (attribute_flag[4] != 0)
7756             geometry.y=argument_list[4].integer_reference;
7757           image=ChopImage(image,&geometry,exception);
7758           break;
7759         }
7760         case 8:  /* Crop */
7761         {
7762           if (attribute_flag[6] != 0)
7763             image->gravity=(GravityType) argument_list[6].integer_reference;
7764           if (attribute_flag[0] != 0)
7765             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7766               &geometry,exception);
7767           if (attribute_flag[1] != 0)
7768             geometry.width=argument_list[1].integer_reference;
7769           if (attribute_flag[2] != 0)
7770             geometry.height=argument_list[2].integer_reference;
7771           if (attribute_flag[3] != 0)
7772             geometry.x=argument_list[3].integer_reference;
7773           if (attribute_flag[4] != 0)
7774             geometry.y=argument_list[4].integer_reference;
7775           if (attribute_flag[5] != 0)
7776             image->fuzz=StringToDoubleInterval(
7777               argument_list[5].string_reference,(double) QuantumRange+1.0);
7778           image=CropImage(image,&geometry,exception);
7779           break;
7780         }
7781         case 9:  /* Despeckle */
7782         {
7783           image=DespeckleImage(image,exception);
7784           break;
7785         }
7786         case 10:  /* Edge */
7787         {
7788           if (attribute_flag[0] != 0)
7789             geometry_info.rho=argument_list[0].real_reference;
7790           image=EdgeImage(image,geometry_info.rho,geometry_info.sigma,
7791             exception);
7792           break;
7793         }
7794         case 11:  /* Emboss */
7795         {
7796           if (attribute_flag[0] != 0)
7797             {
7798               flags=ParseGeometry(argument_list[0].string_reference,
7799                 &geometry_info);
7800               if ((flags & SigmaValue) == 0)
7801                 geometry_info.sigma=1.0;
7802             }
7803           if (attribute_flag[1] != 0)
7804             geometry_info.rho=argument_list[1].real_reference;
7805           if (attribute_flag[2] != 0)
7806             geometry_info.sigma=argument_list[2].real_reference;
7807           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
7808             exception);
7809           break;
7810         }
7811         case 12:  /* Enhance */
7812         {
7813           image=EnhanceImage(image,exception);
7814           break;
7815         }
7816         case 13:  /* Flip */
7817         {
7818           image=FlipImage(image,exception);
7819           break;
7820         }
7821         case 14:  /* Flop */
7822         {
7823           image=FlopImage(image,exception);
7824           break;
7825         }
7826         case 15:  /* Frame */
7827         {
7828           CompositeOperator
7829             compose;
7830
7831           FrameInfo
7832             frame_info;
7833
7834           if (attribute_flag[0] != 0)
7835             {
7836               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7837                 &geometry,exception);
7838               frame_info.width=geometry.width;
7839               frame_info.height=geometry.height;
7840               frame_info.outer_bevel=geometry.x;
7841               frame_info.inner_bevel=geometry.y;
7842             }
7843           if (attribute_flag[1] != 0)
7844             frame_info.width=argument_list[1].integer_reference;
7845           if (attribute_flag[2] != 0)
7846             frame_info.height=argument_list[2].integer_reference;
7847           if (attribute_flag[3] != 0)
7848             frame_info.inner_bevel=argument_list[3].integer_reference;
7849           if (attribute_flag[4] != 0)
7850             frame_info.outer_bevel=argument_list[4].integer_reference;
7851           if (attribute_flag[5] != 0)
7852             QueryColorCompliance(argument_list[5].string_reference,
7853               AllCompliance,&fill_color,exception);
7854           if (attribute_flag[6] != 0)
7855             QueryColorCompliance(argument_list[6].string_reference,
7856               AllCompliance,&fill_color,exception);
7857           frame_info.x=(ssize_t) frame_info.width;
7858           frame_info.y=(ssize_t) frame_info.height;
7859           frame_info.width=image->columns+2*frame_info.x;
7860           frame_info.height=image->rows+2*frame_info.y;
7861           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
7862             image->matte_color=fill_color;
7863           compose=image->compose;
7864           if (attribute_flag[7] != 0)
7865             compose=(CompositeOperator) argument_list[7].integer_reference;
7866           image=FrameImage(image,&frame_info,compose,exception);
7867           break;
7868         }
7869         case 16:  /* Implode */
7870         {
7871           PixelInterpolateMethod
7872             method;
7873
7874           if (attribute_flag[0] == 0)
7875             argument_list[0].real_reference=0.5;
7876           method=UndefinedInterpolatePixel;
7877           if (attribute_flag[1] != 0)
7878             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
7879           image=ImplodeImage(image,argument_list[0].real_reference,
7880             method,exception);
7881           break;
7882         }
7883         case 17:  /* Magnify */
7884         {
7885           image=MagnifyImage(image,exception);
7886           break;
7887         }
7888         case 18:  /* MedianFilter */
7889         {
7890           if (attribute_flag[0] != 0)
7891             {
7892               flags=ParseGeometry(argument_list[0].string_reference,
7893                 &geometry_info);
7894               if ((flags & SigmaValue) == 0)
7895                 geometry_info.sigma=geometry_info.rho;
7896             }
7897           if (attribute_flag[1] != 0)
7898             geometry_info.rho=argument_list[1].real_reference;
7899           if (attribute_flag[2] != 0)
7900             geometry_info.sigma=argument_list[2].real_reference;
7901           if (attribute_flag[3] != 0)
7902             channel=(ChannelType) argument_list[3].integer_reference;
7903           channel_mask=SetImageChannelMask(image,channel);
7904           image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
7905             (size_t) geometry_info.sigma,exception);
7906           if (image != (Image *) NULL)
7907             (void) SetImageChannelMask(image,channel_mask);
7908           break;
7909         }
7910         case 19:  /* Minify */
7911         {
7912           image=MinifyImage(image,exception);
7913           break;
7914         }
7915         case 20:  /* OilPaint */
7916         {
7917           if (attribute_flag[0] == 0)
7918             argument_list[0].real_reference=0.0;
7919           if (attribute_flag[1] == 0)
7920             argument_list[1].real_reference=1.0;
7921           image=OilPaintImage(image,argument_list[0].real_reference,
7922             argument_list[1].real_reference,exception);
7923           break;
7924         }
7925         case 21:  /* ReduceNoise */
7926         {
7927           if (attribute_flag[0] != 0)
7928             {
7929               flags=ParseGeometry(argument_list[0].string_reference,
7930                 &geometry_info);
7931               if ((flags & SigmaValue) == 0)
7932                 geometry_info.sigma=1.0;
7933             }
7934           if (attribute_flag[1] != 0)
7935             geometry_info.rho=argument_list[1].real_reference;
7936           if (attribute_flag[2] != 0)
7937             geometry_info.sigma=argument_list[2].real_reference;
7938           if (attribute_flag[3] != 0)
7939             channel=(ChannelType) argument_list[3].integer_reference;
7940           channel_mask=SetImageChannelMask(image,channel);
7941           image=StatisticImage(image,NonpeakStatistic,(size_t)
7942             geometry_info.rho,(size_t) geometry_info.sigma,exception);
7943           if (image != (Image *) NULL)
7944             (void) SetImageChannelMask(image,channel_mask);
7945           break;
7946         }
7947         case 22:  /* Roll */
7948         {
7949           if (attribute_flag[0] != 0)
7950             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7951               &geometry,exception);
7952           if (attribute_flag[1] != 0)
7953             geometry.x=argument_list[1].integer_reference;
7954           if (attribute_flag[2] != 0)
7955             geometry.y=argument_list[2].integer_reference;
7956           image=RollImage(image,geometry.x,geometry.y,exception);
7957           break;
7958         }
7959         case 23:  /* Rotate */
7960         {
7961           if (attribute_flag[0] == 0)
7962             argument_list[0].real_reference=90.0;
7963           if (attribute_flag[1] != 0)
7964             {
7965               QueryColorCompliance(argument_list[1].string_reference,
7966                 AllCompliance,&image->background_color,exception);
7967               if ((image->background_color.alpha_trait == BlendPixelTrait) &&
7968                   (image->alpha_trait != BlendPixelTrait))
7969                 (void) SetImageAlpha(image,OpaqueAlpha,exception);
7970             }
7971           image=RotateImage(image,argument_list[0].real_reference,exception);
7972           break;
7973         }
7974         case 24:  /* Sample */
7975         {
7976           if (attribute_flag[0] != 0)
7977             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7978               &geometry,exception);
7979           if (attribute_flag[1] != 0)
7980             geometry.width=argument_list[1].integer_reference;
7981           if (attribute_flag[2] != 0)
7982             geometry.height=argument_list[2].integer_reference;
7983           image=SampleImage(image,geometry.width,geometry.height,exception);
7984           break;
7985         }
7986         case 25:  /* Scale */
7987         {
7988           if (attribute_flag[0] != 0)
7989             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7990               &geometry,exception);
7991           if (attribute_flag[1] != 0)
7992             geometry.width=argument_list[1].integer_reference;
7993           if (attribute_flag[2] != 0)
7994             geometry.height=argument_list[2].integer_reference;
7995           image=ScaleImage(image,geometry.width,geometry.height,exception);
7996           break;
7997         }
7998         case 26:  /* Shade */
7999         {
8000           if (attribute_flag[0] != 0)
8001             {
8002               flags=ParseGeometry(argument_list[0].string_reference,
8003                 &geometry_info);
8004               if ((flags & SigmaValue) == 0)
8005                 geometry_info.sigma=0.0;
8006             }
8007           if (attribute_flag[1] != 0)
8008             geometry_info.rho=argument_list[1].real_reference;
8009           if (attribute_flag[2] != 0)
8010             geometry_info.sigma=argument_list[2].real_reference;
8011           image=ShadeImage(image,
8012             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8013             geometry_info.rho,geometry_info.sigma,exception);
8014           break;
8015         }
8016         case 27:  /* Sharpen */
8017         {
8018           if (attribute_flag[0] != 0)
8019             {
8020               flags=ParseGeometry(argument_list[0].string_reference,
8021                 &geometry_info);
8022               if ((flags & SigmaValue) == 0)
8023                 geometry_info.sigma=1.0;
8024             }
8025           if (attribute_flag[1] != 0)
8026             geometry_info.rho=argument_list[1].real_reference;
8027           if (attribute_flag[2] != 0)
8028             geometry_info.sigma=argument_list[2].real_reference;
8029           if (attribute_flag[3] != 0)
8030             channel=(ChannelType) argument_list[3].integer_reference;
8031           channel_mask=SetImageChannelMask(image,channel);
8032           image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
8033             exception);
8034           if (image != (Image *) NULL)
8035             (void) SetImageChannelMask(image,channel_mask);
8036           break;
8037         }
8038         case 28:  /* Shear */
8039         {
8040           if (attribute_flag[0] != 0)
8041             {
8042               flags=ParseGeometry(argument_list[0].string_reference,
8043                 &geometry_info);
8044               if ((flags & SigmaValue) == 0)
8045                 geometry_info.sigma=geometry_info.rho;
8046             }
8047           if (attribute_flag[1] != 0)
8048             geometry_info.rho=argument_list[1].real_reference;
8049           if (attribute_flag[2] != 0)
8050             geometry_info.sigma=argument_list[2].real_reference;
8051           if (attribute_flag[3] != 0)
8052             QueryColorCompliance(argument_list[3].string_reference,
8053               AllCompliance,&image->background_color,exception);
8054           if (attribute_flag[4] != 0)
8055             QueryColorCompliance(argument_list[4].string_reference,
8056               AllCompliance,&image->background_color,exception);
8057           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
8058             exception);
8059           break;
8060         }
8061         case 29:  /* Spread */
8062         {
8063           PixelInterpolateMethod
8064             method;
8065
8066           if (attribute_flag[0] == 0)
8067             argument_list[0].real_reference=1.0;
8068           method=UndefinedInterpolatePixel;
8069           if (attribute_flag[1] != 0)
8070             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8071           image=SpreadImage(image,argument_list[0].real_reference,method,
8072             exception);
8073           break;
8074         }
8075         case 30:  /* Swirl */
8076         {
8077           PixelInterpolateMethod
8078             method;
8079
8080           if (attribute_flag[0] == 0)
8081             argument_list[0].real_reference=50.0;
8082           method=UndefinedInterpolatePixel;
8083           if (attribute_flag[1] != 0)
8084             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8085           image=SwirlImage(image,argument_list[0].real_reference,
8086             method,exception);
8087           break;
8088         }
8089         case 31:  /* Resize */
8090         case 32:  /* Zoom */
8091         {
8092           if (attribute_flag[0] != 0)
8093             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8094               &geometry,exception);
8095           if (attribute_flag[1] != 0)
8096             geometry.width=argument_list[1].integer_reference;
8097           if (attribute_flag[2] != 0)
8098             geometry.height=argument_list[2].integer_reference;
8099           if (attribute_flag[3] == 0)
8100             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
8101           if (attribute_flag[4] != 0)
8102             SetImageArtifact(image,"filter:support",
8103               argument_list[4].string_reference);
8104           image=ResizeImage(image,geometry.width,geometry.height,
8105             (FilterTypes) argument_list[3].integer_reference,
8106             exception);
8107           break;
8108         }
8109         case 33:  /* Annotate */
8110         {
8111           DrawInfo
8112             *draw_info;
8113
8114           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8115             (DrawInfo *) NULL);
8116           if (attribute_flag[0] != 0)
8117             {
8118               char
8119                 *text;
8120
8121               text=InterpretImageProperties(info ? info->image_info :
8122                 (ImageInfo *) NULL,image,argument_list[0].string_reference,
8123                 exception);
8124               (void) CloneString(&draw_info->text,text);
8125               text=DestroyString(text);
8126             }
8127           if (attribute_flag[1] != 0)
8128             (void) CloneString(&draw_info->font,
8129               argument_list[1].string_reference);
8130           if (attribute_flag[2] != 0)
8131             draw_info->pointsize=argument_list[2].real_reference;
8132           if (attribute_flag[3] != 0)
8133             (void) CloneString(&draw_info->density,
8134               argument_list[3].string_reference);
8135           if (attribute_flag[4] != 0)
8136             (void) QueryColorCompliance(argument_list[4].string_reference,
8137               AllCompliance,&draw_info->undercolor,exception);
8138           if (attribute_flag[5] != 0)
8139             {
8140               (void) QueryColorCompliance(argument_list[5].string_reference,
8141                 AllCompliance,&draw_info->stroke,exception);
8142               if (argument_list[5].image_reference != (Image *) NULL)
8143                 draw_info->stroke_pattern=CloneImage(
8144                   argument_list[5].image_reference,0,0,MagickTrue,exception);
8145             }
8146           if (attribute_flag[6] != 0)
8147             {
8148               (void) QueryColorCompliance(argument_list[6].string_reference,
8149                 AllCompliance,&draw_info->fill,exception);
8150               if (argument_list[6].image_reference != (Image *) NULL)
8151                 draw_info->fill_pattern=CloneImage(
8152                   argument_list[6].image_reference,0,0,MagickTrue,exception);
8153             }
8154           if (attribute_flag[7] != 0)
8155             {
8156               (void) CloneString(&draw_info->geometry,
8157                 argument_list[7].string_reference);
8158               flags=ParsePageGeometry(image,argument_list[7].string_reference,
8159                 &geometry,exception);
8160               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8161                 geometry_info.sigma=geometry_info.xi;
8162             }
8163           if (attribute_flag[8] != 0)
8164             (void) QueryColorCompliance(argument_list[8].string_reference,
8165               AllCompliance,&draw_info->fill,exception);
8166           if (attribute_flag[11] != 0)
8167             draw_info->gravity=(GravityType)
8168               argument_list[11].integer_reference;
8169           if (attribute_flag[25] != 0)
8170             {
8171               AV
8172                 *av;
8173
8174               av=(AV *) argument_list[25].array_reference;
8175               if ((av_len(av) != 3) && (av_len(av) != 5))
8176                 {
8177                   ThrowPerlException(exception,OptionError,
8178                     "affine matrix must have 4 or 6 elements",PackageName);
8179                   goto PerlException;
8180                 }
8181               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8182               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8183               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8184               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8185               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8186                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8187                 {
8188                   ThrowPerlException(exception,OptionError,
8189                     "affine matrix is singular",PackageName);
8190                    goto PerlException;
8191                 }
8192               if (av_len(av) == 5)
8193                 {
8194                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8195                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8196                 }
8197             }
8198           for (j=12; j < 17; j++)
8199           {
8200             if (attribute_flag[j] == 0)
8201               continue;
8202             value=argument_list[j].string_reference;
8203             angle=argument_list[j].real_reference;
8204             current=draw_info->affine;
8205             GetAffineMatrix(&affine);
8206             switch (j)
8207             {
8208               case 12:
8209               {
8210                 /*
8211                   Translate.
8212                 */
8213                 flags=ParseGeometry(value,&geometry_info);
8214                 affine.tx=geometry_info.xi;
8215                 affine.ty=geometry_info.psi;
8216                 if ((flags & PsiValue) == 0)
8217                   affine.ty=affine.tx;
8218                 break;
8219               }
8220               case 13:
8221               {
8222                 /*
8223                   Scale.
8224                 */
8225                 flags=ParseGeometry(value,&geometry_info);
8226                 affine.sx=geometry_info.rho;
8227                 affine.sy=geometry_info.sigma;
8228                 if ((flags & SigmaValue) == 0)
8229                   affine.sy=affine.sx;
8230                 break;
8231               }
8232               case 14:
8233               {
8234                 /*
8235                   Rotate.
8236                 */
8237                 if (angle == 0.0)
8238                   break;
8239                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8240                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8241                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8242                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8243                 break;
8244               }
8245               case 15:
8246               {
8247                 /*
8248                   SkewX.
8249                 */
8250                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8251                 break;
8252               }
8253               case 16:
8254               {
8255                 /*
8256                   SkewY.
8257                 */
8258                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8259                 break;
8260               }
8261             }
8262             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8263             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8264             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8265             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8266             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8267               current.tx;
8268             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8269               current.ty;
8270           }
8271           if (attribute_flag[9] == 0)
8272             argument_list[9].real_reference=0.0;
8273           if (attribute_flag[10] == 0)
8274             argument_list[10].real_reference=0.0;
8275           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8276             {
8277               char
8278                 geometry[MaxTextExtent];
8279
8280               (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
8281                 (double) argument_list[9].real_reference+draw_info->affine.tx,
8282                 (double) argument_list[10].real_reference+draw_info->affine.ty);
8283               (void) CloneString(&draw_info->geometry,geometry);
8284             }
8285           if (attribute_flag[17] != 0)
8286             draw_info->stroke_width=argument_list[17].real_reference;
8287           if (attribute_flag[18] != 0)
8288             {
8289               draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8290                 MagickTrue : MagickFalse;
8291               draw_info->stroke_antialias=draw_info->text_antialias;
8292             }
8293           if (attribute_flag[19] != 0)
8294             (void) CloneString(&draw_info->family,
8295               argument_list[19].string_reference);
8296           if (attribute_flag[20] != 0)
8297             draw_info->style=(StyleType) argument_list[20].integer_reference;
8298           if (attribute_flag[21] != 0)
8299             draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8300           if (attribute_flag[22] != 0)
8301             draw_info->weight=argument_list[22].integer_reference;
8302           if (attribute_flag[23] != 0)
8303             draw_info->align=(AlignType) argument_list[23].integer_reference;
8304           if (attribute_flag[24] != 0)
8305             (void) CloneString(&draw_info->encoding,
8306               argument_list[24].string_reference);
8307           if (attribute_flag[25] != 0)
8308             draw_info->fill_pattern=CloneImage(
8309               argument_list[25].image_reference,0,0,MagickTrue,exception);
8310           if (attribute_flag[26] != 0)
8311             draw_info->fill_pattern=CloneImage(
8312               argument_list[26].image_reference,0,0,MagickTrue,exception);
8313           if (attribute_flag[27] != 0)
8314             draw_info->stroke_pattern=CloneImage(
8315               argument_list[27].image_reference,0,0,MagickTrue,exception);
8316           if (attribute_flag[29] != 0)
8317             draw_info->kerning=argument_list[29].real_reference;
8318           if (attribute_flag[30] != 0)
8319             draw_info->interline_spacing=argument_list[30].real_reference;
8320           if (attribute_flag[31] != 0)
8321             draw_info->interword_spacing=argument_list[31].real_reference;
8322           if (attribute_flag[32] != 0)
8323             draw_info->direction=(DirectionType)
8324               argument_list[32].integer_reference;
8325           (void) AnnotateImage(image,draw_info,exception);
8326           draw_info=DestroyDrawInfo(draw_info);
8327           break;
8328         }
8329         case 34:  /* ColorFloodfill */
8330         {
8331           DrawInfo
8332             *draw_info;
8333
8334           MagickBooleanType
8335             invert;
8336
8337           PixelInfo
8338             target;
8339
8340           draw_info=CloneDrawInfo(info ? info->image_info :
8341             (ImageInfo *) NULL,(DrawInfo *) NULL);
8342           if (attribute_flag[0] != 0)
8343             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8344               &geometry,exception);
8345           if (attribute_flag[1] != 0)
8346             geometry.x=argument_list[1].integer_reference;
8347           if (attribute_flag[2] != 0)
8348             geometry.y=argument_list[2].integer_reference;
8349           if (attribute_flag[3] != 0)
8350             (void) QueryColorCompliance(argument_list[3].string_reference,
8351               AllCompliance,&draw_info->fill,exception);
8352           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
8353             geometry.x,geometry.y,&target,exception);
8354           invert=MagickFalse;
8355           if (attribute_flag[4] != 0)
8356             {
8357               QueryColorCompliance(argument_list[4].string_reference,
8358                 AllCompliance,&target,exception);
8359               invert=MagickTrue;
8360             }
8361           if (attribute_flag[5] != 0)
8362             image->fuzz=StringToDoubleInterval(
8363               argument_list[5].string_reference,(double) QuantumRange+1.0);
8364           if (attribute_flag[6] != 0)
8365             invert=(MagickBooleanType) argument_list[6].integer_reference;
8366           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8367             geometry.y,invert,exception);
8368           draw_info=DestroyDrawInfo(draw_info);
8369           break;
8370         }
8371         case 35:  /* Composite */
8372         {
8373           char
8374             composite_geometry[MaxTextExtent];
8375
8376           Image
8377             *composite_image,
8378             *rotate_image;
8379
8380           MagickBooleanType
8381             clip_to_self;
8382
8383           compose=OverCompositeOp;
8384           if (attribute_flag[0] != 0)
8385             composite_image=argument_list[0].image_reference;
8386           else
8387             {
8388               ThrowPerlException(exception,OptionError,
8389                 "CompositeImageRequired",PackageName);
8390               goto PerlException;
8391             }
8392           /*
8393             Parameter Handling used for BOTH normal and tiled composition.
8394           */
8395           if (attribute_flag[1] != 0) /* compose */
8396             compose=(CompositeOperator) argument_list[1].integer_reference;
8397           if (attribute_flag[6] != 0) /* opacity  */
8398             {
8399               if (compose != DissolveCompositeOp)
8400                 (void) SetImageAlpha(composite_image,(Quantum)
8401                   StringToDoubleInterval(argument_list[6].string_reference,
8402                   (double) QuantumRange+1.0),exception);
8403               else
8404                 {
8405                   CacheView
8406                     *composite_view;
8407
8408                   double
8409                     opacity;
8410
8411                   MagickBooleanType
8412                     sync;
8413
8414                   register ssize_t
8415                     x;
8416
8417                   register Quantum
8418                     *q;
8419
8420                   ssize_t
8421                     y;
8422
8423                   /*
8424                     Handle dissolve composite operator (patch by
8425                     Kevin A. McGrail).
8426                   */
8427                   (void) CloneString(&image->geometry,
8428                     argument_list[6].string_reference);
8429                   opacity=(Quantum) StringToDoubleInterval(
8430                     argument_list[6].string_reference,(double) QuantumRange+
8431                     1.0);
8432                   if (composite_image->alpha_trait == BlendPixelTrait)
8433                     (void) SetImageAlpha(composite_image,OpaqueAlpha,exception);
8434                   composite_view=AcquireAuthenticCacheView(composite_image,
8435                     exception);
8436                   for (y=0; y < (ssize_t) composite_image->rows ; y++)
8437                   {
8438                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8439                       composite_image->columns,1,exception);
8440                     for (x=0; x < (ssize_t) composite_image->columns; x++)
8441                     {
8442                       if (GetPixelAlpha(image,q) == OpaqueAlpha)
8443                         SetPixelAlpha(composite_image,ClampToQuantum(opacity),
8444                           q);
8445                       q+=GetPixelChannels(composite_image);
8446                     }
8447                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8448                     if (sync == MagickFalse)
8449                       break;
8450                   }
8451                   composite_view=DestroyCacheView(composite_view);
8452                 }
8453             }
8454           if (attribute_flag[9] != 0)    /* "color=>" */
8455             QueryColorCompliance(argument_list[9].string_reference,
8456               AllCompliance,&composite_image->background_color,exception);
8457           if (attribute_flag[12] != 0) /* "interpolate=>" */
8458             image->interpolate=(PixelInterpolateMethod)
8459               argument_list[12].integer_reference;
8460           if (attribute_flag[13] != 0)   /* "args=>" */
8461             (void) SetImageArtifact(composite_image,"compose:args",
8462               argument_list[13].string_reference);
8463           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8464             (void) SetImageArtifact(composite_image,"compose:args",
8465               argument_list[14].string_reference);
8466           clip_to_self=MagickTrue;
8467           if (attribute_flag[15] != 0)
8468             clip_to_self=(MagickBooleanType)
8469               argument_list[15].integer_reference;
8470           /*
8471             Tiling Composition (with orthogonal rotate).
8472           */
8473           rotate_image=(Image *) NULL;
8474           if (attribute_flag[8] != 0)   /* "rotate=>" */
8475             {
8476                /*
8477                  Rotate image.
8478                */
8479                rotate_image=RotateImage(composite_image,
8480                  argument_list[8].real_reference,exception);
8481                if (rotate_image == (Image *) NULL)
8482                  break;
8483             }
8484           if ((attribute_flag[7] != 0) &&
8485               (argument_list[7].integer_reference != 0)) /* tile */
8486             {
8487               ssize_t
8488                 x,
8489                 y;
8490
8491               /*
8492                 Tile the composite image.
8493               */
8494              if (attribute_flag[8] != 0)   /* "tile=>" */
8495                (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8496                  "false");
8497              else
8498                (void) SetImageArtifact(composite_image,
8499                  "compose:outside-overlay","false");
8500              for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8501                 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8502                 {
8503                   if (attribute_flag[8] != 0) /* rotate */
8504                     (void) CompositeImage(image,rotate_image,compose,
8505                       MagickTrue,x,y,exception);
8506                   else
8507                     (void) CompositeImage(image,composite_image,compose,
8508                       MagickTrue,x,y,exception);
8509                 }
8510               if (attribute_flag[8] != 0) /* rotate */
8511                 rotate_image=DestroyImage(rotate_image);
8512               break;
8513             }
8514           /*
8515             Parameter Handling used used ONLY for normal composition.
8516           */
8517           if (attribute_flag[5] != 0) /* gravity */
8518             image->gravity=(GravityType) argument_list[5].integer_reference;
8519           if (attribute_flag[2] != 0) /* geometry offset */
8520             {
8521               SetGeometry(image,&geometry);
8522               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8523                 &geometry);
8524               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8525                 &geometry);
8526             }
8527           if (attribute_flag[3] != 0) /* x offset */
8528             geometry.x=argument_list[3].integer_reference;
8529           if (attribute_flag[4] != 0) /* y offset */
8530             geometry.y=argument_list[4].integer_reference;
8531           if (attribute_flag[10] != 0) /* mask */
8532             {
8533               if ((image->compose == DisplaceCompositeOp) ||
8534                   (image->compose == DistortCompositeOp))
8535                 {
8536                   /*
8537                     Merge Y displacement into X displacement image.
8538                   */
8539                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8540                     exception);
8541                   (void) CompositeImage(composite_image,
8542                     argument_list[10].image_reference,CopyGreenCompositeOp,
8543                     MagickTrue,0,0,exception);
8544                 }
8545               else
8546                 {
8547                   Image
8548                     *mask_image;
8549
8550                   /*
8551                     Set a blending mask for the composition.
8552                   */
8553                   mask_image=CloneImage(argument_list[10].image_reference,0,0,
8554                     MagickTrue,exception);
8555                   (void) NegateImage(mask_image,MagickFalse,exception);
8556                   (void) SetImageMask(composite_image,mask_image,exception);
8557                   mask_image=DestroyImage(mask_image);
8558                 }
8559             }
8560           if (attribute_flag[11] != 0) /* channel */
8561             channel=(ChannelType) argument_list[11].integer_reference;
8562           /*
8563             Composite two images (normal composition).
8564           */
8565           (void) FormatLocaleString(composite_geometry,MaxTextExtent,
8566             "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8567             (double) composite_image->rows,(double) geometry.x,(double)
8568             geometry.y);
8569           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8570             exception);
8571           channel_mask=SetImageChannelMask(image,channel);
8572           if (attribute_flag[8] == 0) /* no rotate */
8573             CompositeImage(image,composite_image,compose,clip_to_self,
8574               geometry.x,geometry.y,exception);
8575           else
8576             {
8577               /*
8578                 Position adjust rotated image then composite.
8579               */
8580               geometry.x-=(ssize_t) (rotate_image->columns-
8581                 composite_image->columns)/2;
8582               geometry.y-=(ssize_t) (rotate_image->rows-
8583                 composite_image->rows)/2;
8584               CompositeImage(image,rotate_image,compose,clip_to_self,geometry.x,
8585                 geometry.y,exception);
8586               rotate_image=DestroyImage(rotate_image);
8587             }
8588           if (attribute_flag[10] != 0) /* mask */
8589             {
8590               if ((image->compose == DisplaceCompositeOp) ||
8591                   (image->compose == DistortCompositeOp))
8592                 composite_image=DestroyImage(composite_image);
8593               else
8594                 (void) SetImageMask(image,(Image *) NULL,exception);
8595             }
8596           (void) SetImageChannelMask(image,channel_mask);
8597           break;
8598         }
8599         case 36:  /* Contrast */
8600         {
8601           if (attribute_flag[0] == 0)
8602             argument_list[0].integer_reference=0;
8603           (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8604             MagickTrue : MagickFalse,exception);
8605           break;
8606         }
8607         case 37:  /* CycleColormap */
8608         {
8609           if (attribute_flag[0] == 0)
8610             argument_list[0].integer_reference=6;
8611           (void) CycleColormapImage(image,argument_list[0].integer_reference,
8612             exception);
8613           break;
8614         }
8615         case 38:  /* Draw */
8616         {
8617           DrawInfo
8618             *draw_info;
8619
8620           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8621             (DrawInfo *) NULL);
8622           (void) CloneString(&draw_info->primitive,"point");
8623           if (attribute_flag[0] != 0)
8624             {
8625               if (argument_list[0].integer_reference < 0)
8626                 (void) CloneString(&draw_info->primitive,
8627                   argument_list[0].string_reference);
8628               else
8629                 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8630                   MagickPrimitiveOptions,argument_list[0].integer_reference));
8631             }
8632           if (attribute_flag[1] != 0)
8633             {
8634               if (LocaleCompare(draw_info->primitive,"path") == 0)
8635                 {
8636                   (void) ConcatenateString(&draw_info->primitive," '");
8637                   ConcatenateString(&draw_info->primitive,
8638                     argument_list[1].string_reference);
8639                   (void) ConcatenateString(&draw_info->primitive,"'");
8640                 }
8641               else
8642                 {
8643                   (void) ConcatenateString(&draw_info->primitive," ");
8644                   ConcatenateString(&draw_info->primitive,
8645                     argument_list[1].string_reference);
8646                 }
8647             }
8648           if (attribute_flag[2] != 0)
8649             {
8650               (void) ConcatenateString(&draw_info->primitive," ");
8651               (void) ConcatenateString(&draw_info->primitive,
8652                 CommandOptionToMnemonic(MagickMethodOptions,
8653                 argument_list[2].integer_reference));
8654             }
8655           if (attribute_flag[3] != 0)
8656             {
8657               (void) QueryColorCompliance(argument_list[3].string_reference,
8658                 AllCompliance,&draw_info->stroke,exception);
8659               if (argument_list[3].image_reference != (Image *) NULL)
8660                 draw_info->stroke_pattern=CloneImage(
8661                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8662             }
8663           if (attribute_flag[4] != 0)
8664             {
8665               (void) QueryColorCompliance(argument_list[4].string_reference,
8666                 AllCompliance,&draw_info->fill,exception);
8667               if (argument_list[4].image_reference != (Image *) NULL)
8668                 draw_info->fill_pattern=CloneImage(
8669                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8670             }
8671           if (attribute_flag[5] != 0)
8672             draw_info->stroke_width=argument_list[5].real_reference;
8673           if (attribute_flag[6] != 0)
8674             (void) CloneString(&draw_info->font,
8675               argument_list[6].string_reference);
8676           if (attribute_flag[7] != 0)
8677             (void) QueryColorCompliance(argument_list[7].string_reference,
8678               AllCompliance,&draw_info->border_color,exception);
8679           if (attribute_flag[8] != 0)
8680             draw_info->affine.tx=argument_list[8].real_reference;
8681           if (attribute_flag[9] != 0)
8682             draw_info->affine.ty=argument_list[9].real_reference;
8683           if (attribute_flag[20] != 0)
8684             {
8685               AV
8686                 *av;
8687
8688               av=(AV *) argument_list[20].array_reference;
8689               if ((av_len(av) != 3) && (av_len(av) != 5))
8690                 {
8691                   ThrowPerlException(exception,OptionError,
8692                     "affine matrix must have 4 or 6 elements",PackageName);
8693                   goto PerlException;
8694                 }
8695               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8696               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8697               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8698               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8699               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8700                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8701                 {
8702                   ThrowPerlException(exception,OptionError,
8703                     "affine matrix is singular",PackageName);
8704                    goto PerlException;
8705                 }
8706               if (av_len(av) == 5)
8707                 {
8708                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8709                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8710                 }
8711             }
8712           for (j=10; j < 15; j++)
8713           {
8714             if (attribute_flag[j] == 0)
8715               continue;
8716             value=argument_list[j].string_reference;
8717             angle=argument_list[j].real_reference;
8718             current=draw_info->affine;
8719             GetAffineMatrix(&affine);
8720             switch (j)
8721             {
8722               case 10:
8723               {
8724                 /*
8725                   Translate.
8726                 */
8727                 flags=ParseGeometry(value,&geometry_info);
8728                 affine.tx=geometry_info.xi;
8729                 affine.ty=geometry_info.psi;
8730                 if ((flags & PsiValue) == 0)
8731                   affine.ty=affine.tx;
8732                 break;
8733               }
8734               case 11:
8735               {
8736                 /*
8737                   Scale.
8738                 */
8739                 flags=ParseGeometry(value,&geometry_info);
8740                 affine.sx=geometry_info.rho;
8741                 affine.sy=geometry_info.sigma;
8742                 if ((flags & SigmaValue) == 0)
8743                   affine.sy=affine.sx;
8744                 break;
8745               }
8746               case 12:
8747               {
8748                 /*
8749                   Rotate.
8750                 */
8751                 if (angle == 0.0)
8752                   break;
8753                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8754                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8755                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8756                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8757                 break;
8758               }
8759               case 13:
8760               {
8761                 /*
8762                   SkewX.
8763                 */
8764                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8765                 break;
8766               }
8767               case 14:
8768               {
8769                 /*
8770                   SkewY.
8771                 */
8772                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8773                 break;
8774               }
8775             }
8776             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8777             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8778             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8779             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8780             draw_info->affine.tx=
8781               current.sx*affine.tx+current.ry*affine.ty+current.tx;
8782             draw_info->affine.ty=
8783               current.rx*affine.tx+current.sy*affine.ty+current.ty;
8784           }
8785           if (attribute_flag[15] != 0)
8786             draw_info->fill_pattern=CloneImage(
8787               argument_list[15].image_reference,0,0,MagickTrue,exception);
8788           if (attribute_flag[16] != 0)
8789             draw_info->pointsize=argument_list[16].real_reference;
8790           if (attribute_flag[17] != 0)
8791             {
8792               draw_info->stroke_antialias=argument_list[17].integer_reference != 0
8793                 ? MagickTrue : MagickFalse;
8794               draw_info->text_antialias=draw_info->stroke_antialias;
8795             }
8796           if (attribute_flag[18] != 0)
8797             (void) CloneString(&draw_info->density,
8798               argument_list[18].string_reference);
8799           if (attribute_flag[19] != 0)
8800             draw_info->stroke_width=argument_list[19].real_reference;
8801           if (attribute_flag[21] != 0)
8802             draw_info->dash_offset=argument_list[21].real_reference;
8803           if (attribute_flag[22] != 0)
8804             {
8805               AV
8806                 *av;
8807
8808               av=(AV *) argument_list[22].array_reference;
8809               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
8810                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
8811               if (draw_info->dash_pattern != (double *) NULL)
8812                 {
8813                   for (i=0; i <= av_len(av); i++)
8814                     draw_info->dash_pattern[i]=(double)
8815                       SvNV(*(av_fetch(av,i,0)));
8816                   draw_info->dash_pattern[i]=0.0;
8817                 }
8818             }
8819           if (attribute_flag[23] != 0)
8820             image->interpolate=(PixelInterpolateMethod)
8821               argument_list[23].integer_reference;
8822           if ((attribute_flag[24] != 0) &&
8823               (draw_info->fill_pattern != (Image *) NULL))
8824             flags=ParsePageGeometry(draw_info->fill_pattern,
8825               argument_list[24].string_reference,
8826               &draw_info->fill_pattern->tile_offset,exception);
8827           if (attribute_flag[25] != 0)
8828             {
8829               (void) ConcatenateString(&draw_info->primitive," '");
8830               (void) ConcatenateString(&draw_info->primitive,
8831                 argument_list[25].string_reference);
8832               (void) ConcatenateString(&draw_info->primitive,"'");
8833             }
8834           if (attribute_flag[26] != 0)
8835             draw_info->fill_pattern=CloneImage(
8836               argument_list[26].image_reference,0,0,MagickTrue,exception);
8837           if (attribute_flag[27] != 0)
8838             draw_info->stroke_pattern=CloneImage(
8839               argument_list[27].image_reference,0,0,MagickTrue,exception);
8840           if (attribute_flag[28] != 0)
8841             (void) CloneString(&draw_info->primitive,
8842               argument_list[28].string_reference);
8843           if (attribute_flag[29] != 0)
8844             draw_info->kerning=argument_list[29].real_reference;
8845           if (attribute_flag[30] != 0)
8846             draw_info->interline_spacing=argument_list[30].real_reference;
8847           if (attribute_flag[31] != 0)
8848             draw_info->interword_spacing=argument_list[31].real_reference;
8849           if (attribute_flag[32] != 0)
8850             draw_info->direction=(DirectionType)
8851               argument_list[32].integer_reference;
8852           DrawImage(image,draw_info,exception);
8853           draw_info=DestroyDrawInfo(draw_info);
8854           break;
8855         }
8856         case 39:  /* Equalize */
8857         {
8858           if (attribute_flag[0] != 0)
8859             channel=(ChannelType) argument_list[0].integer_reference;
8860           channel_mask=SetImageChannelMask(image,channel);
8861           EqualizeImage(image,exception);
8862           (void) SetImageChannelMask(image,channel_mask);
8863           break;
8864         }
8865         case 40:  /* Gamma */
8866         {
8867           if (attribute_flag[1] != 0)
8868             channel=(ChannelType) argument_list[1].integer_reference;
8869           if (attribute_flag[2] == 0)
8870             argument_list[2].real_reference=1.0;
8871           if (attribute_flag[3] == 0)
8872             argument_list[3].real_reference=1.0;
8873           if (attribute_flag[4] == 0)
8874             argument_list[4].real_reference=1.0;
8875           if (attribute_flag[0] == 0)
8876             {
8877               (void) FormatLocaleString(message,MaxTextExtent,
8878                 "%.15g,%.15g,%.15g",(double) argument_list[2].real_reference,
8879                 (double) argument_list[3].real_reference,
8880                 (double) argument_list[4].real_reference);
8881               argument_list[0].string_reference=message;
8882             }
8883           (void) GammaImage(image,StringToDouble(
8884             argument_list[0].string_reference,(char **) NULL),exception);
8885           break;
8886         }
8887         case 41:  /* Map */
8888         {
8889           QuantizeInfo
8890             *quantize_info;
8891
8892           if (attribute_flag[0] == 0)
8893             {
8894               ThrowPerlException(exception,OptionError,"MapImageRequired",
8895                 PackageName);
8896               goto PerlException;
8897             }
8898           quantize_info=AcquireQuantizeInfo(info->image_info);
8899           if (attribute_flag[1] != 0)
8900             quantize_info->dither_method=(DitherMethod)
8901               argument_list[1].integer_reference;
8902           (void) RemapImages(quantize_info,image,
8903             argument_list[0].image_reference,exception);
8904           quantize_info=DestroyQuantizeInfo(quantize_info);
8905           break;
8906         }
8907         case 42:  /* MatteFloodfill */
8908         {
8909           DrawInfo
8910             *draw_info;
8911
8912           MagickBooleanType
8913             invert;
8914
8915           PixelInfo
8916             target;
8917
8918           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8919             (DrawInfo *) NULL);
8920           if (attribute_flag[0] != 0)
8921             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8922               &geometry,exception);
8923           if (attribute_flag[1] != 0)
8924             geometry.x=argument_list[1].integer_reference;
8925           if (attribute_flag[2] != 0)
8926             geometry.y=argument_list[2].integer_reference;
8927           if (image->alpha_trait != BlendPixelTrait)
8928             (void) SetImageAlpha(image,OpaqueAlpha,exception);
8929           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
8930             geometry.x,geometry.y,&target,exception);
8931           if (attribute_flag[4] != 0)
8932             QueryColorCompliance(argument_list[4].string_reference,
8933               AllCompliance,&target,exception);
8934           if (attribute_flag[3] != 0)
8935             target.alpha=StringToDoubleInterval(
8936               argument_list[3].string_reference,(double) (double) QuantumRange+
8937               1.0);
8938           if (attribute_flag[5] != 0)
8939             image->fuzz=StringToDoubleInterval(
8940               argument_list[5].string_reference,(double) QuantumRange+1.0);
8941           invert=MagickFalse;
8942           if (attribute_flag[6] != 0)
8943             invert=(MagickBooleanType) argument_list[6].integer_reference;
8944           channel_mask=SetImageChannelMask(image,AlphaChannel);
8945           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8946             geometry.y,invert,exception);
8947           (void) SetImageChannelMask(image,channel_mask);
8948           draw_info=DestroyDrawInfo(draw_info);
8949           break;
8950         }
8951         case 43:  /* Modulate */
8952         {
8953           char
8954             modulate[MaxTextExtent];
8955
8956           geometry_info.rho=100.0;
8957           geometry_info.sigma=100.0;
8958           geometry_info.xi=100.0;
8959           if (attribute_flag[0] != 0)
8960             (void)ParseGeometry(argument_list[0].string_reference,
8961               &geometry_info);
8962           if (attribute_flag[1] != 0)
8963             geometry_info.xi=argument_list[1].real_reference;
8964           if (attribute_flag[2] != 0)
8965             geometry_info.sigma=argument_list[2].real_reference;
8966           if (attribute_flag[3] != 0)
8967             {
8968               geometry_info.sigma=argument_list[3].real_reference;
8969               SetImageArtifact(image,"modulate:colorspace","HWB");
8970             }
8971           if (attribute_flag[4] != 0)
8972             {
8973               geometry_info.rho=argument_list[4].real_reference;
8974               SetImageArtifact(image,"modulate:colorspace","HSB");
8975             }
8976           if (attribute_flag[5] != 0)
8977             {
8978               geometry_info.sigma=argument_list[5].real_reference;
8979               SetImageArtifact(image,"modulate:colorspace","HSL");
8980             }
8981           if (attribute_flag[6] != 0)
8982             {
8983               geometry_info.rho=argument_list[6].real_reference;
8984               SetImageArtifact(image,"modulate:colorspace","HWB");
8985             }
8986           (void) FormatLocaleString(modulate,MaxTextExtent,"%.15g,%.15g,%.15g",
8987             geometry_info.rho,geometry_info.sigma,geometry_info.xi);
8988           (void) ModulateImage(image,modulate,exception);
8989           break;
8990         }
8991         case 44:  /* Negate */
8992         {
8993           if (attribute_flag[0] == 0)
8994             argument_list[0].integer_reference=0;
8995           if (attribute_flag[1] != 0)
8996             channel=(ChannelType) argument_list[1].integer_reference;
8997           channel_mask=SetImageChannelMask(image,channel);
8998           (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
8999             MagickTrue : MagickFalse,exception);
9000           (void) SetImageChannelMask(image,channel_mask);
9001           break;
9002         }
9003         case 45:  /* Normalize */
9004         {
9005           if (attribute_flag[0] != 0)
9006             channel=(ChannelType) argument_list[0].integer_reference;
9007           channel_mask=SetImageChannelMask(image,channel);
9008           NormalizeImage(image,exception);
9009           (void) SetImageChannelMask(image,channel_mask);
9010           break;
9011         }
9012         case 46:  /* NumberColors */
9013           break;
9014         case 47:  /* Opaque */
9015         {
9016           MagickBooleanType
9017             invert;
9018
9019           PixelInfo
9020             fill_color,
9021             target;
9022
9023           (void) QueryColorCompliance("none",AllCompliance,&target,
9024              exception);
9025           (void) QueryColorCompliance("none",AllCompliance,&fill_color,
9026             exception);
9027           if (attribute_flag[0] != 0)
9028             (void) QueryColorCompliance(argument_list[0].string_reference,
9029               AllCompliance,&target,exception);
9030           if (attribute_flag[1] != 0)
9031             (void) QueryColorCompliance(argument_list[1].string_reference,
9032               AllCompliance,&fill_color,exception);
9033           if (attribute_flag[2] != 0)
9034             image->fuzz=StringToDoubleInterval(
9035               argument_list[2].string_reference,(double) QuantumRange+1.0);
9036           if (attribute_flag[3] != 0)
9037             channel=(ChannelType) argument_list[3].integer_reference;
9038           invert=MagickFalse;
9039           if (attribute_flag[4] != 0)
9040             invert=(MagickBooleanType) argument_list[4].integer_reference;
9041           channel_mask=SetImageChannelMask(image,channel);
9042           (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
9043           (void) SetImageChannelMask(image,channel_mask);
9044           break;
9045         }
9046         case 48:  /* Quantize */
9047         {
9048           QuantizeInfo
9049             *quantize_info;
9050
9051           quantize_info=AcquireQuantizeInfo(info->image_info);
9052           if (attribute_flag[0] != 0)
9053             quantize_info->number_colors=(size_t)
9054               argument_list[0].integer_reference;
9055           if (attribute_flag[1] != 0)
9056             quantize_info->tree_depth=(size_t)
9057               argument_list[1].integer_reference;
9058           if (attribute_flag[2] != 0)
9059             quantize_info->colorspace=(ColorspaceType)
9060               argument_list[2].integer_reference;
9061           if (attribute_flag[3] != 0)
9062             quantize_info->dither_method=(DitherMethod)
9063               argument_list[3].integer_reference;
9064           if (attribute_flag[4] != 0)
9065             quantize_info->measure_error=argument_list[4].integer_reference !=
9066               0 ? MagickTrue : MagickFalse;
9067           if (attribute_flag[5] != 0)
9068             (void) QueryColorCompliance(argument_list[5].string_reference,
9069               AllCompliance,&image->transparent_color,exception);
9070           if (attribute_flag[5] && argument_list[5].integer_reference)
9071             {
9072               (void) QuantizeImages(quantize_info,image,exception);
9073               goto PerlException;
9074             }
9075           if (attribute_flag[6] != 0)
9076             quantize_info->dither_method=(DitherMethod)
9077               argument_list[6].integer_reference;
9078           if ((image->storage_class == DirectClass) ||
9079               (image->colors > quantize_info->number_colors) ||
9080               (quantize_info->colorspace == GRAYColorspace))
9081             (void) QuantizeImage(quantize_info,image,exception);
9082           else
9083             CompressImageColormap(image,exception);
9084           quantize_info=DestroyQuantizeInfo(quantize_info);
9085           break;
9086         }
9087         case 49:  /* Raise */
9088         {
9089           if (attribute_flag[0] != 0)
9090             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9091               &geometry,exception);
9092           if (attribute_flag[1] != 0)
9093             geometry.width=argument_list[1].integer_reference;
9094           if (attribute_flag[2] != 0)
9095             geometry.height=argument_list[2].integer_reference;
9096           if (attribute_flag[3] == 0)
9097             argument_list[3].integer_reference=1;
9098           (void) RaiseImage(image,&geometry,
9099             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
9100             exception);
9101           break;
9102         }
9103         case 50:  /* Segment */
9104         {
9105           ColorspaceType
9106             colorspace;
9107
9108           double
9109             cluster_threshold,
9110             smoothing_threshold;
9111
9112           MagickBooleanType
9113             verbose;
9114
9115           cluster_threshold=1.0;
9116           smoothing_threshold=1.5;
9117           colorspace=sRGBColorspace;
9118           verbose=MagickFalse;
9119           if (attribute_flag[0] != 0)
9120             {
9121               flags=ParseGeometry(argument_list[0].string_reference,
9122                 &geometry_info);
9123               cluster_threshold=geometry_info.rho;
9124               if (flags & SigmaValue)
9125                 smoothing_threshold=geometry_info.sigma;
9126             }
9127           if (attribute_flag[1] != 0)
9128             cluster_threshold=argument_list[1].real_reference;
9129           if (attribute_flag[2] != 0)
9130             smoothing_threshold=argument_list[2].real_reference;
9131           if (attribute_flag[3] != 0)
9132             colorspace=(ColorspaceType) argument_list[3].integer_reference;
9133           if (attribute_flag[4] != 0)
9134             verbose=argument_list[4].integer_reference != 0 ?
9135               MagickTrue : MagickFalse;
9136           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
9137             smoothing_threshold,exception);
9138           break;
9139         }
9140         case 51:  /* Signature */
9141         {
9142           (void) SignatureImage(image,exception);
9143           break;
9144         }
9145         case 52:  /* Solarize */
9146         {
9147           geometry_info.rho=QuantumRange/2.0;
9148           if (attribute_flag[0] != 0)
9149             flags=ParseGeometry(argument_list[0].string_reference,
9150               &geometry_info);
9151           if (attribute_flag[1] != 0)
9152             geometry_info.rho=StringToDoubleInterval(
9153               argument_list[1].string_reference,(double) QuantumRange+1.0);
9154           (void) SolarizeImage(image,geometry_info.rho,exception);
9155           break;
9156         }
9157         case 53:  /* Sync */
9158         {
9159           (void) SyncImage(image,exception);
9160           break;
9161         }
9162         case 54:  /* Texture */
9163         {
9164           if (attribute_flag[0] == 0)
9165             break;
9166           TextureImage(image,argument_list[0].image_reference,exception);
9167           break;
9168         }
9169         case 55:  /* Evalute */
9170         {
9171           MagickEvaluateOperator
9172             op;
9173
9174           op=SetEvaluateOperator;
9175           if (attribute_flag[0] == MagickFalse)
9176             argument_list[0].real_reference=0.0;
9177           if (attribute_flag[1] != MagickFalse)
9178             op=(MagickEvaluateOperator) argument_list[1].integer_reference;
9179           if (attribute_flag[2] != MagickFalse)
9180             channel=(ChannelType) argument_list[2].integer_reference;
9181           channel_mask=SetImageChannelMask(image,channel);
9182           (void) EvaluateImage(image,op,argument_list[0].real_reference,
9183             exception);
9184           (void) SetImageChannelMask(image,channel_mask);
9185           break;
9186         }
9187         case 56:  /* Transparent */
9188         {
9189           double
9190             opacity;
9191
9192           MagickBooleanType
9193             invert;
9194
9195           PixelInfo
9196             target;
9197
9198           (void) QueryColorCompliance("none",AllCompliance,&target,
9199             exception);
9200           if (attribute_flag[0] != 0)
9201             (void) QueryColorCompliance(argument_list[0].string_reference,
9202               AllCompliance,&target,exception);
9203           opacity=TransparentAlpha;
9204           if (attribute_flag[1] != 0)
9205             opacity=StringToDoubleInterval(argument_list[1].string_reference,
9206               (double) QuantumRange+1.0);
9207           if (attribute_flag[2] != 0)
9208             image->fuzz=StringToDoubleInterval(
9209               argument_list[2].string_reference,(double) QuantumRange+1.0);
9210           if (attribute_flag[3] == 0)
9211             argument_list[3].integer_reference=0;
9212           invert=MagickFalse;
9213           if (attribute_flag[3] != 0)
9214             invert=(MagickBooleanType) argument_list[3].integer_reference;
9215           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9216             invert,exception);
9217           break;
9218         }
9219         case 57:  /* Threshold */
9220         {
9221           double
9222             threshold;
9223
9224           if (attribute_flag[0] == 0)
9225             argument_list[0].string_reference="50%";
9226           if (attribute_flag[1] != 0)
9227             channel=(ChannelType) argument_list[1].integer_reference;
9228           threshold=StringToDoubleInterval(argument_list[0].string_reference,
9229             (double) QuantumRange+1.0);
9230           channel_mask=SetImageChannelMask(image,channel);
9231           (void) BilevelImage(image,threshold,exception);
9232           (void) SetImageChannelMask(image,channel_mask);
9233           break;
9234         }
9235         case 58:  /* Charcoal */
9236         {
9237           if (attribute_flag[0] != 0)
9238             {
9239               flags=ParseGeometry(argument_list[0].string_reference,
9240                 &geometry_info);
9241               if ((flags & SigmaValue) == 0)
9242                 geometry_info.sigma=1.0;
9243             }
9244           if (attribute_flag[1] != 0)
9245             geometry_info.rho=argument_list[1].real_reference;
9246           if (attribute_flag[2] != 0)
9247             geometry_info.sigma=argument_list[2].real_reference;
9248           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9249             exception);
9250           break;
9251         }
9252         case 59:  /* Trim */
9253         {
9254           if (attribute_flag[0] != 0)
9255             image->fuzz=StringToDoubleInterval(
9256               argument_list[0].string_reference,(double) QuantumRange+1.0);
9257           image=TrimImage(image,exception);
9258           break;
9259         }
9260         case 60:  /* Wave */
9261         {
9262           PixelInterpolateMethod
9263             method;
9264
9265           if (attribute_flag[0] != 0)
9266             {
9267               flags=ParseGeometry(argument_list[0].string_reference,
9268                 &geometry_info);
9269               if ((flags & SigmaValue) == 0)
9270                 geometry_info.sigma=1.0;
9271             }
9272           if (attribute_flag[1] != 0)
9273             geometry_info.rho=argument_list[1].real_reference;
9274           if (attribute_flag[2] != 0)
9275             geometry_info.sigma=argument_list[2].real_reference;
9276           method=UndefinedInterpolatePixel;
9277           if (attribute_flag[3] != 0)
9278             method=(PixelInterpolateMethod) argument_list[3].integer_reference;
9279           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9280             method,exception);
9281           break;
9282         }
9283         case 61:  /* Separate */
9284         {
9285           if (attribute_flag[0] != 0)
9286             channel=(ChannelType) argument_list[0].integer_reference;
9287           image=SeparateImage(image,channel,exception);
9288           break;
9289         }
9290         case 63:  /* Stereo */
9291         {
9292           if (attribute_flag[0] == 0)
9293             {
9294               ThrowPerlException(exception,OptionError,"StereoImageRequired",
9295                 PackageName);
9296               goto PerlException;
9297             }
9298           if (attribute_flag[1] != 0)
9299             geometry.x=argument_list[1].integer_reference;
9300           if (attribute_flag[2] != 0)
9301             geometry.y=argument_list[2].integer_reference;
9302           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9303             geometry.x,geometry.y,exception);
9304           break;
9305         }
9306         case 64:  /* Stegano */
9307         {
9308           if (attribute_flag[0] == 0)
9309             {
9310               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9311                 PackageName);
9312               goto PerlException;
9313             }
9314           if (attribute_flag[1] == 0)
9315             argument_list[1].integer_reference=0;
9316           image->offset=argument_list[1].integer_reference;
9317           image=SteganoImage(image,argument_list[0].image_reference,exception);
9318           break;
9319         }
9320         case 65:  /* Deconstruct */
9321         {
9322           image=CompareImagesLayers(image,CompareAnyLayer,exception);
9323           break;
9324         }
9325         case 66:  /* GaussianBlur */
9326         {
9327           if (attribute_flag[0] != 0)
9328             {
9329               flags=ParseGeometry(argument_list[0].string_reference,
9330                 &geometry_info);
9331               if ((flags & SigmaValue) == 0)
9332                 geometry_info.sigma=1.0;
9333             }
9334           if (attribute_flag[1] != 0)
9335             geometry_info.rho=argument_list[1].real_reference;
9336           if (attribute_flag[2] != 0)
9337             geometry_info.sigma=argument_list[2].real_reference;
9338           if (attribute_flag[3] != 0)
9339             channel=(ChannelType) argument_list[3].integer_reference;
9340           channel_mask=SetImageChannelMask(image,channel);
9341           image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9342             exception);
9343           if (image != (Image *) NULL)
9344             (void) SetImageChannelMask(image,channel_mask);
9345           break;
9346         }
9347         case 67:  /* Convolve */
9348         {
9349           KernelInfo
9350             *kernel;
9351
9352           kernel=(KernelInfo *) NULL;
9353           if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9354             break;
9355           if (attribute_flag[0] != 0)
9356             {
9357               AV
9358                 *av;
9359
9360               size_t
9361                 order;
9362
9363               kernel=AcquireKernelInfo((const char *) NULL);
9364               if (kernel == (KernelInfo *) NULL)
9365                 break;
9366               av=(AV *) argument_list[0].array_reference;
9367               order=(size_t) sqrt(av_len(av)+1);
9368               kernel->width=order;
9369               kernel->height=order;
9370               kernel->values=(MagickRealType *) AcquireAlignedMemory(order,
9371                 order*sizeof(*kernel->values));
9372               if (kernel->values == (MagickRealType *) NULL)
9373                 {
9374                   kernel=DestroyKernelInfo(kernel);
9375                   ThrowPerlException(exception,ResourceLimitFatalError,
9376                     "MemoryAllocationFailed",PackageName);
9377                   goto PerlException;
9378                 }
9379               for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9380                 kernel->values[j]=(MagickRealType) SvNV(*(av_fetch(av,j,0)));
9381               for ( ; j < (ssize_t) (order*order); j++)
9382                 kernel->values[j]=0.0;
9383             }
9384           if (attribute_flag[1] != 0)
9385             channel=(ChannelType) argument_list[1].integer_reference;
9386           if (attribute_flag[2] != 0)
9387             SetImageArtifact(image,"filter:blur",
9388               argument_list[2].string_reference);
9389           if (attribute_flag[3] != 0)
9390             {
9391               kernel=AcquireKernelInfo(argument_list[3].string_reference);
9392               if (kernel == (KernelInfo *) NULL)
9393                 break;
9394             }
9395           channel_mask=SetImageChannelMask(image,channel);
9396           image=ConvolveImage(image,kernel,exception);
9397           if (image != (Image *) NULL)
9398             (void) SetImageChannelMask(image,channel_mask);
9399           kernel=DestroyKernelInfo(kernel);
9400           break;
9401         }
9402         case 68:  /* Profile */
9403         {
9404           const char
9405             *name;
9406
9407           Image
9408             *profile_image;
9409
9410           ImageInfo
9411             *profile_info;
9412
9413           StringInfo
9414             *profile;
9415
9416           name="*";
9417           if (attribute_flag[0] != 0)
9418             name=argument_list[0].string_reference;
9419           if (attribute_flag[2] != 0)
9420             image->rendering_intent=(RenderingIntent)
9421               argument_list[2].integer_reference;
9422           if (attribute_flag[3] != 0)
9423             image->black_point_compensation=
9424               argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9425           if (attribute_flag[1] != 0)
9426             {
9427               if (argument_list[1].length == 0)
9428                 {
9429                   /*
9430                     Remove a profile from the image.
9431                   */
9432                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9433                     exception);
9434                   break;
9435                 }
9436               /*
9437                 Associate user supplied profile with the image.
9438               */
9439               profile=AcquireStringInfo(argument_list[1].length);
9440               SetStringInfoDatum(profile,(const unsigned char *)
9441                 argument_list[1].string_reference);
9442               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9443                 (size_t) GetStringInfoLength(profile),exception);
9444               profile=DestroyStringInfo(profile);
9445               break;
9446             }
9447           /*
9448             Associate a profile with the image.
9449           */
9450           profile_info=CloneImageInfo(info ? info->image_info :
9451             (ImageInfo *) NULL);
9452           profile_image=ReadImages(profile_info,name,exception);
9453           if (profile_image == (Image *) NULL)
9454             break;
9455           ResetImageProfileIterator(profile_image);
9456           name=GetNextImageProfile(profile_image);
9457           while (name != (const char *) NULL)
9458           {
9459             const StringInfo
9460               *profile;
9461
9462             profile=GetImageProfile(profile_image,name);
9463             if (profile != (const StringInfo *) NULL)
9464               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9465                 (size_t) GetStringInfoLength(profile),exception);
9466             name=GetNextImageProfile(profile_image);
9467           }
9468           profile_image=DestroyImage(profile_image);
9469           profile_info=DestroyImageInfo(profile_info);
9470           break;
9471         }
9472         case 69:  /* UnsharpMask */
9473         {
9474           if (attribute_flag[0] != 0)
9475             {
9476               flags=ParseGeometry(argument_list[0].string_reference,
9477                 &geometry_info);
9478               if ((flags & SigmaValue) == 0)
9479                 geometry_info.sigma=1.0;
9480               if ((flags & XiValue) == 0)
9481                 geometry_info.xi=1.0;
9482               if ((flags & PsiValue) == 0)
9483                 geometry_info.psi=0.5;
9484             }
9485           if (attribute_flag[1] != 0)
9486             geometry_info.rho=argument_list[1].real_reference;
9487           if (attribute_flag[2] != 0)
9488             geometry_info.sigma=argument_list[2].real_reference;
9489           if (attribute_flag[3] != 0)
9490             geometry_info.xi=argument_list[3].real_reference;
9491           if (attribute_flag[4] != 0)
9492             geometry_info.psi=argument_list[4].real_reference;
9493           if (attribute_flag[5] != 0)
9494             channel=(ChannelType) argument_list[5].integer_reference;
9495           channel_mask=SetImageChannelMask(image,channel);
9496           image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9497             geometry_info.xi,geometry_info.psi,exception);
9498           if (image != (Image *) NULL)
9499             (void) SetImageChannelMask(image,channel_mask);
9500           break;
9501         }
9502         case 70:  /* MotionBlur */
9503         {
9504           if (attribute_flag[0] != 0)
9505             {
9506               flags=ParseGeometry(argument_list[0].string_reference,
9507                 &geometry_info);
9508               if ((flags & SigmaValue) == 0)
9509                 geometry_info.sigma=1.0;
9510               if ((flags & XiValue) == 0)
9511                 geometry_info.xi=1.0;
9512             }
9513           if (attribute_flag[1] != 0)
9514             geometry_info.rho=argument_list[1].real_reference;
9515           if (attribute_flag[2] != 0)
9516             geometry_info.sigma=argument_list[2].real_reference;
9517           if (attribute_flag[3] != 0)
9518             geometry_info.xi=argument_list[3].real_reference;
9519           if (attribute_flag[4] != 0)
9520             channel=(ChannelType) argument_list[4].integer_reference;
9521           channel_mask=SetImageChannelMask(image,channel);
9522           image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9523             geometry_info.xi,exception);
9524           if (image != (Image *) NULL)
9525             (void) SetImageChannelMask(image,channel_mask);
9526           break;
9527         }
9528         case 71:  /* OrderedDither */
9529         {
9530           if (attribute_flag[0] == 0)
9531             argument_list[0].string_reference="o8x8";
9532           if (attribute_flag[1] != 0)
9533             channel=(ChannelType) argument_list[1].integer_reference;
9534           channel_mask=SetImageChannelMask(image,channel);
9535           (void) OrderedPosterizeImage(image,argument_list[0].string_reference,
9536             exception);
9537           (void) SetImageChannelMask(image,channel_mask);
9538           break;
9539         }
9540         case 72:  /* Shave */
9541         {
9542           if (attribute_flag[0] != 0)
9543             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9544               &geometry,exception);
9545           if (attribute_flag[1] != 0)
9546             geometry.width=argument_list[1].integer_reference;
9547           if (attribute_flag[2] != 0)
9548             geometry.height=argument_list[2].integer_reference;
9549           image=ShaveImage(image,&geometry,exception);
9550           break;
9551         }
9552         case 73:  /* Level */
9553         {
9554           double
9555             black_point,
9556             gamma,
9557             white_point;
9558
9559           black_point=0.0;
9560           white_point=(double) image->columns*image->rows;
9561           gamma=1.0;
9562           if (attribute_flag[0] != 0)
9563             {
9564               flags=ParseGeometry(argument_list[0].string_reference,
9565                 &geometry_info);
9566               black_point=geometry_info.rho;
9567               if ((flags & SigmaValue) != 0)
9568                 white_point=geometry_info.sigma;
9569               if ((flags & XiValue) != 0)
9570                 gamma=geometry_info.xi;
9571               if ((flags & PercentValue) != 0)
9572                 {
9573                   black_point*=(double) (QuantumRange/100.0);
9574                   white_point*=(double) (QuantumRange/100.0);
9575                 }
9576               if ((flags & SigmaValue) == 0)
9577                 white_point=(double) QuantumRange-black_point;
9578             }
9579           if (attribute_flag[1] != 0)
9580             black_point=argument_list[1].real_reference;
9581           if (attribute_flag[2] != 0)
9582             white_point=argument_list[2].real_reference;
9583           if (attribute_flag[3] != 0)
9584             gamma=argument_list[3].real_reference;
9585           if (attribute_flag[4] != 0)
9586             channel=(ChannelType) argument_list[4].integer_reference;
9587           if (attribute_flag[5] != 0)
9588             {
9589               argument_list[0].real_reference=argument_list[5].real_reference;
9590               attribute_flag[0]=attribute_flag[5];
9591             }
9592           channel_mask=SetImageChannelMask(image,channel);
9593           (void) LevelImage(image,black_point,white_point,gamma,exception);
9594           (void) SetImageChannelMask(image,channel_mask);
9595           break;
9596         }
9597         case 74:  /* Clip */
9598         {
9599           if (attribute_flag[0] == 0)
9600             argument_list[0].string_reference="#1";
9601           if (attribute_flag[1] == 0)
9602             argument_list[1].integer_reference=MagickTrue;
9603           (void) ClipImagePath(image,argument_list[0].string_reference,
9604             argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse,
9605             exception);
9606           break;
9607         }
9608         case 75:  /* AffineTransform */
9609         {
9610           DrawInfo
9611             *draw_info;
9612
9613           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9614             (DrawInfo *) NULL);
9615           if (attribute_flag[0] != 0)
9616             {
9617               AV
9618                 *av;
9619
9620               av=(AV *) argument_list[0].array_reference;
9621               if ((av_len(av) != 3) && (av_len(av) != 5))
9622                 {
9623                   ThrowPerlException(exception,OptionError,
9624                     "affine matrix must have 4 or 6 elements",PackageName);
9625                   goto PerlException;
9626                 }
9627               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9628               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9629               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9630               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9631               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9632                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9633                 {
9634                   ThrowPerlException(exception,OptionError,
9635                     "affine matrix is singular",PackageName);
9636                    goto PerlException;
9637                 }
9638               if (av_len(av) == 5)
9639                 {
9640                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9641                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9642                 }
9643             }
9644           for (j=1; j < 6; j++)
9645           {
9646             if (attribute_flag[j] == 0)
9647               continue;
9648             value=argument_list[j].string_reference;
9649             angle=argument_list[j].real_reference;
9650             current=draw_info->affine;
9651             GetAffineMatrix(&affine);
9652             switch (j)
9653             {
9654               case 1:
9655               {
9656                 /*
9657                   Translate.
9658                 */
9659                 flags=ParseGeometry(value,&geometry_info);
9660                 affine.tx=geometry_info.xi;
9661                 affine.ty=geometry_info.psi;
9662                 if ((flags & PsiValue) == 0)
9663                   affine.ty=affine.tx;
9664                 break;
9665               }
9666               case 2:
9667               {
9668                 /*
9669                   Scale.
9670                 */
9671                 flags=ParseGeometry(value,&geometry_info);
9672                 affine.sx=geometry_info.rho;
9673                 affine.sy=geometry_info.sigma;
9674                 if ((flags & SigmaValue) == 0)
9675                   affine.sy=affine.sx;
9676                 break;
9677               }
9678               case 3:
9679               {
9680                 /*
9681                   Rotate.
9682                 */
9683                 if (angle == 0.0)
9684                   break;
9685                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9686                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9687                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9688                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9689                 break;
9690               }
9691               case 4:
9692               {
9693                 /*
9694                   SkewX.
9695                 */
9696                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9697                 break;
9698               }
9699               case 5:
9700               {
9701                 /*
9702                   SkewY.
9703                 */
9704                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9705                 break;
9706               }
9707             }
9708             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9709             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9710             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9711             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9712             draw_info->affine.tx=
9713               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9714             draw_info->affine.ty=
9715               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9716           }
9717           if (attribute_flag[6] != 0)
9718             image->interpolate=(PixelInterpolateMethod)
9719               argument_list[6].integer_reference;
9720           if (attribute_flag[7] != 0)
9721             QueryColorCompliance(argument_list[7].string_reference,
9722               AllCompliance,&image->background_color,exception);
9723           image=AffineTransformImage(image,&draw_info->affine,exception);
9724           draw_info=DestroyDrawInfo(draw_info);
9725           break;
9726         }
9727         case 76:  /* Difference */
9728         {
9729           if (attribute_flag[0] == 0)
9730             {
9731               ThrowPerlException(exception,OptionError,
9732                 "ReferenceImageRequired",PackageName);
9733               goto PerlException;
9734             }
9735           if (attribute_flag[1] != 0)
9736             image->fuzz=StringToDoubleInterval(
9737               argument_list[1].string_reference,(double) QuantumRange+1.0);
9738           (void) IsImagesEqual(image,argument_list[0].image_reference,
9739             exception);
9740           break;
9741         }
9742         case 77:  /* AdaptiveThreshold */
9743         {
9744           if (attribute_flag[0] != 0)
9745             {
9746               flags=ParseGeometry(argument_list[0].string_reference,
9747                 &geometry_info);
9748               if ((flags & PercentValue) != 0)
9749                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9750             }
9751           if (attribute_flag[1] != 0)
9752             geometry_info.rho=argument_list[1].integer_reference;
9753           if (attribute_flag[2] != 0)
9754             geometry_info.sigma=argument_list[2].integer_reference;
9755           if (attribute_flag[3] != 0)
9756             geometry_info.xi=argument_list[3].integer_reference;;
9757           image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
9758             (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
9759           break;
9760         }
9761         case 78:  /* Resample */
9762         {
9763           size_t
9764             height,
9765             width;
9766
9767           if (attribute_flag[0] != 0)
9768             {
9769               flags=ParseGeometry(argument_list[0].string_reference,
9770                 &geometry_info);
9771               if ((flags & SigmaValue) == 0)
9772                 geometry_info.sigma=geometry_info.rho;
9773             }
9774           if (attribute_flag[1] != 0)
9775             geometry_info.rho=argument_list[1].real_reference;
9776           if (attribute_flag[2] != 0)
9777             geometry_info.sigma=argument_list[2].real_reference;
9778           if (attribute_flag[3] == 0)
9779             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
9780           if (attribute_flag[4] == 0)
9781             SetImageArtifact(image,"filter:support",
9782               argument_list[4].string_reference);
9783           width=(size_t) (geometry_info.rho*image->columns/
9784             (image->resolution.x == 0.0 ? 72.0 : image->resolution.x)+0.5);
9785           height=(size_t) (geometry_info.sigma*image->rows/
9786             (image->resolution.y == 0.0 ? 72.0 : image->resolution.y)+0.5);
9787           image=ResizeImage(image,width,height,(FilterTypes)
9788             argument_list[3].integer_reference,exception);
9789           if (image != (Image *) NULL)
9790             {
9791               image->resolution.x=geometry_info.rho;
9792               image->resolution.y=geometry_info.sigma;
9793             }
9794           break;
9795         }
9796         case 79:  /* Describe */
9797         {
9798           if (attribute_flag[0] == 0)
9799             argument_list[0].file_reference=(FILE *) NULL;
9800           if (attribute_flag[1] != 0)
9801             (void) SetImageArtifact(image,"identify:features",
9802               argument_list[1].string_reference);
9803           (void) IdentifyImage(image,argument_list[0].file_reference,
9804             MagickTrue,exception);
9805           break;
9806         }
9807         case 80:  /* BlackThreshold */
9808         {
9809           if (attribute_flag[0] == 0)
9810             argument_list[0].string_reference="50%";
9811           if (attribute_flag[2] != 0)
9812             channel=(ChannelType) argument_list[2].integer_reference;
9813           channel_mask=SetImageChannelMask(image,channel);
9814           BlackThresholdImage(image,argument_list[0].string_reference,
9815             exception);
9816           (void) SetImageChannelMask(image,channel_mask);
9817           break;
9818         }
9819         case 81:  /* WhiteThreshold */
9820         {
9821           if (attribute_flag[0] == 0)
9822             argument_list[0].string_reference="50%";
9823           if (attribute_flag[2] != 0)
9824             channel=(ChannelType) argument_list[2].integer_reference;
9825           channel_mask=SetImageChannelMask(image,channel);
9826           WhiteThresholdImage(image,argument_list[0].string_reference,
9827             exception);
9828           (void) SetImageChannelMask(image,channel_mask);
9829           break;
9830         }
9831         case 82:  /* RadialBlur */
9832         {
9833           if (attribute_flag[0] != 0)
9834             {
9835               flags=ParseGeometry(argument_list[0].string_reference,
9836                 &geometry_info);
9837             }
9838           if (attribute_flag[1] != 0)
9839             geometry_info.rho=argument_list[1].real_reference;
9840           if (attribute_flag[2] != 0)
9841             channel=(ChannelType) argument_list[2].integer_reference;
9842           channel_mask=SetImageChannelMask(image,channel);
9843           image=RadialBlurImage(image,geometry_info.rho,exception);
9844           if (image != (Image *) NULL)
9845             (void) SetImageChannelMask(image,channel_mask);
9846           break;
9847         }
9848         case 83:  /* Thumbnail */
9849         {
9850           if (attribute_flag[0] != 0)
9851             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
9852               &geometry,exception);
9853           if (attribute_flag[1] != 0)
9854             geometry.width=argument_list[1].integer_reference;
9855           if (attribute_flag[2] != 0)
9856             geometry.height=argument_list[2].integer_reference;
9857           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
9858           break;
9859         }
9860         case 84:  /* Strip */
9861         {
9862           (void) StripImage(image,exception);
9863           break;
9864         }
9865         case 85:  /* Tint */
9866         {
9867           PixelInfo
9868             tint;
9869
9870           GetPixelInfo(image,&tint);
9871           if (attribute_flag[0] != 0)
9872             (void) QueryColorCompliance(argument_list[0].string_reference,
9873               AllCompliance,&tint,exception);
9874           if (attribute_flag[1] == 0)
9875             argument_list[1].string_reference="100";
9876           image=TintImage(image,argument_list[1].string_reference,&tint,
9877             exception);
9878           break;
9879         }
9880         case 86:  /* Channel */
9881         {
9882           if (attribute_flag[0] != 0)
9883             channel=(ChannelType) argument_list[0].integer_reference;
9884           image=SeparateImage(image,channel,exception);
9885           break;
9886         }
9887         case 87:  /* Splice */
9888         {
9889           if (attribute_flag[0] != 0)
9890             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
9891               &geometry,exception);
9892           if (attribute_flag[1] != 0)
9893             geometry.width=argument_list[1].integer_reference;
9894           if (attribute_flag[2] != 0)
9895             geometry.height=argument_list[2].integer_reference;
9896           if (attribute_flag[3] != 0)
9897             geometry.x=argument_list[3].integer_reference;
9898           if (attribute_flag[4] != 0)
9899             geometry.y=argument_list[4].integer_reference;
9900           if (attribute_flag[5] != 0)
9901             image->fuzz=StringToDoubleInterval(
9902               argument_list[5].string_reference,(double) QuantumRange+1.0);
9903           if (attribute_flag[6] != 0)
9904             (void) QueryColorCompliance(argument_list[6].string_reference,
9905               AllCompliance,&image->background_color,exception);
9906           if (attribute_flag[7] != 0)
9907             image->gravity=(GravityType) argument_list[7].integer_reference;
9908           image=SpliceImage(image,&geometry,exception);
9909           break;
9910         }
9911         case 88:  /* Posterize */
9912         {
9913           if (attribute_flag[0] == 0)
9914             argument_list[0].integer_reference=3;
9915           if (attribute_flag[1] == 0)
9916             argument_list[1].integer_reference=0;
9917           (void) PosterizeImage(image,argument_list[0].integer_reference,
9918             argument_list[1].integer_reference ? RiemersmaDitherMethod :
9919             NoDitherMethod,exception);
9920           break;
9921         }
9922         case 89:  /* Shadow */
9923         {
9924           if (attribute_flag[0] != 0)
9925             {
9926               flags=ParseGeometry(argument_list[0].string_reference,
9927                 &geometry_info);
9928               if ((flags & SigmaValue) == 0)
9929                 geometry_info.sigma=1.0;
9930               if ((flags & XiValue) == 0)
9931                 geometry_info.xi=4.0;
9932               if ((flags & PsiValue) == 0)
9933                 geometry_info.psi=4.0;
9934             }
9935           if (attribute_flag[1] != 0)
9936             geometry_info.rho=argument_list[1].real_reference;
9937           if (attribute_flag[2] != 0)
9938             geometry_info.sigma=argument_list[2].real_reference;
9939           if (attribute_flag[3] != 0)
9940             geometry_info.xi=argument_list[3].integer_reference;
9941           if (attribute_flag[4] != 0)
9942             geometry_info.psi=argument_list[4].integer_reference;
9943           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
9944             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
9945             ceil(geometry_info.psi-0.5),exception);
9946           break;
9947         }
9948         case 90:  /* Identify */
9949         {
9950           if (attribute_flag[0] == 0)
9951             argument_list[0].file_reference=(FILE *) NULL;
9952           if (attribute_flag[1] != 0)
9953             (void) SetImageArtifact(image,"identify:features",
9954               argument_list[1].string_reference);
9955           if ((attribute_flag[2] != 0) &&
9956               (argument_list[2].integer_reference != 0))
9957             (void) SetImageArtifact(image,"identify:unique","true");
9958           (void) IdentifyImage(image,argument_list[0].file_reference,
9959             MagickTrue,exception);
9960           break;
9961         }
9962         case 91:  /* SepiaTone */
9963         {
9964           if (attribute_flag[0] == 0)
9965             argument_list[0].real_reference=80.0*QuantumRange/100.0;
9966           image=SepiaToneImage(image,argument_list[0].real_reference,
9967             exception);
9968           break;
9969         }
9970         case 92:  /* SigmoidalContrast */
9971         {
9972           MagickBooleanType
9973             sharpen;
9974
9975           if (attribute_flag[0] != 0)
9976             {
9977               flags=ParseGeometry(argument_list[0].string_reference,
9978                 &geometry_info);
9979               if ((flags & SigmaValue) == 0)
9980                 geometry_info.sigma=QuantumRange/2.0;
9981               if ((flags & PercentValue) != 0)
9982                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
9983             }
9984           if (attribute_flag[1] != 0)
9985             geometry_info.rho=argument_list[1].real_reference;
9986           if (attribute_flag[2] != 0)
9987             geometry_info.sigma=argument_list[2].real_reference;
9988           if (attribute_flag[3] != 0)
9989             channel=(ChannelType) argument_list[3].integer_reference;
9990           sharpen=MagickTrue;
9991           if (attribute_flag[4] != 0)
9992             sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
9993               MagickFalse;
9994           channel_mask=SetImageChannelMask(image,channel);
9995           (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
9996             geometry_info.sigma,exception);
9997           (void) SetImageChannelMask(image,channel_mask);
9998           break;
9999         }
10000         case 93:  /* Extent */
10001         {
10002           if (attribute_flag[7] != 0)
10003             image->gravity=(GravityType) argument_list[7].integer_reference;
10004           if (attribute_flag[0] != 0)
10005             {
10006               int
10007                 flags;
10008
10009               flags=ParseGravityGeometry(image,
10010                 argument_list[0].string_reference,&geometry,exception);
10011               (void) flags;
10012               if (geometry.width == 0)
10013                 geometry.width=image->columns;
10014               if (geometry.height == 0)
10015                 geometry.height=image->rows;
10016             }
10017           if (attribute_flag[1] != 0)
10018             geometry.width=argument_list[1].integer_reference;
10019           if (attribute_flag[2] != 0)
10020             geometry.height=argument_list[2].integer_reference;
10021           if (attribute_flag[3] != 0)
10022             geometry.x=argument_list[3].integer_reference;
10023           if (attribute_flag[4] != 0)
10024             geometry.y=argument_list[4].integer_reference;
10025           if (attribute_flag[5] != 0)
10026             image->fuzz=StringToDoubleInterval(
10027               argument_list[5].string_reference,(double) QuantumRange+1.0);
10028           if (attribute_flag[6] != 0)
10029             (void) QueryColorCompliance(argument_list[6].string_reference,
10030               AllCompliance,&image->background_color,exception);
10031           image=ExtentImage(image,&geometry,exception);
10032           break;
10033         }
10034         case 94:  /* Vignette */
10035         {
10036           if (attribute_flag[0] != 0)
10037             {
10038               flags=ParseGeometry(argument_list[0].string_reference,
10039                 &geometry_info);
10040               if ((flags & SigmaValue) == 0)
10041                 geometry_info.sigma=1.0;
10042               if ((flags & XiValue) == 0)
10043                 geometry_info.xi=0.1*image->columns;
10044               if ((flags & PsiValue) == 0)
10045                 geometry_info.psi=0.1*image->rows;
10046             }
10047           if (attribute_flag[1] != 0)
10048             geometry_info.rho=argument_list[1].real_reference;
10049           if (attribute_flag[2] != 0)
10050             geometry_info.sigma=argument_list[2].real_reference;
10051           if (attribute_flag[3] != 0)
10052             geometry_info.xi=argument_list[3].integer_reference;
10053           if (attribute_flag[4] != 0)
10054             geometry_info.psi=argument_list[4].integer_reference;
10055           if (attribute_flag[5] != 0)
10056             (void) QueryColorCompliance(argument_list[5].string_reference,
10057               AllCompliance,&image->background_color,exception);
10058           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
10059             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10060             ceil(geometry_info.psi-0.5),exception);
10061           break;
10062         }
10063         case 95:  /* ContrastStretch */
10064         {
10065           double
10066             black_point,
10067             white_point;
10068
10069           black_point=0.0;
10070           white_point=(double) image->columns*image->rows;
10071           if (attribute_flag[0] != 0)
10072             {
10073               flags=ParseGeometry(argument_list[0].string_reference,
10074                 &geometry_info);
10075               black_point=geometry_info.rho;
10076               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
10077                 black_point;
10078               if ((flags & PercentValue) != 0)
10079                 {
10080                   black_point*=(double) image->columns*image->rows/100.0;
10081                   white_point*=(double) image->columns*image->rows/100.0;
10082                 }
10083               white_point=(double) image->columns*image->rows-
10084                 white_point;
10085             }
10086           if (attribute_flag[1] != 0)
10087             black_point=argument_list[1].real_reference;
10088           if (attribute_flag[2] != 0)
10089             white_point=argument_list[2].real_reference;
10090           if (attribute_flag[4] != 0)
10091             channel=(ChannelType) argument_list[4].integer_reference;
10092           channel_mask=SetImageChannelMask(image,channel);
10093           (void) ContrastStretchImage(image,black_point,white_point,exception);
10094           (void) SetImageChannelMask(image,channel_mask);
10095           break;
10096         }
10097         case 96:  /* Sans0 */
10098         {
10099           break;
10100         }
10101         case 97:  /* Sans1 */
10102         {
10103           break;
10104         }
10105         case 98:  /* AdaptiveSharpen */
10106         {
10107           if (attribute_flag[0] != 0)
10108             {
10109               flags=ParseGeometry(argument_list[0].string_reference,
10110                 &geometry_info);
10111               if ((flags & SigmaValue) == 0)
10112                 geometry_info.sigma=1.0;
10113               if ((flags & XiValue) == 0)
10114                 geometry_info.xi=0.0;
10115             }
10116           if (attribute_flag[1] != 0)
10117             geometry_info.rho=argument_list[1].real_reference;
10118           if (attribute_flag[2] != 0)
10119             geometry_info.sigma=argument_list[2].real_reference;
10120           if (attribute_flag[3] != 0)
10121             geometry_info.xi=argument_list[3].real_reference;
10122           if (attribute_flag[4] != 0)
10123             channel=(ChannelType) argument_list[4].integer_reference;
10124           channel_mask=SetImageChannelMask(image,channel);
10125           image=AdaptiveSharpenImage(image,geometry_info.rho,
10126             geometry_info.sigma,exception);
10127           if (image != (Image *) NULL)
10128             (void) SetImageChannelMask(image,channel_mask);
10129           break;
10130         }
10131         case 99:  /* Transpose */
10132         {
10133           image=TransposeImage(image,exception);
10134           break;
10135         }
10136         case 100:  /* Tranverse */
10137         {
10138           image=TransverseImage(image,exception);
10139           break;
10140         }
10141         case 101:  /* AutoOrient */
10142         {
10143           switch (image->orientation)
10144           {
10145             case TopRightOrientation:
10146             {
10147               image=FlopImage(image,exception);
10148               break;
10149             }
10150             case BottomRightOrientation:
10151             {
10152               image=RotateImage(image,180.0,exception);
10153               break;
10154             }
10155             case BottomLeftOrientation:
10156             {
10157               image=FlipImage(image,exception);
10158               break;
10159             }
10160             case LeftTopOrientation:
10161             {
10162               image=TransposeImage(image,exception);
10163               break;
10164             }
10165             case RightTopOrientation:
10166             {
10167               image=RotateImage(image,90.0,exception);
10168               break;
10169             }
10170             case RightBottomOrientation:
10171             {
10172               image=TransverseImage(image,exception);
10173               break;
10174             }
10175             case LeftBottomOrientation:
10176             {
10177               image=RotateImage(image,270.0,exception);
10178               break;
10179             }
10180             default:
10181               break;
10182           }
10183           break;
10184         }
10185         case 102:  /* AdaptiveBlur */
10186         {
10187           if (attribute_flag[0] != 0)
10188             {
10189               flags=ParseGeometry(argument_list[0].string_reference,
10190                 &geometry_info);
10191               if ((flags & SigmaValue) == 0)
10192                 geometry_info.sigma=1.0;
10193               if ((flags & XiValue) == 0)
10194                 geometry_info.xi=0.0;
10195             }
10196           if (attribute_flag[1] != 0)
10197             geometry_info.rho=argument_list[1].real_reference;
10198           if (attribute_flag[2] != 0)
10199             geometry_info.sigma=argument_list[2].real_reference;
10200           if (attribute_flag[3] != 0)
10201             channel=(ChannelType) argument_list[3].integer_reference;
10202           channel_mask=SetImageChannelMask(image,channel);
10203           image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10204             exception);
10205           if (image != (Image *) NULL)
10206             (void) SetImageChannelMask(image,channel_mask);
10207           break;
10208         }
10209         case 103:  /* Sketch */
10210         {
10211           if (attribute_flag[0] != 0)
10212             {
10213               flags=ParseGeometry(argument_list[0].string_reference,
10214                 &geometry_info);
10215               if ((flags & SigmaValue) == 0)
10216                 geometry_info.sigma=1.0;
10217               if ((flags & XiValue) == 0)
10218                 geometry_info.xi=1.0;
10219             }
10220           if (attribute_flag[1] != 0)
10221             geometry_info.rho=argument_list[1].real_reference;
10222           if (attribute_flag[2] != 0)
10223             geometry_info.sigma=argument_list[2].real_reference;
10224           if (attribute_flag[3] != 0)
10225             geometry_info.xi=argument_list[3].real_reference;
10226           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10227             geometry_info.xi,exception);
10228           break;
10229         }
10230         case 104:  /* UniqueColors */
10231         {
10232           image=UniqueImageColors(image,exception);
10233           break;
10234         }
10235         case 105:  /* AdaptiveResize */
10236         {
10237           if (attribute_flag[0] != 0)
10238             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10239               &geometry,exception);
10240           if (attribute_flag[1] != 0)
10241             geometry.width=argument_list[1].integer_reference;
10242           if (attribute_flag[2] != 0)
10243             geometry.height=argument_list[2].integer_reference;
10244           if (attribute_flag[3] != 0)
10245             image->filter=(FilterTypes) argument_list[4].integer_reference;
10246           if (attribute_flag[4] != 0)
10247             SetImageArtifact(image,"filter:support",
10248               argument_list[4].string_reference);
10249           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10250             exception);
10251           break;
10252         }
10253         case 106:  /* ClipMask */
10254         {
10255           Image
10256             *mask_image;
10257
10258           if (attribute_flag[0] == 0)
10259             {
10260               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10261                 PackageName);
10262               goto PerlException;
10263             }
10264           mask_image=CloneImage(argument_list[0].image_reference,0,0,MagickTrue,
10265             exception);
10266           (void) NegateImage(mask_image,MagickFalse,exception);
10267           (void) SetImageMask(image,mask_image,exception);
10268           mask_image=DestroyImage(mask_image);
10269           break;
10270         }
10271         case 107:  /* LinearStretch */
10272         {
10273            double
10274              black_point,
10275              white_point;
10276
10277            black_point=0.0;
10278            white_point=(double) image->columns*image->rows;
10279            if (attribute_flag[0] != 0)
10280              {
10281                flags=ParseGeometry(argument_list[0].string_reference,
10282                  &geometry_info);
10283                if ((flags & SigmaValue) != 0)
10284                   white_point=geometry_info.sigma;
10285                if ((flags & PercentValue) != 0)
10286                  {
10287                    black_point*=(double) image->columns*image->rows/100.0;
10288                    white_point*=(double) image->columns*image->rows/100.0;
10289                  }
10290                if ((flags & SigmaValue) == 0)
10291                  white_point=(double) image->columns*image->rows-black_point;
10292              }
10293           if (attribute_flag[1] != 0)
10294             black_point=argument_list[1].real_reference;
10295           if (attribute_flag[2] != 0)
10296             white_point=argument_list[2].real_reference;
10297           (void) LinearStretchImage(image,black_point,white_point,exception);
10298           break;
10299         }
10300         case 108:  /* ColorMatrix */
10301         {
10302           AV
10303             *av;
10304
10305           double
10306             *color_matrix;
10307
10308           KernelInfo
10309             *kernel_info;
10310
10311           size_t
10312             order;
10313
10314           if (attribute_flag[0] == 0)
10315             break;
10316           av=(AV *) argument_list[0].array_reference;
10317           order=(size_t) sqrt(av_len(av)+1);
10318           color_matrix=(double *) AcquireQuantumMemory(order,order*
10319             sizeof(*color_matrix));
10320           if (color_matrix == (double *) NULL)
10321             {
10322               ThrowPerlException(exception,ResourceLimitFatalError,
10323                 "MemoryAllocationFailed",PackageName);
10324               goto PerlException;
10325            }
10326           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10327             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10328           for ( ; j < (ssize_t) (order*order); j++)
10329             color_matrix[j]=0.0;
10330           kernel_info=AcquireKernelInfo((const char *) NULL);
10331           if (kernel_info == (KernelInfo *) NULL)
10332             break;
10333           kernel_info->width=order;
10334           kernel_info->height=order;
10335           kernel_info->values=(MagickRealType *) AcquireAlignedMemory(order,
10336             order*sizeof(*kernel_info->values));
10337           if (kernel_info->values != (MagickRealType *) NULL)
10338             {
10339               for (i=0; i < (ssize_t) (order*order); i++)
10340                 kernel_info->values[i]=(MagickRealType) color_matrix[i];
10341               image=ColorMatrixImage(image,kernel_info,exception);
10342             }
10343           kernel_info=DestroyKernelInfo(kernel_info);
10344           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10345           break;
10346         }
10347         case 109:  /* Mask */
10348         {
10349           Image
10350             *mask_image;
10351
10352           if (attribute_flag[0] == 0)
10353             {
10354               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10355                 PackageName);
10356               goto PerlException;
10357             }
10358           mask_image=CloneImage(argument_list[0].image_reference,0,0,
10359             MagickTrue,exception);
10360           (void) NegateImage(mask_image,MagickFalse,exception);
10361           (void) SetImageMask(image,mask_image,exception);
10362           mask_image=DestroyImage(mask_image);
10363           break;
10364         }
10365         case 110:  /* Polaroid */
10366         {
10367           char
10368             *caption;
10369
10370           DrawInfo
10371             *draw_info;
10372
10373           double
10374             angle;
10375
10376           PixelInterpolateMethod
10377             method;
10378
10379           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10380             (DrawInfo *) NULL);
10381           caption=(char *) NULL;
10382           if (attribute_flag[0] != 0)
10383             caption=InterpretImageProperties(info ? info->image_info :
10384               (ImageInfo *) NULL,image,argument_list[0].string_reference,
10385               exception);
10386           angle=0.0;
10387           if (attribute_flag[1] != 0)
10388             angle=argument_list[1].real_reference;
10389           if (attribute_flag[2] != 0)
10390             (void) CloneString(&draw_info->font,
10391               argument_list[2].string_reference);
10392           if (attribute_flag[3] != 0)
10393             (void) QueryColorCompliance(argument_list[3].string_reference,
10394               AllCompliance,&draw_info->stroke,exception);
10395           if (attribute_flag[4] != 0)
10396             (void) QueryColorCompliance(argument_list[4].string_reference,
10397               AllCompliance,&draw_info->fill,exception);
10398           if (attribute_flag[5] != 0)
10399             draw_info->stroke_width=argument_list[5].real_reference;
10400           if (attribute_flag[6] != 0)
10401             draw_info->pointsize=argument_list[6].real_reference;
10402           if (attribute_flag[7] != 0)
10403             draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10404           if (attribute_flag[8] != 0)
10405             (void) QueryColorCompliance(argument_list[8].string_reference,
10406               AllCompliance,&image->background_color,exception);
10407           method=UndefinedInterpolatePixel;
10408           if (attribute_flag[9] != 0)
10409             method=(PixelInterpolateMethod) argument_list[9].integer_reference;
10410           image=PolaroidImage(image,draw_info,caption,angle,method,exception);
10411           draw_info=DestroyDrawInfo(draw_info);
10412           if (caption != (char *) NULL)
10413             caption=DestroyString(caption);
10414           break;
10415         }
10416         case 111:  /* FloodfillPaint */
10417         {
10418           DrawInfo
10419             *draw_info;
10420
10421           MagickBooleanType
10422             invert;
10423
10424           PixelInfo
10425             target;
10426
10427           draw_info=CloneDrawInfo(info ? info->image_info :
10428             (ImageInfo *) NULL,(DrawInfo *) NULL);
10429           if (attribute_flag[0] != 0)
10430             flags=ParsePageGeometry(image,argument_list[0].string_reference,
10431               &geometry,exception);
10432           if (attribute_flag[1] != 0)
10433             geometry.x=argument_list[1].integer_reference;
10434           if (attribute_flag[2] != 0)
10435             geometry.y=argument_list[2].integer_reference;
10436           if (attribute_flag[3] != 0)
10437             (void) QueryColorCompliance(argument_list[3].string_reference,
10438               AllCompliance,&draw_info->fill,exception);
10439           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
10440             geometry.x,geometry.y,&target,exception);
10441           if (attribute_flag[4] != 0)
10442             QueryColorCompliance(argument_list[4].string_reference,
10443               AllCompliance,&target,exception);
10444           if (attribute_flag[5] != 0)
10445             image->fuzz=StringToDoubleInterval(
10446               argument_list[5].string_reference,(double) QuantumRange+1.0);
10447           if (attribute_flag[6] != 0)
10448             channel=(ChannelType) argument_list[6].integer_reference;
10449           invert=MagickFalse;
10450           if (attribute_flag[7] != 0)
10451             invert=(MagickBooleanType) argument_list[7].integer_reference;
10452           channel_mask=SetImageChannelMask(image,channel);
10453           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10454             geometry.y,invert,exception);
10455           (void) SetImageChannelMask(image,channel_mask);
10456           draw_info=DestroyDrawInfo(draw_info);
10457           break;
10458         }
10459         case 112:  /* Distort */
10460         {
10461           AV
10462             *av;
10463
10464           double
10465             *coordinates;
10466
10467           DistortImageMethod
10468             method;
10469
10470           size_t
10471             number_coordinates;
10472
10473           VirtualPixelMethod
10474             virtual_pixel;
10475
10476           if (attribute_flag[0] == 0)
10477             break;
10478           method=UndefinedDistortion;
10479           if (attribute_flag[1] != 0)
10480             method=(DistortImageMethod) argument_list[1].integer_reference;
10481           av=(AV *) argument_list[0].array_reference;
10482           number_coordinates=(size_t) av_len(av)+1;
10483           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10484             sizeof(*coordinates));
10485           if (coordinates == (double *) NULL)
10486             {
10487               ThrowPerlException(exception,ResourceLimitFatalError,
10488                 "MemoryAllocationFailed",PackageName);
10489               goto PerlException;
10490             }
10491           for (j=0; j < (ssize_t) number_coordinates; j++)
10492             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10493           virtual_pixel=UndefinedVirtualPixelMethod;
10494           if (attribute_flag[2] != 0)
10495             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10496               argument_list[2].integer_reference,exception);
10497           image=DistortImage(image,method,number_coordinates,coordinates,
10498             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10499             exception);
10500           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10501             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10502               exception);
10503           coordinates=(double *) RelinquishMagickMemory(coordinates);
10504           break;
10505         }
10506         case 113:  /* Clut */
10507         {
10508           PixelInterpolateMethod
10509             method;
10510
10511           if (attribute_flag[0] == 0)
10512             {
10513               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10514                 PackageName);
10515               goto PerlException;
10516             }
10517           method=UndefinedInterpolatePixel;
10518           if (attribute_flag[1] != 0)
10519             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
10520           if (attribute_flag[2] != 0)
10521             channel=(ChannelType) argument_list[2].integer_reference;
10522           channel_mask=SetImageChannelMask(image,channel);
10523           (void) ClutImage(image,argument_list[0].image_reference,method,
10524             exception);
10525           (void) SetImageChannelMask(image,channel_mask);
10526           break;
10527         }
10528         case 114:  /* LiquidRescale */
10529         {
10530           if (attribute_flag[0] != 0)
10531             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10532               &geometry,exception);
10533           if (attribute_flag[1] != 0)
10534             geometry.width=argument_list[1].integer_reference;
10535           if (attribute_flag[2] != 0)
10536             geometry.height=argument_list[2].integer_reference;
10537           if (attribute_flag[3] == 0)
10538             argument_list[3].real_reference=1.0;
10539           if (attribute_flag[4] == 0)
10540             argument_list[4].real_reference=0.0;
10541           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10542             argument_list[3].real_reference,argument_list[4].real_reference,
10543             exception);
10544           break;
10545         }
10546         case 115:  /* EncipherImage */
10547         {
10548           (void) EncipherImage(image,argument_list[0].string_reference,
10549             exception);
10550           break;
10551         }
10552         case 116:  /* DecipherImage */
10553         {
10554           (void) DecipherImage(image,argument_list[0].string_reference,
10555             exception);
10556           break;
10557         }
10558         case 117:  /* Deskew */
10559         {
10560           geometry_info.rho=QuantumRange/2.0;
10561           if (attribute_flag[0] != 0)
10562             flags=ParseGeometry(argument_list[0].string_reference,
10563               &geometry_info);
10564           if (attribute_flag[1] != 0)
10565             geometry_info.rho=StringToDoubleInterval(
10566               argument_list[1].string_reference,(double) QuantumRange+1.0);
10567           image=DeskewImage(image,geometry_info.rho,exception);
10568           break;
10569         }
10570         case 118:  /* Remap */
10571         {
10572           QuantizeInfo
10573             *quantize_info;
10574
10575           if (attribute_flag[0] == 0)
10576             {
10577               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10578                 PackageName);
10579               goto PerlException;
10580             }
10581           quantize_info=AcquireQuantizeInfo(info->image_info);
10582           if (attribute_flag[1] != 0)
10583             quantize_info->dither_method=(DitherMethod)
10584               argument_list[1].integer_reference;
10585           (void) RemapImages(quantize_info,image,
10586             argument_list[0].image_reference,exception);
10587           quantize_info=DestroyQuantizeInfo(quantize_info);
10588           break;
10589         }
10590         case 119:  /* SparseColor */
10591         {
10592           AV
10593             *av;
10594
10595           double
10596             *coordinates;
10597
10598           SparseColorMethod
10599             method;
10600
10601           size_t
10602             number_coordinates;
10603
10604           VirtualPixelMethod
10605             virtual_pixel;
10606
10607           if (attribute_flag[0] == 0)
10608             break;
10609           method=UndefinedColorInterpolate;
10610           if (attribute_flag[1] != 0)
10611             method=(SparseColorMethod) argument_list[1].integer_reference;
10612           av=(AV *) argument_list[0].array_reference;
10613           number_coordinates=(size_t) av_len(av)+1;
10614           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10615             sizeof(*coordinates));
10616           if (coordinates == (double *) NULL)
10617             {
10618               ThrowPerlException(exception,ResourceLimitFatalError,
10619                 "MemoryAllocationFailed",PackageName);
10620               goto PerlException;
10621             }
10622           for (j=0; j < (ssize_t) number_coordinates; j++)
10623             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10624           virtual_pixel=UndefinedVirtualPixelMethod;
10625           if (attribute_flag[2] != 0)
10626             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10627               argument_list[2].integer_reference,exception);
10628           if (attribute_flag[3] != 0)
10629             channel=(ChannelType) argument_list[3].integer_reference;
10630           channel_mask=SetImageChannelMask(image,channel);
10631           image=SparseColorImage(image,method,number_coordinates,coordinates,
10632             exception);
10633           if (image != (Image *) NULL)
10634             (void) SetImageChannelMask(image,channel_mask);
10635           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10636             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10637               exception);
10638           coordinates=(double *) RelinquishMagickMemory(coordinates);
10639           break;
10640         }
10641         case 120:  /* Function */
10642         {
10643           AV
10644             *av;
10645
10646           double
10647             *parameters;
10648
10649           MagickFunction
10650             function;
10651
10652           size_t
10653             number_parameters;
10654
10655           VirtualPixelMethod
10656             virtual_pixel;
10657
10658           if (attribute_flag[0] == 0)
10659             break;
10660           function=UndefinedFunction;
10661           if (attribute_flag[1] != 0)
10662             function=(MagickFunction) argument_list[1].integer_reference;
10663           av=(AV *) argument_list[0].array_reference;
10664           number_parameters=(size_t) av_len(av)+1;
10665           parameters=(double *) AcquireQuantumMemory(number_parameters,
10666             sizeof(*parameters));
10667           if (parameters == (double *) NULL)
10668             {
10669               ThrowPerlException(exception,ResourceLimitFatalError,
10670                 "MemoryAllocationFailed",PackageName);
10671               goto PerlException;
10672             }
10673           for (j=0; j < (ssize_t) number_parameters; j++)
10674             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10675           virtual_pixel=UndefinedVirtualPixelMethod;
10676           if (attribute_flag[2] != 0)
10677             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10678               argument_list[2].integer_reference,exception);
10679           (void) FunctionImage(image,function,number_parameters,parameters,
10680             exception);
10681           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10682             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10683               exception);
10684           parameters=(double *) RelinquishMagickMemory(parameters);
10685           break;
10686         }
10687         case 121:  /* SelectiveBlur */
10688         {
10689           if (attribute_flag[0] != 0)
10690             {
10691               flags=ParseGeometry(argument_list[0].string_reference,
10692                 &geometry_info);
10693               if ((flags & SigmaValue) == 0)
10694                 geometry_info.sigma=1.0;
10695               if ((flags & PercentValue) != 0)
10696                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10697             }
10698           if (attribute_flag[1] != 0)
10699             geometry_info.rho=argument_list[1].real_reference;
10700           if (attribute_flag[2] != 0)
10701             geometry_info.sigma=argument_list[2].real_reference;
10702           if (attribute_flag[3] != 0)
10703             geometry_info.xi=argument_list[3].integer_reference;;
10704           if (attribute_flag[5] != 0)
10705             channel=(ChannelType) argument_list[5].integer_reference;
10706           channel_mask=SetImageChannelMask(image,channel);
10707           image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10708             geometry_info.xi,exception);
10709           if (image != (Image *) NULL)
10710             (void) SetImageChannelMask(image,channel_mask);
10711           break;
10712         }
10713         case 122:  /* HaldClut */
10714         {
10715           if (attribute_flag[0] == 0)
10716             {
10717               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10718                 PackageName);
10719               goto PerlException;
10720             }
10721           if (attribute_flag[1] != 0)
10722             channel=(ChannelType) argument_list[1].integer_reference;
10723           channel_mask=SetImageChannelMask(image,channel);
10724           (void) HaldClutImage(image,argument_list[0].image_reference,
10725             exception);
10726           (void) SetImageChannelMask(image,channel_mask);
10727           break;
10728         }
10729         case 123:  /* BlueShift */
10730         {
10731           if (attribute_flag[0] != 0)
10732             (void) ParseGeometry(argument_list[0].string_reference,
10733               &geometry_info);
10734           image=BlueShiftImage(image,geometry_info.rho,exception);
10735           break;
10736         }
10737         case 124:  /* ForwardFourierTransformImage */
10738         {
10739           image=ForwardFourierTransformImage(image,
10740             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10741             exception);
10742           break;
10743         }
10744         case 125:  /* InverseFourierTransformImage */
10745         {
10746           image=InverseFourierTransformImage(image,image->next,
10747             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10748             exception);
10749           break;
10750         }
10751         case 126:  /* ColorDecisionList */
10752         {
10753           if (attribute_flag[0] == 0)
10754             argument_list[0].string_reference=(char *) NULL;
10755           (void) ColorDecisionListImage(image,
10756             argument_list[0].string_reference,exception);
10757           break;
10758         }
10759         case 127:  /* AutoGamma */
10760         {
10761           if (attribute_flag[0] != 0)
10762             channel=(ChannelType) argument_list[0].integer_reference;
10763           channel_mask=SetImageChannelMask(image,channel);
10764           (void) AutoGammaImage(image,exception);
10765           (void) SetImageChannelMask(image,channel_mask);
10766           break;
10767         }
10768         case 128:  /* AutoLevel */
10769         {
10770           if (attribute_flag[0] != 0)
10771             channel=(ChannelType) argument_list[0].integer_reference;
10772           channel_mask=SetImageChannelMask(image,channel);
10773           (void) AutoLevelImage(image,exception);
10774           (void) SetImageChannelMask(image,channel_mask);
10775           break;
10776         }
10777         case 129:  /* LevelColors */
10778         {
10779           PixelInfo
10780             black_point,
10781             white_point;
10782
10783           (void) QueryColorCompliance("#000000",AllCompliance,&black_point,
10784             exception);
10785           (void) QueryColorCompliance("#ffffff",AllCompliance,&white_point,
10786             exception);
10787           if (attribute_flag[1] != 0)
10788              (void) QueryColorCompliance(
10789                argument_list[1].string_reference,AllCompliance,&black_point,
10790                exception);
10791           if (attribute_flag[2] != 0)
10792              (void) QueryColorCompliance(
10793                argument_list[2].string_reference,AllCompliance,&white_point,
10794                exception);
10795           if (attribute_flag[3] != 0)
10796             channel=(ChannelType) argument_list[3].integer_reference;
10797           channel_mask=SetImageChannelMask(image,channel);
10798           (void) LevelImageColors(image,&black_point,&white_point,
10799             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10800             exception);
10801           (void) SetImageChannelMask(image,channel_mask);
10802           break;
10803         }
10804         case 130:  /* Clamp */
10805         {
10806           if (attribute_flag[0] != 0)
10807             channel=(ChannelType) argument_list[0].integer_reference;
10808           channel_mask=SetImageChannelMask(image,channel);
10809           (void) ClampImage(image,exception);
10810           (void) SetImageChannelMask(image,channel_mask);
10811           break;
10812         }
10813         case 131:  /* BrightnessContrast */
10814         {
10815           double
10816             brightness,
10817             contrast;
10818
10819           brightness=0.0;
10820           contrast=0.0;
10821           if (attribute_flag[0] != 0)
10822             {
10823               flags=ParseGeometry(argument_list[0].string_reference,
10824                 &geometry_info);
10825               brightness=geometry_info.rho;
10826               if ((flags & SigmaValue) == 0)
10827                 contrast=geometry_info.sigma;
10828             }
10829           if (attribute_flag[1] != 0)
10830             brightness=argument_list[1].real_reference;
10831           if (attribute_flag[2] != 0)
10832             contrast=argument_list[2].real_reference;
10833           if (attribute_flag[4] != 0)
10834             channel=(ChannelType) argument_list[4].integer_reference;
10835           channel_mask=SetImageChannelMask(image,channel);
10836           (void) BrightnessContrastImage(image,brightness,contrast,exception);
10837           (void) SetImageChannelMask(image,channel_mask);
10838           break;
10839         }
10840         case 132:  /* Morphology */
10841         {
10842           KernelInfo
10843             *kernel;
10844
10845           MorphologyMethod
10846             method;
10847
10848           ssize_t
10849             iterations;
10850
10851           if (attribute_flag[0] == 0)
10852             break;
10853           kernel=AcquireKernelInfo(argument_list[0].string_reference);
10854           if (kernel == (KernelInfo *) NULL)
10855             break;
10856           if (attribute_flag[1] != 0)
10857             channel=(ChannelType) argument_list[1].integer_reference;
10858           method=UndefinedMorphology;
10859           if (attribute_flag[2] != 0)
10860             method=argument_list[2].integer_reference;
10861           iterations=1;
10862           if (attribute_flag[3] != 0)
10863             iterations=argument_list[3].integer_reference;
10864           channel_mask=SetImageChannelMask(image,channel);
10865           image=MorphologyImage(image,method,iterations,kernel,exception);
10866           if (image != (Image *) NULL)
10867             (void) SetImageChannelMask(image,channel_mask);
10868           kernel=DestroyKernelInfo(kernel);
10869           break;
10870         }
10871         case 133:  /* Mode */
10872         {
10873           if (attribute_flag[0] != 0)
10874             {
10875               flags=ParseGeometry(argument_list[0].string_reference,
10876                 &geometry_info);
10877               if ((flags & SigmaValue) == 0)
10878                 geometry_info.sigma=1.0;
10879             }
10880           if (attribute_flag[1] != 0)
10881             geometry_info.rho=argument_list[1].real_reference;
10882           if (attribute_flag[2] != 0)
10883             geometry_info.sigma=argument_list[2].real_reference;
10884           if (attribute_flag[3] != 0)
10885             channel=(ChannelType) argument_list[3].integer_reference;
10886           channel_mask=SetImageChannelMask(image,channel);
10887           image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
10888             (size_t) geometry_info.sigma,exception);
10889           if (image != (Image *) NULL)
10890             (void) SetImageChannelMask(image,channel_mask);
10891           break;
10892         }
10893         case 134:  /* Statistic */
10894         {
10895           StatisticType
10896             statistic;
10897
10898           statistic=UndefinedStatistic;
10899           if (attribute_flag[0] != 0)
10900             {
10901               flags=ParseGeometry(argument_list[0].string_reference,
10902                 &geometry_info);
10903               if ((flags & SigmaValue) == 0)
10904                 geometry_info.sigma=1.0;
10905             }
10906           if (attribute_flag[1] != 0)
10907             geometry_info.rho=argument_list[1].real_reference;
10908           if (attribute_flag[2] != 0)
10909             geometry_info.sigma=argument_list[2].real_reference;
10910           if (attribute_flag[3] != 0)
10911             channel=(ChannelType) argument_list[3].integer_reference;
10912           if (attribute_flag[4] != 0)
10913             statistic=(StatisticType) argument_list[4].integer_reference;
10914           channel_mask=SetImageChannelMask(image,channel);
10915           image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
10916             (size_t) geometry_info.sigma,exception);
10917           if (image != (Image *) NULL)
10918             (void) SetImageChannelMask(image,channel_mask);
10919           break;
10920         }
10921         case 135:  /* Perceptible */
10922         {
10923           double
10924             epsilon;
10925
10926           epsilon=MagickEpsilon;
10927           if (attribute_flag[0] != 0)
10928             epsilon=argument_list[0].real_reference;
10929           if (attribute_flag[1] != 0)
10930             channel=(ChannelType) argument_list[1].integer_reference;
10931           channel_mask=SetImageChannelMask(image,channel);
10932           (void) PerceptibleImage(image,epsilon,exception);
10933           (void) SetImageChannelMask(image,channel_mask);
10934           break;
10935         }
10936         case 136:  /* Poly */
10937         {
10938           AV
10939             *av;
10940
10941           double
10942             *terms;
10943
10944           size_t
10945             number_terms;
10946
10947           if (attribute_flag[0] == 0)
10948             break;
10949           if (attribute_flag[1] != 0)
10950             channel=(ChannelType) argument_list[1].integer_reference;
10951           av=(AV *) argument_list[0].array_reference;
10952           number_terms=(size_t) av_len(av);
10953           terms=(double *) AcquireQuantumMemory(number_terms,sizeof(*terms));
10954           if (terms == (double *) NULL)
10955             {
10956               ThrowPerlException(exception,ResourceLimitFatalError,
10957                 "MemoryAllocationFailed",PackageName);
10958               goto PerlException;
10959             }
10960           for (j=0; j < av_len(av); j++)
10961             terms[j]=(double) SvNV(*(av_fetch(av,j,0)));
10962           image=PolynomialImage(image,number_terms >> 1,terms,exception);
10963           terms=(double *) RelinquishMagickMemory(terms);
10964           break;
10965         }
10966       }
10967       if (next != (Image *) NULL)
10968         (void) CatchImageException(next);
10969       if (region_image != (Image *) NULL)
10970         {
10971           /*
10972             Composite region.
10973           */ 
10974           status=CompositeImage(region_image,image,CopyCompositeOp,MagickTrue,
10975             region_info.x,region_info.y,exception);
10976           (void) status;
10977           (void) CatchImageException(region_image);
10978           image=DestroyImage(image);
10979           image=region_image;
10980         }
10981       if (image != (Image *) NULL)
10982         {
10983           number_images++;
10984           if (next && (next != image))
10985             {
10986               image->next=next->next;
10987               if (image->next != (Image *) NULL)
10988                 image->next->previous=image;
10989               DeleteImageFromRegistry(*pv,next);
10990             }
10991           sv_setiv(*pv,PTR2IV(image));
10992           next=image;
10993         }
10994       if (*pv)
10995         pv++;
10996     }
10997
10998   PerlException:
10999     if (reference_vector)
11000       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
11001     InheritPerlException(exception,perl_exception);
11002     exception=DestroyExceptionInfo(exception);
11003     sv_setiv(perl_exception,(IV) number_images);
11004     SvPOK_on(perl_exception);
11005     ST(0)=sv_2mortal(perl_exception);
11006     XSRETURN(1);
11007   }
11008 \f
11009 #
11010 ###############################################################################
11011 #                                                                             #
11012 #                                                                             #
11013 #                                                                             #
11014 #   M o n t a g e                                                             #
11015 #                                                                             #
11016 #                                                                             #
11017 #                                                                             #
11018 ###############################################################################
11019 #
11020 #
11021 void
11022 Montage(ref,...)
11023   Image::Magick ref=NO_INIT
11024   ALIAS:
11025     MontageImage  = 1
11026     montage       = 2
11027     montageimage  = 3
11028   PPCODE:
11029   {
11030     AV
11031       *av;
11032
11033     char
11034       *attribute;
11035
11036     ExceptionInfo
11037       *exception;
11038
11039     HV
11040       *hv;
11041
11042     Image
11043       *image,
11044       *next;
11045
11046     PixelInfo
11047       transparent_color;
11048
11049     MontageInfo
11050       *montage_info;
11051
11052     register ssize_t
11053       i;
11054
11055     ssize_t
11056       sp;
11057
11058     struct PackageInfo
11059       *info;
11060
11061     SV
11062       *av_reference,
11063       *perl_exception,
11064       *reference,
11065       *rv,
11066       *sv;
11067
11068     PERL_UNUSED_VAR(ref);
11069     PERL_UNUSED_VAR(ix);
11070     exception=AcquireExceptionInfo();
11071     perl_exception=newSVpv("",0);
11072     sv=NULL;
11073     attribute=NULL;
11074     if (sv_isobject(ST(0)) == 0)
11075       {
11076         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11077           PackageName);
11078         goto PerlException;
11079       }
11080     reference=SvRV(ST(0));
11081     hv=SvSTASH(reference);
11082     av=newAV();
11083     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11084     SvREFCNT_dec(av);
11085     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11086     if (image == (Image *) NULL)
11087       {
11088         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11089           PackageName);
11090         goto PerlException;
11091       }
11092     /*
11093       Get options.
11094     */
11095     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11096     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
11097     (void) QueryColorCompliance("none",AllCompliance,&transparent_color,
11098       exception);
11099     for (i=2; i < items; i+=2)
11100     {
11101       attribute=(char *) SvPV(ST(i-1),na);
11102       switch (*attribute)
11103       {
11104         case 'B':
11105         case 'b':
11106         {
11107           if (LocaleCompare(attribute,"background") == 0)
11108             {
11109               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11110                 &montage_info->background_color,exception);
11111               for (next=image; next; next=next->next)
11112                 next->background_color=montage_info->background_color;
11113               break;
11114             }
11115           if (LocaleCompare(attribute,"border") == 0)
11116             {
11117               montage_info->border_width=SvIV(ST(i));
11118               break;
11119             }
11120           if (LocaleCompare(attribute,"bordercolor") == 0)
11121             {
11122               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11123                 &montage_info->border_color,exception);
11124               for (next=image; next; next=next->next)
11125                 next->border_color=montage_info->border_color;
11126               break;
11127             }
11128           if (LocaleCompare(attribute,"borderwidth") == 0)
11129             {
11130               montage_info->border_width=SvIV(ST(i));
11131               break;
11132             }
11133           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11134             attribute);
11135           break;
11136         }
11137         case 'C':
11138         case 'c':
11139         {
11140           if (LocaleCompare(attribute,"compose") == 0)
11141             {
11142               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11143                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
11144               if (sp < 0)
11145                 {
11146                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11147                     SvPV(ST(i),na));
11148                   break;
11149                 }
11150               for (next=image; next; next=next->next)
11151                 next->compose=(CompositeOperator) sp;
11152               break;
11153             }
11154           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11155             attribute);
11156           break;
11157         }
11158         case 'F':
11159         case 'f':
11160         {
11161           if (LocaleCompare(attribute,"fill") == 0)
11162             {
11163               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11164                 &montage_info->fill,exception);
11165               break;
11166             }
11167           if (LocaleCompare(attribute,"font") == 0)
11168             {
11169               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
11170               break;
11171             }
11172           if (LocaleCompare(attribute,"frame") == 0)
11173             {
11174               char
11175                 *p;
11176
11177               p=SvPV(ST(i),na);
11178               if (IsGeometry(p) == MagickFalse)
11179                 {
11180                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11181                     p);
11182                   break;
11183                 }
11184               (void) CloneString(&montage_info->frame,p);
11185               if (*p == '\0')
11186                 montage_info->frame=(char *) NULL;
11187               break;
11188             }
11189           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11190             attribute);
11191           break;
11192         }
11193         case 'G':
11194         case 'g':
11195         {
11196           if (LocaleCompare(attribute,"geometry") == 0)
11197             {
11198               char
11199                 *p;
11200
11201               p=SvPV(ST(i),na);
11202               if (IsGeometry(p) == MagickFalse)
11203                 {
11204                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11205                     p);
11206                   break;
11207                 }
11208              (void) CloneString(&montage_info->geometry,p);
11209              if (*p == '\0')
11210                montage_info->geometry=(char *) NULL;
11211              break;
11212            }
11213          if (LocaleCompare(attribute,"gravity") == 0)
11214            {
11215              ssize_t
11216                in;
11217
11218              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11219                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11220              if (in < 0)
11221                {
11222                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
11223                    SvPV(ST(i),na));
11224                  return;
11225                }
11226              montage_info->gravity=(GravityType) in;
11227              for (next=image; next; next=next->next)
11228                next->gravity=(GravityType) in;
11229              break;
11230            }
11231           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11232             attribute);
11233           break;
11234         }
11235         case 'L':
11236         case 'l':
11237         {
11238           if (LocaleCompare(attribute,"label") == 0)
11239             {
11240               for (next=image; next; next=next->next)
11241                 (void) SetImageProperty(next,"label",InterpretImageProperties(
11242                   info ? info->image_info : (ImageInfo *) NULL,next,
11243                   SvPV(ST(i),na),exception),exception);
11244               break;
11245             }
11246           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11247             attribute);
11248           break;
11249         }
11250         case 'M':
11251         case 'm':
11252         {
11253           if (LocaleCompare(attribute,"mattecolor") == 0)
11254             {
11255               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11256                 &montage_info->matte_color,exception);
11257               for (next=image; next; next=next->next)
11258                 next->matte_color=montage_info->matte_color;
11259               break;
11260             }
11261           if (LocaleCompare(attribute,"mode") == 0)
11262             {
11263               ssize_t
11264                 in;
11265
11266               in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11267                 MagickModeOptions,MagickFalse,SvPV(ST(i),na));
11268               switch (in)
11269               {
11270                 default:
11271                 {
11272                   ThrowPerlException(exception,OptionError,
11273                     "UnrecognizedModeType",SvPV(ST(i),na));
11274                   break;
11275                 }
11276                 case FrameMode:
11277                 {
11278                   (void) CloneString(&montage_info->frame,"15x15+3+3");
11279                   montage_info->shadow=MagickTrue;
11280                   break;
11281                 }
11282                 case UnframeMode:
11283                 {
11284                   montage_info->frame=(char *) NULL;
11285                   montage_info->shadow=MagickFalse;
11286                   montage_info->border_width=0;
11287                   break;
11288                 }
11289                 case ConcatenateMode:
11290                 {
11291                   montage_info->frame=(char *) NULL;
11292                   montage_info->shadow=MagickFalse;
11293                   (void) CloneString(&montage_info->geometry,"+0+0");
11294                   montage_info->border_width=0;
11295                 }
11296               }
11297               break;
11298             }
11299           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11300             attribute);
11301           break;
11302         }
11303         case 'P':
11304         case 'p':
11305         {
11306           if (LocaleCompare(attribute,"pointsize") == 0)
11307             {
11308               montage_info->pointsize=SvIV(ST(i));
11309               break;
11310             }
11311           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11312             attribute);
11313           break;
11314         }
11315         case 'S':
11316         case 's':
11317         {
11318           if (LocaleCompare(attribute,"shadow") == 0)
11319             {
11320               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11321                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11322               if (sp < 0)
11323                 {
11324                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11325                     SvPV(ST(i),na));
11326                   break;
11327                 }
11328              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11329              break;
11330             }
11331           if (LocaleCompare(attribute,"stroke") == 0)
11332             {
11333               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11334                 &montage_info->stroke,exception);
11335               break;
11336             }
11337           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11338             attribute);
11339           break;
11340         }
11341         case 'T':
11342         case 't':
11343         {
11344           if (LocaleCompare(attribute,"texture") == 0)
11345             {
11346               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11347               break;
11348             }
11349           if (LocaleCompare(attribute,"tile") == 0)
11350             {
11351               char *p=SvPV(ST(i),na);
11352               if (IsGeometry(p) == MagickFalse)
11353                 {
11354                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11355                     p);
11356                   break;
11357                 }
11358               (void) CloneString(&montage_info->tile,p);
11359               if (*p == '\0')
11360                 montage_info->tile=(char *) NULL;
11361               break;
11362             }
11363           if (LocaleCompare(attribute,"title") == 0)
11364             {
11365               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11366               break;
11367             }
11368           if (LocaleCompare(attribute,"transparent") == 0)
11369             {
11370               PixelInfo
11371                 transparent_color;
11372
11373               QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11374                 &transparent_color,exception);
11375               for (next=image; next; next=next->next)
11376                 (void) TransparentPaintImage(next,&transparent_color,
11377                   TransparentAlpha,MagickFalse,exception);
11378               break;
11379             }
11380           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11381             attribute);
11382           break;
11383         }
11384         default:
11385         {
11386           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11387             attribute);
11388           break;
11389         }
11390       }
11391     }
11392     image=MontageImageList(info->image_info,montage_info,image,exception);
11393     montage_info=DestroyMontageInfo(montage_info);
11394     if (image == (Image *) NULL)
11395       goto PerlException;
11396     if (transparent_color.alpha != TransparentAlpha)
11397       for (next=image; next; next=next->next)
11398         (void) TransparentPaintImage(next,&transparent_color,
11399           TransparentAlpha,MagickFalse,exception);
11400     for (  ; image; image=image->next)
11401     {
11402       AddImageToRegistry(sv,image);
11403       rv=newRV(sv);
11404       av_push(av,sv_bless(rv,hv));
11405       SvREFCNT_dec(sv);
11406     }
11407     exception=DestroyExceptionInfo(exception);
11408     ST(0)=av_reference;
11409     SvREFCNT_dec(perl_exception);
11410     XSRETURN(1);
11411
11412   PerlException:
11413     InheritPerlException(exception,perl_exception);
11414     exception=DestroyExceptionInfo(exception);
11415     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11416     SvPOK_on(perl_exception);
11417     ST(0)=sv_2mortal(perl_exception);
11418     XSRETURN(1);
11419   }
11420 \f
11421 #
11422 ###############################################################################
11423 #                                                                             #
11424 #                                                                             #
11425 #                                                                             #
11426 #   M o r p h                                                                 #
11427 #                                                                             #
11428 #                                                                             #
11429 #                                                                             #
11430 ###############################################################################
11431 #
11432 #
11433 void
11434 Morph(ref,...)
11435   Image::Magick ref=NO_INIT
11436   ALIAS:
11437     MorphImage  = 1
11438     morph       = 2
11439     morphimage  = 3
11440   PPCODE:
11441   {
11442     AV
11443       *av;
11444
11445     char
11446       *attribute;
11447
11448     ExceptionInfo
11449       *exception;
11450
11451     HV
11452       *hv;
11453
11454     Image
11455       *image;
11456
11457     register ssize_t
11458       i;
11459
11460     ssize_t
11461       number_frames;
11462
11463     struct PackageInfo
11464       *info;
11465
11466     SV
11467       *av_reference,
11468       *perl_exception,
11469       *reference,
11470       *rv,
11471       *sv;
11472
11473     PERL_UNUSED_VAR(ref);
11474     PERL_UNUSED_VAR(ix);
11475     exception=AcquireExceptionInfo();
11476     perl_exception=newSVpv("",0);
11477     sv=NULL;
11478     av=NULL;
11479     attribute=NULL;
11480     if (sv_isobject(ST(0)) == 0)
11481       {
11482         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11483           PackageName);
11484         goto PerlException;
11485       }
11486     reference=SvRV(ST(0));
11487     hv=SvSTASH(reference);
11488     av=newAV();
11489     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11490     SvREFCNT_dec(av);
11491     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11492     if (image == (Image *) NULL)
11493       {
11494         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11495           PackageName);
11496         goto PerlException;
11497       }
11498     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11499     /*
11500       Get attribute.
11501     */
11502     number_frames=30;
11503     for (i=2; i < items; i+=2)
11504     {
11505       attribute=(char *) SvPV(ST(i-1),na);
11506       switch (*attribute)
11507       {
11508         case 'F':
11509         case 'f':
11510         {
11511           if (LocaleCompare(attribute,"frames") == 0)
11512             {
11513               number_frames=SvIV(ST(i));
11514               break;
11515             }
11516           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11517             attribute);
11518           break;
11519         }
11520         default:
11521         {
11522           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11523             attribute);
11524           break;
11525         }
11526       }
11527     }
11528     image=MorphImages(image,number_frames,exception);
11529     if (image == (Image *) NULL)
11530       goto PerlException;
11531     for ( ; image; image=image->next)
11532     {
11533       AddImageToRegistry(sv,image);
11534       rv=newRV(sv);
11535       av_push(av,sv_bless(rv,hv));
11536       SvREFCNT_dec(sv);
11537     }
11538     exception=DestroyExceptionInfo(exception);
11539     ST(0)=av_reference;
11540     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11541     XSRETURN(1);
11542
11543   PerlException:
11544     InheritPerlException(exception,perl_exception);
11545     exception=DestroyExceptionInfo(exception);
11546     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11547     SvPOK_on(perl_exception);
11548     ST(0)=sv_2mortal(perl_exception);
11549     XSRETURN(1);
11550   }
11551 \f
11552 #
11553 ###############################################################################
11554 #                                                                             #
11555 #                                                                             #
11556 #                                                                             #
11557 #   M o s a i c                                                               #
11558 #                                                                             #
11559 #                                                                             #
11560 #                                                                             #
11561 ###############################################################################
11562 #
11563 #
11564 void
11565 Mosaic(ref)
11566   Image::Magick ref=NO_INIT
11567   ALIAS:
11568     MosaicImage   = 1
11569     mosaic        = 2
11570     mosaicimage   = 3
11571   PPCODE:
11572   {
11573     AV
11574       *av;
11575
11576     ExceptionInfo
11577       *exception;
11578
11579     HV
11580       *hv;
11581
11582     Image
11583       *image;
11584
11585     struct PackageInfo
11586       *info;
11587
11588     SV
11589       *perl_exception,
11590       *reference,
11591       *rv,
11592       *sv;
11593
11594     PERL_UNUSED_VAR(ref);
11595     PERL_UNUSED_VAR(ix);
11596     exception=AcquireExceptionInfo();
11597     perl_exception=newSVpv("",0);
11598     sv=NULL;
11599     if (sv_isobject(ST(0)) == 0)
11600       {
11601         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11602           PackageName);
11603         goto PerlException;
11604       }
11605     reference=SvRV(ST(0));
11606     hv=SvSTASH(reference);
11607     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11608     if (image == (Image *) NULL)
11609       {
11610         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11611           PackageName);
11612         goto PerlException;
11613       }
11614     image=MergeImageLayers(image,MosaicLayer,exception);
11615     /*
11616       Create blessed Perl array for the returned image.
11617     */
11618     av=newAV();
11619     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11620     SvREFCNT_dec(av);
11621     AddImageToRegistry(sv,image);
11622     rv=newRV(sv);
11623     av_push(av,sv_bless(rv,hv));
11624     SvREFCNT_dec(sv);
11625     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11626     (void) CopyMagickString(info->image_info->filename,image->filename,
11627       MaxTextExtent);
11628     SetImageInfo(info->image_info,0,exception);
11629     exception=DestroyExceptionInfo(exception);
11630     SvREFCNT_dec(perl_exception);
11631     XSRETURN(1);
11632
11633   PerlException:
11634     InheritPerlException(exception,perl_exception);
11635     exception=DestroyExceptionInfo(exception);
11636     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11637     SvPOK_on(perl_exception);  /* return messages in string context */
11638     ST(0)=sv_2mortal(perl_exception);
11639     XSRETURN(1);
11640   }
11641 \f
11642 #
11643 ###############################################################################
11644 #                                                                             #
11645 #                                                                             #
11646 #                                                                             #
11647 #   P i n g                                                                   #
11648 #                                                                             #
11649 #                                                                             #
11650 #                                                                             #
11651 ###############################################################################
11652 #
11653 #
11654 void
11655 Ping(ref,...)
11656   Image::Magick ref=NO_INIT
11657   ALIAS:
11658     PingImage  = 1
11659     ping       = 2
11660     pingimage  = 3
11661   PPCODE:
11662   {
11663     AV
11664       *av;
11665
11666     char
11667       **keep,
11668       **list;
11669
11670     ExceptionInfo
11671       *exception;
11672
11673     Image
11674       *image,
11675       *next;
11676
11677     int
11678       n;
11679
11680     MagickBooleanType
11681       status;
11682
11683     register char
11684       **p;
11685
11686     register ssize_t
11687       i;
11688
11689     ssize_t
11690       ac;
11691
11692     STRLEN
11693       *length;
11694
11695     struct PackageInfo
11696       *info,
11697       *package_info;
11698
11699     SV
11700       *perl_exception,
11701       *reference;
11702
11703     size_t
11704       count;
11705
11706     PERL_UNUSED_VAR(ref);
11707     PERL_UNUSED_VAR(ix);
11708     exception=AcquireExceptionInfo();
11709     perl_exception=newSVpv("",0);
11710     package_info=(struct PackageInfo *) NULL;
11711     ac=(items < 2) ? 1 : items-1;
11712     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
11713     keep=list;
11714     length=(STRLEN *) NULL;
11715     if (list == (char **) NULL)
11716       {
11717         ThrowPerlException(exception,ResourceLimitError,
11718           "MemoryAllocationFailed",PackageName);
11719         goto PerlException;
11720       }
11721     keep=list;
11722     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
11723     if (length == (STRLEN *) NULL)
11724       {
11725         ThrowPerlException(exception,ResourceLimitError,
11726           "MemoryAllocationFailed",PackageName);
11727         goto PerlException;
11728       }
11729     if (sv_isobject(ST(0)) == 0)
11730       {
11731         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11732           PackageName);
11733         goto PerlException;
11734       }
11735     reference=SvRV(ST(0));
11736     if (SvTYPE(reference) != SVt_PVAV)
11737       {
11738         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11739           PackageName);
11740         goto PerlException;
11741       }
11742     av=(AV *) reference;
11743     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11744       exception);
11745     package_info=ClonePackageInfo(info,exception);
11746     n=1;
11747     if (items <= 1)
11748       *list=(char *) (*package_info->image_info->filename ?
11749         package_info->image_info->filename : "XC:black");
11750     else
11751       for (n=0, i=0; i < ac; i++)
11752       {
11753         list[n]=(char *) SvPV(ST(i+1),length[n]);
11754         if ((items >= 3) && strEQcase(list[n],"blob"))
11755           {
11756             void
11757               *blob;
11758
11759             i++;
11760             blob=(void *) (SvPV(ST(i+1),length[n]));
11761             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
11762           }
11763         if ((items >= 3) && strEQcase(list[n],"filename"))
11764           continue;
11765         if ((items >= 3) && strEQcase(list[n],"file"))
11766           {
11767             FILE
11768               *file;
11769
11770             PerlIO
11771               *io_info;
11772
11773             i++;
11774             io_info=IoIFP(sv_2io(ST(i+1)));
11775             if (io_info == (PerlIO *) NULL)
11776               {
11777                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11778                   PackageName);
11779                 continue;
11780               }
11781             file=PerlIO_findFILE(io_info);
11782             if (file == (FILE *) NULL)
11783               {
11784                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11785                   PackageName);
11786                 continue;
11787               }
11788             SetImageInfoFile(package_info->image_info,file);
11789           }
11790         if ((items >= 3) && strEQcase(list[n],"magick"))
11791           continue;
11792         n++;
11793       }
11794     list[n]=(char *) NULL;
11795     keep=list;
11796     status=ExpandFilenames(&n,&list);
11797     if (status == MagickFalse)
11798       {
11799         ThrowPerlException(exception,ResourceLimitError,
11800           "MemoryAllocationFailed",PackageName);
11801         goto PerlException;
11802       }
11803     count=0;
11804     for (i=0; i < n; i++)
11805     {
11806       (void) CopyMagickString(package_info->image_info->filename,list[i],
11807         MaxTextExtent);
11808       image=PingImage(package_info->image_info,exception);
11809       if (image == (Image *) NULL)
11810         break;
11811       if ((package_info->image_info->file != (FILE *) NULL) ||
11812           (package_info->image_info->blob != (void *) NULL))
11813         DisassociateImageStream(image);
11814       count+=GetImageListLength(image);
11815       EXTEND(sp,4*count);
11816       for (next=image; next; next=next->next)
11817       {
11818         PUSHs(sv_2mortal(newSViv(next->columns)));
11819         PUSHs(sv_2mortal(newSViv(next->rows)));
11820         PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
11821         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
11822       }
11823       image=DestroyImageList(image);
11824     }
11825     /*
11826       Free resources.
11827     */
11828     for (i=0; i < n; i++)
11829       if (list[i] != (char *) NULL)
11830         for (p=keep; list[i] != *p++; )
11831           if (*p == NULL)
11832             {
11833               list[i]=(char *) RelinquishMagickMemory(list[i]);
11834               break;
11835             }
11836
11837   PerlException:
11838     if (package_info != (struct PackageInfo *) NULL)
11839       DestroyPackageInfo(package_info);
11840     if (list && (list != keep))
11841       list=(char **) RelinquishMagickMemory(list);
11842     if (keep)
11843       keep=(char **) RelinquishMagickMemory(keep);
11844     if (length)
11845       length=(STRLEN *) RelinquishMagickMemory(length);
11846     InheritPerlException(exception,perl_exception);
11847     exception=DestroyExceptionInfo(exception);
11848     SvREFCNT_dec(perl_exception);  /* throw away all errors */
11849   }
11850 \f
11851 #
11852 ###############################################################################
11853 #                                                                             #
11854 #                                                                             #
11855 #                                                                             #
11856 #   P r e v i e w                                                             #
11857 #                                                                             #
11858 #                                                                             #
11859 #                                                                             #
11860 ###############################################################################
11861 #
11862 #
11863 void
11864 Preview(ref,...)
11865   Image::Magick ref=NO_INIT
11866   ALIAS:
11867     PreviewImage = 1
11868     preview      = 2
11869     previewimage = 3
11870   PPCODE:
11871   {
11872     AV
11873       *av;
11874
11875     ExceptionInfo
11876       *exception;
11877
11878     HV
11879       *hv;
11880
11881     Image
11882       *image,
11883       *preview_image;
11884
11885     PreviewType
11886       preview_type;
11887
11888     struct PackageInfo
11889       *info;
11890
11891     SV
11892       *av_reference,
11893       *perl_exception,
11894       *reference,
11895       *rv,
11896       *sv;
11897
11898     PERL_UNUSED_VAR(ref);
11899     PERL_UNUSED_VAR(ix);
11900     exception=AcquireExceptionInfo();
11901     perl_exception=newSVpv("",0);
11902     sv=NULL;
11903     av=NULL;
11904     if (sv_isobject(ST(0)) == 0)
11905       {
11906         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11907           PackageName);
11908         goto PerlException;
11909       }
11910     reference=SvRV(ST(0));
11911     hv=SvSTASH(reference);
11912     av=newAV();
11913     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11914     SvREFCNT_dec(av);
11915     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11916     if (image == (Image *) NULL)
11917       {
11918         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11919           PackageName);
11920         goto PerlException;
11921       }
11922     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11923     preview_type=GammaPreview;
11924     if (items > 1)
11925       preview_type=(PreviewType)
11926         ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
11927     for ( ; image; image=image->next)
11928     {
11929       preview_image=PreviewImage(image,preview_type,exception);
11930       if (preview_image == (Image *) NULL)
11931         goto PerlException;
11932       AddImageToRegistry(sv,preview_image);
11933       rv=newRV(sv);
11934       av_push(av,sv_bless(rv,hv));
11935       SvREFCNT_dec(sv);
11936     }
11937     exception=DestroyExceptionInfo(exception);
11938     ST(0)=av_reference;
11939     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11940     XSRETURN(1);
11941
11942   PerlException:
11943     InheritPerlException(exception,perl_exception);
11944     exception=DestroyExceptionInfo(exception);
11945     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11946     SvPOK_on(perl_exception);
11947     ST(0)=sv_2mortal(perl_exception);
11948     XSRETURN(1);
11949   }
11950 \f
11951 #
11952 ###############################################################################
11953 #                                                                             #
11954 #                                                                             #
11955 #                                                                             #
11956 #   Q u e r y C o l o r                                                       #
11957 #                                                                             #
11958 #                                                                             #
11959 #                                                                             #
11960 ###############################################################################
11961 #
11962 #
11963 void
11964 QueryColor(ref,...)
11965   Image::Magick ref=NO_INIT
11966   ALIAS:
11967     querycolor = 1
11968   PPCODE:
11969   {
11970     char
11971       *name;
11972
11973     ExceptionInfo
11974       *exception;
11975
11976     PixelInfo
11977       color;
11978
11979     register ssize_t
11980       i;
11981
11982     SV
11983       *perl_exception;
11984
11985     PERL_UNUSED_VAR(ref);
11986     PERL_UNUSED_VAR(ix);
11987     exception=AcquireExceptionInfo();
11988     perl_exception=newSVpv("",0);
11989     if (items == 1)
11990       {
11991         const ColorInfo
11992           **colorlist;
11993
11994         size_t
11995           colors;
11996
11997         colorlist=GetColorInfoList("*",&colors,exception);
11998         EXTEND(sp,colors);
11999         for (i=0; i < (ssize_t) colors; i++)
12000         {
12001           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
12002         }
12003         colorlist=(const ColorInfo **)
12004           RelinquishMagickMemory((ColorInfo **) colorlist);
12005         goto PerlException;
12006       }
12007     EXTEND(sp,5*items);
12008     for (i=1; i < items; i++)
12009     {
12010       name=(char *) SvPV(ST(i),na);
12011       if (QueryColorCompliance(name,AllCompliance,&color,exception) == MagickFalse)
12012         {
12013           PUSHs(&sv_undef);
12014           continue;
12015         }
12016       PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
12017       PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
12018       PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
12019       if (color.colorspace == CMYKColorspace)
12020         PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
12021       if (color.alpha_trait == BlendPixelTrait)
12022         PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
12023     }
12024
12025   PerlException:
12026     InheritPerlException(exception,perl_exception);
12027     exception=DestroyExceptionInfo(exception);
12028     SvREFCNT_dec(perl_exception);
12029   }
12030 \f
12031 #
12032 ###############################################################################
12033 #                                                                             #
12034 #                                                                             #
12035 #                                                                             #
12036 #   Q u e r y C o l o r N a m e                                               #
12037 #                                                                             #
12038 #                                                                             #
12039 #                                                                             #
12040 ###############################################################################
12041 #
12042 #
12043 void
12044 QueryColorname(ref,...)
12045   Image::Magick ref=NO_INIT
12046   ALIAS:
12047     querycolorname = 1
12048   PPCODE:
12049   {
12050     AV
12051       *av;
12052
12053     char
12054       message[MaxTextExtent];
12055
12056     ExceptionInfo
12057       *exception;
12058
12059     Image
12060       *image;
12061
12062     PixelInfo
12063       target_color;
12064
12065     register ssize_t
12066       i;
12067
12068     struct PackageInfo
12069       *info;
12070
12071     SV
12072       *perl_exception,
12073       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12074
12075     PERL_UNUSED_VAR(ref);
12076     PERL_UNUSED_VAR(ix);
12077     exception=AcquireExceptionInfo();
12078     perl_exception=newSVpv("",0);
12079     reference=SvRV(ST(0));
12080     av=(AV *) reference;
12081     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12082       exception);
12083     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12084     if (image == (Image *) NULL)
12085       {
12086         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12087           PackageName);
12088         goto PerlException;
12089       }
12090     EXTEND(sp,items);
12091     for (i=1; i < items; i++)
12092     {
12093       (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,&target_color,
12094         exception);
12095       (void) QueryColorname(image,&target_color,SVGCompliance,message,
12096         exception);
12097       PUSHs(sv_2mortal(newSVpv(message,0)));
12098     }
12099
12100   PerlException:
12101     InheritPerlException(exception,perl_exception);
12102     exception=DestroyExceptionInfo(exception);
12103     SvREFCNT_dec(perl_exception);
12104   }
12105 \f
12106 #
12107 ###############################################################################
12108 #                                                                             #
12109 #                                                                             #
12110 #                                                                             #
12111 #   Q u e r y F o n t                                                         #
12112 #                                                                             #
12113 #                                                                             #
12114 #                                                                             #
12115 ###############################################################################
12116 #
12117 #
12118 void
12119 QueryFont(ref,...)
12120   Image::Magick ref=NO_INIT
12121   ALIAS:
12122     queryfont = 1
12123   PPCODE:
12124   {
12125     char
12126       *name,
12127       message[MaxTextExtent];
12128
12129     ExceptionInfo
12130       *exception;
12131
12132     register ssize_t
12133       i;
12134
12135     SV
12136       *perl_exception;
12137
12138     volatile const TypeInfo
12139       *type_info;
12140
12141     PERL_UNUSED_VAR(ref);
12142     PERL_UNUSED_VAR(ix);
12143     exception=AcquireExceptionInfo();
12144     perl_exception=newSVpv("",0);
12145     if (items == 1)
12146       {
12147         const TypeInfo
12148           **typelist;
12149
12150         size_t
12151           types;
12152
12153         typelist=GetTypeInfoList("*",&types,exception);
12154         EXTEND(sp,types);
12155         for (i=0; i < (ssize_t) types; i++)
12156         {
12157           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
12158         }
12159         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
12160           typelist);
12161         goto PerlException;
12162       }
12163     EXTEND(sp,10*items);
12164     for (i=1; i < items; i++)
12165     {
12166       name=(char *) SvPV(ST(i),na);
12167       type_info=GetTypeInfo(name,exception);
12168       if (type_info == (TypeInfo *) NULL)
12169         {
12170           PUSHs(&sv_undef);
12171           continue;
12172         }
12173       if (type_info->name == (char *) NULL)
12174         PUSHs(&sv_undef);
12175       else
12176         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
12177       if (type_info->description == (char *) NULL)
12178         PUSHs(&sv_undef);
12179       else
12180         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
12181       if (type_info->family == (char *) NULL)
12182         PUSHs(&sv_undef);
12183       else
12184         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
12185       if (type_info->style == UndefinedStyle)
12186         PUSHs(&sv_undef);
12187       else
12188         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
12189           type_info->style),0)));
12190       if (type_info->stretch == UndefinedStretch)
12191         PUSHs(&sv_undef);
12192       else
12193         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
12194           type_info->stretch),0)));
12195       (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
12196         type_info->weight);
12197       PUSHs(sv_2mortal(newSVpv(message,0)));
12198       if (type_info->encoding == (char *) NULL)
12199         PUSHs(&sv_undef);
12200       else
12201         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
12202       if (type_info->foundry == (char *) NULL)
12203         PUSHs(&sv_undef);
12204       else
12205         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
12206       if (type_info->format == (char *) NULL)
12207         PUSHs(&sv_undef);
12208       else
12209         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
12210       if (type_info->metrics == (char *) NULL)
12211         PUSHs(&sv_undef);
12212       else
12213         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
12214       if (type_info->glyphs == (char *) NULL)
12215         PUSHs(&sv_undef);
12216       else
12217         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
12218     }
12219
12220   PerlException:
12221     InheritPerlException(exception,perl_exception);
12222     exception=DestroyExceptionInfo(exception);
12223     SvREFCNT_dec(perl_exception);
12224   }
12225 \f
12226 #
12227 ###############################################################################
12228 #                                                                             #
12229 #                                                                             #
12230 #                                                                             #
12231 #   Q u e r y F o n t M e t r i c s                                           #
12232 #                                                                             #
12233 #                                                                             #
12234 #                                                                             #
12235 ###############################################################################
12236 #
12237 #
12238 void
12239 QueryFontMetrics(ref,...)
12240   Image::Magick ref=NO_INIT
12241   ALIAS:
12242     queryfontmetrics = 1
12243   PPCODE:
12244   {
12245     AffineMatrix
12246       affine,
12247       current;
12248
12249     AV
12250       *av;
12251
12252     char
12253       *attribute;
12254
12255     double
12256       x,
12257       y;
12258
12259     DrawInfo
12260       *draw_info;
12261
12262     ExceptionInfo
12263       *exception;
12264
12265     GeometryInfo
12266       geometry_info;
12267
12268     Image
12269       *image;
12270
12271     MagickBooleanType
12272       status;
12273
12274     MagickStatusType
12275       flags;
12276
12277     register ssize_t
12278       i;
12279
12280     ssize_t
12281       type;
12282
12283     struct PackageInfo
12284       *info,
12285       *package_info;
12286
12287     SV
12288       *perl_exception,
12289       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12290
12291     TypeMetric
12292       metrics;
12293
12294     PERL_UNUSED_VAR(ref);
12295     PERL_UNUSED_VAR(ix);
12296     exception=AcquireExceptionInfo();
12297     package_info=(struct PackageInfo *) NULL;
12298     perl_exception=newSVpv("",0);
12299     reference=SvRV(ST(0));
12300     av=(AV *) reference;
12301     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12302       exception);
12303     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12304     if (image == (Image *) NULL)
12305       {
12306         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12307           PackageName);
12308         goto PerlException;
12309       }
12310     package_info=ClonePackageInfo(info,exception);
12311     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12312     CloneString(&draw_info->text,"");
12313     current=draw_info->affine;
12314     GetAffineMatrix(&affine);
12315     x=0.0;
12316     y=0.0;
12317     EXTEND(sp,7*items);
12318     for (i=2; i < items; i+=2)
12319     {
12320       attribute=(char *) SvPV(ST(i-1),na);
12321       switch (*attribute)
12322       {
12323         case 'A':
12324         case 'a':
12325         {
12326           if (LocaleCompare(attribute,"antialias") == 0)
12327             {
12328               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12329                 SvPV(ST(i),na));
12330               if (type < 0)
12331                 {
12332                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12333                     SvPV(ST(i),na));
12334                   break;
12335                 }
12336               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12337               break;
12338             }
12339           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12340             attribute);
12341           break;
12342         }
12343         case 'd':
12344         case 'D':
12345         {
12346           if (LocaleCompare(attribute,"density") == 0)
12347             {
12348               CloneString(&draw_info->density,SvPV(ST(i),na));
12349               break;
12350             }
12351           if (LocaleCompare(attribute,"direction") == 0)
12352             {
12353               draw_info->direction=(DirectionType) ParseCommandOption(
12354                 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12355               break;
12356             }
12357           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12358             attribute);
12359           break;
12360         }
12361         case 'e':
12362         case 'E':
12363         {
12364           if (LocaleCompare(attribute,"encoding") == 0)
12365             {
12366               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12367               break;
12368             }
12369           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12370             attribute);
12371           break;
12372         }
12373         case 'f':
12374         case 'F':
12375         {
12376           if (LocaleCompare(attribute,"family") == 0)
12377             {
12378               CloneString(&draw_info->family,SvPV(ST(i),na));
12379               break;
12380             }
12381           if (LocaleCompare(attribute,"fill") == 0)
12382             {
12383               if (info)
12384                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12385                   &draw_info->fill,exception);
12386               break;
12387             }
12388           if (LocaleCompare(attribute,"font") == 0)
12389             {
12390               CloneString(&draw_info->font,SvPV(ST(i),na));
12391               break;
12392             }
12393           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12394             attribute);
12395           break;
12396         }
12397         case 'g':
12398         case 'G':
12399         {
12400           if (LocaleCompare(attribute,"geometry") == 0)
12401             {
12402               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12403               break;
12404             }
12405           if (LocaleCompare(attribute,"gravity") == 0)
12406             {
12407               draw_info->gravity=(GravityType) ParseCommandOption(
12408                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12409               break;
12410             }
12411           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12412             attribute);
12413           break;
12414         }
12415         case 'i':
12416         case 'I':
12417         {
12418           if (LocaleCompare(attribute,"interline-spacing") == 0)
12419             {
12420               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12421               draw_info->interline_spacing=geometry_info.rho;
12422               break;
12423             }
12424           if (LocaleCompare(attribute,"interword-spacing") == 0)
12425             {
12426               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12427               draw_info->interword_spacing=geometry_info.rho;
12428               break;
12429             }
12430           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12431             attribute);
12432           break;
12433         }
12434         case 'k':
12435         case 'K':
12436         {
12437           if (LocaleCompare(attribute,"kerning") == 0)
12438             {
12439               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12440               draw_info->kerning=geometry_info.rho;
12441               break;
12442             }
12443           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12444             attribute);
12445           break;
12446         }
12447         case 'p':
12448         case 'P':
12449         {
12450           if (LocaleCompare(attribute,"pointsize") == 0)
12451             {
12452               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12453               draw_info->pointsize=geometry_info.rho;
12454               break;
12455             }
12456           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12457             attribute);
12458           break;
12459         }
12460         case 'r':
12461         case 'R':
12462         {
12463           if (LocaleCompare(attribute,"rotate") == 0)
12464             {
12465               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12466               affine.rx=geometry_info.rho;
12467               affine.ry=geometry_info.sigma;
12468               if ((flags & SigmaValue) == 0)
12469                 affine.ry=affine.rx;
12470               break;
12471             }
12472           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12473             attribute);
12474           break;
12475         }
12476         case 's':
12477         case 'S':
12478         {
12479           if (LocaleCompare(attribute,"scale") == 0)
12480             {
12481               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12482               affine.sx=geometry_info.rho;
12483               affine.sy=geometry_info.sigma;
12484               if ((flags & SigmaValue) == 0)
12485                 affine.sy=affine.sx;
12486               break;
12487             }
12488           if (LocaleCompare(attribute,"skew") == 0)
12489             {
12490               double
12491                 x_angle,
12492                 y_angle;
12493
12494               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12495               x_angle=geometry_info.rho;
12496               y_angle=geometry_info.sigma;
12497               if ((flags & SigmaValue) == 0)
12498                 y_angle=x_angle;
12499               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12500               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12501               break;
12502             }
12503           if (LocaleCompare(attribute,"stroke") == 0)
12504             {
12505               if (info)
12506                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12507                   &draw_info->stroke,exception);
12508               break;
12509             }
12510           if (LocaleCompare(attribute,"style") == 0)
12511             {
12512               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12513                 SvPV(ST(i),na));
12514               if (type < 0)
12515                 {
12516                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12517                     SvPV(ST(i),na));
12518                   break;
12519                 }
12520               draw_info->style=(StyleType) type;
12521               break;
12522             }
12523           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12524             attribute);
12525           break;
12526         }
12527         case 't':
12528         case 'T':
12529         {
12530           if (LocaleCompare(attribute,"text") == 0)
12531             {
12532               CloneString(&draw_info->text,SvPV(ST(i),na));
12533               break;
12534             }
12535           if (LocaleCompare(attribute,"translate") == 0)
12536             {
12537               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12538               affine.tx=geometry_info.rho;
12539               affine.ty=geometry_info.sigma;
12540               if ((flags & SigmaValue) == 0)
12541                 affine.ty=affine.tx;
12542               break;
12543             }
12544           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12545             attribute);
12546           break;
12547         }
12548         case 'w':
12549         case 'W':
12550         {
12551           if (LocaleCompare(attribute,"weight") == 0)
12552             {
12553               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12554               draw_info->weight=(size_t) geometry_info.rho;
12555               break;
12556             }
12557           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12558             attribute);
12559           break;
12560         }
12561         case 'x':
12562         case 'X':
12563         {
12564           if (LocaleCompare(attribute,"x") == 0)
12565             {
12566               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12567               x=geometry_info.rho;
12568               break;
12569             }
12570           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12571             attribute);
12572           break;
12573         }
12574         case 'y':
12575         case 'Y':
12576         {
12577           if (LocaleCompare(attribute,"y") == 0)
12578             {
12579               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12580               y=geometry_info.rho;
12581               break;
12582             }
12583           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12584             attribute);
12585           break;
12586         }
12587         default:
12588         {
12589           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12590             attribute);
12591           break;
12592         }
12593       }
12594     }
12595     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12596     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12597     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12598     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12599     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12600     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12601     if (draw_info->geometry == (char *) NULL)
12602       {
12603         draw_info->geometry=AcquireString((char *) NULL);
12604         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12605           "%.15g,%.15g",x,y);
12606       }
12607     status=GetTypeMetrics(image,draw_info,&metrics,exception);
12608     (void) CatchImageException(image);
12609     if (status == MagickFalse)
12610       PUSHs(&sv_undef);
12611     else
12612       {
12613         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12614         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12615         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12616         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12617         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12618         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12619         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12620         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12621         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12622         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12623         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12624         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12625         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12626       }
12627     draw_info=DestroyDrawInfo(draw_info);
12628
12629   PerlException:
12630     if (package_info != (struct PackageInfo *) NULL)
12631       DestroyPackageInfo(package_info);
12632     InheritPerlException(exception,perl_exception);
12633     exception=DestroyExceptionInfo(exception);
12634     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12635   }
12636 \f
12637 #
12638 ###############################################################################
12639 #                                                                             #
12640 #                                                                             #
12641 #                                                                             #
12642 #   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                         #
12643 #                                                                             #
12644 #                                                                             #
12645 #                                                                             #
12646 ###############################################################################
12647 #
12648 #
12649 void
12650 QueryMultilineFontMetrics(ref,...)
12651   Image::Magick ref=NO_INIT
12652   ALIAS:
12653     querymultilinefontmetrics = 1
12654   PPCODE:
12655   {
12656     AffineMatrix
12657       affine,
12658       current;
12659
12660     AV
12661       *av;
12662
12663     char
12664       *attribute;
12665
12666     double
12667       x,
12668       y;
12669
12670     DrawInfo
12671       *draw_info;
12672
12673     ExceptionInfo
12674       *exception;
12675
12676     GeometryInfo
12677       geometry_info;
12678
12679     Image
12680       *image;
12681
12682     MagickBooleanType
12683       status;
12684
12685     MagickStatusType
12686       flags;
12687
12688     register ssize_t
12689       i;
12690
12691     ssize_t
12692       type;
12693
12694     struct PackageInfo
12695       *info,
12696       *package_info;
12697
12698     SV
12699       *perl_exception,
12700       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12701
12702     TypeMetric
12703       metrics;
12704
12705     PERL_UNUSED_VAR(ref);
12706     PERL_UNUSED_VAR(ix);
12707     exception=AcquireExceptionInfo();
12708     package_info=(struct PackageInfo *) NULL;
12709     perl_exception=newSVpv("",0);
12710     reference=SvRV(ST(0));
12711     av=(AV *) reference;
12712     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12713       exception);
12714     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12715     if (image == (Image *) NULL)
12716       {
12717         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12718           PackageName);
12719         goto PerlException;
12720       }
12721     package_info=ClonePackageInfo(info,exception);
12722     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12723     CloneString(&draw_info->text,"");
12724     current=draw_info->affine;
12725     GetAffineMatrix(&affine);
12726     x=0.0;
12727     y=0.0;
12728     EXTEND(sp,7*items);
12729     for (i=2; i < items; i+=2)
12730     {
12731       attribute=(char *) SvPV(ST(i-1),na);
12732       switch (*attribute)
12733       {
12734         case 'A':
12735         case 'a':
12736         {
12737           if (LocaleCompare(attribute,"antialias") == 0)
12738             {
12739               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12740                 SvPV(ST(i),na));
12741               if (type < 0)
12742                 {
12743                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12744                     SvPV(ST(i),na));
12745                   break;
12746                 }
12747               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12748               break;
12749             }
12750           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12751             attribute);
12752           break;
12753         }
12754         case 'd':
12755         case 'D':
12756         {
12757           if (LocaleCompare(attribute,"density") == 0)
12758             {
12759               CloneString(&draw_info->density,SvPV(ST(i),na));
12760               break;
12761             }
12762           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12763             attribute);
12764           break;
12765         }
12766         case 'e':
12767         case 'E':
12768         {
12769           if (LocaleCompare(attribute,"encoding") == 0)
12770             {
12771               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12772               break;
12773             }
12774           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12775             attribute);
12776           break;
12777         }
12778         case 'f':
12779         case 'F':
12780         {
12781           if (LocaleCompare(attribute,"family") == 0)
12782             {
12783               CloneString(&draw_info->family,SvPV(ST(i),na));
12784               break;
12785             }
12786           if (LocaleCompare(attribute,"fill") == 0)
12787             {
12788               if (info)
12789                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12790                   &draw_info->fill,exception);
12791               break;
12792             }
12793           if (LocaleCompare(attribute,"font") == 0)
12794             {
12795               CloneString(&draw_info->font,SvPV(ST(i),na));
12796               break;
12797             }
12798           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12799             attribute);
12800           break;
12801         }
12802         case 'g':
12803         case 'G':
12804         {
12805           if (LocaleCompare(attribute,"geometry") == 0)
12806             {
12807               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12808               break;
12809             }
12810           if (LocaleCompare(attribute,"gravity") == 0)
12811             {
12812               draw_info->gravity=(GravityType) ParseCommandOption(
12813                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12814               break;
12815             }
12816           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12817             attribute);
12818           break;
12819         }
12820         case 'p':
12821         case 'P':
12822         {
12823           if (LocaleCompare(attribute,"pointsize") == 0)
12824             {
12825               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12826               draw_info->pointsize=geometry_info.rho;
12827               break;
12828             }
12829           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12830             attribute);
12831           break;
12832         }
12833         case 'r':
12834         case 'R':
12835         {
12836           if (LocaleCompare(attribute,"rotate") == 0)
12837             {
12838               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12839               affine.rx=geometry_info.rho;
12840               affine.ry=geometry_info.sigma;
12841               if ((flags & SigmaValue) == 0)
12842                 affine.ry=affine.rx;
12843               break;
12844             }
12845           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12846             attribute);
12847           break;
12848         }
12849         case 's':
12850         case 'S':
12851         {
12852           if (LocaleCompare(attribute,"scale") == 0)
12853             {
12854               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12855               affine.sx=geometry_info.rho;
12856               affine.sy=geometry_info.sigma;
12857               if ((flags & SigmaValue) == 0)
12858                 affine.sy=affine.sx;
12859               break;
12860             }
12861           if (LocaleCompare(attribute,"skew") == 0)
12862             {
12863               double
12864                 x_angle,
12865                 y_angle;
12866
12867               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12868               x_angle=geometry_info.rho;
12869               y_angle=geometry_info.sigma;
12870               if ((flags & SigmaValue) == 0)
12871                 y_angle=x_angle;
12872               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12873               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12874               break;
12875             }
12876           if (LocaleCompare(attribute,"stroke") == 0)
12877             {
12878               if (info)
12879                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12880                   &draw_info->stroke,exception);
12881               break;
12882             }
12883           if (LocaleCompare(attribute,"style") == 0)
12884             {
12885               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12886                 SvPV(ST(i),na));
12887               if (type < 0)
12888                 {
12889                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12890                     SvPV(ST(i),na));
12891                   break;
12892                 }
12893               draw_info->style=(StyleType) type;
12894               break;
12895             }
12896           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12897             attribute);
12898           break;
12899         }
12900         case 't':
12901         case 'T':
12902         {
12903           if (LocaleCompare(attribute,"text") == 0)
12904             {
12905               CloneString(&draw_info->text,SvPV(ST(i),na));
12906               break;
12907             }
12908           if (LocaleCompare(attribute,"translate") == 0)
12909             {
12910               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12911               affine.tx=geometry_info.rho;
12912               affine.ty=geometry_info.sigma;
12913               if ((flags & SigmaValue) == 0)
12914                 affine.ty=affine.tx;
12915               break;
12916             }
12917           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12918             attribute);
12919           break;
12920         }
12921         case 'w':
12922         case 'W':
12923         {
12924           if (LocaleCompare(attribute,"weight") == 0)
12925             {
12926               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12927               draw_info->weight=(size_t) geometry_info.rho;
12928               break;
12929             }
12930           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12931             attribute);
12932           break;
12933         }
12934         case 'x':
12935         case 'X':
12936         {
12937           if (LocaleCompare(attribute,"x") == 0)
12938             {
12939               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12940               x=geometry_info.rho;
12941               break;
12942             }
12943           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12944             attribute);
12945           break;
12946         }
12947         case 'y':
12948         case 'Y':
12949         {
12950           if (LocaleCompare(attribute,"y") == 0)
12951             {
12952               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12953               y=geometry_info.rho;
12954               break;
12955             }
12956           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12957             attribute);
12958           break;
12959         }
12960         default:
12961         {
12962           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12963             attribute);
12964           break;
12965         }
12966       }
12967     }
12968     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12969     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12970     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12971     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12972     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12973     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12974     if (draw_info->geometry == (char *) NULL)
12975       {
12976         draw_info->geometry=AcquireString((char *) NULL);
12977         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12978           "%.15g,%.15g",x,y);
12979       }
12980     status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
12981     (void) CatchException(exception);
12982     if (status == MagickFalse)
12983       PUSHs(&sv_undef);
12984     else
12985       {
12986         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12987         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12988         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12989         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12990         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12991         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12992         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12993         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12994         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12995         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12996         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12997         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12998         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12999       }
13000     draw_info=DestroyDrawInfo(draw_info);
13001
13002   PerlException:
13003     if (package_info != (struct PackageInfo *) NULL)
13004       DestroyPackageInfo(package_info);
13005     InheritPerlException(exception,perl_exception);
13006     exception=DestroyExceptionInfo(exception);
13007     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13008   }
13009 \f
13010 #
13011 ###############################################################################
13012 #                                                                             #
13013 #                                                                             #
13014 #                                                                             #
13015 #   Q u e r y F o r m a t                                                     #
13016 #                                                                             #
13017 #                                                                             #
13018 #                                                                             #
13019 ###############################################################################
13020 #
13021 #
13022 void
13023 QueryFormat(ref,...)
13024   Image::Magick ref=NO_INIT
13025   ALIAS:
13026     queryformat = 1
13027   PPCODE:
13028   {
13029     char
13030       *name;
13031
13032     ExceptionInfo
13033       *exception;
13034
13035     register ssize_t
13036       i;
13037
13038     SV
13039       *perl_exception;
13040
13041     volatile const MagickInfo
13042       *magick_info;
13043
13044     PERL_UNUSED_VAR(ref);
13045     PERL_UNUSED_VAR(ix);
13046     exception=AcquireExceptionInfo();
13047     perl_exception=newSVpv("",0);
13048     if (items == 1)
13049       {
13050         char
13051           format[MaxTextExtent];
13052
13053         const MagickInfo
13054           **format_list;
13055
13056         size_t
13057           types;
13058
13059         format_list=GetMagickInfoList("*",&types,exception);
13060         EXTEND(sp,types);
13061         for (i=0; i < (ssize_t) types; i++)
13062         {
13063           (void) CopyMagickString(format,format_list[i]->name,MaxTextExtent);
13064           LocaleLower(format);
13065           PUSHs(sv_2mortal(newSVpv(format,0)));
13066         }
13067         format_list=(const MagickInfo **)
13068           RelinquishMagickMemory((MagickInfo *) format_list);
13069         goto PerlException;
13070       }
13071     EXTEND(sp,8*items);
13072     for (i=1; i < items; i++)
13073     {
13074       name=(char *) SvPV(ST(i),na);
13075       magick_info=GetMagickInfo(name,exception);
13076       if (magick_info == (const MagickInfo *) NULL)
13077         {
13078           PUSHs(&sv_undef);
13079           continue;
13080         }
13081       PUSHs(sv_2mortal(newSViv(magick_info->adjoin)));
13082       PUSHs(sv_2mortal(newSViv(magick_info->blob_support)));
13083       PUSHs(sv_2mortal(newSViv(magick_info->raw)));
13084       PUSHs(sv_2mortal(newSViv((long) magick_info->decoder)));
13085       PUSHs(sv_2mortal(newSViv((long) magick_info->encoder)));
13086       if (magick_info->description == (char *) NULL)
13087         PUSHs(&sv_undef);
13088       else
13089         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
13090       if (magick_info->module == (char *) NULL)
13091         PUSHs(&sv_undef);
13092       else
13093         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
13094     }
13095
13096   PerlException:
13097     InheritPerlException(exception,perl_exception);
13098     exception=DestroyExceptionInfo(exception);
13099     SvREFCNT_dec(perl_exception);
13100   }
13101 \f
13102 #
13103 ###############################################################################
13104 #                                                                             #
13105 #                                                                             #
13106 #                                                                             #
13107 #   Q u e r y O p t i o n                                                     #
13108 #                                                                             #
13109 #                                                                             #
13110 #                                                                             #
13111 ###############################################################################
13112 #
13113 #
13114 void
13115 QueryOption(ref,...)
13116   Image::Magick ref=NO_INIT
13117   ALIAS:
13118     queryoption = 1
13119   PPCODE:
13120   {
13121     char
13122       **options;
13123
13124     ExceptionInfo
13125       *exception;
13126
13127     register ssize_t
13128       i;
13129
13130     ssize_t
13131       j,
13132       option;
13133
13134     SV
13135       *perl_exception;
13136
13137     PERL_UNUSED_VAR(ref);
13138     PERL_UNUSED_VAR(ix);
13139     exception=AcquireExceptionInfo();
13140     perl_exception=newSVpv("",0);
13141     EXTEND(sp,8*items);
13142     for (i=1; i < items; i++)
13143     {
13144       option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
13145         SvPV(ST(i),na));
13146       options=GetCommandOptions((CommandOption) option);
13147       if (options == (char **) NULL)
13148         PUSHs(&sv_undef);
13149       else
13150         {
13151           for (j=0; options[j] != (char *) NULL; j++)
13152             PUSHs(sv_2mortal(newSVpv(options[j],0)));
13153           options=DestroyStringList(options);
13154         }
13155     }
13156
13157     InheritPerlException(exception,perl_exception);
13158     exception=DestroyExceptionInfo(exception);
13159     SvREFCNT_dec(perl_exception);
13160   }
13161 \f
13162 #
13163 ###############################################################################
13164 #                                                                             #
13165 #                                                                             #
13166 #                                                                             #
13167 #   R e a d                                                                   #
13168 #                                                                             #
13169 #                                                                             #
13170 #                                                                             #
13171 ###############################################################################
13172 #
13173 #
13174 void
13175 Read(ref,...)
13176   Image::Magick ref=NO_INIT
13177   ALIAS:
13178     ReadImage  = 1
13179     read       = 2
13180     readimage  = 3
13181   PPCODE:
13182   {
13183     AV
13184       *av;
13185
13186     char
13187       **keep,
13188       **list;
13189
13190     ExceptionInfo
13191       *exception;
13192
13193     HV
13194       *hv;
13195
13196     Image
13197       *image;
13198
13199     int
13200       n;
13201
13202     MagickBooleanType
13203       status;
13204
13205     register char
13206       **p;
13207
13208     register ssize_t
13209       i;
13210
13211     ssize_t
13212       ac,
13213       number_images;
13214
13215     STRLEN
13216       *length;
13217
13218     struct PackageInfo
13219       *info,
13220       *package_info;
13221
13222     SV
13223       *perl_exception,  /* Perl variable for storing messages */
13224       *reference,
13225       *rv,
13226       *sv;
13227
13228     PERL_UNUSED_VAR(ref);
13229     PERL_UNUSED_VAR(ix);
13230     exception=AcquireExceptionInfo();
13231     perl_exception=newSVpv("",0);
13232     sv=NULL;
13233     package_info=(struct PackageInfo *) NULL;
13234     number_images=0;
13235     ac=(items < 2) ? 1 : items-1;
13236     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
13237     keep=list;
13238     length=(STRLEN *) NULL;
13239     if (list == (char **) NULL)
13240       {
13241         ThrowPerlException(exception,ResourceLimitError,
13242           "MemoryAllocationFailed",PackageName);
13243         goto PerlException;
13244       }
13245     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
13246     if (length == (STRLEN *) NULL)
13247       {
13248         ThrowPerlException(exception,ResourceLimitError,
13249           "MemoryAllocationFailed",PackageName);
13250         goto PerlException;
13251       }
13252     if (sv_isobject(ST(0)) == 0)
13253       {
13254         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13255           PackageName);
13256         goto PerlException;
13257       }
13258     reference=SvRV(ST(0));
13259     hv=SvSTASH(reference);
13260     if (SvTYPE(reference) != SVt_PVAV)
13261       {
13262         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13263           PackageName);
13264         goto PerlException;
13265       }
13266     av=(AV *) reference;
13267     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13268       exception);
13269     package_info=ClonePackageInfo(info,exception);
13270     n=1;
13271     if (items <= 1)
13272       *list=(char *) (*package_info->image_info->filename ?
13273         package_info->image_info->filename : "XC:black");
13274     else
13275       for (n=0, i=0; i < ac; i++)
13276       {
13277         list[n]=(char *) SvPV(ST(i+1),length[n]);
13278         if ((items >= 3) && strEQcase(list[n],"blob"))
13279           {
13280             void
13281               *blob;
13282
13283             i++;
13284             blob=(void *) (SvPV(ST(i+1),length[n]));
13285             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13286           }
13287         if ((items >= 3) && strEQcase(list[n],"filename"))
13288           continue;
13289         if ((items >= 3) && strEQcase(list[n],"file"))
13290           {
13291             FILE
13292               *file;
13293
13294             PerlIO
13295               *io_info;
13296
13297             i++;
13298             io_info=IoIFP(sv_2io(ST(i+1)));
13299             if (io_info == (PerlIO *) NULL)
13300               {
13301                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13302                   PackageName);
13303                 continue;
13304               }
13305             file=PerlIO_findFILE(io_info);
13306             if (file == (FILE *) NULL)
13307               {
13308                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13309                   PackageName);
13310                 continue;
13311               }
13312             SetImageInfoFile(package_info->image_info,file);
13313           }
13314         if ((items >= 3) && strEQcase(list[n],"magick"))
13315           continue;
13316         n++;
13317       }
13318     list[n]=(char *) NULL;
13319     keep=list;
13320     status=ExpandFilenames(&n,&list);
13321     if (status == MagickFalse)
13322       {
13323         ThrowPerlException(exception,ResourceLimitError,
13324           "MemoryAllocationFailed",PackageName);
13325         goto PerlException;
13326       }
13327     number_images=0;
13328     for (i=0; i < n; i++)
13329     {
13330       if ((package_info->image_info->file == (FILE *) NULL) &&
13331           (package_info->image_info->blob == (void *) NULL))
13332         image=ReadImages(package_info->image_info,list[i],exception);
13333       else
13334         {
13335           image=ReadImages(package_info->image_info,
13336             package_info->image_info->filename,exception);
13337           if (image != (Image *) NULL)
13338             DisassociateImageStream(image);
13339         }
13340       if (image == (Image *) NULL)
13341         break;
13342       for ( ; image; image=image->next)
13343       {
13344         AddImageToRegistry(sv,image);
13345         rv=newRV(sv);
13346         av_push(av,sv_bless(rv,hv));
13347         SvREFCNT_dec(sv);
13348         number_images++;
13349       }
13350     }
13351     /*
13352       Free resources.
13353     */
13354     for (i=0; i < n; i++)
13355       if (list[i] != (char *) NULL)
13356         for (p=keep; list[i] != *p++; )
13357           if (*p == (char *) NULL)
13358             {
13359               list[i]=(char *) RelinquishMagickMemory(list[i]);
13360               break;
13361             }
13362
13363   PerlException:
13364     if (package_info != (struct PackageInfo *) NULL)
13365       DestroyPackageInfo(package_info);
13366     if (list && (list != keep))
13367       list=(char **) RelinquishMagickMemory(list);
13368     if (keep)
13369       keep=(char **) RelinquishMagickMemory(keep);
13370     if (length)
13371       length=(STRLEN *) RelinquishMagickMemory(length);
13372     InheritPerlException(exception,perl_exception);
13373     exception=DestroyExceptionInfo(exception);
13374     sv_setiv(perl_exception,(IV) number_images);
13375     SvPOK_on(perl_exception);
13376     ST(0)=sv_2mortal(perl_exception);
13377     XSRETURN(1);
13378   }
13379 \f
13380 #
13381 ###############################################################################
13382 #                                                                             #
13383 #                                                                             #
13384 #                                                                             #
13385 #   R e m o t e                                                               #
13386 #                                                                             #
13387 #                                                                             #
13388 #                                                                             #
13389 ###############################################################################
13390 #
13391 #
13392 void
13393 Remote(ref,...)
13394   Image::Magick ref=NO_INIT
13395   ALIAS:
13396     RemoteCommand  = 1
13397     remote         = 2
13398     remoteCommand  = 3
13399   PPCODE:
13400   {
13401     AV
13402       *av;
13403
13404     ExceptionInfo
13405       *exception;
13406
13407     register ssize_t
13408       i;
13409
13410     SV
13411       *perl_exception,
13412       *reference;
13413
13414     struct PackageInfo
13415       *info;
13416
13417     PERL_UNUSED_VAR(ref);
13418     PERL_UNUSED_VAR(ix);
13419     exception=AcquireExceptionInfo();
13420     perl_exception=newSVpv("",0);
13421     reference=SvRV(ST(0));
13422     av=(AV *) reference;
13423     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13424       exception);
13425     for (i=1; i < items; i++)
13426       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13427         SvPV(ST(i),na),exception);
13428     InheritPerlException(exception,perl_exception);
13429     exception=DestroyExceptionInfo(exception);
13430     SvREFCNT_dec(perl_exception);    /* throw away all errors */
13431   }
13432 \f
13433 #
13434 ###############################################################################
13435 #                                                                             #
13436 #                                                                             #
13437 #                                                                             #
13438 #   S e t                                                                     #
13439 #                                                                             #
13440 #                                                                             #
13441 #                                                                             #
13442 ###############################################################################
13443 #
13444 #
13445 void
13446 Set(ref,...)
13447   Image::Magick ref=NO_INIT
13448   ALIAS:
13449     SetAttributes  = 1
13450     SetAttribute   = 2
13451     set            = 3
13452     setattributes  = 4
13453     setattribute   = 5
13454   PPCODE:
13455   {
13456     ExceptionInfo
13457       *exception;
13458
13459     Image
13460       *image;
13461
13462     register ssize_t
13463       i;
13464
13465     struct PackageInfo
13466       *info;
13467
13468     SV
13469       *perl_exception,
13470       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13471
13472     PERL_UNUSED_VAR(ref);
13473     PERL_UNUSED_VAR(ix);
13474     exception=AcquireExceptionInfo();
13475     perl_exception=newSVpv("",0);
13476     if (sv_isobject(ST(0)) == 0)
13477       {
13478         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13479           PackageName);
13480         goto PerlException;
13481       }
13482     reference=SvRV(ST(0));
13483     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13484     if (items == 2)
13485       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13486     else
13487       for (i=2; i < items; i+=2)
13488         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13489
13490   PerlException:
13491     InheritPerlException(exception,perl_exception);
13492     exception=DestroyExceptionInfo(exception);
13493     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13494     SvPOK_on(perl_exception);
13495     ST(0)=sv_2mortal(perl_exception);
13496     XSRETURN(1);
13497   }
13498 \f
13499 #
13500 ###############################################################################
13501 #                                                                             #
13502 #                                                                             #
13503 #                                                                             #
13504 #   S e t P i x e l                                                           #
13505 #                                                                             #
13506 #                                                                             #
13507 #                                                                             #
13508 ###############################################################################
13509 #
13510 #
13511 void
13512 SetPixel(ref,...)
13513   Image::Magick ref=NO_INIT
13514   ALIAS:
13515     setpixel = 1
13516     setPixel = 2
13517   PPCODE:
13518   {
13519     AV
13520       *av;
13521
13522     char
13523       *attribute;
13524
13525     ChannelType
13526       channel,
13527       channel_mask;
13528
13529     ExceptionInfo
13530       *exception;
13531
13532     Image
13533       *image;
13534
13535     MagickBooleanType
13536       normalize;
13537
13538     RectangleInfo
13539       region;
13540
13541     register ssize_t
13542       i;
13543
13544     register Quantum
13545       *q;
13546
13547     ssize_t
13548       option;
13549
13550     struct PackageInfo
13551       *info;
13552
13553     SV
13554       *perl_exception,
13555       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13556
13557     PERL_UNUSED_VAR(ref);
13558     PERL_UNUSED_VAR(ix);
13559     exception=AcquireExceptionInfo();
13560     perl_exception=newSVpv("",0);
13561     reference=SvRV(ST(0));
13562     av=(AV *) reference;
13563     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13564       exception);
13565     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13566     if (image == (Image *) NULL)
13567       {
13568         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13569           PackageName);
13570         goto PerlException;
13571       }
13572     av=(AV *) NULL;
13573     normalize=MagickTrue;
13574     region.x=0;
13575     region.y=0;
13576     region.width=image->columns;
13577     region.height=1;
13578     if (items == 1)
13579       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13580     channel=DefaultChannels;
13581     for (i=2; i < items; i+=2)
13582     {
13583       attribute=(char *) SvPV(ST(i-1),na);
13584       switch (*attribute)
13585       {
13586         case 'C':
13587         case 'c':
13588         {
13589           if (LocaleCompare(attribute,"channel") == 0)
13590             {
13591               ssize_t
13592                 option;
13593
13594               option=ParseChannelOption(SvPV(ST(i),na));
13595               if (option < 0)
13596                 {
13597                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13598                     SvPV(ST(i),na));
13599                   return;
13600                 }
13601               channel=(ChannelType) option;
13602               break;
13603             }
13604           if (LocaleCompare(attribute,"color") == 0)
13605             {
13606               if (SvTYPE(ST(i)) != SVt_RV)
13607                 {
13608                   char
13609                     message[MaxTextExtent];
13610
13611                   (void) FormatLocaleString(message,MaxTextExtent,
13612                     "invalid %.60s value",attribute);
13613                   ThrowPerlException(exception,OptionError,message,
13614                     SvPV(ST(i),na));
13615                 }
13616               av=(AV *) SvRV(ST(i));
13617               break;
13618             }
13619           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13620             attribute);
13621           break;
13622         }
13623         case 'g':
13624         case 'G':
13625         {
13626           if (LocaleCompare(attribute,"geometry") == 0)
13627             {
13628               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
13629               break;
13630             }
13631           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13632             attribute);
13633           break;
13634         }
13635         case 'N':
13636         case 'n':
13637         {
13638           if (LocaleCompare(attribute,"normalize") == 0)
13639             {
13640               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13641                 SvPV(ST(i),na));
13642               if (option < 0)
13643                 {
13644                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13645                     SvPV(ST(i),na));
13646                   break;
13647                 }
13648              normalize=option != 0 ? MagickTrue : MagickFalse;
13649              break;
13650             }
13651           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13652             attribute);
13653           break;
13654         }
13655         case 'x':
13656         case 'X':
13657         {
13658           if (LocaleCompare(attribute,"x") == 0)
13659             {
13660               region.x=SvIV(ST(i));
13661               break;
13662             }
13663           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13664             attribute);
13665           break;
13666         }
13667         case 'y':
13668         case 'Y':
13669         {
13670           if (LocaleCompare(attribute,"y") == 0)
13671             {
13672               region.y=SvIV(ST(i));
13673               break;
13674             }
13675           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13676             attribute);
13677           break;
13678         }
13679         default:
13680         {
13681           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13682             attribute);
13683           break;
13684         }
13685       }
13686     }
13687     (void) SetImageStorageClass(image,DirectClass,exception);
13688     channel_mask=SetImageChannelMask(image,channel);
13689     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
13690     if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
13691         (SvTYPE(av) != SVt_PVAV))
13692       PUSHs(&sv_undef);
13693     else
13694       {
13695         double
13696           scale;
13697
13698         register ssize_t
13699           i;
13700
13701         i=0;
13702         scale=1.0;
13703         if (normalize != MagickFalse)
13704           scale=QuantumRange;
13705         if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
13706             (i <= av_len(av)))
13707           {
13708             SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
13709               av_fetch(av,i,0)))),q);
13710             i++;
13711           }
13712         if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
13713             (i <= av_len(av)))
13714           {
13715             SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
13716               av_fetch(av,i,0)))),q);
13717             i++;
13718           }
13719         if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
13720             (i <= av_len(av)))
13721           {
13722             SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
13723               av_fetch(av,i,0)))),q);
13724             i++;
13725           }
13726         if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
13727             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
13728           {
13729             SetPixelBlack(image,ClampToQuantum(scale*
13730               SvNV(*(av_fetch(av,i,0)))),q);
13731             i++;
13732           }
13733         if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
13734             (i <= av_len(av)))
13735           {
13736             SetPixelAlpha(image,ClampToQuantum(scale*
13737               SvNV(*(av_fetch(av,i,0)))),q);
13738             i++;
13739           }
13740         (void) SyncAuthenticPixels(image,exception);
13741       }
13742     (void) SetImageChannelMask(image,channel_mask);
13743
13744   PerlException:
13745     InheritPerlException(exception,perl_exception);
13746     exception=DestroyExceptionInfo(exception);
13747     SvREFCNT_dec(perl_exception);
13748   }
13749 \f
13750 #
13751 ###############################################################################
13752 #                                                                             #
13753 #                                                                             #
13754 #                                                                             #
13755 #   S m u s h                                                                 #
13756 #                                                                             #
13757 #                                                                             #
13758 #                                                                             #
13759 ###############################################################################
13760 #
13761 #
13762 void
13763 Smush(ref,...)
13764   Image::Magick ref=NO_INIT
13765   ALIAS:
13766     SmushImage  = 1
13767     smush       = 2
13768     smushimage  = 3
13769   PPCODE:
13770   {
13771     AV
13772       *av;
13773
13774     char
13775       *attribute;
13776
13777     ExceptionInfo
13778       *exception;
13779
13780     HV
13781       *hv;
13782
13783     Image
13784       *image;
13785
13786     register ssize_t
13787       i;
13788
13789     ssize_t
13790       offset,
13791       stack;
13792
13793     struct PackageInfo
13794       *info;
13795
13796     SV
13797       *av_reference,
13798       *perl_exception,
13799       *reference,
13800       *rv,
13801       *sv;
13802
13803     PERL_UNUSED_VAR(ref);
13804     PERL_UNUSED_VAR(ix);
13805     exception=AcquireExceptionInfo();
13806     perl_exception=newSVpv("",0);
13807     sv=NULL;
13808     attribute=NULL;
13809     av=NULL;
13810     if (sv_isobject(ST(0)) == 0)
13811       {
13812         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13813           PackageName);
13814         goto PerlException;
13815       }
13816     reference=SvRV(ST(0));
13817     hv=SvSTASH(reference);
13818     av=newAV();
13819     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13820     SvREFCNT_dec(av);
13821     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13822     if (image == (Image *) NULL)
13823       {
13824         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13825           PackageName);
13826         goto PerlException;
13827       }
13828     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13829     /*
13830       Get options.
13831     */
13832     offset=0;
13833     stack=MagickTrue;
13834     for (i=2; i < items; i+=2)
13835     {
13836       attribute=(char *) SvPV(ST(i-1),na);
13837       switch (*attribute)
13838       {
13839         case 'O':
13840         case 'o':
13841         {
13842           if (LocaleCompare(attribute,"offset") == 0)
13843             {
13844               offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
13845               break;
13846             }
13847           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13848             attribute);
13849           break;
13850         }
13851         case 'S':
13852         case 's':
13853         {
13854           if (LocaleCompare(attribute,"stack") == 0)
13855             {
13856               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13857                 SvPV(ST(i),na));
13858               if (stack < 0)
13859                 {
13860                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13861                     SvPV(ST(i),na));
13862                   return;
13863                 }
13864               break;
13865             }
13866           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13867             attribute);
13868           break;
13869         }
13870         default:
13871         {
13872           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13873             attribute);
13874           break;
13875         }
13876       }
13877     }
13878     image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
13879       exception);
13880     if (image == (Image *) NULL)
13881       goto PerlException;
13882     for ( ; image; image=image->next)
13883     {
13884       AddImageToRegistry(sv,image);
13885       rv=newRV(sv);
13886       av_push(av,sv_bless(rv,hv));
13887       SvREFCNT_dec(sv);
13888     }
13889     exception=DestroyExceptionInfo(exception);
13890     ST(0)=av_reference;
13891     SvREFCNT_dec(perl_exception);
13892     XSRETURN(1);
13893
13894   PerlException:
13895     InheritPerlException(exception,perl_exception);
13896     exception=DestroyExceptionInfo(exception);
13897     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
13898     SvPOK_on(perl_exception);
13899     ST(0)=sv_2mortal(perl_exception);
13900     XSRETURN(1);
13901   }
13902 \f
13903 #
13904 ###############################################################################
13905 #                                                                             #
13906 #                                                                             #
13907 #                                                                             #
13908 #   S t a t i s t i c s                                                       #
13909 #                                                                             #
13910 #                                                                             #
13911 #                                                                             #
13912 ###############################################################################
13913 #
13914 #
13915 void
13916 Statistics(ref,...)
13917   Image::Magick ref=NO_INIT
13918   ALIAS:
13919     StatisticsImage = 1
13920     statistics      = 2
13921     statisticsimage = 3
13922   PPCODE:
13923   {
13924 #define ChannelStatistics(channel) \
13925 { \
13926   (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
13927     (double) channel_statistics[channel].depth); \
13928   PUSHs(sv_2mortal(newSVpv(message,0))); \
13929   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13930     channel_statistics[channel].minima/scale); \
13931   PUSHs(sv_2mortal(newSVpv(message,0))); \
13932   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13933     channel_statistics[channel].maxima/scale); \
13934   PUSHs(sv_2mortal(newSVpv(message,0))); \
13935   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13936     channel_statistics[channel].mean/scale); \
13937   PUSHs(sv_2mortal(newSVpv(message,0))); \
13938   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13939     channel_statistics[channel].standard_deviation/scale); \
13940   PUSHs(sv_2mortal(newSVpv(message,0))); \
13941   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13942     channel_statistics[channel].kurtosis); \
13943   PUSHs(sv_2mortal(newSVpv(message,0))); \
13944   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13945     channel_statistics[channel].skewness); \
13946   PUSHs(sv_2mortal(newSVpv(message,0))); \
13947 }
13948
13949     AV
13950       *av;
13951
13952     char
13953       message[MaxTextExtent];
13954
13955     ChannelStatistics
13956       *channel_statistics;
13957
13958     double
13959       scale;
13960
13961     ExceptionInfo
13962       *exception;
13963
13964     Image
13965       *image;
13966
13967     ssize_t
13968       count;
13969
13970     struct PackageInfo
13971       *info;
13972
13973     SV
13974       *perl_exception,
13975       *reference;
13976
13977     PERL_UNUSED_VAR(ref);
13978     PERL_UNUSED_VAR(ix);
13979     exception=AcquireExceptionInfo();
13980     perl_exception=newSVpv("",0);
13981     av=NULL;
13982     if (sv_isobject(ST(0)) == 0)
13983       {
13984         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13985           PackageName);
13986         goto PerlException;
13987       }
13988     reference=SvRV(ST(0));
13989     av=newAV();
13990     SvREFCNT_dec(av);
13991     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13992     if (image == (Image *) NULL)
13993       {
13994         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13995           PackageName);
13996         goto PerlException;
13997       }
13998     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13999     count=0;
14000     for ( ; image; image=image->next)
14001     {
14002       channel_statistics=GetImageStatistics(image,exception);
14003       if (channel_statistics == (ChannelStatistics *) NULL)
14004         continue;
14005       count++;
14006       EXTEND(sp,35*count);
14007       scale=(double) QuantumRange;
14008       ChannelStatistics(RedChannel);
14009       ChannelStatistics(GreenChannel);
14010       ChannelStatistics(BlueChannel);
14011       if (image->colorspace == CMYKColorspace)
14012         ChannelStatistics(BlackChannel);
14013       if (image->alpha_trait == BlendPixelTrait)
14014         ChannelStatistics(AlphaChannel);
14015       channel_statistics=(ChannelStatistics *)
14016         RelinquishMagickMemory(channel_statistics);
14017     }
14018
14019   PerlException:
14020     InheritPerlException(exception,perl_exception);
14021     exception=DestroyExceptionInfo(exception);
14022     SvREFCNT_dec(perl_exception);
14023   }
14024 \f
14025 #
14026 ###############################################################################
14027 #                                                                             #
14028 #                                                                             #
14029 #                                                                             #
14030 #   S y n c A u t h e n t i c P i x e l s                                     #
14031 #                                                                             #
14032 #                                                                             #
14033 #                                                                             #
14034 ###############################################################################
14035 #
14036 #
14037 void
14038 SyncAuthenticPixels(ref,...)
14039   Image::Magick ref = NO_INIT
14040   ALIAS:
14041     Syncauthenticpixels = 1
14042     SyncImagePixels = 2
14043     syncimagepixels = 3
14044   CODE:
14045   {
14046     ExceptionInfo
14047       *exception;
14048
14049     Image
14050       *image;
14051
14052     MagickBooleanType
14053       status;
14054
14055     struct PackageInfo
14056       *info;
14057
14058     SV
14059       *perl_exception,
14060       *reference;
14061
14062     PERL_UNUSED_VAR(ref);
14063     PERL_UNUSED_VAR(ix);
14064     exception=AcquireExceptionInfo();
14065     perl_exception=newSVpv("",0);
14066     if (sv_isobject(ST(0)) == 0)
14067       {
14068         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14069           PackageName);
14070         goto PerlException;
14071       }
14072
14073     reference=SvRV(ST(0));
14074     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14075     if (image == (Image *) NULL)
14076       {
14077         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14078           PackageName);
14079         goto PerlException;
14080       }
14081
14082     status=SyncAuthenticPixels(image,exception);
14083     if (status != MagickFalse)
14084       return;
14085
14086   PerlException:
14087     InheritPerlException(exception,perl_exception);
14088     exception=DestroyExceptionInfo(exception);
14089     SvREFCNT_dec(perl_exception);  /* throw away all errors */
14090   }
14091 \f
14092 #
14093 ###############################################################################
14094 #                                                                             #
14095 #                                                                             #
14096 #                                                                             #
14097 #   T r a n s f o r m                                                         #
14098 #                                                                             #
14099 #                                                                             #
14100 #                                                                             #
14101 ###############################################################################
14102 #
14103 #
14104 void
14105 Transform(ref,...)
14106   Image::Magick ref=NO_INIT
14107   ALIAS:
14108     TransformImage = 1
14109     transform      = 2
14110     transformimage = 3
14111   PPCODE:
14112   {
14113     AV
14114       *av;
14115
14116     char
14117       *attribute,
14118       *crop_geometry,
14119       *geometry;
14120
14121     ExceptionInfo
14122       *exception;
14123
14124     HV
14125       *hv;
14126
14127     Image
14128       *clone,
14129       *image;
14130
14131     register ssize_t
14132       i;
14133
14134     struct PackageInfo
14135       *info;
14136
14137     SV
14138       *av_reference,
14139       *perl_exception,
14140       *reference,
14141       *rv,
14142       *sv;
14143
14144     PERL_UNUSED_VAR(ref);
14145     PERL_UNUSED_VAR(ix);
14146     exception=AcquireExceptionInfo();
14147     perl_exception=newSVpv("",0);
14148     sv=NULL;
14149     av=NULL;
14150     attribute=NULL;
14151     if (sv_isobject(ST(0)) == 0)
14152       {
14153         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14154           PackageName);
14155         goto PerlException;
14156       }
14157     reference=SvRV(ST(0));
14158     hv=SvSTASH(reference);
14159     av=newAV();
14160     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14161     SvREFCNT_dec(av);
14162     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14163     if (image == (Image *) NULL)
14164       {
14165         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14166           PackageName);
14167         goto PerlException;
14168       }
14169     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14170     /*
14171       Get attribute.
14172     */
14173     crop_geometry=(char *) NULL;
14174     geometry=(char *) NULL;
14175     for (i=2; i < items; i+=2)
14176     {
14177       attribute=(char *) SvPV(ST(i-1),na);
14178       switch (*attribute)
14179       {
14180         case 'c':
14181         case 'C':
14182         {
14183           if (LocaleCompare(attribute,"crop") == 0)
14184             {
14185               crop_geometry=SvPV(ST(i),na);
14186               break;
14187             }
14188           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14189             attribute);
14190           break;
14191         }
14192         case 'g':
14193         case 'G':
14194         {
14195           if (LocaleCompare(attribute,"geometry") == 0)
14196             {
14197               geometry=SvPV(ST(i),na);
14198               break;
14199             }
14200           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14201             attribute);
14202           break;
14203         }
14204         default:
14205         {
14206           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14207             attribute);
14208           break;
14209         }
14210       }
14211     }
14212     for ( ; image; image=image->next)
14213     {
14214       clone=CloneImage(image,0,0,MagickTrue,exception);
14215       if (clone == (Image *) NULL)
14216         goto PerlException;
14217       TransformImage(&clone,crop_geometry,geometry,exception);
14218       for ( ; clone; clone=clone->next)
14219       {
14220         AddImageToRegistry(sv,clone);
14221         rv=newRV(sv);
14222         av_push(av,sv_bless(rv,hv));
14223         SvREFCNT_dec(sv);
14224       }
14225     }
14226     exception=DestroyExceptionInfo(exception);
14227     ST(0)=av_reference;
14228     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
14229     XSRETURN(1);
14230
14231   PerlException:
14232     InheritPerlException(exception,perl_exception);
14233     exception=DestroyExceptionInfo(exception);
14234     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14235     SvPOK_on(perl_exception);
14236     ST(0)=sv_2mortal(perl_exception);
14237     XSRETURN(1);
14238   }
14239 \f
14240 #
14241 ###############################################################################
14242 #                                                                             #
14243 #                                                                             #
14244 #                                                                             #
14245 #   W r i t e                                                                 #
14246 #                                                                             #
14247 #                                                                             #
14248 #                                                                             #
14249 ###############################################################################
14250 #
14251 #
14252 void
14253 Write(ref,...)
14254   Image::Magick ref=NO_INIT
14255   ALIAS:
14256     WriteImage    = 1
14257     write         = 2
14258     writeimage    = 3
14259   PPCODE:
14260   {
14261     char
14262       filename[MaxTextExtent];
14263
14264     ExceptionInfo
14265       *exception;
14266
14267     Image
14268       *image,
14269       *next;
14270
14271     register ssize_t
14272       i;
14273
14274     ssize_t
14275       number_images,
14276       scene;
14277
14278     struct PackageInfo
14279       *info,
14280       *package_info;
14281
14282     SV
14283       *perl_exception,
14284       *reference;
14285
14286     PERL_UNUSED_VAR(ref);
14287     PERL_UNUSED_VAR(ix);
14288     exception=AcquireExceptionInfo();
14289     perl_exception=newSVpv("",0);
14290     number_images=0;
14291     package_info=(struct PackageInfo *) NULL;
14292     if (sv_isobject(ST(0)) == 0)
14293       {
14294         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14295           PackageName);
14296         goto PerlException;
14297       }
14298     reference=SvRV(ST(0));
14299     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14300     if (image == (Image *) NULL)
14301       {
14302         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14303           PackageName);
14304         goto PerlException;
14305       }
14306     package_info=ClonePackageInfo(info,exception);
14307     if (items == 2)
14308       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14309     else
14310       if (items > 2)
14311         for (i=2; i < items; i+=2)
14312           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14313             exception);
14314     (void) CopyMagickString(filename,package_info->image_info->filename,
14315       MaxTextExtent);
14316     scene=0;
14317     for (next=image; next; next=next->next)
14318     {
14319       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
14320       next->scene=scene++;
14321     }
14322     SetImageInfo(package_info->image_info,(unsigned int)
14323       GetImageListLength(image),exception);
14324     for (next=image; next; next=next->next)
14325     {
14326       (void) WriteImage(package_info->image_info,next,exception);
14327       number_images++;
14328       if (package_info->image_info->adjoin)
14329         break;
14330     }
14331
14332   PerlException:
14333     if (package_info != (struct PackageInfo *) NULL)
14334       DestroyPackageInfo(package_info);
14335     InheritPerlException(exception,perl_exception);
14336     exception=DestroyExceptionInfo(exception);
14337     sv_setiv(perl_exception,(IV) number_images);
14338     SvPOK_on(perl_exception);
14339     ST(0)=sv_2mortal(perl_exception);
14340     XSRETURN(1);
14341   }