]> granicus.if.org Git - imagemagick/blob - PerlMagick/Magick.xs
(no commit message)
[imagemagick] / PerlMagick / Magick.xs
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                         PPPP   EEEEE  RRRR   L                              %
6 %                         P   P  E      R   R  L                              %
7 %                         PPPP   EEE    RRRR   L                              %
8 %                         P      E      R  R   L                              %
9 %                         P      EEEEE  R   R  LLLLL                          %
10 %                                                                             %
11 %                  M   M   AAA    GGGG  IIIII   CCCC  K   K                   %
12 %                  MM MM  A   A  G        I    C      K  K                    %
13 %                  M M M  AAAAA  G GGG    I    C      KKK                     %
14 %                  M   M  A   A  G   G    I    C      K  K                    %
15 %                  M   M  A   A   GGGG  IIIII   CCCC  K   K                   %
16 %                                                                             %
17 %                                                                             %
18 %                Object-oriented Perl interface to ImageMagick                %
19 %                                                                             %
20 %                            Software Design                                  %
21 %                              Kyle Shorter                                   %
22 %                              John Cristy                                    %
23 %                             February 1997                                   %
24 %                                                                             %
25 %                                                                             %
26 %  Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization      %
27 %  dedicated to making software imaging solutions freely available.           %
28 %                                                                             %
29 %  You may not use this file except in compliance with the License.  You may  %
30 %  obtain a copy of the License at                                            %
31 %                                                                             %
32 %    http://www.imagemagick.org/script/license.php                            %
33 %                                                                             %
34 %  Unless required by applicable law or agreed to in writing, software        %
35 %  distributed under the License is distributed on an "AS IS" BASIS,          %
36 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
37 %  See the License for the specific language governing permissions and        %
38 %  limitations under the License.                                             %
39 %                                                                             %
40 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
41 %
42 %  PerlMagick is an objected-oriented Perl interface to ImageMagick.  Use
43 %  the module to read, manipulate, or write an image or image sequence from
44 %  within a Perl script.  This makes PerlMagick suitable for Web CGI scripts.
45 %
46 */
47 \f
48 /*
49   Include declarations.
50 */
51 #if defined(__cplusplus) || defined(c_plusplus)
52 extern "C" {
53 #endif
54
55 #define PERL_NO_GET_CONTEXT
56 #include "EXTERN.h"
57 #include "perl.h"
58 #include "XSUB.h"
59 #include <math.h>
60 #include <MagickCore/MagickCore.h>
61 #undef tainted
62
63 #if defined(__cplusplus) || defined(c_plusplus)
64 }
65 #endif
66 \f
67 /*
68   Define declarations.
69 */
70 #ifndef aTHX_
71 #define aTHX_
72 #define pTHX_
73 #define dTHX
74 #endif
75 #define DegreesToRadians(x)  (MagickPI*(x)/180.0)
76 #define EndOf(array)  (&array[NumberOf(array)])
77 #define MaxArguments  33
78 #ifndef na
79 #define na  PL_na
80 #endif
81 #define NumberOf(array)  (sizeof(array)/sizeof(*array))
82 #define PackageName   "Image::Magick"
83 #if PERL_VERSION <= 6
84 #define PerlIO  FILE
85 #define PerlIO_importFILE(f, fl)  (f)
86 #define PerlIO_findFILE(f)  NULL
87 #endif
88 #ifndef sv_undef
89 #define sv_undef  PL_sv_undef
90 #endif
91
92 #define AddImageToRegistry(sv,image) \
93 { \
94   if (magick_registry != (SplayTreeInfo *) NULL) \
95     { \
96       (void) AddValueToSplayTree(magick_registry,image,image); \
97       (sv)=newSViv((IV) image); \
98     } \
99 }
100
101 #define DeleteImageFromRegistry(reference,image) \
102 { \
103   if (magick_registry != (SplayTreeInfo *) NULL) \
104     { \
105       if (GetImageReferenceCount(image) == 1) \
106        (void) DeleteNodeByValueFromSplayTree(magick_registry,image); \
107       image=DestroyImage(image); \
108       sv_setiv(reference,0); \
109     } \
110 }
111
112 #define InheritPerlException(exception,perl_exception) \
113 { \
114   char \
115     message[MaxTextExtent]; \
116  \
117   if ((exception)->severity != UndefinedException) \
118     { \
119       (void) FormatLocaleString(message,MaxTextExtent,"Exception %d: %s%s%s%s",\
120         (exception)->severity, (exception)->reason ? \
121         GetLocaleExceptionMessage((exception)->severity,(exception)->reason) : \
122         "Unknown", (exception)->description ? " (" : "", \
123         (exception)->description ? GetLocaleExceptionMessage( \
124         (exception)->severity,(exception)->description) : "", \
125         (exception)->description ? ")" : ""); \
126       if ((perl_exception) != (SV *) NULL) \
127         { \
128           if (SvCUR(perl_exception)) \
129             sv_catpv(perl_exception,"\n"); \
130           sv_catpv(perl_exception,message); \
131         } \
132     } \
133 }
134
135 #define ThrowPerlException(exception,severity,tag,reason) \
136   (void) ThrowMagickException(exception,GetMagickModule(),severity, \
137     tag,"`%s'",reason); \
138 \f
139 /*
140   Typedef and structure declarations.
141 */
142 typedef enum
143 {
144   ArrayReference = (~0),
145   RealReference = (~0)-1,
146   FileReference = (~0)-2,
147   ImageReference = (~0)-3,
148   IntegerReference = (~0)-4,
149   StringReference = (~0)-5
150 } MagickReference;
151
152 typedef struct _Arguments
153 {
154   const char
155     *method;
156
157   ssize_t
158     type;
159 } Arguments;
160
161 struct ArgumentList
162 {
163   ssize_t
164     integer_reference;
165
166   MagickRealType
167     real_reference;
168
169   const char
170     *string_reference;
171
172   Image
173     *image_reference;
174
175   SV
176     *array_reference;
177
178   FILE
179     *file_reference;
180
181   size_t
182     length;
183 };
184
185 struct PackageInfo
186 {
187   ImageInfo
188     *image_info;
189 };
190
191 typedef void
192   *Image__Magick;  /* data type for the Image::Magick package */
193 \f
194 /*
195   Static declarations.
196 */
197 static struct
198   Methods
199   {
200     const char
201       *name;
202
203     Arguments
204       arguments[MaxArguments];
205   } Methods[] =
206   {
207     { "Comment", { {"comment", StringReference} } },
208     { "Label", { {"label", StringReference} } },
209     { "AddNoise", { {"noise", MagickNoiseOptions},
210       {"channel", MagickChannelOptions} } },
211     { "Colorize", { {"fill", StringReference}, {"opacity", StringReference} } },
212     { "Border", { {"geometry", StringReference}, {"width", IntegerReference},
213       {"height", IntegerReference}, {"fill", StringReference},
214       {"bordercolor", StringReference}, {"color", StringReference},
215       {"compose", MagickComposeOptions} } },
216     { "Blur", { {"geometry", StringReference}, {"radius", RealReference},
217       {"sigma", RealReference}, {"bias", RealReference},
218       {"channel", MagickChannelOptions} } },
219     { "Chop", { {"geometry", StringReference}, {"width", IntegerReference},
220       {"height", IntegerReference}, {"x", IntegerReference},
221       {"y", IntegerReference} } },
222     { "Crop", { {"geometry", StringReference}, {"width", IntegerReference},
223       {"height", IntegerReference}, {"x", IntegerReference},
224       {"y", IntegerReference}, {"fuzz", StringReference},
225       {"gravity", MagickGravityOptions} } },
226     { "Despeckle", },
227     { "Edge", { {"radius", RealReference} } },
228     { "Emboss", { {"geometry", StringReference}, {"radius", RealReference},
229       {"sigma", RealReference} } },
230     { "Enhance", },
231     { "Flip", },
232     { "Flop", },
233     { "Frame", { {"geometry", StringReference}, {"width", IntegerReference},
234       {"height", IntegerReference}, {"inner", IntegerReference},
235       {"outer", IntegerReference}, {"fill", StringReference},
236       {"color", StringReference}, {"compose", MagickComposeOptions} } },
237     { "Implode", { {"amount", RealReference},
238       {"interpolate", MagickInterpolateOptions} } },
239     { "Magnify", },
240     { "MedianFilter", { {"geometry", StringReference},
241       {"width", IntegerReference}, {"height", IntegerReference},
242       {"channel", MagickChannelOptions} } },
243     { "Minify", },
244     { "OilPaint", { {"radius", RealReference}, {"sigma", RealReference} } },
245     { "ReduceNoise", { {"geometry", StringReference},
246       {"width", IntegerReference},{"height", IntegerReference},
247       {"channel", MagickChannelOptions} } },
248     { "Roll", { {"geometry", StringReference}, {"x", IntegerReference},
249       {"y", IntegerReference} } },
250     { "Rotate", { {"degrees", RealReference}, {"fill", StringReference},
251       {"color", StringReference}, {"background", StringReference} } },
252     { "Sample", { {"geometry", StringReference}, {"width", IntegerReference},
253       {"height", IntegerReference} } },
254     { "Scale", { {"geometry", StringReference}, {"width", IntegerReference},
255       {"height", IntegerReference} } },
256     { "Shade", { {"geometry", StringReference}, {"azimuth", RealReference},
257       {"elevation", RealReference}, {"gray", MagickBooleanOptions} } },
258     { "Sharpen", { {"geometry", StringReference}, {"radius", RealReference},
259       {"sigma", RealReference}, {"bias", RealReference},
260       {"channel", MagickChannelOptions} } },
261     { "Shear", { {"geometry", StringReference}, {"x", RealReference},
262       {"y", RealReference}, { "fill", StringReference},
263       {"color", StringReference} } },
264     { "Spread", { {"radius", RealReference} } },
265     { "Swirl", { {"degrees", RealReference},
266       {"interpolate", MagickInterpolateOptions} } },
267     { "Resize", { {"geometry", StringReference}, {"width", IntegerReference},
268       {"height", IntegerReference}, {"filter", MagickFilterOptions},
269       {"support", StringReference }, {"blur", RealReference } } },
270     { "Zoom", { {"geometry", StringReference}, {"width", IntegerReference},
271       {"height", IntegerReference}, {"filter", MagickFilterOptions},
272       {"support", RealReference }, {"blur", RealReference } } },
273     { "Annotate", { {"text", StringReference}, {"font", StringReference},
274       {"pointsize", RealReference}, {"density", StringReference},
275       {"undercolor", StringReference}, {"stroke", StringReference},
276       {"fill", StringReference}, {"geometry", StringReference},
277       {"pen", StringReference}, {"x", RealReference},
278       {"y", RealReference}, {"gravity", MagickGravityOptions},
279       {"translate", StringReference}, {"scale", StringReference},
280       {"rotate", RealReference}, {"skewX", RealReference},
281       {"skewY", RealReference}, {"strokewidth", RealReference},
282       {"antialias", MagickBooleanOptions}, {"family", StringReference},
283       {"style", MagickStyleOptions}, {"stretch", MagickStretchOptions},
284       {"weight", IntegerReference}, {"align", MagickAlignOptions},
285       {"encoding", StringReference}, {"affine", ArrayReference},
286       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
287       {"tile", ImageReference}, {"kerning", RealReference},
288       {"interline-spacing", RealReference},
289       {"interword-spacing", RealReference},
290       {"direction", MagickDirectionOptions} } },
291     { "ColorFloodfill", { {"geometry", StringReference},
292       {"x", IntegerReference}, {"y", IntegerReference},
293       {"fill", StringReference}, {"bordercolor", StringReference},
294       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
295     { "Composite", { {"image", ImageReference},
296       {"compose", MagickComposeOptions}, {"geometry", StringReference},
297       {"x", IntegerReference}, {"y", IntegerReference},
298       {"gravity", MagickGravityOptions}, {"opacity", StringReference},
299       {"tile", MagickBooleanOptions}, {"rotate", RealReference},
300       {"color", StringReference}, {"mask", ImageReference},
301       {"channel", MagickChannelOptions},
302       {"interpolate", MagickInterpolateOptions}, {"args", StringReference},
303       {"blend", StringReference} } },
304     { "Contrast", { {"sharpen", MagickBooleanOptions} } },
305     { "CycleColormap", { {"display", IntegerReference} } },
306     { "Draw", { {"primitive", MagickPrimitiveOptions},
307       {"points", StringReference}, {"method", MagickMethodOptions},
308       {"stroke", StringReference}, {"fill", StringReference},
309       {"strokewidth", RealReference}, {"font", StringReference},
310       {"bordercolor", StringReference}, {"x", RealReference},
311       {"y", RealReference}, {"translate", StringReference},
312       {"scale", StringReference}, {"rotate", RealReference},
313       {"skewX", RealReference}, {"skewY", RealReference},
314       {"tile", ImageReference}, {"pointsize", RealReference},
315       {"antialias", MagickBooleanOptions}, {"density", StringReference},
316       {"linewidth", RealReference}, {"affine", ArrayReference},
317       {"stroke-dashoffset", RealReference},
318       {"stroke-dasharray", ArrayReference},
319       {"interpolate", MagickInterpolateOptions},
320       {"origin", StringReference}, {"text", StringReference},
321       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
322       {"vector-graphics", StringReference}, {"kerning", RealReference},
323       {"interline-spacing", RealReference},
324       {"interword-spacing", RealReference},
325       {"direction", MagickDirectionOptions} } },
326     { "Equalize", { {"channel", MagickChannelOptions} } },
327     { "Gamma", { {"gamma", StringReference}, {"channel", MagickChannelOptions},
328       {"red", RealReference}, {"green", RealReference},
329       {"blue", RealReference} } },
330     { "Map", { {"image", ImageReference}, {"dither", MagickBooleanOptions},
331       {"dither-method", MagickDitherOptions} } },
332     { "MatteFloodfill", { {"geometry", StringReference},
333       {"x", IntegerReference}, {"y", IntegerReference},
334       {"opacity", StringReference}, {"bordercolor", StringReference},
335       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
336     { "Modulate", { {"factor", StringReference}, {"hue", RealReference},
337       {"saturation", RealReference}, {"whiteness", RealReference},
338       {"brightness", RealReference}, {"lightness", RealReference},
339       {"blackness", RealReference} } },
340     { "Negate", { {"gray", MagickBooleanOptions},
341       {"channel", MagickChannelOptions} } },
342     { "Normalize", { {"channel", MagickChannelOptions} } },
343     { "NumberColors", },
344     { "Opaque", { {"color", StringReference}, {"fill", StringReference},
345       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
346       {"invert", MagickBooleanOptions} } },
347     { "Quantize", { {"colors", IntegerReference},
348       {"treedepth", IntegerReference}, {"colorspace", MagickColorspaceOptions},
349       {"dither", MagickBooleanOptions}, {"measure", MagickBooleanOptions},
350       {"global", MagickBooleanOptions}, {"transparent-color", StringReference},
351       {"dither-method", MagickDitherOptions} } },
352     { "Raise", { {"geometry", StringReference}, {"width", IntegerReference},
353       {"height", IntegerReference}, {"raise", MagickBooleanOptions} } },
354     { "Segment", { {"geometry", StringReference},
355       {"cluster-threshold", RealReference},
356       {"smoothing-threshold", RealReference},
357       {"colorspace", MagickColorspaceOptions},
358       {"verbose", MagickBooleanOptions} } },
359     { "Signature", },
360     { "Solarize", { {"geometry", StringReference},
361       {"threshold", StringReference} } },
362     { "Sync", },
363     { "Texture", { {"texture", ImageReference} } },
364     { "Evaluate", { {"value", RealReference},
365       {"operator", MagickEvaluateOptions},
366       {"channel", MagickChannelOptions} } },
367     { "Transparent", { {"color", StringReference}, {"opacity", StringReference},
368       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
369     { "Threshold", { {"threshold", StringReference},
370       {"channel", MagickChannelOptions} } },
371     { "Charcoal", { {"geometry", StringReference}, {"radius", RealReference},
372       {"sigma", RealReference}, {"biabias", RealReference} } },
373     { "Trim", { {"fuzz", StringReference} } },
374     { "Wave", { {"geometry", StringReference}, {"amplitude", RealReference},
375       {"wavelength", RealReference},
376       {"interpolate", MagickInterpolateOptions} } },
377     { "Separate", { {"channel", MagickChannelOptions} } },
378     { "Condense", },
379     { "Stereo", { {"image", ImageReference}, {"x", IntegerReference},
380       {"y", IntegerReference} } },
381     { "Stegano", { {"image", ImageReference}, {"offset", IntegerReference} } },
382     { "Deconstruct", },
383     { "GaussianBlur", { {"geometry", StringReference},
384       {"radius", RealReference}, {"sigma", RealReference},
385       {"bias", RealReference}, {"channel", MagickChannelOptions} } },
386     { "Convolve", { {"coefficients", ArrayReference},
387       {"channel", MagickChannelOptions}, {"bias", StringReference},
388       {"kernel", StringReference} } },
389     { "Profile", { {"name", StringReference}, {"profile", StringReference},
390       { "rendering-intent", MagickIntentOptions},
391       { "black-point-compensation", MagickBooleanOptions} } },
392     { "UnsharpMask", { {"geometry", StringReference},
393       {"radius", RealReference}, {"sigma", RealReference},
394       {"amount", RealReference}, {"threshold", RealReference},
395       {"channel", MagickChannelOptions} } },
396     { "MotionBlur", { {"geometry", StringReference},
397       {"radius", RealReference}, {"sigma", RealReference},
398       {"angle", RealReference}, {"bias", RealReference},
399       {"channel", MagickChannelOptions} } },
400     { "OrderedDither", { {"threshold", StringReference},
401       {"channel", MagickChannelOptions} } },
402     { "Shave", { {"geometry", StringReference}, {"width", IntegerReference},
403       {"height", IntegerReference} } },
404     { "Level", { {"levels", StringReference}, {"black-point", RealReference},
405       {"white-point", RealReference}, {"gamma", RealReference},
406       {"channel", MagickChannelOptions}, {"level", StringReference} } },
407     { "Clip", { {"id", StringReference}, {"inside", MagickBooleanOptions} } },
408     { "AffineTransform", { {"affine", ArrayReference},
409       {"translate", StringReference}, {"scale", StringReference},
410       {"rotate", RealReference}, {"skewX", RealReference},
411       {"skewY", RealReference}, {"interpolate", MagickInterpolateOptions},
412       {"background", StringReference} } },
413     { "Difference", { {"image", ImageReference}, {"fuzz", StringReference} } },
414     { "AdaptiveThreshold", { {"geometry", StringReference},
415       {"width", IntegerReference}, {"height", IntegerReference},
416       {"bias", RealReference} } },
417     { "Resample", { {"density", StringReference}, {"x", RealReference},
418       {"y", RealReference}, {"filter", MagickFilterOptions},
419       {"support", RealReference }, {"blur", RealReference } } },
420     { "Describe", { {"file", FileReference} } },
421     { "BlackThreshold", { {"threshold", StringReference},
422       {"channel", MagickChannelOptions} } },
423     { "WhiteThreshold", { {"threshold", StringReference},
424       {"channel", MagickChannelOptions} } },
425     { "RadialBlur", { {"geometry", StringReference}, {"angle", RealReference},
426       {"bias", RealReference}, {"channel", MagickChannelOptions} } },
427     { "Thumbnail", { {"geometry", StringReference}, {"width", IntegerReference},
428       {"height", IntegerReference} } },
429     { "Strip", },
430     { "Tint", { {"fill", StringReference}, {"opacity", StringReference} } },
431     { "Channel", { {"channel", MagickChannelOptions} } },
432     { "Splice", { {"geometry", StringReference}, {"width", IntegerReference},
433       {"height", IntegerReference}, {"x", IntegerReference},
434       {"y", IntegerReference}, {"fuzz", StringReference},
435       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
436     { "Posterize", { {"levels", IntegerReference},
437       {"dither", MagickBooleanOptions} } },
438     { "Shadow", { {"geometry", StringReference}, {"opacity", RealReference},
439       {"sigma", RealReference}, {"x", IntegerReference},
440       {"y", IntegerReference} } },
441     { "Identify", { {"file", FileReference}, {"features", StringReference},
442       {"unique", MagickBooleanOptions} } },
443     { "SepiaTone", { {"threshold", RealReference} } },
444     { "SigmoidalContrast", { {"geometry", StringReference},
445       {"contrast", RealReference}, {"mid-point", RealReference},
446       {"channel", MagickChannelOptions}, {"sharpen", MagickBooleanOptions} } },
447     { "Extent", { {"geometry", StringReference}, {"width", IntegerReference},
448       {"height", IntegerReference}, {"x", IntegerReference},
449       {"y", IntegerReference}, {"fuzz", StringReference},
450       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
451     { "Vignette", { {"geometry", StringReference}, {"radius", RealReference},
452       {"sigma", RealReference}, {"x", IntegerReference},
453       {"y", IntegerReference}, {"background", StringReference} } },
454     { "ContrastStretch", { {"levels", StringReference},
455       {"black-point", RealReference},{"white-point", RealReference},
456       {"channel", MagickChannelOptions} } },
457     { "Sans0", },
458     { "Sans1", },
459     { "AdaptiveSharpen", { {"geometry", StringReference},
460       {"radius", RealReference}, {"sigma", RealReference},
461       {"bias", RealReference}, {"channel", MagickChannelOptions} } },
462     { "Transpose", },
463     { "Transverse", },
464     { "AutoOrient", },
465     { "AdaptiveBlur", { {"geometry", StringReference},
466       {"radius", RealReference}, {"sigma", RealReference},
467       {"bias", RealReference}, {"channel", MagickChannelOptions} } },
468     { "Sketch", { {"geometry", StringReference},
469       {"radius", RealReference}, {"sigma", RealReference},
470       {"angle", RealReference}, {"bias", RealReference} } },
471     { "UniqueColors", },
472     { "AdaptiveResize", { {"geometry", StringReference},
473       {"width", IntegerReference}, {"height", IntegerReference},
474       {"filter", MagickFilterOptions}, {"support", StringReference },
475       {"blur", RealReference } } },
476     { "ClipMask", { {"mask", ImageReference} } },
477     { "LinearStretch", { {"levels", StringReference},
478       {"black-point", RealReference},{"white-point", RealReference} } },
479     { "Recolor", { {"matrix", ArrayReference} } },
480     { "Mask", { {"mask", ImageReference} } },
481     { "Polaroid", { {"caption", StringReference}, {"angle", RealReference},
482       {"font", StringReference}, {"stroke", StringReference},
483       {"fill", StringReference}, {"strokewidth", RealReference},
484       {"pointsize", RealReference}, {"gravity", MagickGravityOptions},
485       {"background", StringReference} } },
486     { "FloodfillPaint", { {"geometry", StringReference},
487       {"x", IntegerReference}, {"y", IntegerReference},
488       {"fill", StringReference}, {"bordercolor", StringReference},
489       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
490       {"invert", MagickBooleanOptions} } },
491     { "Distort", { {"points", ArrayReference}, {"method", MagickDistortOptions},
492       {"virtual-pixel", MagickVirtualPixelOptions},
493       {"best-fit", MagickBooleanOptions} } },
494     { "Clut", { {"image", ImageReference},
495       {"channel", MagickChannelOptions} } },
496     { "LiquidRescale", { {"geometry", StringReference},
497       {"width", IntegerReference}, {"height", IntegerReference},
498       {"delta-x", RealReference}, {"rigidity", RealReference } } },
499     { "Encipher", { {"passphrase", StringReference} } },
500     { "Decipher", { {"passphrase", StringReference} } },
501     { "Deskew", { {"geometry", StringReference},
502       {"threshold", StringReference} } },
503     { "Remap", { {"image", ImageReference}, {"dither", MagickBooleanOptions},
504       {"dither-method", MagickDitherOptions} } },
505     { "SparseColor", { {"points", ArrayReference},
506       {"method", MagickSparseColorOptions},
507       {"virtual-pixel", MagickVirtualPixelOptions},
508       {"channel", MagickChannelOptions} } },
509     { "Function", { {"parameters", ArrayReference},
510       {"function", MagickFunctionOptions},
511       {"virtual-pixel", MagickVirtualPixelOptions} } },
512     { "SelectiveBlur", { {"geometry", StringReference},
513       {"radius", RealReference}, {"sigma", RealReference},
514       {"threshold", RealReference}, {"bias", RealReference},
515       {"channel", MagickChannelOptions} } },
516     { "HaldClut", { {"image", ImageReference},
517       {"channel", MagickChannelOptions} } },
518     { "BlueShift", { {"factor", StringReference} } },
519     { "ForwardFourierTransform", { {"magnitude", MagickBooleanOptions} } },
520     { "InverseFourierTransform", { {"magnitude", MagickBooleanOptions} } },
521     { "ColorDecisionList", {
522       {"color-correction-collection", StringReference} } },
523     { "AutoGamma", { {"channel", MagickChannelOptions} } },
524     { "AutoLevel", { {"channel", MagickChannelOptions} } },
525     { "LevelColors", { {"invert", MagickBooleanOptions},
526       {"black-point", StringReference}, {"white-point", StringReference},
527       {"channel", MagickChannelOptions}, {"invert", MagickBooleanOptions} } },
528     { "Clamp", { {"channel", MagickChannelOptions} } },
529     { "BrightnessContrast", { {"levels", StringReference},
530       {"brightness", RealReference},{"contrast", RealReference},
531       {"channel", MagickChannelOptions} } },
532     { "Morphology", { {"kernel", StringReference},
533       {"channel", MagickChannelOptions}, {"method", MagickMorphologyOptions},
534       {"iterations", IntegerReference} } },
535     { "ColorMatrix", { {"matrix", ArrayReference} } },
536     { "Color", { {"color", StringReference} } },
537     { "Mode", { {"geometry", StringReference},
538       {"width", IntegerReference},{"height", IntegerReference},
539       {"channel", MagickChannelOptions} } },
540     { "Statistic", { {"geometry", StringReference},
541       {"width", IntegerReference},{"height", IntegerReference},
542       {"channel", MagickChannelOptions}, {"type", MagickStatisticOptions} } }
543   };
544
545 static SplayTreeInfo
546   *magick_registry = (SplayTreeInfo *) NULL;
547 \f
548 /*
549   Forward declarations.
550 */
551 static Image
552   *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
553
554 static ssize_t
555   strEQcase(const char *,const char *);
556 \f
557 /*
558 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
559 %                                                                             %
560 %                                                                             %
561 %                                                                             %
562 %   C l o n e P a c k a g e I n f o                                           %
563 %                                                                             %
564 %                                                                             %
565 %                                                                             %
566 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
567 %
568 %  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
569 %  a new one.
570 %
571 %  The format of the ClonePackageInfo routine is:
572 %
573 %      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
574 %        exception)
575 %
576 %  A description of each parameter follows:
577 %
578 %    o info: a structure of type info.
579 %
580 %    o exception: Return any errors or warnings in this structure.
581 %
582 */
583 static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
584   ExceptionInfo *exception)
585 {
586   struct PackageInfo
587     *clone_info;
588
589   clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
590   if (clone_info == (struct PackageInfo *) NULL)
591     {
592       ThrowPerlException(exception,ResourceLimitError,
593         "UnableToClonePackageInfo",PackageName);
594       return((struct PackageInfo *) NULL);
595     }
596   if (info == (struct PackageInfo *) NULL)
597     {
598       clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
599       return(clone_info);
600     }
601   *clone_info=(*info);
602   clone_info->image_info=CloneImageInfo(info->image_info);
603   return(clone_info);
604 }
605 \f
606 /*
607 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
608 %                                                                             %
609 %                                                                             %
610 %                                                                             %
611 %   c o n s t a n t                                                           %
612 %                                                                             %
613 %                                                                             %
614 %                                                                             %
615 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
616 %
617 %  constant() returns a double value for the specified name.
618 %
619 %  The format of the constant routine is:
620 %
621 %      double constant(char *name,ssize_t sans)
622 %
623 %  A description of each parameter follows:
624 %
625 %    o value: Method constant returns a double value for the specified name.
626 %
627 %    o name: The name of the constant.
628 %
629 %    o sans: This integer value is not used.
630 %
631 */
632 static double constant(char *name,ssize_t sans)
633 {
634   (void) sans;
635   errno=0;
636   switch (*name)
637   {
638     case 'B':
639     {
640       if (strEQ(name,"BlobError"))
641         return(BlobError);
642       if (strEQ(name,"BlobWarning"))
643         return(BlobWarning);
644       break;
645     }
646     case 'C':
647     {
648       if (strEQ(name,"CacheError"))
649         return(CacheError);
650       if (strEQ(name,"CacheWarning"))
651         return(CacheWarning);
652       if (strEQ(name,"CoderError"))
653         return(CoderError);
654       if (strEQ(name,"CoderWarning"))
655         return(CoderWarning);
656       if (strEQ(name,"ConfigureError"))
657         return(ConfigureError);
658       if (strEQ(name,"ConfigureWarning"))
659         return(ConfigureWarning);
660       if (strEQ(name,"CorruptImageError"))
661         return(CorruptImageError);
662       if (strEQ(name,"CorruptImageWarning"))
663         return(CorruptImageWarning);
664       break;
665     }
666     case 'D':
667     {
668       if (strEQ(name,"DelegateError"))
669         return(DelegateError);
670       if (strEQ(name,"DelegateWarning"))
671         return(DelegateWarning);
672       if (strEQ(name,"DrawError"))
673         return(DrawError);
674       if (strEQ(name,"DrawWarning"))
675         return(DrawWarning);
676       break;
677     }
678     case 'E':
679     {
680       if (strEQ(name,"ErrorException"))
681         return(ErrorException);
682       if (strEQ(name,"ExceptionError"))
683         return(CoderError);
684       if (strEQ(name,"ExceptionWarning"))
685         return(CoderWarning);
686       break;
687     }
688     case 'F':
689     {
690       if (strEQ(name,"FatalErrorException"))
691         return(FatalErrorException);
692       if (strEQ(name,"FileOpenError"))
693         return(FileOpenError);
694       if (strEQ(name,"FileOpenWarning"))
695         return(FileOpenWarning);
696       break;
697     }
698     case 'I':
699     {
700       if (strEQ(name,"ImageError"))
701         return(ImageError);
702       if (strEQ(name,"ImageWarning"))
703         return(ImageWarning);
704       break;
705     }
706     case 'M':
707     {
708       if (strEQ(name,"MaxRGB"))
709         return(QuantumRange);
710       if (strEQ(name,"MissingDelegateError"))
711         return(MissingDelegateError);
712       if (strEQ(name,"MissingDelegateWarning"))
713         return(MissingDelegateWarning);
714       if (strEQ(name,"ModuleError"))
715         return(ModuleError);
716       if (strEQ(name,"ModuleWarning"))
717         return(ModuleWarning);
718       break;
719     }
720     case 'O':
721     {
722       if (strEQ(name,"Opaque"))
723         return(OpaqueAlpha);
724       if (strEQ(name,"OptionError"))
725         return(OptionError);
726       if (strEQ(name,"OptionWarning"))
727         return(OptionWarning);
728       break;
729     }
730     case 'Q':
731     {
732       if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
733         return(MAGICKCORE_QUANTUM_DEPTH);
734       if (strEQ(name,"QuantumDepth"))
735         return(MAGICKCORE_QUANTUM_DEPTH);
736       if (strEQ(name,"QuantumRange"))
737         return(QuantumRange);
738       break;
739     }
740     case 'R':
741     {
742       if (strEQ(name,"ResourceLimitError"))
743         return(ResourceLimitError);
744       if (strEQ(name,"ResourceLimitWarning"))
745         return(ResourceLimitWarning);
746       if (strEQ(name,"RegistryError"))
747         return(RegistryError);
748       if (strEQ(name,"RegistryWarning"))
749         return(RegistryWarning);
750       break;
751     }
752     case 'S':
753     {
754       if (strEQ(name,"StreamError"))
755         return(StreamError);
756       if (strEQ(name,"StreamWarning"))
757         return(StreamWarning);
758       if (strEQ(name,"Success"))
759         return(0);
760       break;
761     }
762     case 'T':
763     {
764       if (strEQ(name,"Transparent"))
765         return(TransparentAlpha);
766       if (strEQ(name,"TypeError"))
767         return(TypeError);
768       if (strEQ(name,"TypeWarning"))
769         return(TypeWarning);
770       break;
771     }
772     case 'W':
773     {
774       if (strEQ(name,"WarningException"))
775         return(WarningException);
776       break;
777     }
778     case 'X':
779     {
780       if (strEQ(name,"XServerError"))
781         return(XServerError);
782       if (strEQ(name,"XServerWarning"))
783         return(XServerWarning);
784       break;
785     }
786   }
787   errno=EINVAL;
788   return(0);
789 }
790 \f
791 /*
792 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
793 %                                                                             %
794 %                                                                             %
795 %                                                                             %
796 %   D e s t r o y P a c k a g e I n f o                                       %
797 %                                                                             %
798 %                                                                             %
799 %                                                                             %
800 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
801 %
802 %  Method DestroyPackageInfo frees a previously created info structure.
803 %
804 %  The format of the DestroyPackageInfo routine is:
805 %
806 %      DestroyPackageInfo(struct PackageInfo *info)
807 %
808 %  A description of each parameter follows:
809 %
810 %    o info: a structure of type info.
811 %
812 */
813 static void DestroyPackageInfo(struct PackageInfo *info)
814 {
815   info->image_info=DestroyImageInfo(info->image_info);
816   info=(struct PackageInfo *) RelinquishMagickMemory(info);
817 }
818 \f
819 /*
820 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
821 %                                                                             %
822 %                                                                             %
823 %                                                                             %
824 %   G e t L i s t                                                             %
825 %                                                                             %
826 %                                                                             %
827 %                                                                             %
828 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
829 %
830 %  Method GetList is recursively called by SetupList to traverse the
831 %  Image__Magick reference.  If building an reference_vector (see SetupList),
832 %  *current is the current position in *reference_vector and *last is the final
833 %  entry in *reference_vector.
834 %
835 %  The format of the GetList routine is:
836 %
837 %      GetList(info)
838 %
839 %  A description of each parameter follows:
840 %
841 %    o info: a structure of type info.
842 %
843 */
844 static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
845   ssize_t *current,ssize_t *last,ExceptionInfo *exception)
846 {
847   Image
848     *image;
849
850   if (reference == (SV *) NULL)
851     return(NULL);
852   switch (SvTYPE(reference))
853   {
854     case SVt_PVAV:
855     {
856       AV
857         *av;
858
859       Image
860         *head,
861         *previous;
862
863       register ssize_t
864         i;
865
866       ssize_t
867         n;
868
869       /*
870         Array of images.
871       */
872       previous=(Image *) NULL;
873       head=(Image *) NULL;
874       av=(AV *) reference;
875       n=av_len(av);
876       for (i=0; i <= n; i++)
877       {
878         SV
879           **rv;
880
881         rv=av_fetch(av,i,0);
882         if (rv && *rv && sv_isobject(*rv))
883           {
884             image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
885               exception);
886             if (image == (Image *) NULL)
887               continue;
888             if (image == previous)
889               {
890                 image=CloneImage(image,0,0,MagickTrue,exception);
891                 if (image == (Image *) NULL)
892                   return(NULL);
893               }
894             image->previous=previous;
895             *(previous ? &previous->next : &head)=image;
896             for (previous=image; previous->next; previous=previous->next) ;
897           }
898       }
899       return(head);
900     }
901     case SVt_PVMG:
902     {
903       /*
904         Blessed scalar, one image.
905       */
906       image=(Image *) SvIV(reference);
907       if (image == (Image *) NULL)
908         return(NULL);
909       image->previous=(Image *) NULL;
910       image->next=(Image *) NULL;
911       if (reference_vector)
912         {
913           if (*current == *last)
914             {
915               *last+=256;
916               if (*reference_vector == (SV **) NULL)
917                 *reference_vector=(SV **) AcquireQuantumMemory(*last,
918                   sizeof(*reference_vector));
919               else
920                 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
921                   *last,sizeof(*reference_vector));
922             }
923           if (*reference_vector == (SV **) NULL)
924             {
925               ThrowPerlException(exception,ResourceLimitError,
926                 "MemoryAllocationFailed",PackageName);
927               return((Image *) NULL);
928             }
929           (*reference_vector)[*current]=reference;
930           (*reference_vector)[++(*current)]=NULL;
931         }
932       return(image);
933     }
934     default:
935       break;
936   }
937   (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
938     (double) SvTYPE(reference));
939   return((Image *) NULL);
940 }
941 \f
942 /*
943 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
944 %                                                                             %
945 %                                                                             %
946 %                                                                             %
947 %   G e t P a c k a g e I n f o                                               %
948 %                                                                             %
949 %                                                                             %
950 %                                                                             %
951 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
952 %
953 %  Method GetPackageInfo looks up or creates an info structure for the given
954 %  Image__Magick reference.  If it does create a new one, the information in
955 %  package_info is used to initialize it.
956 %
957 %  The format of the GetPackageInfo routine is:
958 %
959 %      struct PackageInfo *GetPackageInfo(void *reference,
960 %        struct PackageInfo *package_info,ExceptionInfo *exception)
961 %
962 %  A description of each parameter follows:
963 %
964 %    o info: a structure of type info.
965 %
966 %    o exception: Return any errors or warnings in this structure.
967 %
968 */
969 static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
970   struct PackageInfo *package_info,ExceptionInfo *exception)
971 {
972   char
973     message[MaxTextExtent];
974
975   struct PackageInfo
976     *clone_info;
977
978   SV
979     *sv;
980
981   (void) FormatLocaleString(message,MaxTextExtent,"%s::package%s%p",
982     PackageName,XS_VERSION,reference);
983   sv=perl_get_sv(message,(TRUE | 0x02));
984   if (sv == (SV *) NULL)
985     {
986       ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
987         message);
988       return(package_info);
989     }
990   if (SvREFCNT(sv) == 0)
991     (void) SvREFCNT_inc(sv);
992   if (SvIOKp(sv) && (clone_info=(struct PackageInfo *) SvIV(sv)))
993     return(clone_info);
994   clone_info=ClonePackageInfo(package_info,exception);
995   sv_setiv(sv,(IV) clone_info);
996   return(clone_info);
997 }
998 \f
999 /*
1000 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1001 %                                                                             %
1002 %                                                                             %
1003 %                                                                             %
1004 %   S e t A t t r i b u t e                                                   %
1005 %                                                                             %
1006 %                                                                             %
1007 %                                                                             %
1008 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1009 %
1010 %  SetAttribute() sets the attribute to the value in sval.  This can change
1011 %  either or both of image or info.
1012 %
1013 %  The format of the SetAttribute routine is:
1014 %
1015 %      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1016 %        SV *sval,ExceptionInfo *exception)
1017 %
1018 %  A description of each parameter follows:
1019 %
1020 %    o list: a list of strings.
1021 %
1022 %    o string: a character string.
1023 %
1024 */
1025
1026 static double SiPrefixToDouble(const char *string,const double interval)
1027 {
1028   char
1029     *q;
1030
1031   double
1032     scale,
1033     value;
1034
1035   value=InterpretLocaleValue(string,&q);
1036   scale=1000.0;
1037   if ((*q != '\0') && (tolower((int) ((unsigned char) *(q+1))) == 'i'))
1038     scale=1024.0;
1039   switch (tolower((int) ((unsigned char) *q)))
1040   {
1041     case '%': value*=pow(scale,0)*interval/100.0; break;
1042     case 'k': value*=pow(scale,1); break;
1043     case 'm': value*=pow(scale,2); break;
1044     case 'g': value*=pow(scale,3); break;
1045     case 't': value*=pow(scale,4); break;
1046     case 'p': value*=pow(scale,5); break;
1047     case 'e': value*=pow(scale,6); break;
1048     case 'z': value*=pow(scale,7); break;
1049     case 'y': value*=pow(scale,8); break;
1050     default:  break;
1051   }
1052   return(value);
1053 }
1054
1055 static inline ssize_t StringToLong(const char *value)
1056 {
1057   return(strtol(value,(char **) NULL,10));
1058 }
1059
1060 static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1061   const char *attribute,SV *sval,ExceptionInfo *exception)
1062 {
1063   GeometryInfo
1064     geometry_info;
1065
1066   long
1067     x,
1068     y;
1069
1070   PixelInfo
1071     pixel;
1072
1073   MagickStatusType
1074     flags;
1075
1076   PixelPacket
1077     *color,
1078     target_color;
1079
1080   ssize_t
1081     sp;
1082
1083   switch (*attribute)
1084   {
1085     case 'A':
1086     case 'a':
1087     {
1088       if (LocaleCompare(attribute,"adjoin") == 0)
1089         {
1090           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1091             SvPV(sval,na)) : SvIV(sval);
1092           if (sp < 0)
1093             {
1094               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1095                 SvPV(sval,na));
1096               break;
1097             }
1098           if (info)
1099             info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1100           break;
1101         }
1102       if (LocaleCompare(attribute,"alpha") == 0)
1103         {
1104           sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaOptions,MagickFalse,
1105             SvPV(sval,na)) : SvIV(sval);
1106           if (sp < 0)
1107             {
1108               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1109                 SvPV(sval,na));
1110               break;
1111             }
1112           for ( ; image; image=image->next)
1113             (void) SetImageAlphaChannel(image,(AlphaChannelType) sp,exception);
1114           break;
1115         }
1116       if (LocaleCompare(attribute,"antialias") == 0)
1117         {
1118           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1119             SvPV(sval,na)) : SvIV(sval);
1120           if (sp < 0)
1121             {
1122               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1123                 SvPV(sval,na));
1124               break;
1125             }
1126           if (info)
1127             info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1128           break;
1129         }
1130       if (LocaleCompare(attribute,"area-limit") == 0)
1131         {
1132           MagickSizeType
1133             limit;
1134
1135           limit=MagickResourceInfinity;
1136           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1137             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1138           (void) SetMagickResourceLimit(AreaResource,limit);
1139           break;
1140         }
1141       if (LocaleCompare(attribute,"attenuate") == 0)
1142         {
1143           if (info)
1144             (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1145           break;
1146         }
1147       if (LocaleCompare(attribute,"authenticate") == 0)
1148         {
1149           if (info)
1150             (void) CloneString(&info->image_info->authenticate,SvPV(sval,na));
1151           break;
1152         }
1153       if (info)
1154         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1155       for ( ; image; image=image->next)
1156         SetImageProperty(image,attribute,SvPV(sval,na));
1157       break;
1158     }
1159     case 'B':
1160     case 'b':
1161     {
1162       if (LocaleCompare(attribute,"background") == 0)
1163         {
1164           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1165           if (info)
1166             info->image_info->background_color=target_color;
1167           for ( ; image; image=image->next)
1168             image->background_color=target_color;
1169           break;
1170         }
1171       if (LocaleCompare(attribute,"bias") == 0)
1172         {
1173           for ( ; image; image=image->next)
1174             image->bias=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1175           break;
1176         }
1177       if (LocaleCompare(attribute,"blue-primary") == 0)
1178         {
1179           for ( ; image; image=image->next)
1180           {
1181             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1182             image->chromaticity.blue_primary.x=geometry_info.rho;
1183             image->chromaticity.blue_primary.y=geometry_info.sigma;
1184             if ((flags & SigmaValue) == 0)
1185               image->chromaticity.blue_primary.y=
1186                 image->chromaticity.blue_primary.x;
1187           }
1188           break;
1189         }
1190       if (LocaleCompare(attribute,"bordercolor") == 0)
1191         {
1192           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1193           if (info)
1194             info->image_info->border_color=target_color;
1195           for ( ; image; image=image->next)
1196             image->border_color=target_color;
1197           break;
1198         }
1199       if (info)
1200         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1201       for ( ; image; image=image->next)
1202         SetImageProperty(image,attribute,SvPV(sval,na));
1203       break;
1204     }
1205     case 'C':
1206     case 'c':
1207     {
1208       if (LocaleCompare(attribute,"cache-threshold") == 0)
1209         {
1210           (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1211             SiPrefixToDouble(SvPV(sval,na),100.0));
1212           (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1213             (2*SiPrefixToDouble(SvPV(sval,na),100.0)));
1214           break;
1215         }
1216       if (LocaleCompare(attribute,"clip-mask") == 0)
1217         {
1218           Image
1219             *clip_mask;
1220
1221           clip_mask=(Image *) NULL;
1222           if (SvPOK(sval))
1223             clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1224           for ( ; image; image=image->next)
1225             SetImageClipMask(image,clip_mask,exception);
1226           break;
1227         }
1228       if (LocaleNCompare(attribute,"colormap",8) == 0)
1229         {
1230           for ( ; image; image=image->next)
1231           {
1232             int
1233               items;
1234
1235             long
1236               i;
1237
1238             if (image->storage_class == DirectClass)
1239               continue;
1240             i=0;
1241             items=sscanf(attribute,"%*[^[][%ld",&i);
1242             (void) items;
1243             if (i > (ssize_t) image->colors)
1244               i%=image->colors;
1245             if ((strchr(SvPV(sval,na),',') == 0) ||
1246                 (strchr(SvPV(sval,na),')') != 0))
1247               QueryColorDatabase(SvPV(sval,na),image->colormap+i,exception);
1248             else
1249               {
1250                 color=image->colormap+i;
1251                 pixel.red=color->red;
1252                 pixel.green=color->green;
1253                 pixel.blue=color->blue;
1254                 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1255                 pixel.red=geometry_info.rho;
1256                 pixel.green=geometry_info.sigma;
1257                 pixel.blue=geometry_info.xi;
1258                 color->red=ClampToQuantum(pixel.red);
1259                 color->green=ClampToQuantum(pixel.green);
1260                 color->blue=ClampToQuantum(pixel.blue);
1261               }
1262           }
1263           break;
1264         }
1265       if (LocaleCompare(attribute,"colorspace") == 0)
1266         {
1267           sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1268             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1269           if (sp < 0)
1270             {
1271               ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1272                 SvPV(sval,na));
1273               break;
1274             }
1275           for ( ; image; image=image->next)
1276             (void) TransformImageColorspace(image,(ColorspaceType) sp);
1277           break;
1278         }
1279       if (LocaleCompare(attribute,"comment") == 0)
1280         {
1281           for ( ; image; image=image->next)
1282             (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1283               info ? info->image_info : (ImageInfo *) NULL,image,
1284               SvPV(sval,na),exception));
1285           break;
1286         }
1287       if (LocaleCompare(attribute,"compression") == 0)
1288         {
1289           sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1290             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1291           if (sp < 0)
1292             {
1293               ThrowPerlException(exception,OptionError,
1294                 "UnrecognizedImageCompression",SvPV(sval,na));
1295               break;
1296             }
1297           if (info)
1298             info->image_info->compression=(CompressionType) sp;
1299           for ( ; image; image=image->next)
1300             image->compression=(CompressionType) sp;
1301           break;
1302         }
1303       if (info)
1304         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1305       for ( ; image; image=image->next)
1306         SetImageProperty(image,attribute,SvPV(sval,na));
1307       break;
1308     }
1309     case 'D':
1310     case 'd':
1311     {
1312       if (LocaleCompare(attribute,"debug") == 0)
1313         {
1314           SetLogEventMask(SvPV(sval,na));
1315           break;
1316         }
1317       if (LocaleCompare(attribute,"delay") == 0)
1318         {
1319           flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1320           for ( ; image; image=image->next)
1321           {
1322             image->delay=(size_t) floor(geometry_info.rho+0.5);
1323             if ((flags & SigmaValue) != 0)
1324               image->ticks_per_second=(ssize_t)
1325                 floor(geometry_info.sigma+0.5);
1326           }
1327           break;
1328         }
1329       if (LocaleCompare(attribute,"disk-limit") == 0)
1330         {
1331           MagickSizeType
1332             limit;
1333
1334           limit=MagickResourceInfinity;
1335           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1336             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1337           (void) SetMagickResourceLimit(DiskResource,limit);
1338           break;
1339         }
1340       if (LocaleCompare(attribute,"density") == 0)
1341         {
1342           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1343             {
1344               ThrowPerlException(exception,OptionError,"MissingGeometry",
1345                 SvPV(sval,na));
1346               break;
1347             }
1348           if (info)
1349             (void) CloneString(&info->image_info->density,SvPV(sval,na));
1350           for ( ; image; image=image->next)
1351           {
1352             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1353             image->x_resolution=geometry_info.rho;
1354             image->y_resolution=geometry_info.sigma;
1355             if ((flags & SigmaValue) == 0)
1356               image->y_resolution=image->x_resolution;
1357           }
1358           break;
1359         }
1360       if (LocaleCompare(attribute,"depth") == 0)
1361         {
1362           if (info)
1363             info->image_info->depth=SvIV(sval);
1364           for ( ; image; image=image->next)
1365             (void) SetImageDepth(image,SvIV(sval));
1366           break;
1367         }
1368       if (LocaleCompare(attribute,"dispose") == 0)
1369         {
1370           sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1371             SvPV(sval,na)) : SvIV(sval);
1372           if (sp < 0)
1373             {
1374               ThrowPerlException(exception,OptionError,
1375                 "UnrecognizedDisposeMethod",SvPV(sval,na));
1376               break;
1377             }
1378           for ( ; image; image=image->next)
1379             image->dispose=(DisposeType) sp;
1380           break;
1381         }
1382       if (LocaleCompare(attribute,"dither") == 0)
1383         {
1384           if (info)
1385             {
1386               sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1387                 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1388               if (sp < 0)
1389                 {
1390                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
1391                     SvPV(sval,na));
1392                   break;
1393                 }
1394               info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1395             }
1396           break;
1397         }
1398       if (LocaleCompare(attribute,"display") == 0)
1399         {
1400           display:
1401           if (info)
1402             (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1403           break;
1404         }
1405       if (info)
1406         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1407       for ( ; image; image=image->next)
1408         SetImageProperty(image,attribute,SvPV(sval,na));
1409       break;
1410     }
1411     case 'E':
1412     case 'e':
1413     {
1414       if (LocaleCompare(attribute,"endian") == 0)
1415         {
1416           sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1417             SvPV(sval,na)) : SvIV(sval);
1418           if (sp < 0)
1419             {
1420               ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1421                 SvPV(sval,na));
1422               break;
1423             }
1424           if (info)
1425             info->image_info->endian=(EndianType) sp;
1426           for ( ; image; image=image->next)
1427             image->endian=(EndianType) sp;
1428           break;
1429         }
1430       if (LocaleCompare(attribute,"extract") == 0)
1431         {
1432           /*
1433             Set image extract geometry.
1434           */
1435           (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1436           break;
1437         }
1438       if (info)
1439         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1440       for ( ; image; image=image->next)
1441         SetImageProperty(image,attribute,SvPV(sval,na));
1442       break;
1443     }
1444     case 'F':
1445     case 'f':
1446     {
1447       if (LocaleCompare(attribute,"filename") == 0)
1448         {
1449           if (info)
1450             (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1451               MaxTextExtent);
1452           for ( ; image; image=image->next)
1453             (void) CopyMagickString(image->filename,SvPV(sval,na),
1454               MaxTextExtent);
1455           break;
1456         }
1457       if (LocaleCompare(attribute,"file") == 0)
1458         {
1459           FILE
1460             *file;
1461
1462           PerlIO
1463             *io_info;
1464
1465           if (info == (struct PackageInfo *) NULL)
1466             break;
1467           io_info=IoIFP(sv_2io(sval));
1468           if (io_info == (PerlIO *) NULL)
1469             {
1470               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1471                 PackageName);
1472               break;
1473             }
1474           file=PerlIO_findFILE(io_info);
1475           if (file == (FILE *) NULL)
1476             {
1477               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1478                 PackageName);
1479               break;
1480             }
1481           SetImageInfoFile(info->image_info,file);
1482           break;
1483         }
1484       if (LocaleCompare(attribute,"fill") == 0)
1485         {
1486           if (info)
1487             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1488           break;
1489         }
1490       if (LocaleCompare(attribute,"font") == 0)
1491         {
1492           if (info)
1493             (void) CloneString(&info->image_info->font,SvPV(sval,na));
1494           break;
1495         }
1496       if (LocaleCompare(attribute,"foreground") == 0)
1497         break;
1498       if (LocaleCompare(attribute,"fuzz") == 0)
1499         {
1500           if (info)
1501             info->image_info->fuzz=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1502           for ( ; image; image=image->next)
1503             image->fuzz=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1504           break;
1505         }
1506       if (info)
1507         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1508       for ( ; image; image=image->next)
1509         SetImageProperty(image,attribute,SvPV(sval,na));
1510       break;
1511     }
1512     case 'G':
1513     case 'g':
1514     {
1515       if (LocaleCompare(attribute,"gamma") == 0)
1516         {
1517           for ( ; image; image=image->next)
1518             image->gamma=SvNV(sval);
1519           break;
1520         }
1521       if (LocaleCompare(attribute,"gravity") == 0)
1522         {
1523           sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1524             SvPV(sval,na)) : SvIV(sval);
1525           if (sp < 0)
1526             {
1527               ThrowPerlException(exception,OptionError,
1528                 "UnrecognizedGravityType",SvPV(sval,na));
1529               break;
1530             }
1531           if (info)
1532             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1533           for ( ; image; image=image->next)
1534             image->gravity=(GravityType) sp;
1535           break;
1536         }
1537       if (LocaleCompare(attribute,"green-primary") == 0)
1538         {
1539           for ( ; image; image=image->next)
1540           {
1541             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1542             image->chromaticity.green_primary.x=geometry_info.rho;
1543             image->chromaticity.green_primary.y=geometry_info.sigma;
1544             if ((flags & SigmaValue) == 0)
1545               image->chromaticity.green_primary.y=
1546                 image->chromaticity.green_primary.x;
1547           }
1548           break;
1549         }
1550       if (info)
1551         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1552       for ( ; image; image=image->next)
1553         SetImageProperty(image,attribute,SvPV(sval,na));
1554       break;
1555     }
1556     case 'I':
1557     case 'i':
1558     {
1559       if (LocaleNCompare(attribute,"index",5) == 0)
1560         {
1561           int
1562             items;
1563
1564           long
1565             index;
1566
1567           register Quantum
1568             *q;
1569
1570           CacheView
1571             *image_view;
1572
1573           for ( ; image; image=image->next)
1574           {
1575             if (image->storage_class != PseudoClass)
1576               continue;
1577             x=0;
1578             y=0;
1579             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1580             (void) items;
1581             image_view=AcquireCacheView(image);
1582             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1583             if (q != (Quantum *) NULL)
1584               {
1585                 items=sscanf(SvPV(sval,na),"%ld",&index);
1586                 if ((index >= 0) && (index < (ssize_t) image->colors))
1587                   SetPixelIndex(image,index,q);
1588                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1589               }
1590             image_view=DestroyCacheView(image_view);
1591           }
1592           break;
1593         }
1594       if (LocaleCompare(attribute,"iterations") == 0)
1595         {
1596   iterations:
1597           for ( ; image; image=image->next)
1598             image->iterations=SvIV(sval);
1599           break;
1600         }
1601       if (LocaleCompare(attribute,"interlace") == 0)
1602         {
1603           sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1604             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1605           if (sp < 0)
1606             {
1607               ThrowPerlException(exception,OptionError,
1608                 "UnrecognizedInterlaceType",SvPV(sval,na));
1609               break;
1610             }
1611           if (info)
1612             info->image_info->interlace=(InterlaceType) sp;
1613           for ( ; image; image=image->next)
1614             image->interlace=(InterlaceType) sp;
1615           break;
1616         }
1617       if (info)
1618         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1619       for ( ; image; image=image->next)
1620         SetImageProperty(image,attribute,SvPV(sval,na));
1621       break;
1622     }
1623     case 'L':
1624     case 'l':
1625     {
1626       if (LocaleCompare(attribute,"label") == 0)
1627         {
1628           for ( ; image; image=image->next)
1629             (void) SetImageProperty(image,"label",InterpretImageProperties(
1630               info ? info->image_info : (ImageInfo *) NULL,image,
1631               SvPV(sval,na),exception));
1632           break;
1633         }
1634       if (LocaleCompare(attribute,"loop") == 0)
1635         goto iterations;
1636       if (info)
1637         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1638       for ( ; image; image=image->next)
1639         SetImageProperty(image,attribute,SvPV(sval,na));
1640       break;
1641     }
1642     case 'M':
1643     case 'm':
1644     {
1645       if (LocaleCompare(attribute,"magick") == 0)
1646         {
1647           if (info)
1648             (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
1649               "%s:",SvPV(sval,na));
1650           for ( ; image; image=image->next)
1651             (void) CopyMagickString(image->magick,SvPV(sval,na),MaxTextExtent);
1652           break;
1653         }
1654       if (LocaleCompare(attribute,"map-limit") == 0)
1655         {
1656           MagickSizeType
1657             limit;
1658
1659           limit=MagickResourceInfinity;
1660           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1661             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1662           (void) SetMagickResourceLimit(MapResource,limit);
1663           break;
1664         }
1665       if (LocaleCompare(attribute,"mask") == 0)
1666         {
1667           Image
1668             *mask;
1669
1670           mask=(Image *) NULL;
1671           if (SvPOK(sval))
1672             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1673           for ( ; image; image=image->next)
1674             SetImageMask(image,mask,exception);
1675           break;
1676         }
1677       if (LocaleCompare(attribute,"mattecolor") == 0)
1678         {
1679           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1680           if (info)
1681             info->image_info->matte_color=target_color;
1682           for ( ; image; image=image->next)
1683             image->matte_color=target_color;
1684           break;
1685         }
1686       if (LocaleCompare(attribute,"matte") == 0)
1687         {
1688           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1689             SvPV(sval,na)) : SvIV(sval);
1690           if (sp < 0)
1691             {
1692               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1693                 SvPV(sval,na));
1694               break;
1695             }
1696           for ( ; image; image=image->next)
1697             image->matte=sp != 0 ? MagickTrue : MagickFalse;
1698           break;
1699         }
1700       if (LocaleCompare(attribute,"memory-limit") == 0)
1701         {
1702           MagickSizeType
1703             limit;
1704
1705           limit=MagickResourceInfinity;
1706           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1707             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1708           (void) SetMagickResourceLimit(MemoryResource,limit);
1709           break;
1710         }
1711       if (LocaleCompare(attribute,"monochrome") == 0)
1712         {
1713           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1714             SvPV(sval,na)) : SvIV(sval);
1715           if (sp < 0)
1716             {
1717               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1718                 SvPV(sval,na));
1719               break;
1720             }
1721           if (info)
1722             info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1723           for ( ; image; image=image->next)
1724             (void) SetImageType(image,BilevelType,exception);
1725           break;
1726         }
1727       if (info)
1728         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1729       for ( ; image; image=image->next)
1730         SetImageProperty(image,attribute,SvPV(sval,na));
1731       break;
1732     }
1733     case 'O':
1734     case 'o':
1735     {
1736       if (LocaleCompare(attribute,"option") == 0)
1737         {
1738           if (info)
1739             DefineImageOption(info->image_info,SvPV(sval,na));
1740           break;
1741         }
1742       if (LocaleCompare(attribute,"orientation") == 0)
1743         {
1744           sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1745             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1746           if (sp < 0)
1747             {
1748               ThrowPerlException(exception,OptionError,
1749                 "UnrecognizedOrientationType",SvPV(sval,na));
1750               break;
1751             }
1752           if (info)
1753             info->image_info->orientation=(OrientationType) sp;
1754           for ( ; image; image=image->next)
1755             image->orientation=(OrientationType) sp;
1756           break;
1757         }
1758       if (info)
1759         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1760       for ( ; image; image=image->next)
1761         SetImageProperty(image,attribute,SvPV(sval,na));
1762       break;
1763     }
1764     case 'P':
1765     case 'p':
1766     {
1767       if (LocaleCompare(attribute,"page") == 0)
1768         {
1769           char
1770             *geometry;
1771
1772           geometry=GetPageGeometry(SvPV(sval,na));
1773           if (info)
1774             (void) CloneString(&info->image_info->page,geometry);
1775           for ( ; image; image=image->next)
1776             (void) ParsePageGeometry(image,geometry,&image->page,exception);
1777           geometry=(char *) RelinquishMagickMemory(geometry);
1778           break;
1779         }
1780       if (LocaleCompare(attribute,"pen") == 0)
1781         {
1782           if (info)
1783             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1784           break;
1785         }
1786       if (LocaleNCompare(attribute,"pixel",5) == 0)
1787         {
1788           int
1789             items;
1790
1791           PixelInfo
1792             pixel;
1793
1794           register Quantum
1795             *q;
1796
1797           CacheView
1798             *image_view;
1799
1800           for ( ; image; image=image->next)
1801           {
1802             if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1803               break;
1804             x=0;
1805             y=0;
1806             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1807             (void) items;
1808             image_view=AcquireCacheView(image);
1809             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1810             if (q != (Quantum *) NULL)
1811               {
1812                 if ((strchr(SvPV(sval,na),',') == 0) ||
1813                     (strchr(SvPV(sval,na),')') != 0))
1814                   QueryMagickColor(SvPV(sval,na),&pixel,exception);
1815                 else
1816                   {
1817                     GetPixelInfo(image,&pixel);
1818                     flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1819                     pixel.red=geometry_info.rho;
1820                     if ((flags & SigmaValue) != 0)
1821                       pixel.green=geometry_info.sigma;
1822                     if ((flags & XiValue) != 0)
1823                       pixel.blue=geometry_info.xi;
1824                     if ((flags & PsiValue) != 0)
1825                       pixel.alpha=geometry_info.psi;
1826                     if ((flags & ChiValue) != 0)
1827                       pixel.black=geometry_info.chi;
1828                   }
1829                 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1830                 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1831                 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1832                 if (image->colorspace == CMYKColorspace)
1833                   SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1834                 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1835                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1836               }
1837             image_view=DestroyCacheView(image_view);
1838           }
1839           break;
1840         }
1841       if (LocaleCompare(attribute,"pointsize") == 0)
1842         {
1843           if (info)
1844             {
1845               (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1846               info->image_info->pointsize=geometry_info.rho;
1847             }
1848           break;
1849         }
1850       if (LocaleCompare(attribute,"preview") == 0)
1851         {
1852           sp=SvPOK(sval) ? ParseCommandOption(MagickPreviewOptions,MagickFalse,
1853             SvPV(sval,na)) : SvIV(sval);
1854           if (sp < 0)
1855             {
1856               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1857                 SvPV(sval,na));
1858               break;
1859             }
1860           if (info)
1861             info->image_info->preview_type=(PreviewType) sp;
1862           break;
1863         }
1864       if (info)
1865         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1866       for ( ; image; image=image->next)
1867         SetImageProperty(image,attribute,SvPV(sval,na));
1868       break;
1869     }
1870     case 'Q':
1871     case 'q':
1872     {
1873       if (LocaleCompare(attribute,"quality") == 0)
1874         {
1875           if (info)
1876             info->image_info->quality=SvIV(sval);
1877           for ( ; image; image=image->next)
1878             image->quality=SvIV(sval);
1879           break;
1880         }
1881       if (info)
1882         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1883       for ( ; image; image=image->next)
1884         SetImageProperty(image,attribute,SvPV(sval,na));
1885       break;
1886     }
1887     case 'R':
1888     case 'r':
1889     {
1890       if (LocaleCompare(attribute,"red-primary") == 0)
1891         {
1892           for ( ; image; image=image->next)
1893           {
1894             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1895             image->chromaticity.red_primary.x=geometry_info.rho;
1896             image->chromaticity.red_primary.y=geometry_info.sigma;
1897             if ((flags & SigmaValue) == 0)
1898               image->chromaticity.red_primary.y=
1899                 image->chromaticity.red_primary.x;
1900           }
1901           break;
1902         }
1903       if (LocaleCompare(attribute,"render") == 0)
1904         {
1905           sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1906             SvPV(sval,na)) : SvIV(sval);
1907           if (sp < 0)
1908             {
1909               ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1910                 SvPV(sval,na));
1911               break;
1912             }
1913          for ( ; image; image=image->next)
1914            image->rendering_intent=(RenderingIntent) sp;
1915          break;
1916        }
1917       if (LocaleCompare(attribute,"repage") == 0)
1918         {
1919           RectangleInfo
1920             geometry;
1921
1922           for ( ; image; image=image->next)
1923           {
1924             flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
1925             if ((flags & WidthValue) != 0)
1926               {
1927                 if ((flags & HeightValue) == 0)
1928                   geometry.height=geometry.width;
1929                 image->page.width=geometry.width;
1930                 image->page.height=geometry.height;
1931               }
1932             if ((flags & AspectValue) != 0)
1933               {
1934                 if ((flags & XValue) != 0)
1935                   image->page.x+=geometry.x;
1936                 if ((flags & YValue) != 0)
1937                   image->page.y+=geometry.y;
1938               }
1939             else
1940               {
1941                 if ((flags & XValue) != 0)
1942                   {
1943                     image->page.x=geometry.x;
1944                     if (((flags & WidthValue) != 0) && (geometry.x > 0))
1945                       image->page.width=image->columns+geometry.x;
1946                   }
1947                 if ((flags & YValue) != 0)
1948                   {
1949                     image->page.y=geometry.y;
1950                     if (((flags & HeightValue) != 0) && (geometry.y > 0))
1951                       image->page.height=image->rows+geometry.y;
1952                   }
1953               }
1954           }
1955           break;
1956         }
1957       if (info)
1958         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1959       for ( ; image; image=image->next)
1960         SetImageProperty(image,attribute,SvPV(sval,na));
1961       break;
1962     }
1963     case 'S':
1964     case 's':
1965     {
1966       if (LocaleCompare(attribute,"sampling-factor") == 0)
1967         {
1968           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1969             {
1970               ThrowPerlException(exception,OptionError,"MissingGeometry",
1971                 SvPV(sval,na));
1972               break;
1973             }
1974           if (info)
1975             (void) CloneString(&info->image_info->sampling_factor,
1976               SvPV(sval,na));
1977           break;
1978         }
1979       if (LocaleCompare(attribute,"scene") == 0)
1980         {
1981           for ( ; image; image=image->next)
1982             image->scene=SvIV(sval);
1983           break;
1984         }
1985       if (LocaleCompare(attribute,"server") == 0)
1986         goto display;
1987       if (LocaleCompare(attribute,"size") == 0)
1988         {
1989           if (info)
1990             {
1991               if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1992                 {
1993                   ThrowPerlException(exception,OptionError,"MissingGeometry",
1994                     SvPV(sval,na));
1995                   break;
1996                 }
1997               (void) CloneString(&info->image_info->size,SvPV(sval,na));
1998             }
1999           break;
2000         }
2001       if (LocaleCompare(attribute,"stroke") == 0)
2002         {
2003           if (info)
2004             (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2005           break;
2006         }
2007       if (info)
2008         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2009       for ( ; image; image=image->next)
2010         SetImageProperty(image,attribute,SvPV(sval,na));
2011       break;
2012     }
2013     case 'T':
2014     case 't':
2015     {
2016       if (LocaleCompare(attribute,"texture") == 0)
2017         {
2018           if (info)
2019             (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2020           break;
2021         }
2022       if (LocaleCompare(attribute,"thread-limit") == 0)
2023         {
2024           MagickSizeType
2025             limit;
2026
2027           limit=MagickResourceInfinity;
2028           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2029             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
2030           (void) SetMagickResourceLimit(ThreadResource,limit);
2031           break;
2032         }
2033       if (LocaleCompare(attribute,"tile-offset") == 0)
2034         {
2035           char
2036             *geometry;
2037
2038           geometry=GetPageGeometry(SvPV(sval,na));
2039           if (info)
2040             (void) CloneString(&info->image_info->page,geometry);
2041           for ( ; image; image=image->next)
2042             (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2043               exception);
2044           geometry=(char *) RelinquishMagickMemory(geometry);
2045           break;
2046         }
2047       if (LocaleCompare(attribute,"time-limit") == 0)
2048         {
2049           MagickSizeType
2050             limit;
2051
2052           limit=MagickResourceInfinity;
2053           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2054             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
2055           (void) SetMagickResourceLimit(TimeResource,limit);
2056           break;
2057         }
2058       if (LocaleCompare(attribute,"transparent-color") == 0)
2059         {
2060           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
2061           if (info)
2062             info->image_info->transparent_color=target_color;
2063           for ( ; image; image=image->next)
2064             image->transparent_color=target_color;
2065           break;
2066         }
2067       if (LocaleCompare(attribute,"type") == 0)
2068         {
2069           sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2070             SvPV(sval,na)) : SvIV(sval);
2071           if (sp < 0)
2072             {
2073               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2074                 SvPV(sval,na));
2075               break;
2076             }
2077           if (info)
2078             info->image_info->type=(ImageType) sp;
2079           for ( ; image; image=image->next)
2080             SetImageType(image,(ImageType) sp,exception);
2081           break;
2082         }
2083       if (info)
2084         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2085       for ( ; image; image=image->next)
2086         SetImageProperty(image,attribute,SvPV(sval,na));
2087       break;
2088     }
2089     case 'U':
2090     case 'u':
2091     {
2092       if (LocaleCompare(attribute,"units") == 0)
2093         {
2094           sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2095             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2096           if (sp < 0)
2097             {
2098               ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2099                 SvPV(sval,na));
2100               break;
2101             }
2102           if (info)
2103             info->image_info->units=(ResolutionType) sp;
2104           for ( ; image; image=image->next)
2105           {
2106             ResolutionType
2107               units;
2108
2109             units=(ResolutionType) sp;
2110             if (image->units != units)
2111               switch (image->units)
2112               {
2113                 case UndefinedResolution:
2114                 case PixelsPerInchResolution:
2115                 {
2116                   if (units == PixelsPerCentimeterResolution)
2117                     {
2118                       image->x_resolution*=2.54;
2119                       image->y_resolution*=2.54;
2120                     }
2121                   break;
2122                 }
2123                 case PixelsPerCentimeterResolution:
2124                 {
2125                   if (units == PixelsPerInchResolution)
2126                     {
2127                       image->x_resolution/=2.54;
2128                       image->y_resolution/=2.54;
2129                     }
2130                   break;
2131                 }
2132               }
2133             image->units=units;
2134           }
2135           break;
2136         }
2137       if (info)
2138         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2139       for ( ; image; image=image->next)
2140         SetImageProperty(image,attribute,SvPV(sval,na));
2141       break;
2142     }
2143     case 'V':
2144     case 'v':
2145     {
2146       if (LocaleCompare(attribute,"verbose") == 0)
2147         {
2148           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2149             SvPV(sval,na)) : SvIV(sval);
2150           if (sp < 0)
2151             {
2152               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2153                 SvPV(sval,na));
2154               break;
2155             }
2156           if (info)
2157             info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2158           break;
2159         }
2160       if (LocaleCompare(attribute,"view") == 0)
2161         {
2162           if (info)
2163             (void) CloneString(&info->image_info->view,SvPV(sval,na));
2164           break;
2165         }
2166       if (LocaleCompare(attribute,"virtual-pixel") == 0)
2167         {
2168           sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2169             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2170           if (sp < 0)
2171             {
2172               ThrowPerlException(exception,OptionError,
2173                 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2174               break;
2175             }
2176           if (info)
2177             info->image_info->virtual_pixel_method=(VirtualPixelMethod) sp;
2178           for ( ; image; image=image->next)
2179             SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp);
2180           break;
2181         }
2182       if (info)
2183         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2184       for ( ; image; image=image->next)
2185         SetImageProperty(image,attribute,SvPV(sval,na));
2186       break;
2187     }
2188     case 'W':
2189     case 'w':
2190     {
2191       if (LocaleCompare(attribute,"white-point") == 0)
2192         {
2193           for ( ; image; image=image->next)
2194           {
2195             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2196             image->chromaticity.white_point.x=geometry_info.rho;
2197             image->chromaticity.white_point.y=geometry_info.sigma;
2198             if ((flags & SigmaValue) == 0)
2199               image->chromaticity.white_point.y=
2200                 image->chromaticity.white_point.x;
2201           }
2202           break;
2203         }
2204       if (info)
2205         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2206       for ( ; image; image=image->next)
2207         SetImageProperty(image,attribute,SvPV(sval,na));
2208       break;
2209     }
2210     default:
2211     {
2212       if (info)
2213         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2214       for ( ; image; image=image->next)
2215         SetImageProperty(image,attribute,SvPV(sval,na));
2216       break;
2217     }
2218   }
2219 }
2220 \f
2221 /*
2222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2223 %                                                                             %
2224 %                                                                             %
2225 %                                                                             %
2226 %   S e t u p L i s t                                                         %
2227 %                                                                             %
2228 %                                                                             %
2229 %                                                                             %
2230 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2231 %
2232 %  Method SetupList returns the list of all the images linked by their
2233 %  image->next and image->previous link lists for use with ImageMagick.  If
2234 %  info is non-NULL, an info structure is returned in *info.  If
2235 %  reference_vector is non-NULL,an array of SV* are returned in
2236 %  *reference_vector.  Reference_vector is used when the images are going to be
2237 %  replaced with new Image*'s.
2238 %
2239 %  The format of the SetupList routine is:
2240 %
2241 %      Image *SetupList(SV *reference,struct PackageInfo **info,
2242 %        SV ***reference_vector,ExceptionInfo *exception)
2243 %
2244 %  A description of each parameter follows:
2245 %
2246 %    o list: a list of strings.
2247 %
2248 %    o string: a character string.
2249 %
2250 %    o exception: Return any errors or warnings in this structure.
2251 %
2252 */
2253 static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2254   SV ***reference_vector,ExceptionInfo *exception)
2255 {
2256   Image
2257     *image;
2258
2259   ssize_t
2260     current,
2261     last;
2262
2263   if (reference_vector)
2264     *reference_vector=NULL;
2265   if (info)
2266     *info=NULL;
2267   current=0;
2268   last=0;
2269   image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2270   if (info && (SvTYPE(reference) == SVt_PVAV))
2271     *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2272       exception);
2273   return(image);
2274 }
2275 \f
2276 /*
2277 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2278 %                                                                             %
2279 %                                                                             %
2280 %                                                                             %
2281 %   s t r E Q c a s e                                                         %
2282 %                                                                             %
2283 %                                                                             %
2284 %                                                                             %
2285 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2286 %
2287 %  strEQcase() compares two strings and returns 0 if they are the
2288 %  same or if the second string runs out first.  The comparison is case
2289 %  insensitive.
2290 %
2291 %  The format of the strEQcase routine is:
2292 %
2293 %      ssize_t strEQcase(const char *p,const char *q)
2294 %
2295 %  A description of each parameter follows:
2296 %
2297 %    o p: a character string.
2298 %
2299 %    o q: a character string.
2300 %
2301 %
2302 */
2303 static ssize_t strEQcase(const char *p,const char *q)
2304 {
2305   char
2306     c;
2307
2308   register ssize_t
2309     i;
2310
2311   for (i=0 ; (c=(*q)) != 0; i++)
2312   {
2313     if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2314         (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2315       return(0);
2316     p++;
2317     q++;
2318   }
2319   return(((*q == 0) && (*p == 0)) ? i : 0);
2320 }
2321 \f
2322 /*
2323 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2324 %                                                                             %
2325 %                                                                             %
2326 %                                                                             %
2327 %   I m a g e : : M a g i c k                                                 %
2328 %                                                                             %
2329 %                                                                             %
2330 %                                                                             %
2331 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2332 %
2333 %
2334 */
2335 MODULE = Image::Magick PACKAGE = Image::Magick
2336
2337 PROTOTYPES: ENABLE
2338
2339 BOOT:
2340   MagickCoreGenesis("PerlMagick",MagickFalse);
2341   SetWarningHandler(NULL);
2342   SetErrorHandler(NULL);
2343   magick_registry=NewSplayTree((int (*)(const void *,const void *))
2344     NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2345
2346 void
2347 UNLOAD()
2348   PPCODE:
2349   {
2350     if (magick_registry != (SplayTreeInfo *) NULL)
2351       magick_registry=DestroySplayTree(magick_registry);
2352     MagickCoreTerminus();
2353   }
2354
2355 double
2356 constant(name,argument)
2357   char *name
2358   ssize_t argument
2359 \f
2360 #
2361 ###############################################################################
2362 #                                                                             #
2363 #                                                                             #
2364 #                                                                             #
2365 #   A n i m a t e                                                             #
2366 #                                                                             #
2367 #                                                                             #
2368 #                                                                             #
2369 ###############################################################################
2370 #
2371 #
2372 void
2373 Animate(ref,...)
2374   Image::Magick ref=NO_INIT
2375   ALIAS:
2376     AnimateImage  = 1
2377     animate       = 2
2378     animateimage  = 3
2379   PPCODE:
2380   {
2381     ExceptionInfo
2382       *exception;
2383
2384     Image
2385       *image;
2386
2387     register ssize_t
2388       i;
2389
2390     struct PackageInfo
2391       *info,
2392       *package_info;
2393
2394     SV
2395       *perl_exception,
2396       *reference;
2397
2398     PERL_UNUSED_VAR(ref);
2399     PERL_UNUSED_VAR(ix);
2400     exception=AcquireExceptionInfo();
2401     perl_exception=newSVpv("",0);
2402     package_info=(struct PackageInfo *) NULL;
2403     if (sv_isobject(ST(0)) == 0)
2404       {
2405         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2406           PackageName);
2407         goto PerlException;
2408       }
2409     reference=SvRV(ST(0));
2410     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2411     if (image == (Image *) NULL)
2412       {
2413         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2414           PackageName);
2415         goto PerlException;
2416       }
2417     package_info=ClonePackageInfo(info,exception);
2418     if (items == 2)
2419       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2420     else
2421       if (items > 2)
2422         for (i=2; i < items; i+=2)
2423           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2424             exception);
2425     (void) AnimateImages(package_info->image_info,image,exception);
2426     (void) CatchImageException(image);
2427
2428   PerlException:
2429     if (package_info != (struct PackageInfo *) NULL)
2430       DestroyPackageInfo(package_info);
2431     InheritPerlException(exception,perl_exception);
2432     exception=DestroyExceptionInfo(exception);
2433     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2434     SvPOK_on(perl_exception);
2435     ST(0)=sv_2mortal(perl_exception);
2436     XSRETURN(1);
2437   }
2438 \f
2439 #
2440 ###############################################################################
2441 #                                                                             #
2442 #                                                                             #
2443 #                                                                             #
2444 #   A p p e n d                                                               #
2445 #                                                                             #
2446 #                                                                             #
2447 #                                                                             #
2448 ###############################################################################
2449 #
2450 #
2451 void
2452 Append(ref,...)
2453   Image::Magick ref=NO_INIT
2454   ALIAS:
2455     AppendImage  = 1
2456     append       = 2
2457     appendimage  = 3
2458   PPCODE:
2459   {
2460     AV
2461       *av;
2462
2463     char
2464       *attribute;
2465
2466     ExceptionInfo
2467       *exception;
2468
2469     HV
2470       *hv;
2471
2472     Image
2473       *image;
2474
2475     register ssize_t
2476       i;
2477
2478     ssize_t
2479       stack;
2480
2481     struct PackageInfo
2482       *info;
2483
2484     SV
2485       *av_reference,
2486       *perl_exception,
2487       *reference,
2488       *rv,
2489       *sv;
2490
2491     PERL_UNUSED_VAR(ref);
2492     PERL_UNUSED_VAR(ix);
2493     exception=AcquireExceptionInfo();
2494     perl_exception=newSVpv("",0);
2495     sv=NULL;
2496     attribute=NULL;
2497     av=NULL;
2498     if (sv_isobject(ST(0)) == 0)
2499       {
2500         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2501           PackageName);
2502         goto PerlException;
2503       }
2504     reference=SvRV(ST(0));
2505     hv=SvSTASH(reference);
2506     av=newAV();
2507     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2508     SvREFCNT_dec(av);
2509     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2510     if (image == (Image *) NULL)
2511       {
2512         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2513           PackageName);
2514         goto PerlException;
2515       }
2516     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2517     /*
2518       Get options.
2519     */
2520     stack=MagickTrue;
2521     for (i=2; i < items; i+=2)
2522     {
2523       attribute=(char *) SvPV(ST(i-1),na);
2524       switch (*attribute)
2525       {
2526         case 'S':
2527         case 's':
2528         {
2529           if (LocaleCompare(attribute,"stack") == 0)
2530             {
2531               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2532                 SvPV(ST(i),na));
2533               if (stack < 0)
2534                 {
2535                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
2536                     SvPV(ST(i),na));
2537                   return;
2538                 }
2539               break;
2540             }
2541           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2542             attribute);
2543           break;
2544         }
2545         default:
2546         {
2547           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2548             attribute);
2549           break;
2550         }
2551       }
2552     }
2553     image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2554     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2555       goto PerlException;
2556     for ( ; image; image=image->next)
2557     {
2558       AddImageToRegistry(sv,image);
2559       rv=newRV(sv);
2560       av_push(av,sv_bless(rv,hv));
2561       SvREFCNT_dec(sv);
2562     }
2563     exception=DestroyExceptionInfo(exception);
2564     ST(0)=av_reference;
2565     SvREFCNT_dec(perl_exception);
2566     XSRETURN(1);
2567
2568   PerlException:
2569     InheritPerlException(exception,perl_exception);
2570     exception=DestroyExceptionInfo(exception);
2571     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2572     SvPOK_on(perl_exception);
2573     ST(0)=sv_2mortal(perl_exception);
2574     XSRETURN(1);
2575   }
2576 \f
2577 #
2578 ###############################################################################
2579 #                                                                             #
2580 #                                                                             #
2581 #                                                                             #
2582 #   A v e r a g e                                                             #
2583 #                                                                             #
2584 #                                                                             #
2585 #                                                                             #
2586 ###############################################################################
2587 #
2588 #
2589 void
2590 Average(ref)
2591   Image::Magick ref=NO_INIT
2592   ALIAS:
2593     AverageImage   = 1
2594     average        = 2
2595     averageimage   = 3
2596   PPCODE:
2597   {
2598     AV
2599       *av;
2600
2601     char
2602       *p;
2603
2604     ExceptionInfo
2605       *exception;
2606
2607     HV
2608       *hv;
2609
2610     Image
2611       *image;
2612
2613     struct PackageInfo
2614       *info;
2615
2616     SV
2617       *perl_exception,
2618       *reference,
2619       *rv,
2620       *sv;
2621
2622     PERL_UNUSED_VAR(ref);
2623     PERL_UNUSED_VAR(ix);
2624     exception=AcquireExceptionInfo();
2625     perl_exception=newSVpv("",0);
2626     sv=NULL;
2627     if (sv_isobject(ST(0)) == 0)
2628       {
2629         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2630           PackageName);
2631         goto PerlException;
2632       }
2633     reference=SvRV(ST(0));
2634     hv=SvSTASH(reference);
2635     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2636     if (image == (Image *) NULL)
2637       {
2638         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2639           PackageName);
2640         goto PerlException;
2641       }
2642     image=EvaluateImages(image,MeanEvaluateOperator,exception);
2643     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2644       goto PerlException;
2645     /*
2646       Create blessed Perl array for the returned image.
2647     */
2648     av=newAV();
2649     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2650     SvREFCNT_dec(av);
2651     AddImageToRegistry(sv,image);
2652     rv=newRV(sv);
2653     av_push(av,sv_bless(rv,hv));
2654     SvREFCNT_dec(sv);
2655     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2656     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
2657       "average-%.*s",(int) (MaxTextExtent-9),
2658       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2659     (void) CopyMagickString(image->filename,info->image_info->filename,
2660       MaxTextExtent);
2661     SetImageInfo(info->image_info,0,exception);
2662     exception=DestroyExceptionInfo(exception);
2663     SvREFCNT_dec(perl_exception);
2664     XSRETURN(1);
2665
2666   PerlException:
2667     InheritPerlException(exception,perl_exception);
2668     exception=DestroyExceptionInfo(exception);
2669     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2670     SvPOK_on(perl_exception);
2671     ST(0)=sv_2mortal(perl_exception);
2672     XSRETURN(1);
2673   }
2674 \f
2675 #
2676 ###############################################################################
2677 #                                                                             #
2678 #                                                                             #
2679 #                                                                             #
2680 #   B l o b T o I m a g e                                                     #
2681 #                                                                             #
2682 #                                                                             #
2683 #                                                                             #
2684 ###############################################################################
2685 #
2686 #
2687 void
2688 BlobToImage(ref,...)
2689   Image::Magick ref=NO_INIT
2690   ALIAS:
2691     BlobToImage  = 1
2692     blobtoimage  = 2
2693     blobto       = 3
2694   PPCODE:
2695   {
2696     AV
2697       *av;
2698
2699     char
2700       **keep,
2701       **list;
2702
2703     ExceptionInfo
2704       *exception;
2705
2706     HV
2707       *hv;
2708
2709     Image
2710       *image;
2711
2712     register char
2713       **p;
2714
2715     register ssize_t
2716       i;
2717
2718     ssize_t
2719       ac,
2720       n,
2721       number_images;
2722
2723     STRLEN
2724       *length;
2725
2726     struct PackageInfo
2727       *info;
2728
2729     SV
2730       *perl_exception,
2731       *reference,
2732       *rv,
2733       *sv;
2734
2735     PERL_UNUSED_VAR(ref);
2736     PERL_UNUSED_VAR(ix);
2737     exception=AcquireExceptionInfo();
2738     perl_exception=newSVpv("",0);
2739     sv=NULL;
2740     number_images=0;
2741     ac=(items < 2) ? 1 : items-1;
2742     length=(STRLEN *) NULL;
2743     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2744     if (list == (char **) NULL)
2745       {
2746         ThrowPerlException(exception,ResourceLimitError,
2747           "MemoryAllocationFailed",PackageName);
2748         goto PerlException;
2749       }
2750     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2751     if (length == (STRLEN *) NULL)
2752       {
2753         ThrowPerlException(exception,ResourceLimitError,
2754           "MemoryAllocationFailed",PackageName);
2755         goto PerlException;
2756       }
2757     if (sv_isobject(ST(0)) == 0)
2758       {
2759         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2760           PackageName);
2761         goto PerlException;
2762       }
2763     reference=SvRV(ST(0));
2764     hv=SvSTASH(reference);
2765     if (SvTYPE(reference) != SVt_PVAV)
2766       {
2767         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2768           PackageName);
2769         goto PerlException;
2770       }
2771     av=(AV *) reference;
2772     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2773       exception);
2774     n=1;
2775     if (items <= 1)
2776       {
2777         ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2778         goto PerlException;
2779       }
2780     for (n=0, i=0; i < ac; i++)
2781     {
2782       list[n]=(char *) (SvPV(ST(i+1),length[n]));
2783       if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2784         {
2785           list[n]=(char *) (SvPV(ST(i+2),length[n]));
2786           continue;
2787         }
2788       n++;
2789     }
2790     list[n]=(char *) NULL;
2791     keep=list;
2792     for (i=number_images=0; i < n; i++)
2793     {
2794       image=BlobToImage(info->image_info,list[i],length[i],exception);
2795       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2796         break;
2797       for ( ; image; image=image->next)
2798       {
2799         AddImageToRegistry(sv,image);
2800         rv=newRV(sv);
2801         av_push(av,sv_bless(rv,hv));
2802         SvREFCNT_dec(sv);
2803         number_images++;
2804       }
2805     }
2806     /*
2807       Free resources.
2808     */
2809     for (i=0; i < n; i++)
2810       if (list[i] != (char *) NULL)
2811         for (p=keep; list[i] != *p++; )
2812           if (*p == (char *) NULL)
2813             {
2814               list[i]=(char *) RelinquishMagickMemory(list[i]);
2815               break;
2816             }
2817
2818   PerlException:
2819     if (list)
2820       list=(char **) RelinquishMagickMemory(list);
2821     if (length)
2822       length=(STRLEN *) RelinquishMagickMemory(length);
2823     InheritPerlException(exception,perl_exception);
2824     exception=DestroyExceptionInfo(exception);
2825     sv_setiv(perl_exception,(IV) number_images);
2826     SvPOK_on(perl_exception);
2827     ST(0)=sv_2mortal(perl_exception);
2828     XSRETURN(1);
2829   }
2830 \f
2831 #
2832 ###############################################################################
2833 #                                                                             #
2834 #                                                                             #
2835 #                                                                             #
2836 #   C l o n e                                                                 #
2837 #                                                                             #
2838 #                                                                             #
2839 #                                                                             #
2840 ###############################################################################
2841 #
2842 #
2843 void
2844 Clone(ref)
2845   Image::Magick ref=NO_INIT
2846   ALIAS:
2847     CopyImage   = 1
2848     copy        = 2
2849     copyimage   = 3
2850     CloneImage  = 4
2851     clone       = 5
2852     cloneimage  = 6
2853     Clone       = 7
2854   PPCODE:
2855   {
2856     AV
2857       *av;
2858
2859     ExceptionInfo
2860       *exception;
2861
2862     HV
2863       *hv;
2864
2865     Image
2866       *clone,
2867       *image;
2868
2869     struct PackageInfo
2870       *info;
2871
2872     SV
2873       *perl_exception,
2874       *reference,
2875       *rv,
2876       *sv;
2877
2878     PERL_UNUSED_VAR(ref);
2879     PERL_UNUSED_VAR(ix);
2880     exception=AcquireExceptionInfo();
2881     perl_exception=newSVpv("",0);
2882     sv=NULL;
2883     if (sv_isobject(ST(0)) == 0)
2884       {
2885         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2886           PackageName);
2887         goto PerlException;
2888       }
2889     reference=SvRV(ST(0));
2890     hv=SvSTASH(reference);
2891     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2892     if (image == (Image *) NULL)
2893       {
2894         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2895           PackageName);
2896         goto PerlException;
2897       }
2898     /*
2899       Create blessed Perl array for the returned image.
2900     */
2901     av=newAV();
2902     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2903     SvREFCNT_dec(av);
2904     for ( ; image; image=image->next)
2905     {
2906       clone=CloneImage(image,0,0,MagickTrue,exception);
2907       if ((clone == (Image *) NULL) || (exception->severity >= ErrorException))
2908         break;
2909       AddImageToRegistry(sv,clone);
2910       rv=newRV(sv);
2911       av_push(av,sv_bless(rv,hv));
2912       SvREFCNT_dec(sv);
2913     }
2914     exception=DestroyExceptionInfo(exception);
2915     SvREFCNT_dec(perl_exception);
2916     XSRETURN(1);
2917
2918   PerlException:
2919     InheritPerlException(exception,perl_exception);
2920     exception=DestroyExceptionInfo(exception);
2921     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2922     SvPOK_on(perl_exception);
2923     ST(0)=sv_2mortal(perl_exception);
2924     XSRETURN(1);
2925   }
2926 \f
2927 #
2928 ###############################################################################
2929 #                                                                             #
2930 #                                                                             #
2931 #                                                                             #
2932 #   C L O N E                                                                 #
2933 #                                                                             #
2934 #                                                                             #
2935 #                                                                             #
2936 ###############################################################################
2937 #
2938 #
2939 void
2940 CLONE(ref,...)
2941   SV *ref;
2942   CODE:
2943   {
2944     PERL_UNUSED_VAR(ref);
2945     if (magick_registry != (SplayTreeInfo *) NULL)
2946       {
2947         register Image
2948           *p;
2949
2950         ResetSplayTreeIterator(magick_registry);
2951         p=(Image *) GetNextKeyInSplayTree(magick_registry);
2952         while (p != (Image *) NULL)
2953         {
2954           ReferenceImage(p);
2955           p=(Image *) GetNextKeyInSplayTree(magick_registry);
2956         }
2957       }
2958   }
2959 \f
2960 #
2961 ###############################################################################
2962 #                                                                             #
2963 #                                                                             #
2964 #                                                                             #
2965 #   C o a l e s c e                                                           #
2966 #                                                                             #
2967 #                                                                             #
2968 #                                                                             #
2969 ###############################################################################
2970 #
2971 #
2972 void
2973 Coalesce(ref)
2974   Image::Magick ref=NO_INIT
2975   ALIAS:
2976     CoalesceImage   = 1
2977     coalesce        = 2
2978     coalesceimage   = 3
2979   PPCODE:
2980   {
2981     AV
2982       *av;
2983
2984     ExceptionInfo
2985       *exception;
2986
2987     HV
2988       *hv;
2989
2990     Image
2991       *image;
2992
2993     struct PackageInfo
2994       *info;
2995
2996     SV
2997       *av_reference,
2998       *perl_exception,
2999       *reference,
3000       *rv,
3001       *sv;
3002
3003     PERL_UNUSED_VAR(ref);
3004     PERL_UNUSED_VAR(ix);
3005     exception=AcquireExceptionInfo();
3006     perl_exception=newSVpv("",0);
3007     sv=NULL;
3008     if (sv_isobject(ST(0)) == 0)
3009       {
3010         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3011           PackageName);
3012         goto PerlException;
3013       }
3014     reference=SvRV(ST(0));
3015     hv=SvSTASH(reference);
3016     av=newAV();
3017     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3018     SvREFCNT_dec(av);
3019     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3020     if (image == (Image *) NULL)
3021       {
3022         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3023           PackageName);
3024         goto PerlException;
3025       }
3026     image=CoalesceImages(image,exception);
3027     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3028       goto PerlException;
3029     for ( ; image; image=image->next)
3030     {
3031       AddImageToRegistry(sv,image);
3032       rv=newRV(sv);
3033       av_push(av,sv_bless(rv,hv));
3034       SvREFCNT_dec(sv);
3035     }
3036     exception=DestroyExceptionInfo(exception);
3037     ST(0)=av_reference;
3038     SvREFCNT_dec(perl_exception);
3039     XSRETURN(1);
3040
3041   PerlException:
3042     InheritPerlException(exception,perl_exception);
3043     exception=DestroyExceptionInfo(exception);
3044     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3045     SvPOK_on(perl_exception);
3046     ST(0)=sv_2mortal(perl_exception);
3047     XSRETURN(1);
3048   }
3049 \f
3050 #
3051 ###############################################################################
3052 #                                                                             #
3053 #                                                                             #
3054 #                                                                             #
3055 #   C o m p a r e                                                             #
3056 #                                                                             #
3057 #                                                                             #
3058 #                                                                             #
3059 ###############################################################################
3060 #
3061 #
3062 void
3063 Compare(ref,...)
3064   Image::Magick ref=NO_INIT
3065   ALIAS:
3066     CompareImages = 1
3067     compare      = 2
3068     compareimage = 3
3069   PPCODE:
3070   {
3071     AV
3072       *av;
3073
3074     char
3075       *attribute;
3076
3077     double
3078       distortion;
3079
3080     ExceptionInfo
3081       *exception;
3082
3083     HV
3084       *hv;
3085
3086     Image
3087       *difference_image,
3088       *image,
3089       *reconstruct_image;
3090
3091     MetricType
3092       metric;
3093
3094     register ssize_t
3095       i;
3096
3097     ssize_t
3098       option;
3099
3100     struct PackageInfo
3101       *info;
3102
3103     SV
3104       *av_reference,
3105       *perl_exception,
3106       *reference,
3107       *rv,
3108       *sv;
3109
3110     PERL_UNUSED_VAR(ref);
3111     PERL_UNUSED_VAR(ix);
3112     exception=AcquireExceptionInfo();
3113     perl_exception=newSVpv("",0);
3114     sv=NULL;
3115     av=NULL;
3116     attribute=NULL;
3117     if (sv_isobject(ST(0)) == 0)
3118       {
3119         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3120           PackageName);
3121         goto PerlException;
3122       }
3123     reference=SvRV(ST(0));
3124     hv=SvSTASH(reference);
3125     av=newAV();
3126     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3127     SvREFCNT_dec(av);
3128     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3129     if (image == (Image *) NULL)
3130       {
3131         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3132           PackageName);
3133         goto PerlException;
3134       }
3135     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3136     /*
3137       Get attribute.
3138     */
3139     reconstruct_image=image;
3140     metric=RootMeanSquaredErrorMetric;
3141     for (i=2; i < items; i+=2)
3142     {
3143       attribute=(char *) SvPV(ST(i-1),na);
3144       switch (*attribute)
3145       {
3146         case 'C':
3147         case 'c':
3148         {
3149           if (LocaleCompare(attribute,"channel") == 0)
3150             {
3151               ssize_t
3152                 option;
3153
3154               option=ParseChannelOption(SvPV(ST(i),na));
3155               if (option < 0)
3156                 {
3157                   ThrowPerlException(exception,OptionError,
3158                     "UnrecognizedType",SvPV(ST(i),na));
3159                   return;
3160                 }
3161               SetPixelChannelMap(image,(ChannelType) option);
3162               break;
3163             }
3164           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3165             attribute);
3166           break;
3167         }
3168         case 'F':
3169         case 'f':
3170         {
3171           if (LocaleCompare(attribute,"fuzz") == 0)
3172             {
3173               image->fuzz=SiPrefixToDouble(SvPV(ST(i),na),100.0);
3174               break;
3175             }
3176           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3177             attribute);
3178           break;
3179         }
3180         case 'I':
3181         case 'i':
3182         {
3183           if (LocaleCompare(attribute,"image") == 0)
3184             {
3185               reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3186                 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3187               break;
3188             }
3189           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3190             attribute);
3191           break;
3192         }
3193         case 'M':
3194         case 'm':
3195         {
3196           if (LocaleCompare(attribute,"metric") == 0)
3197             {
3198               option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3199                 SvPV(ST(i),na));
3200               if (option < 0)
3201                 {
3202                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3203                     SvPV(ST(i),na));
3204                   break;
3205                 }
3206               metric=(MetricType) option;
3207               break;
3208             }
3209           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3210             attribute);
3211           break;
3212         }
3213         default:
3214         {
3215           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3216             attribute);
3217           break;
3218         }
3219       }
3220     }
3221     difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3222       exception);
3223     if (difference_image != (Image *) NULL)
3224       {
3225         difference_image->error.mean_error_per_pixel=distortion;
3226         AddImageToRegistry(sv,difference_image);
3227         rv=newRV(sv);
3228         av_push(av,sv_bless(rv,hv));
3229         SvREFCNT_dec(sv);
3230       }
3231     exception=DestroyExceptionInfo(exception);
3232     ST(0)=av_reference;
3233     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3234     XSRETURN(1);
3235
3236   PerlException:
3237     InheritPerlException(exception,perl_exception);
3238     exception=DestroyExceptionInfo(exception);
3239     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3240     SvPOK_on(perl_exception);
3241     ST(0)=sv_2mortal(perl_exception);
3242     XSRETURN(1);
3243   }
3244 \f
3245 #
3246 ###############################################################################
3247 #                                                                             #
3248 #                                                                             #
3249 #                                                                             #
3250 #   C o m p a r e L a y e r s                                                 #
3251 #                                                                             #
3252 #                                                                             #
3253 #                                                                             #
3254 ###############################################################################
3255 #
3256 #
3257 void
3258 CompareLayers(ref)
3259   Image::Magick ref=NO_INIT
3260   ALIAS:
3261     CompareImagesLayers   = 1
3262     comparelayers        = 2
3263     compareimagelayers   = 3
3264   PPCODE:
3265   {
3266     AV
3267       *av;
3268
3269     char
3270       *attribute;
3271
3272     ExceptionInfo
3273       *exception;
3274
3275     HV
3276       *hv;
3277
3278     Image
3279       *image;
3280
3281     ImageLayerMethod
3282       method;
3283
3284     register ssize_t
3285       i;
3286
3287     ssize_t
3288       option;
3289
3290     struct PackageInfo
3291       *info;
3292
3293     SV
3294       *av_reference,
3295       *perl_exception,
3296       *reference,
3297       *rv,
3298       *sv;
3299
3300     PERL_UNUSED_VAR(ref);
3301     PERL_UNUSED_VAR(ix);
3302     exception=AcquireExceptionInfo();
3303     perl_exception=newSVpv("",0);
3304     sv=NULL;
3305     if (sv_isobject(ST(0)) == 0)
3306       {
3307         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3308           PackageName);
3309         goto PerlException;
3310       }
3311     reference=SvRV(ST(0));
3312     hv=SvSTASH(reference);
3313     av=newAV();
3314     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3315     SvREFCNT_dec(av);
3316     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3317     if (image == (Image *) NULL)
3318       {
3319         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3320           PackageName);
3321         goto PerlException;
3322       }
3323     method=CompareAnyLayer;
3324     for (i=2; i < items; i+=2)
3325     {
3326       attribute=(char *) SvPV(ST(i-1),na);
3327       switch (*attribute)
3328       {
3329         case 'M':
3330         case 'm':
3331         {
3332           if (LocaleCompare(attribute,"method") == 0)
3333             {
3334               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3335                 SvPV(ST(i),na));
3336               if (option < 0)
3337                 {
3338                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3339                     SvPV(ST(i),na));
3340                   break;
3341                 }
3342                method=(ImageLayerMethod) option;
3343               break;
3344             }
3345           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3346             attribute);
3347           break;
3348         }
3349         default:
3350         {
3351           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3352             attribute);
3353           break;
3354         }
3355       }
3356     }
3357     image=CompareImagesLayers(image,method,exception);
3358     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3359       goto PerlException;
3360     for ( ; image; image=image->next)
3361     {
3362       AddImageToRegistry(sv,image);
3363       rv=newRV(sv);
3364       av_push(av,sv_bless(rv,hv));
3365       SvREFCNT_dec(sv);
3366     }
3367     exception=DestroyExceptionInfo(exception);
3368     ST(0)=av_reference;
3369     SvREFCNT_dec(perl_exception);
3370     XSRETURN(1);
3371
3372   PerlException:
3373     InheritPerlException(exception,perl_exception);
3374     exception=DestroyExceptionInfo(exception);
3375     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3376     SvPOK_on(perl_exception);
3377     ST(0)=sv_2mortal(perl_exception);
3378     XSRETURN(1);
3379   }
3380 \f
3381 #
3382 ###############################################################################
3383 #                                                                             #
3384 #                                                                             #
3385 #                                                                             #
3386 #   D e s t r o y                                                             #
3387 #                                                                             #
3388 #                                                                             #
3389 #                                                                             #
3390 ###############################################################################
3391 #
3392 #
3393 void
3394 DESTROY(ref)
3395   Image::Magick ref=NO_INIT
3396   PPCODE:
3397   {
3398     SV
3399       *reference;
3400
3401     PERL_UNUSED_VAR(ref);
3402     if (sv_isobject(ST(0)) == 0)
3403       croak("ReferenceIsNotMyType");
3404     reference=SvRV(ST(0));
3405     switch (SvTYPE(reference))
3406     {
3407       case SVt_PVAV:
3408       {
3409         char
3410           message[MaxTextExtent];
3411
3412         const SV
3413           *key;
3414
3415         HV
3416           *hv;
3417
3418         GV
3419           **gvp;
3420
3421         struct PackageInfo
3422           *info;
3423
3424         SV
3425           *sv;
3426
3427         /*
3428           Array (AV *) reference
3429         */
3430         (void) FormatLocaleString(message,MaxTextExtent,"package%s%p",
3431           XS_VERSION,reference);
3432         hv=gv_stashpv(PackageName, FALSE);
3433         if (!hv)
3434           break;
3435         gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3436         if (!gvp)
3437           break;
3438         sv=GvSV(*gvp);
3439         if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3440           {
3441             info=(struct PackageInfo *) SvIV(sv);
3442             DestroyPackageInfo(info);
3443           }
3444         key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3445         (void) key;
3446         break;
3447       }
3448       case SVt_PVMG:
3449       {
3450         Image
3451           *image;
3452
3453         /*
3454           Blessed scalar = (Image *) SvIV(reference)
3455         */
3456         image=(Image *) SvIV(reference);
3457         if (image != (Image *) NULL)
3458           DeleteImageFromRegistry(reference,image);
3459         break;
3460       }
3461       default:
3462         break;
3463     }
3464   }
3465 \f
3466 #
3467 ###############################################################################
3468 #                                                                             #
3469 #                                                                             #
3470 #                                                                             #
3471 #   D i s p l a y                                                             #
3472 #                                                                             #
3473 #                                                                             #
3474 #                                                                             #
3475 ###############################################################################
3476 #
3477 #
3478 void
3479 Display(ref,...)
3480   Image::Magick ref=NO_INIT
3481   ALIAS:
3482     DisplayImage  = 1
3483     display       = 2
3484     displayimage  = 3
3485   PPCODE:
3486   {
3487     ExceptionInfo
3488       *exception;
3489
3490     Image
3491       *image;
3492
3493     register ssize_t
3494       i;
3495
3496     struct PackageInfo
3497       *info,
3498       *package_info;
3499
3500     SV
3501       *perl_exception,
3502       *reference;
3503
3504     PERL_UNUSED_VAR(ref);
3505     PERL_UNUSED_VAR(ix);
3506     exception=AcquireExceptionInfo();
3507     perl_exception=newSVpv("",0);
3508     package_info=(struct PackageInfo *) NULL;
3509     if (sv_isobject(ST(0)) == 0)
3510       {
3511         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3512           PackageName);
3513         goto PerlException;
3514       }
3515     reference=SvRV(ST(0));
3516     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3517     if (image == (Image *) NULL)
3518       {
3519         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3520           PackageName);
3521         goto PerlException;
3522       }
3523     package_info=ClonePackageInfo(info,exception);
3524     if (items == 2)
3525       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3526     else
3527       if (items > 2)
3528         for (i=2; i < items; i+=2)
3529           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3530             exception);
3531     (void) DisplayImages(package_info->image_info,image,exception);
3532     (void) CatchImageException(image);
3533
3534   PerlException:
3535     if (package_info != (struct PackageInfo *) NULL)
3536       DestroyPackageInfo(package_info);
3537     InheritPerlException(exception,perl_exception);
3538     exception=DestroyExceptionInfo(exception);
3539     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3540     SvPOK_on(perl_exception);
3541     ST(0)=sv_2mortal(perl_exception);
3542     XSRETURN(1);
3543   }
3544 \f
3545 #
3546 ###############################################################################
3547 #                                                                             #
3548 #                                                                             #
3549 #                                                                             #
3550 #   E v a l u a t e I m a g e s                                               #
3551 #                                                                             #
3552 #                                                                             #
3553 #                                                                             #
3554 ###############################################################################
3555 #
3556 #
3557 void
3558 EvaluateImages(ref)
3559   Image::Magick ref=NO_INIT
3560   ALIAS:
3561     EvaluateImages   = 1
3562     evaluateimages   = 2
3563   PPCODE:
3564   {
3565     AV
3566       *av;
3567
3568     char
3569       *attribute,
3570       *p;
3571
3572     ExceptionInfo
3573       *exception;
3574
3575     HV
3576       *hv;
3577
3578     Image
3579       *image;
3580
3581     MagickEvaluateOperator
3582       op;
3583
3584     register ssize_t
3585       i;
3586
3587     struct PackageInfo
3588       *info;
3589
3590     SV
3591       *perl_exception,
3592       *reference,
3593       *rv,
3594       *sv;
3595
3596     PERL_UNUSED_VAR(ref);
3597     PERL_UNUSED_VAR(ix);
3598     exception=AcquireExceptionInfo();
3599     perl_exception=newSVpv("",0);
3600     sv=NULL;
3601     if (sv_isobject(ST(0)) == 0)
3602       {
3603         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3604           PackageName);
3605         goto PerlException;
3606       }
3607     reference=SvRV(ST(0));
3608     hv=SvSTASH(reference);
3609     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3610     if (image == (Image *) NULL)
3611       {
3612         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3613           PackageName);
3614         goto PerlException;
3615       }
3616     op=MeanEvaluateOperator;
3617     if (items == 2)
3618       {
3619         ssize_t
3620           in;
3621
3622         in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
3623           SvPV(ST(1),na));
3624         if (in < 0)
3625           {
3626             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3627               SvPV(ST(1),na));
3628             return;
3629           }
3630         op=(MagickEvaluateOperator) in;
3631       }
3632     else
3633       for (i=2; i < items; i+=2)
3634       {
3635         attribute=(char *) SvPV(ST(i-1),na);
3636         switch (*attribute)
3637         {
3638           case 'O':
3639           case 'o':
3640           {
3641             if (LocaleCompare(attribute,"operator") == 0)
3642               {
3643                 ssize_t
3644                   in;
3645
3646                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3647                   MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
3648                 if (in < 0)
3649                   {
3650                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3651                       SvPV(ST(i),na));
3652                     return;
3653                   }
3654                 op=(MagickEvaluateOperator) in;
3655                 break;
3656               }
3657             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3658               attribute);
3659             break;
3660           }
3661           default:
3662           {
3663             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3664               attribute);
3665             break;
3666           }
3667         }
3668       }
3669     image=EvaluateImages(image,op,exception);
3670     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3671       goto PerlException;
3672     /*
3673       Create blessed Perl array for the returned image.
3674     */
3675     av=newAV();
3676     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3677     SvREFCNT_dec(av);
3678     AddImageToRegistry(sv,image);
3679     rv=newRV(sv);
3680     av_push(av,sv_bless(rv,hv));
3681     SvREFCNT_dec(sv);
3682     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3683     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
3684       "evaluate-%.*s",(int) (MaxTextExtent-9),
3685       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3686     (void) CopyMagickString(image->filename,info->image_info->filename,
3687       MaxTextExtent);
3688     SetImageInfo(info->image_info,0,exception);
3689     exception=DestroyExceptionInfo(exception);
3690     SvREFCNT_dec(perl_exception);
3691     XSRETURN(1);
3692
3693   PerlException:
3694     InheritPerlException(exception,perl_exception);
3695     exception=DestroyExceptionInfo(exception);
3696     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3697     SvPOK_on(perl_exception);
3698     ST(0)=sv_2mortal(perl_exception);
3699     XSRETURN(1);
3700   }
3701 \f
3702 #
3703 ###############################################################################
3704 #                                                                             #
3705 #                                                                             #
3706 #                                                                             #
3707 #   F e a t u r e s                                                           #
3708 #                                                                             #
3709 #                                                                             #
3710 #                                                                             #
3711 ###############################################################################
3712 #
3713 #
3714 void
3715 Features(ref,...)
3716   Image::Magick ref=NO_INIT
3717   ALIAS:
3718     FeaturesImage = 1
3719     features      = 2
3720     featuresimage = 3
3721   PPCODE:
3722   {
3723 #define ChannelFeatures(channel,direction) \
3724 { \
3725   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3726     channel_features[channel].angular_second_moment[direction]); \
3727   PUSHs(sv_2mortal(newSVpv(message,0))); \
3728   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3729     channel_features[channel].contrast[direction]); \
3730   PUSHs(sv_2mortal(newSVpv(message,0))); \
3731   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3732     channel_features[channel].contrast[direction]); \
3733   PUSHs(sv_2mortal(newSVpv(message,0))); \
3734   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3735     channel_features[channel].variance_sum_of_squares[direction]); \
3736   PUSHs(sv_2mortal(newSVpv(message,0))); \
3737   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3738     channel_features[channel].inverse_difference_moment[direction]); \
3739   PUSHs(sv_2mortal(newSVpv(message,0))); \
3740   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3741     channel_features[channel].sum_average[direction]); \
3742   PUSHs(sv_2mortal(newSVpv(message,0))); \
3743   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3744     channel_features[channel].sum_variance[direction]); \
3745   PUSHs(sv_2mortal(newSVpv(message,0))); \
3746   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3747     channel_features[channel].sum_entropy[direction]); \
3748   PUSHs(sv_2mortal(newSVpv(message,0))); \
3749   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3750     channel_features[channel].entropy[direction]); \
3751   PUSHs(sv_2mortal(newSVpv(message,0))); \
3752   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3753     channel_features[channel].difference_variance[direction]); \
3754   PUSHs(sv_2mortal(newSVpv(message,0))); \
3755   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3756     channel_features[channel].difference_entropy[direction]); \
3757   PUSHs(sv_2mortal(newSVpv(message,0))); \
3758   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3759     channel_features[channel].measure_of_correlation_1[direction]); \
3760   PUSHs(sv_2mortal(newSVpv(message,0))); \
3761   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3762     channel_features[channel].measure_of_correlation_2[direction]); \
3763   PUSHs(sv_2mortal(newSVpv(message,0))); \
3764   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3765     channel_features[channel].maximum_correlation_coefficient[direction]); \
3766   PUSHs(sv_2mortal(newSVpv(message,0))); \
3767 }
3768
3769     AV
3770       *av;
3771
3772     char
3773       *attribute,
3774       message[MaxTextExtent];
3775
3776     ChannelFeatures
3777       *channel_features;
3778
3779     double
3780       distance;
3781
3782     ExceptionInfo
3783       *exception;
3784
3785     Image
3786       *image;
3787
3788     register ssize_t
3789       i;
3790
3791     ssize_t
3792       count;
3793
3794     struct PackageInfo
3795       *info;
3796
3797     SV
3798       *perl_exception,
3799       *reference;
3800
3801     PERL_UNUSED_VAR(ref);
3802     PERL_UNUSED_VAR(ix);
3803     exception=AcquireExceptionInfo();
3804     perl_exception=newSVpv("",0);
3805     av=NULL;
3806     if (sv_isobject(ST(0)) == 0)
3807       {
3808         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3809           PackageName);
3810         goto PerlException;
3811       }
3812     reference=SvRV(ST(0));
3813     av=newAV();
3814     SvREFCNT_dec(av);
3815     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3816     if (image == (Image *) NULL)
3817       {
3818         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3819           PackageName);
3820         goto PerlException;
3821       }
3822     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3823     distance=1;
3824     for (i=2; i < items; i+=2)
3825     {
3826       attribute=(char *) SvPV(ST(i-1),na);
3827       switch (*attribute)
3828       {
3829         case 'D':
3830         case 'd':
3831         {
3832           if (LocaleCompare(attribute,"distance") == 0)
3833             {
3834               distance=StringToLong((char *) SvPV(ST(1),na));
3835               break;
3836             }
3837           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3838             attribute);
3839           break;
3840         }
3841         default:
3842         {
3843           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3844             attribute);
3845           break;
3846         }
3847       }
3848     }
3849     count=0;
3850     for ( ; image; image=image->next)
3851     {
3852       channel_features=GetImageFeatures(image,distance,
3853         &image->exception);
3854       if (channel_features == (ChannelFeatures *) NULL)
3855         continue;
3856       count++;
3857       EXTEND(sp,75*count);
3858       for (i=0; i < 4; i++)
3859       {
3860         ChannelFeatures(RedChannel,i);
3861         ChannelFeatures(GreenChannel,i);
3862         ChannelFeatures(BlueChannel,i);
3863         if (image->colorspace == CMYKColorspace)
3864           ChannelFeatures(BlackChannel,i);
3865         if (image->matte != MagickFalse)
3866           ChannelFeatures(AlphaChannel,i);
3867       }
3868       channel_features=(ChannelFeatures *)
3869         RelinquishMagickMemory(channel_features);
3870     }
3871
3872   PerlException:
3873     InheritPerlException(exception,perl_exception);
3874     exception=DestroyExceptionInfo(exception);
3875     SvREFCNT_dec(perl_exception);
3876   }
3877 \f
3878 #
3879 ###############################################################################
3880 #                                                                             #
3881 #                                                                             #
3882 #                                                                             #
3883 #   F l a t t e n                                                             #
3884 #                                                                             #
3885 #                                                                             #
3886 #                                                                             #
3887 ###############################################################################
3888 #
3889 #
3890 void
3891 Flatten(ref)
3892   Image::Magick ref=NO_INIT
3893   ALIAS:
3894     FlattenImage   = 1
3895     flatten        = 2
3896     flattenimage   = 3
3897   PPCODE:
3898   {
3899     AV
3900       *av;
3901
3902     char
3903       *attribute,
3904       *p;
3905
3906     ExceptionInfo
3907       *exception;
3908
3909     HV
3910       *hv;
3911
3912     Image
3913       *image;
3914
3915     PixelPacket
3916       background_color;
3917
3918     register ssize_t
3919       i;
3920
3921     struct PackageInfo
3922       *info;
3923
3924     SV
3925       *perl_exception,
3926       *reference,
3927       *rv,
3928       *sv;
3929
3930     PERL_UNUSED_VAR(ref);
3931     PERL_UNUSED_VAR(ix);
3932     exception=AcquireExceptionInfo();
3933     perl_exception=newSVpv("",0);
3934     sv=NULL;
3935     if (sv_isobject(ST(0)) == 0)
3936       {
3937         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3938           PackageName);
3939         goto PerlException;
3940       }
3941     reference=SvRV(ST(0));
3942     hv=SvSTASH(reference);
3943     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3944     if (image == (Image *) NULL)
3945       {
3946         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3947           PackageName);
3948         goto PerlException;
3949       }
3950     background_color=image->background_color;
3951     if (items == 2)
3952       (void) QueryColorDatabase((char *) SvPV(ST(1),na),&background_color,
3953         exception);
3954     else
3955       for (i=2; i < items; i+=2)
3956       {
3957         attribute=(char *) SvPV(ST(i-1),na);
3958         switch (*attribute)
3959         {
3960           case 'B':
3961           case 'b':
3962           {
3963             if (LocaleCompare(attribute,"background") == 0)
3964               {
3965                 (void) QueryColorDatabase((char *) SvPV(ST(1),na),
3966                   &background_color,exception);
3967                 break;
3968               }
3969             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3970               attribute);
3971             break;
3972           }
3973           default:
3974           {
3975             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3976               attribute);
3977             break;
3978           }
3979         }
3980       }
3981     image->background_color=background_color;
3982     image=MergeImageLayers(image,FlattenLayer,exception);
3983     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3984       goto PerlException;
3985     /*
3986       Create blessed Perl array for the returned image.
3987     */
3988     av=newAV();
3989     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3990     SvREFCNT_dec(av);
3991     AddImageToRegistry(sv,image);
3992     rv=newRV(sv);
3993     av_push(av,sv_bless(rv,hv));
3994     SvREFCNT_dec(sv);
3995     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3996     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
3997       "flatten-%.*s",(int) (MaxTextExtent-9),
3998       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3999     (void) CopyMagickString(image->filename,info->image_info->filename,
4000       MaxTextExtent);
4001     SetImageInfo(info->image_info,0,exception);
4002     exception=DestroyExceptionInfo(exception);
4003     SvREFCNT_dec(perl_exception);
4004     XSRETURN(1);
4005
4006   PerlException:
4007     InheritPerlException(exception,perl_exception);
4008     exception=DestroyExceptionInfo(exception);
4009     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4010     SvPOK_on(perl_exception);  /* return messages in string context */
4011     ST(0)=sv_2mortal(perl_exception);
4012     XSRETURN(1);
4013   }
4014 \f
4015 #
4016 ###############################################################################
4017 #                                                                             #
4018 #                                                                             #
4019 #                                                                             #
4020 #   F x                                                                       #
4021 #                                                                             #
4022 #                                                                             #
4023 #                                                                             #
4024 ###############################################################################
4025 #
4026 #
4027 void
4028 Fx(ref,...)
4029   Image::Magick ref=NO_INIT
4030   ALIAS:
4031     FxImage  = 1
4032     fx       = 2
4033     fximage  = 3
4034   PPCODE:
4035   {
4036     AV
4037       *av;
4038
4039     char
4040       *attribute,
4041       expression[MaxTextExtent];
4042
4043     ChannelType
4044       channel,
4045       channel_mask;
4046
4047     ExceptionInfo
4048       *exception;
4049
4050     HV
4051       *hv;
4052
4053     Image
4054       *image;
4055
4056     register ssize_t
4057       i;
4058
4059     struct PackageInfo
4060       *info;
4061
4062     SV
4063       *av_reference,
4064       *perl_exception,
4065       *reference,
4066       *rv,
4067       *sv;
4068
4069     PERL_UNUSED_VAR(ref);
4070     PERL_UNUSED_VAR(ix);
4071     exception=AcquireExceptionInfo();
4072     perl_exception=newSVpv("",0);
4073     sv=NULL;
4074     attribute=NULL;
4075     av=NULL;
4076     if (sv_isobject(ST(0)) == 0)
4077       {
4078         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4079           PackageName);
4080         goto PerlException;
4081       }
4082     reference=SvRV(ST(0));
4083     hv=SvSTASH(reference);
4084     av=newAV();
4085     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4086     SvREFCNT_dec(av);
4087     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4088     if (image == (Image *) NULL)
4089       {
4090         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4091           PackageName);
4092         goto PerlException;
4093       }
4094     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4095     /*
4096       Get options.
4097     */
4098     channel=DefaultChannels;
4099     (void) CopyMagickString(expression,"u",MaxTextExtent);
4100     if (items == 2)
4101       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MaxTextExtent);
4102     else
4103       for (i=2; i < items; i+=2)
4104       {
4105         attribute=(char *) SvPV(ST(i-1),na);
4106         switch (*attribute)
4107         {
4108           case 'C':
4109           case 'c':
4110           {
4111             if (LocaleCompare(attribute,"channel") == 0)
4112               {
4113                 ssize_t
4114                   option;
4115
4116                 option=ParseChannelOption(SvPV(ST(i),na));
4117                 if (option < 0)
4118                   {
4119                     ThrowPerlException(exception,OptionError,
4120                       "UnrecognizedType",SvPV(ST(i),na));
4121                     return;
4122                   }
4123                 channel=(ChannelType) option;
4124                 break;
4125               }
4126             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4127               attribute);
4128             break;
4129           }
4130           case 'E':
4131           case 'e':
4132           {
4133             if (LocaleCompare(attribute,"expression") == 0)
4134               {
4135                 (void) CopyMagickString(expression,SvPV(ST(i),na),
4136                   MaxTextExtent);
4137                 break;
4138               }
4139             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4140               attribute);
4141             break;
4142           }
4143           default:
4144           {
4145             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4146               attribute);
4147             break;
4148           }
4149         }
4150       }
4151     channel_mask=SetPixelChannelMask(image,channel);
4152     image=FxImage(image,expression,exception);
4153     if (image != (Image *) NULL)
4154       (void) SetPixelChannelMask(image,channel_mask);
4155     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
4156       goto PerlException;
4157     for ( ; image; image=image->next)
4158     {
4159       AddImageToRegistry(sv,image);
4160       rv=newRV(sv);
4161       av_push(av,sv_bless(rv,hv));
4162       SvREFCNT_dec(sv);
4163     }
4164     exception=DestroyExceptionInfo(exception);
4165     ST(0)=av_reference;
4166     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4167     XSRETURN(1);
4168
4169   PerlException:
4170     InheritPerlException(exception,perl_exception);
4171     exception=DestroyExceptionInfo(exception);
4172     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4173     SvPOK_on(perl_exception);
4174     ST(0)=sv_2mortal(perl_exception);
4175     XSRETURN(1);
4176   }
4177 \f
4178 #
4179 ###############################################################################
4180 #                                                                             #
4181 #                                                                             #
4182 #                                                                             #
4183 #   G e t                                                                     #
4184 #                                                                             #
4185 #                                                                             #
4186 #                                                                             #
4187 ###############################################################################
4188 #
4189 #
4190 void
4191 Get(ref,...)
4192   Image::Magick ref=NO_INIT
4193   ALIAS:
4194     GetAttributes = 1
4195     GetAttribute  = 2
4196     get           = 3
4197     getattributes = 4
4198     getattribute  = 5
4199   PPCODE:
4200   {
4201     char
4202       *attribute,
4203       color[MaxTextExtent];
4204
4205     const char
4206       *value;
4207
4208     ExceptionInfo
4209       *exception;
4210
4211     Image
4212       *image;
4213
4214     long
4215       j;
4216
4217     register ssize_t
4218       i;
4219
4220     struct PackageInfo
4221       *info;
4222
4223     SV
4224       *perl_exception,
4225       *reference,
4226       *s;
4227
4228     PERL_UNUSED_VAR(ref);
4229     PERL_UNUSED_VAR(ix);
4230     exception=AcquireExceptionInfo();
4231     perl_exception=newSVpv("",0);
4232     if (sv_isobject(ST(0)) == 0)
4233       {
4234         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4235           PackageName);
4236         XSRETURN_EMPTY;
4237       }
4238     reference=SvRV(ST(0));
4239     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4240     if (image == (Image *) NULL && !info)
4241       XSRETURN_EMPTY;
4242     EXTEND(sp,items);
4243     for (i=1; i < items; i++)
4244     {
4245       attribute=(char *) SvPV(ST(i),na);
4246       s=NULL;
4247       switch (*attribute)
4248       {
4249         case 'A':
4250         case 'a':
4251         {
4252           if (LocaleCompare(attribute,"adjoin") == 0)
4253             {
4254               if (info)
4255                 s=newSViv((ssize_t) info->image_info->adjoin);
4256               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4257               continue;
4258             }
4259           if (LocaleCompare(attribute,"antialias") == 0)
4260             {
4261               if (info)
4262                 s=newSViv((ssize_t) info->image_info->antialias);
4263               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4264               continue;
4265             }
4266           if (LocaleCompare(attribute,"area") == 0)
4267             {
4268               s=newSViv(GetMagickResource(AreaResource));
4269               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4270               continue;
4271             }
4272           if (LocaleCompare(attribute,"attenuate") == 0)
4273             {
4274               const char
4275                 *value;
4276
4277               value=GetImageProperty(image,attribute);
4278               if (value != (const char *) NULL)
4279                 s=newSVpv(value,0);
4280               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4281               continue;
4282             }
4283           if (LocaleCompare(attribute,"authenticate") == 0)
4284             {
4285               if (info)
4286                 s=newSVpv(info->image_info->authenticate,0);
4287               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4288               continue;
4289             }
4290           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4291             attribute);
4292           break;
4293         }
4294         case 'B':
4295         case 'b':
4296         {
4297           if (LocaleCompare(attribute,"background") == 0)
4298             {
4299               if (image == (Image *) NULL)
4300                 break;
4301               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4302                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4303                 image->background_color.red,image->background_color.green,
4304                 image->background_color.blue,image->background_color.alpha);
4305               s=newSVpv(color,0);
4306               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4307               continue;
4308             }
4309           if (LocaleCompare(attribute,"base-columns") == 0)
4310             {
4311               if (image != (Image *) NULL)
4312                 s=newSViv((ssize_t) image->magick_columns);
4313               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4314               continue;
4315             }
4316           if (LocaleCompare(attribute,"base-filename") == 0)
4317             {
4318               if (image != (Image *) NULL)
4319                 s=newSVpv(image->magick_filename,0);
4320               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4321               continue;
4322             }
4323           if (LocaleCompare(attribute,"base-height") == 0)
4324             {
4325               if (image != (Image *) NULL)
4326                 s=newSViv((ssize_t) image->magick_rows);
4327               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4328               continue;
4329             }
4330           if (LocaleCompare(attribute,"base-rows") == 0)
4331             {
4332               if (image != (Image *) NULL)
4333                 s=newSViv((ssize_t) image->magick_rows);
4334               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4335               continue;
4336             }
4337           if (LocaleCompare(attribute,"base-width") == 0)
4338             {
4339               if (image != (Image *) NULL)
4340                 s=newSViv((ssize_t) image->magick_columns);
4341               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4342               continue;
4343             }
4344           if (LocaleCompare(attribute,"bias") == 0)
4345             {
4346               if (image != (Image *) NULL)
4347                 s=newSVnv(image->bias);
4348               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4349               continue;
4350             }
4351           if (LocaleCompare(attribute,"blue-primary") == 0)
4352             {
4353               if (image == (Image *) NULL)
4354                 break;
4355               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4356                 image->chromaticity.blue_primary.x,
4357                 image->chromaticity.blue_primary.y);
4358               s=newSVpv(color,0);
4359               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4360               continue;
4361             }
4362           if (LocaleCompare(attribute,"bordercolor") == 0)
4363             {
4364               if (image == (Image *) NULL)
4365                 break;
4366               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4367                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4368                 image->border_color.red,image->border_color.green,
4369                 image->border_color.blue,image->border_color.alpha);
4370               s=newSVpv(color,0);
4371               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4372               continue;
4373             }
4374           if (LocaleCompare(attribute,"bounding-box") == 0)
4375             {
4376               char
4377                 geometry[MaxTextExtent];
4378
4379               RectangleInfo
4380                 page;
4381
4382               if (image == (Image *) NULL)
4383                 break;
4384               page=GetImageBoundingBox(image,&image->exception);
4385               (void) FormatLocaleString(geometry,MaxTextExtent,
4386                 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4387                 page.height,(double) page.x,(double) page.y);
4388               s=newSVpv(geometry,0);
4389               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4390               continue;
4391             }
4392           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4393             attribute);
4394           break;
4395         }
4396         case 'C':
4397         case 'c':
4398         {
4399           if (LocaleCompare(attribute,"class") == 0)
4400             {
4401               if (image == (Image *) NULL)
4402                 break;
4403               s=newSViv(image->storage_class);
4404               (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4405                 image->storage_class));
4406               SvIOK_on(s);
4407               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4408               continue;
4409             }
4410           if (LocaleCompare(attribute,"clip-mask") == 0)
4411             {
4412               if (image != (Image *) NULL)
4413                 {
4414                   SV
4415                     *sv;
4416
4417                   sv=NULL;
4418                   if (image->mask == (Image *) NULL)
4419                     ClipImage(image,exception);
4420                   if (image->mask != (Image *) NULL)
4421                     {
4422                       AddImageToRegistry(sv,image->mask);
4423                       s=sv_bless(newRV(sv),SvSTASH(reference));
4424                     }
4425                 }
4426               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4427               continue;
4428             }
4429           if (LocaleCompare(attribute,"clip-path") == 0)
4430             {
4431               if (image != (Image *) NULL)
4432                 {
4433                   SV
4434                     *sv;
4435
4436                   sv=NULL;
4437                   if (image->clip_mask == (Image *) NULL)
4438                     ClipImage(image,exception);
4439                   if (image->clip_mask != (Image *) NULL)
4440                     {
4441                       AddImageToRegistry(sv,image->clip_mask);
4442                       s=sv_bless(newRV(sv),SvSTASH(reference));
4443                     }
4444                 }
4445               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4446               continue;
4447             }
4448           if (LocaleCompare(attribute,"compression") == 0)
4449             {
4450               j=info ? info->image_info->compression : image ?
4451                 image->compression : UndefinedCompression;
4452               if (info)
4453                 if (info->image_info->compression == UndefinedCompression)
4454                   j=image->compression;
4455               s=newSViv(j);
4456               (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4457                 j));
4458               SvIOK_on(s);
4459               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4460               continue;
4461             }
4462           if (LocaleCompare(attribute,"colorspace") == 0)
4463             {
4464               j=image ? image->colorspace : RGBColorspace;
4465               s=newSViv(j);
4466               (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4467                 j));
4468               SvIOK_on(s);
4469               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4470               continue;
4471             }
4472           if (LocaleCompare(attribute,"colors") == 0)
4473             {
4474               if (image != (Image *) NULL)
4475                 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4476                   &image->exception));
4477               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4478               continue;
4479             }
4480           if (LocaleNCompare(attribute,"colormap",8) == 0)
4481             {
4482               int
4483                 items;
4484
4485               if (image == (Image *) NULL || !image->colormap)
4486                 break;
4487               j=0;
4488               items=sscanf(attribute,"%*[^[][%ld",&j);
4489               (void) items;
4490               if (j > (ssize_t) image->colors)
4491                 j%=image->colors;
4492               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4493                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4494                 image->colormap[j].red,image->colormap[j].green,
4495                 image->colormap[j].blue,image->colormap[j].alpha);
4496               s=newSVpv(color,0);
4497               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4498               continue;
4499             }
4500           if (LocaleCompare(attribute,"columns") == 0)
4501             {
4502               if (image != (Image *) NULL)
4503                 s=newSViv((ssize_t) image->columns);
4504               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4505               continue;
4506             }
4507           if (LocaleCompare(attribute,"comment") == 0)
4508             {
4509               const char
4510                 *value;
4511
4512               value=GetImageProperty(image,attribute);
4513               if (value != (const char *) NULL)
4514                 s=newSVpv(value,0);
4515               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4516               continue;
4517             }
4518           if (LocaleCompare(attribute,"copyright") == 0)
4519             {
4520               s=newSVpv(GetMagickCopyright(),0);
4521               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4522               continue;
4523             }
4524           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4525             attribute);
4526           break;
4527         }
4528         case 'D':
4529         case 'd':
4530         {
4531           if (LocaleCompare(attribute,"density") == 0)
4532             {
4533               char
4534                 geometry[MaxTextExtent];
4535
4536               if (image == (Image *) NULL)
4537                 break;
4538               (void) FormatLocaleString(geometry,MaxTextExtent,"%.15gx%.15g",
4539                 image->x_resolution,image->y_resolution);
4540               s=newSVpv(geometry,0);
4541               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4542               continue;
4543             }
4544           if (LocaleCompare(attribute,"delay") == 0)
4545             {
4546               if (image != (Image *) NULL)
4547                 s=newSViv((ssize_t) image->delay);
4548               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4549               continue;
4550             }
4551           if (LocaleCompare(attribute,"depth") == 0)
4552             {
4553               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4554               if (image != (Image *) NULL)
4555                 s=newSViv((ssize_t) GetImageDepth(image,&image->exception));
4556               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4557               continue;
4558             }
4559           if (LocaleCompare(attribute,"directory") == 0)
4560             {
4561               if (image && image->directory)
4562                 s=newSVpv(image->directory,0);
4563               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4564               continue;
4565             }
4566           if (LocaleCompare(attribute,"dispose") == 0)
4567             {
4568               if (image == (Image *) NULL)
4569                 break;
4570
4571               s=newSViv(image->dispose);
4572               (void) sv_setpv(s,
4573                 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
4574               SvIOK_on(s);
4575               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4576               continue;
4577             }
4578           if (LocaleCompare(attribute,"disk") == 0)
4579             {
4580               s=newSViv(GetMagickResource(DiskResource));
4581               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4582               continue;
4583             }
4584           if (LocaleCompare(attribute,"dither") == 0)
4585             {
4586               if (info)
4587                 s=newSViv((ssize_t) info->image_info->dither);
4588               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4589               continue;
4590             }
4591           if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4592             {
4593               if (info && info->image_info->server_name)
4594                 s=newSVpv(info->image_info->server_name,0);
4595               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4596               continue;
4597             }
4598           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4599             attribute);
4600           break;
4601         }
4602         case 'E':
4603         case 'e':
4604         {
4605           if (LocaleCompare(attribute,"elapsed-time") == 0)
4606             {
4607               if (image != (Image *) NULL)
4608                 s=newSVnv(GetElapsedTime(&image->timer));
4609               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4610               continue;
4611             }
4612           if (LocaleCompare(attribute,"endian") == 0)
4613             {
4614               j=info ? info->image_info->endian : image ? image->endian :
4615                 UndefinedEndian;
4616               s=newSViv(j);
4617               (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
4618               SvIOK_on(s);
4619               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4620               continue;
4621             }
4622           if (LocaleCompare(attribute,"error") == 0)
4623             {
4624               if (image != (Image *) NULL)
4625                 s=newSVnv(image->error.mean_error_per_pixel);
4626               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4627               continue;
4628             }
4629           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4630             attribute);
4631           break;
4632         }
4633         case 'F':
4634         case 'f':
4635         {
4636           if (LocaleCompare(attribute,"filesize") == 0)
4637             {
4638               if (image != (Image *) NULL)
4639                 s=newSViv((ssize_t) GetBlobSize(image));
4640               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4641               continue;
4642             }
4643           if (LocaleCompare(attribute,"filename") == 0)
4644             {
4645               if (info && info->image_info->filename &&
4646                   *info->image_info->filename)
4647                 s=newSVpv(info->image_info->filename,0);
4648               if (image != (Image *) NULL)
4649                 s=newSVpv(image->filename,0);
4650               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4651               continue;
4652             }
4653           if (LocaleCompare(attribute,"filter") == 0)
4654             {
4655               s=image ? newSViv(image->filter) : newSViv(0);
4656               (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
4657                 image->filter));
4658               SvIOK_on(s);
4659               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4660               continue;
4661             }
4662           if (LocaleCompare(attribute,"font") == 0)
4663             {
4664               if (info && info->image_info->font)
4665                 s=newSVpv(info->image_info->font,0);
4666               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4667               continue;
4668             }
4669           if (LocaleCompare(attribute,"foreground") == 0)
4670             continue;
4671           if (LocaleCompare(attribute,"format") == 0)
4672             {
4673               const MagickInfo
4674                 *magick_info;
4675
4676               magick_info=(const MagickInfo *) NULL;
4677               if (info && (*info->image_info->magick != '\0'))
4678                 magick_info=GetMagickInfo(info->image_info->magick,exception);
4679               if (image != (Image *) NULL)
4680                 magick_info=GetMagickInfo(image->magick,&image->exception);
4681               if ((magick_info != (const MagickInfo *) NULL) &&
4682                   (*magick_info->description != '\0'))
4683                 s=newSVpv((char *) magick_info->description,0);
4684               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4685               continue;
4686             }
4687           if (LocaleCompare(attribute,"fuzz") == 0)
4688             {
4689               if (info)
4690                 s=newSVnv(info->image_info->fuzz);
4691               if (image != (Image *) NULL)
4692                 s=newSVnv(image->fuzz);
4693               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4694               continue;
4695             }
4696           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4697             attribute);
4698           break;
4699         }
4700         case 'G':
4701         case 'g':
4702         {
4703           if (LocaleCompare(attribute,"gamma") == 0)
4704             {
4705               if (image != (Image *) NULL)
4706                 s=newSVnv(image->gamma);
4707               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4708               continue;
4709             }
4710           if (LocaleCompare(attribute,"geometry") == 0)
4711             {
4712               if (image && image->geometry)
4713                 s=newSVpv(image->geometry,0);
4714               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4715               continue;
4716             }
4717           if (LocaleCompare(attribute,"gravity") == 0)
4718             {
4719               s=image ? newSViv(image->gravity) : newSViv(0);
4720               (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
4721                 image->gravity));
4722               SvIOK_on(s);
4723               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4724               continue;
4725             }
4726           if (LocaleCompare(attribute,"green-primary") == 0)
4727             {
4728               if (image == (Image *) NULL)
4729                 break;
4730               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4731                 image->chromaticity.green_primary.x,
4732                 image->chromaticity.green_primary.y);
4733               s=newSVpv(color,0);
4734               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4735               continue;
4736             }
4737           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4738             attribute);
4739           break;
4740         }
4741         case 'H':
4742         case 'h':
4743         {
4744           if (LocaleCompare(attribute,"height") == 0)
4745             {
4746               if (image != (Image *) NULL)
4747                 s=newSViv((ssize_t) image->rows);
4748               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4749               continue;
4750             }
4751           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4752             attribute);
4753           break;
4754         }
4755         case 'I':
4756         case 'i':
4757         {
4758           if (LocaleCompare(attribute,"icc") == 0)
4759             {
4760               if (image != (Image *) NULL)
4761                 {
4762                   const StringInfo
4763                     *profile;
4764
4765                   profile=GetImageProfile(image,"icc");
4766                   if (profile != (StringInfo *) NULL)
4767                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4768                       GetStringInfoLength(profile));
4769                 }
4770               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4771               continue;
4772             }
4773           if (LocaleCompare(attribute,"icm") == 0)
4774             {
4775               if (image != (Image *) NULL)
4776                 {
4777                   const StringInfo
4778                     *profile;
4779
4780                   profile=GetImageProfile(image,"icm");
4781                   if (profile != (const StringInfo *) NULL)
4782                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4783                       GetStringInfoLength(profile));
4784                 }
4785               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4786               continue;
4787             }
4788           if (LocaleCompare(attribute,"id") == 0)
4789             {
4790               if (image != (Image *) NULL)
4791                 {
4792                   char
4793                     key[MaxTextExtent];
4794
4795                   MagickBooleanType
4796                     status;
4797
4798                   static ssize_t
4799                     id = 0;
4800
4801                   (void) FormatLocaleString(key,MaxTextExtent,"%.20g\n",(double)
4802                     id);
4803                   status=SetImageRegistry(ImageRegistryType,key,image,
4804                     &image->exception);
4805                   (void) status;
4806                   s=newSViv(id++);
4807                 }
4808               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4809               continue;
4810             }
4811           if (LocaleNCompare(attribute,"index",5) == 0)
4812             {
4813               char
4814                 name[MaxTextExtent];
4815
4816               int
4817                 items;
4818
4819               long
4820                 x,
4821                 y;
4822
4823               register const Quantum
4824                 *p;
4825
4826               CacheView
4827                 *image_view;
4828
4829               if (image == (Image *) NULL)
4830                 break;
4831               if (image->storage_class != PseudoClass)
4832                 break;
4833               x=0;
4834               y=0;
4835               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
4836               (void) items;
4837               image_view=AcquireCacheView(image);
4838               p=GetCacheViewVirtualPixels(image_view,x,y,1,1,&image->exception);
4839               if (p != (const Quantum *) NULL)
4840                 {
4841                   (void) FormatLocaleString(name,MaxTextExtent,QuantumFormat,
4842                     GetPixelIndex(image,p));
4843                   s=newSVpv(name,0);
4844                   PUSHs(s ? sv_2mortal(s) : &sv_undef);
4845                 }
4846               image_view=DestroyCacheView(image_view);
4847               continue;
4848             }
4849           if (LocaleCompare(attribute,"iptc") == 0)
4850             {
4851               if (image != (Image *) NULL)
4852                 {
4853                   const StringInfo
4854                     *profile;
4855
4856                   profile=GetImageProfile(image,"iptc");
4857                   if (profile != (const StringInfo *) NULL)
4858                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4859                       GetStringInfoLength(profile));
4860                 }
4861               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4862               continue;
4863             }
4864           if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
4865             {
4866               if (image != (Image *) NULL)
4867                 s=newSViv((ssize_t) image->iterations);
4868               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4869               continue;
4870             }
4871           if (LocaleCompare(attribute,"interlace") == 0)
4872             {
4873               j=info ? info->image_info->interlace : image ? image->interlace :
4874                 UndefinedInterlace;
4875               s=newSViv(j);
4876               (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
4877                 j));
4878               SvIOK_on(s);
4879               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4880               continue;
4881             }
4882           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4883             attribute);
4884           break;
4885         }
4886         case 'L':
4887         case 'l':
4888         {
4889           if (LocaleCompare(attribute,"label") == 0)
4890             {
4891               const char
4892                 *value;
4893
4894               if (image == (Image *) NULL)
4895                 break;
4896               value=GetImageProperty(image,"Label");
4897               if (value != (const char *) NULL)
4898                 s=newSVpv(value,0);
4899               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4900               continue;
4901             }
4902           if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
4903             {
4904               if (image != (Image *) NULL)
4905                 s=newSViv((ssize_t) image->iterations);
4906               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4907               continue;
4908             }
4909           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4910             attribute);
4911           break;
4912         }
4913         case 'M':
4914         case 'm':
4915         {
4916           if (LocaleCompare(attribute,"magick") == 0)
4917             {
4918               if (info && *info->image_info->magick)
4919                 s=newSVpv(info->image_info->magick,0);
4920               if (image != (Image *) NULL)
4921                 s=newSVpv(image->magick,0);
4922               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4923               continue;
4924             }
4925           if (LocaleCompare(attribute,"map") == 0)
4926             {
4927               s=newSViv(GetMagickResource(MapResource));
4928               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4929               continue;
4930             }
4931           if (LocaleCompare(attribute,"maximum-error") == 0)
4932             {
4933               if (image != (Image *) NULL)
4934                 s=newSVnv(image->error.normalized_maximum_error);
4935               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4936               continue;
4937             }
4938           if (LocaleCompare(attribute,"memory") == 0)
4939             {
4940               s=newSViv(GetMagickResource(MemoryResource));
4941               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4942               continue;
4943             }
4944           if (LocaleCompare(attribute,"mean-error") == 0)
4945             {
4946               if (image != (Image *) NULL)
4947                 s=newSVnv(image->error.normalized_mean_error);
4948               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4949               continue;
4950             }
4951           if (LocaleCompare(attribute,"mime") == 0)
4952             {
4953               if (info && *info->image_info->magick)
4954                 s=newSVpv(MagickToMime(info->image_info->magick),0);
4955               if (image != (Image *) NULL)
4956                 s=newSVpv(MagickToMime(image->magick),0);
4957               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4958               continue;
4959             }
4960           if (LocaleCompare(attribute,"mattecolor") == 0)
4961             {
4962               if (image == (Image *) NULL)
4963                 break;
4964               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4965                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4966                 image->matte_color.red,image->matte_color.green,
4967                 image->matte_color.blue,image->matte_color.alpha);
4968               s=newSVpv(color,0);
4969               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4970               continue;
4971             }
4972           if (LocaleCompare(attribute,"matte") == 0)
4973             {
4974               if (image != (Image *) NULL)
4975                 s=newSViv((ssize_t) image->matte);
4976               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4977               continue;
4978             }
4979           if (LocaleCompare(attribute,"mime") == 0)
4980             {
4981               const char
4982                 *magick;
4983
4984               magick=NULL;
4985               if (info && *info->image_info->magick)
4986                 magick=info->image_info->magick;
4987               if (image != (Image *) NULL)
4988                 magick=image->magick;
4989               if (magick)
4990                 {
4991                   char
4992                     *mime;
4993
4994                   mime=MagickToMime(magick);
4995                   s=newSVpv(mime,0);
4996                   mime=(char *) RelinquishMagickMemory(mime);
4997                 }
4998               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4999               continue;
5000             }
5001           if (LocaleCompare(attribute,"monochrome") == 0)
5002             {
5003               if (image == (Image *) NULL)
5004                 continue;
5005               j=info ? info->image_info->monochrome :
5006                 IsImageMonochrome(image,&image->exception);
5007               s=newSViv(j);
5008               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5009               continue;
5010             }
5011           if (LocaleCompare(attribute,"montage") == 0)
5012             {
5013               if (image && image->montage)
5014                 s=newSVpv(image->montage,0);
5015               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5016               continue;
5017             }
5018           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5019             attribute);
5020           break;
5021         }
5022         case 'O':
5023         case 'o':
5024         {
5025           if (LocaleCompare(attribute,"orientation") == 0)
5026             {
5027               j=info ? info->image_info->orientation : image ?
5028                 image->orientation : UndefinedOrientation;
5029               s=newSViv(j);
5030               (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5031                 j));
5032               SvIOK_on(s);
5033               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5034               continue;
5035             }
5036           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5037             attribute);
5038           break;
5039         }
5040         case 'P':
5041         case 'p':
5042         {
5043           if (LocaleCompare(attribute,"page") == 0)
5044             {
5045               if (info && info->image_info->page)
5046                 s=newSVpv(info->image_info->page,0);
5047               if (image != (Image *) NULL)
5048                 {
5049                   char
5050                     geometry[MaxTextExtent];
5051
5052                   (void) FormatLocaleString(geometry,MaxTextExtent,
5053                     "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5054                     (double) image->page.height,(double) image->page.x,(double)
5055                     image->page.y);
5056                   s=newSVpv(geometry,0);
5057                 }
5058               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5059               continue;
5060             }
5061           if (LocaleCompare(attribute,"page.x") == 0)
5062             {
5063               if (image != (Image *) NULL)
5064                 s=newSViv((ssize_t) image->page.x);
5065               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5066               continue;
5067             }
5068           if (LocaleCompare(attribute,"page.y") == 0)
5069             {
5070               if (image != (Image *) NULL)
5071                 s=newSViv((ssize_t) image->page.y);
5072               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5073               continue;
5074             }
5075           if (LocaleNCompare(attribute,"pixel",5) == 0)
5076             {
5077               char
5078                 tuple[MaxTextExtent];
5079
5080               int
5081                 items;
5082
5083               long
5084                 x,
5085                 y;
5086
5087               register const Quantum
5088                 *p;
5089
5090               if (image == (Image *) NULL)
5091                 break;
5092               x=0;
5093               y=0;
5094               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5095               (void) items;
5096               p=GetVirtualPixels(image,x,y,1,1,exception);
5097               if (image->colorspace != CMYKColorspace)
5098                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5099                   QuantumFormat "," QuantumFormat "," QuantumFormat,
5100                   GetPixelRed(image,p),GetPixelGreen(image,p),
5101                   GetPixelBlue(image,p),GetPixelAlpha(image,p));
5102               else
5103                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5104                   QuantumFormat "," QuantumFormat "," QuantumFormat ","
5105                   QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5106                   GetPixelBlue(image,p),GetPixelBlack(image,p),
5107                   GetPixelAlpha(image,p));
5108               s=newSVpv(tuple,0);
5109               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5110               continue;
5111             }
5112           if (LocaleCompare(attribute,"pointsize") == 0)
5113             {
5114               if (info)
5115                 s=newSViv((ssize_t) info->image_info->pointsize);
5116               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5117               continue;
5118             }
5119           if (LocaleCompare(attribute,"preview") == 0)
5120             {
5121               s=newSViv(info->image_info->preview_type);
5122               (void) sv_setpv(s,CommandOptionToMnemonic(MagickPreviewOptions,
5123                 info->image_info->preview_type));
5124               SvIOK_on(s);
5125               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5126               continue;
5127             }
5128           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5129             attribute);
5130           break;
5131         }
5132         case 'Q':
5133         case 'q':
5134         {
5135           if (LocaleCompare(attribute,"quality") == 0)
5136             {
5137               if (info)
5138                 s=newSViv((ssize_t) info->image_info->quality);
5139               if (image != (Image *) NULL)
5140                 s=newSViv((ssize_t) image->quality);
5141               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5142               continue;
5143             }
5144           if (LocaleCompare(attribute,"quantum") == 0)
5145             {
5146               if (info)
5147                 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5148               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5149               continue;
5150             }
5151           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5152             attribute);
5153           break;
5154         }
5155         case 'R':
5156         case 'r':
5157         {
5158           if (LocaleCompare(attribute,"rendering-intent") == 0)
5159             {
5160               s=newSViv(image->rendering_intent);
5161               (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5162                 image->rendering_intent));
5163               SvIOK_on(s);
5164               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5165               continue;
5166             }
5167           if (LocaleCompare(attribute,"red-primary") == 0)
5168             {
5169               if (image == (Image *) NULL)
5170                 break;
5171               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5172                 image->chromaticity.red_primary.x,
5173                 image->chromaticity.red_primary.y);
5174               s=newSVpv(color,0);
5175               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5176               continue;
5177             }
5178           if (LocaleCompare(attribute,"rows") == 0)
5179             {
5180               if (image != (Image *) NULL)
5181                 s=newSViv((ssize_t) image->rows);
5182               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5183               continue;
5184             }
5185           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5186             attribute);
5187           break;
5188         }
5189         case 'S':
5190         case 's':
5191         {
5192           if (LocaleCompare(attribute,"sampling-factor") == 0)
5193             {
5194               if (info && info->image_info->sampling_factor)
5195                 s=newSVpv(info->image_info->sampling_factor,0);
5196               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5197               continue;
5198             }
5199           if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5200             {
5201               if (info && info->image_info->server_name)
5202                 s=newSVpv(info->image_info->server_name,0);
5203               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5204               continue;
5205             }
5206           if (LocaleCompare(attribute,"size") == 0)
5207             {
5208               if (info && info->image_info->size)
5209                 s=newSVpv(info->image_info->size,0);
5210               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5211               continue;
5212             }
5213           if (LocaleCompare(attribute,"scene") == 0)
5214             {
5215               if (image != (Image *) NULL)
5216                 s=newSViv((ssize_t) image->scene);
5217               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5218               continue;
5219             }
5220           if (LocaleCompare(attribute,"scenes") == 0)
5221             {
5222               if (image != (Image *) NULL)
5223                 s=newSViv((ssize_t) info->image_info->number_scenes);
5224               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5225               continue;
5226             }
5227           if (LocaleCompare(attribute,"signature") == 0)
5228             {
5229               const char
5230                 *value;
5231
5232               if (image == (Image *) NULL)
5233                 break;
5234               (void) SignatureImage(image,exception);
5235               value=GetImageProperty(image,"Signature");
5236               if (value != (const char *) NULL)
5237                 s=newSVpv(value,0);
5238               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5239               continue;
5240             }
5241           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5242             attribute);
5243           break;
5244         }
5245         case 'T':
5246         case 't':
5247         {
5248           if (LocaleCompare(attribute,"taint") == 0)
5249             {
5250               if (image != (Image *) NULL)
5251                 s=newSViv((ssize_t) IsTaintImage(image));
5252               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5253               continue;
5254             }
5255           if (LocaleCompare(attribute,"texture") == 0)
5256             {
5257               if (info && info->image_info->texture)
5258                 s=newSVpv(info->image_info->texture,0);
5259               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5260               continue;
5261             }
5262           if (LocaleCompare(attribute,"total-ink-density") == 0)
5263             {
5264               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5265               if (image != (Image *) NULL)
5266                 s=newSVnv(GetImageTotalInkDensity(image));
5267               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5268               continue;
5269             }
5270           if (LocaleCompare(attribute,"transparent-color") == 0)
5271             {
5272               if (image == (Image *) NULL)
5273                 break;
5274               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
5275                 QuantumFormat "," QuantumFormat "," QuantumFormat,
5276                 image->transparent_color.red,image->transparent_color.green,
5277                 image->transparent_color.blue,image->transparent_color.alpha);
5278               s=newSVpv(color,0);
5279               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5280               continue;
5281             }
5282           if (LocaleCompare(attribute,"type") == 0)
5283             {
5284               if (image == (Image *) NULL)
5285                 break;
5286               j=(ssize_t) GetImageType(image,&image->exception);
5287               s=newSViv(j);
5288               (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5289               SvIOK_on(s);
5290               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5291               continue;
5292             }
5293           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5294             attribute);
5295           break;
5296         }
5297         case 'U':
5298         case 'u':
5299         {
5300           if (LocaleCompare(attribute,"units") == 0)
5301             {
5302               j=info ? info->image_info->units : image ? image->units :
5303                 UndefinedResolution;
5304               if (info && (info->image_info->units == UndefinedResolution))
5305                 if (image)
5306                   j=image->units;
5307               if (j == UndefinedResolution)
5308                 s=newSVpv("undefined units",0);
5309               else
5310                 if (j == PixelsPerInchResolution)
5311                   s=newSVpv("pixels / inch",0);
5312                 else
5313                   s=newSVpv("pixels / centimeter",0);
5314               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5315               continue;
5316             }
5317           if (LocaleCompare(attribute,"user-time") == 0)
5318             {
5319               if (image != (Image *) NULL)
5320                 s=newSVnv(GetUserTime(&image->timer));
5321               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5322               continue;
5323             }
5324           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5325             attribute);
5326           break;
5327         }
5328         case 'V':
5329         case 'v':
5330         {
5331           if (LocaleCompare(attribute,"verbose") == 0)
5332             {
5333               if (info)
5334                 s=newSViv((ssize_t) info->image_info->verbose);
5335               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5336               continue;
5337             }
5338           if (LocaleCompare(attribute,"version") == 0)
5339             {
5340               s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5341               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5342               continue;
5343             }
5344           if (LocaleCompare(attribute,"view") == 0)
5345             {
5346               if (info && info->image_info->view)
5347                 s=newSVpv(info->image_info->view,0);
5348               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5349               continue;
5350             }
5351           if (LocaleCompare(attribute,"virtual-pixel") == 0)
5352             {
5353               if (image == (Image *) NULL)
5354                 break;
5355               j=(ssize_t) GetImageVirtualPixelMethod(image);
5356               s=newSViv(j);
5357               (void) sv_setpv(s,CommandOptionToMnemonic(
5358                 MagickVirtualPixelOptions,j));
5359               SvIOK_on(s);
5360               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5361               continue;
5362             }
5363           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5364             attribute);
5365           break;
5366         }
5367         case 'W':
5368         case 'w':
5369         {
5370           if (LocaleCompare(attribute,"white-point") == 0)
5371             {
5372               if (image == (Image *) NULL)
5373                 break;
5374               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5375                 image->chromaticity.white_point.x,
5376                 image->chromaticity.white_point.y);
5377               s=newSVpv(color,0);
5378               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5379               continue;
5380             }
5381           if (LocaleCompare(attribute,"width") == 0)
5382             {
5383               if (image != (Image *) NULL)
5384                 s=newSViv((ssize_t) image->columns);
5385               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5386               continue;
5387             }
5388           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5389              attribute);
5390           break;
5391         }
5392         case 'X':
5393         case 'x':
5394         {
5395           if (LocaleCompare(attribute,"x-resolution") == 0)
5396             {
5397               if (image != (Image *) NULL)
5398                 s=newSVnv(image->x_resolution);
5399               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5400               continue;
5401             }
5402           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5403             attribute);
5404           break;
5405         }
5406         case 'Y':
5407         case 'y':
5408         {
5409           if (LocaleCompare(attribute,"y-resolution") == 0)
5410             {
5411               if (image != (Image *) NULL)
5412                 s=newSVnv(image->y_resolution);
5413               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5414               continue;
5415             }
5416           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5417             attribute);
5418           break;
5419         }
5420         default:
5421           break;
5422       }
5423       if (image == (Image *) NULL)
5424         ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5425           attribute)
5426       else
5427         {
5428           value=GetImageProperty(image,attribute);
5429           if (value != (const char *) NULL)
5430             {
5431               s=newSVpv(value,0);
5432               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5433             }
5434           else
5435             if (*attribute != '%')
5436               ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5437                 attribute)
5438             else
5439               {
5440                  char
5441                    *meta;
5442
5443                  meta=InterpretImageProperties(info ? info->image_info :
5444                    (ImageInfo *) NULL,image,attribute,exception);
5445                  s=newSVpv(meta,0);
5446                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5447                  meta=(char *) RelinquishMagickMemory(meta);
5448               }
5449         }
5450     }
5451     exception=DestroyExceptionInfo(exception);
5452     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5453   }
5454 \f
5455 #
5456 ###############################################################################
5457 #                                                                             #
5458 #                                                                             #
5459 #                                                                             #
5460 #   G e t A u t h e n t i c P i x e l s                                       #
5461 #                                                                             #
5462 #                                                                             #
5463 #                                                                             #
5464 ###############################################################################
5465 #
5466 #
5467 void *
5468 GetAuthenticPixels(ref,...)
5469   Image::Magick ref = NO_INIT
5470   ALIAS:
5471     getauthenticpixels = 1
5472     GetImagePixels = 2
5473     getimagepixels = 3
5474   CODE:
5475   {
5476     char
5477       *attribute;
5478
5479     ExceptionInfo
5480       *exception;
5481
5482     Image
5483       *image;
5484
5485     RectangleInfo
5486       region;
5487
5488     ssize_t
5489       i;
5490
5491     struct PackageInfo
5492       *info;
5493
5494     SV
5495       *perl_exception,
5496       *reference;
5497
5498     void
5499       *blob = NULL;
5500
5501     PERL_UNUSED_VAR(ref);
5502     PERL_UNUSED_VAR(ix);
5503     exception=AcquireExceptionInfo();
5504     perl_exception=newSVpv("",0);
5505     if (sv_isobject(ST(0)) == 0)
5506       {
5507         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5508           PackageName);
5509         goto PerlException;
5510       }
5511     reference=SvRV(ST(0));
5512
5513     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5514     if (image == (Image *) NULL)
5515       {
5516         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5517           PackageName);
5518         goto PerlException;
5519       }
5520
5521     region.x=0;
5522     region.y=0;
5523     region.width=image->columns;
5524     region.height=1;
5525     if (items == 1)
5526       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5527     for (i=2; i < items; i+=2)
5528     {
5529       attribute=(char *) SvPV(ST(i-1),na);
5530       switch (*attribute)
5531       {
5532         case 'g':
5533         case 'G':
5534         {
5535           if (LocaleCompare(attribute,"geometry") == 0)
5536             {
5537               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5538               break;
5539             }
5540           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5541             attribute);
5542           break;
5543         }
5544         case 'H':
5545         case 'h':
5546         {
5547           if (LocaleCompare(attribute,"height") == 0)
5548             {
5549               region.height=SvIV(ST(i));
5550               continue;
5551             }
5552           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5553             attribute);
5554           break;
5555         }
5556         case 'X':
5557         case 'x':
5558         {
5559           if (LocaleCompare(attribute,"x") == 0)
5560             {
5561               region.x=SvIV(ST(i));
5562               continue;
5563             }
5564           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5565             attribute);
5566           break;
5567         }
5568         case 'Y':
5569         case 'y':
5570         {
5571           if (LocaleCompare(attribute,"y") == 0)
5572             {
5573               region.y=SvIV(ST(i));
5574               continue;
5575             }
5576           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5577             attribute);
5578           break;
5579         }
5580         case 'W':
5581         case 'w':
5582         {
5583           if (LocaleCompare(attribute,"width") == 0)
5584             {
5585               region.width=SvIV(ST(i));
5586               continue;
5587             }
5588           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5589             attribute);
5590           break;
5591         }
5592       }
5593     }
5594     blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5595       region.height,exception);
5596     if (blob != (void *) NULL)
5597       goto PerlEnd;
5598
5599   PerlException:
5600     InheritPerlException(exception,perl_exception);
5601     exception=DestroyExceptionInfo(exception);
5602     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5603
5604   PerlEnd:
5605     RETVAL = blob;
5606   }
5607   OUTPUT:
5608     RETVAL
5609 \f
5610 #
5611 ###############################################################################
5612 #                                                                             #
5613 #                                                                             #
5614 #                                                                             #
5615 #   G e t V i r t u a l P i x e l s                                           #
5616 #                                                                             #
5617 #                                                                             #
5618 #                                                                             #
5619 ###############################################################################
5620 #
5621 #
5622 void *
5623 GetVirtualPixels(ref,...)
5624   Image::Magick ref = NO_INIT
5625   ALIAS:
5626     getvirtualpixels = 1
5627     AcquireImagePixels = 2
5628     acquireimagepixels = 3
5629   CODE:
5630   {
5631     char
5632       *attribute;
5633
5634     const void
5635       *blob = NULL;
5636
5637     ExceptionInfo
5638       *exception;
5639
5640     Image
5641       *image;
5642
5643     RectangleInfo
5644       region;
5645
5646     ssize_t
5647       i;
5648
5649     struct PackageInfo
5650       *info;
5651
5652     SV
5653       *perl_exception,
5654       *reference;
5655
5656     PERL_UNUSED_VAR(ref);
5657     PERL_UNUSED_VAR(ix);
5658     exception=AcquireExceptionInfo();
5659     perl_exception=newSVpv("",0);
5660     if (sv_isobject(ST(0)) == 0)
5661       {
5662         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5663           PackageName);
5664         goto PerlException;
5665       }
5666     reference=SvRV(ST(0));
5667
5668     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5669     if (image == (Image *) NULL)
5670       {
5671         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5672           PackageName);
5673         goto PerlException;
5674       }
5675
5676     region.x=0;
5677     region.y=0;
5678     region.width=image->columns;
5679     region.height=1;
5680     if (items == 1)
5681       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5682     for (i=2; i < items; i+=2)
5683     {
5684       attribute=(char *) SvPV(ST(i-1),na);
5685       switch (*attribute)
5686       {
5687         case 'g':
5688         case 'G':
5689         {
5690           if (LocaleCompare(attribute,"geometry") == 0)
5691             {
5692               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5693               break;
5694             }
5695           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5696             attribute);
5697           break;
5698         }
5699         case 'H':
5700         case 'h':
5701         {
5702           if (LocaleCompare(attribute,"height") == 0)
5703             {
5704               region.height=SvIV(ST(i));
5705               continue;
5706             }
5707           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5708             attribute);
5709           break;
5710         }
5711         case 'X':
5712         case 'x':
5713         {
5714           if (LocaleCompare(attribute,"x") == 0)
5715             {
5716               region.x=SvIV(ST(i));
5717               continue;
5718             }
5719           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5720             attribute);
5721           break;
5722         }
5723         case 'Y':
5724         case 'y':
5725         {
5726           if (LocaleCompare(attribute,"y") == 0)
5727             {
5728               region.y=SvIV(ST(i));
5729               continue;
5730             }
5731           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5732             attribute);
5733           break;
5734         }
5735         case 'W':
5736         case 'w':
5737         {
5738           if (LocaleCompare(attribute,"width") == 0)
5739             {
5740               region.width=SvIV(ST(i));
5741               continue;
5742             }
5743           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5744             attribute);
5745           break;
5746         }
5747       }
5748     }
5749     blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
5750       region.height,exception);
5751     if (blob != (void *) NULL)
5752       goto PerlEnd;
5753
5754   PerlException:
5755     InheritPerlException(exception,perl_exception);
5756     exception=DestroyExceptionInfo(exception);
5757     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5758
5759   PerlEnd:
5760     RETVAL = (void *) blob;
5761   }
5762   OUTPUT:
5763     RETVAL
5764 \f
5765 #
5766 ###############################################################################
5767 #                                                                             #
5768 #                                                                             #
5769 #                                                                             #
5770 #   G e t A u t h e n t i c M e t a c o n t e n t                             #
5771 #                                                                             #
5772 #                                                                             #
5773 #                                                                             #
5774 ###############################################################################
5775 #
5776 #
5777 void *
5778 GetAuthenticMetacontent(ref,...)
5779   Image::Magick ref = NO_INIT
5780   ALIAS:
5781     getauthenticmetacontent = 1
5782     GetMetacontent = 2
5783     getmetacontent = 3
5784   CODE:
5785   {
5786     ExceptionInfo
5787       *exception;
5788
5789     Image
5790       *image;
5791
5792     struct PackageInfo
5793       *info;
5794
5795     SV
5796       *perl_exception,
5797       *reference;
5798
5799     void
5800       *blob = NULL;
5801
5802     PERL_UNUSED_VAR(ref);
5803     PERL_UNUSED_VAR(ix);
5804     exception=AcquireExceptionInfo();
5805     perl_exception=newSVpv("",0);
5806     if (sv_isobject(ST(0)) == 0)
5807       {
5808         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5809           PackageName);
5810         goto PerlException;
5811       }
5812     reference=SvRV(ST(0));
5813
5814     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5815     if (image == (Image *) NULL)
5816       {
5817         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5818           PackageName);
5819         goto PerlException;
5820       }
5821
5822     blob=(void *) GetAuthenticMetacontent(image);
5823     if (blob != (void *) NULL)
5824       goto PerlEnd;
5825
5826   PerlException:
5827     InheritPerlException(exception,perl_exception);
5828     exception=DestroyExceptionInfo(exception);
5829     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5830
5831   PerlEnd:
5832     RETVAL = blob;
5833   }
5834   OUTPUT:
5835     RETVAL
5836 \f
5837 #
5838 ###############################################################################
5839 #                                                                             #
5840 #                                                                             #
5841 #                                                                             #
5842 #   G e t V i r t u a l M e t a c o n t e n t                                 #
5843 #                                                                             #
5844 #                                                                             #
5845 #                                                                             #
5846 ###############################################################################
5847 #
5848 #
5849 void *
5850 GetVirtualMetacontent(ref,...)
5851   Image::Magick ref = NO_INIT
5852   ALIAS:
5853     getvirtualmetacontent = 1
5854   CODE:
5855   {
5856     ExceptionInfo
5857       *exception;
5858
5859     Image
5860       *image;
5861
5862     struct PackageInfo
5863       *info;
5864
5865     SV
5866       *perl_exception,
5867       *reference;
5868
5869     void
5870       *blob = NULL;
5871
5872     PERL_UNUSED_VAR(ref);
5873     PERL_UNUSED_VAR(ix);
5874     exception=AcquireExceptionInfo();
5875     perl_exception=newSVpv("",0);
5876     if (sv_isobject(ST(0)) == 0)
5877       {
5878         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5879           PackageName);
5880         goto PerlException;
5881       }
5882     reference=SvRV(ST(0));
5883
5884     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5885     if (image == (Image *) NULL)
5886       {
5887         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5888           PackageName);
5889         goto PerlException;
5890       }
5891
5892     blob=(void *) GetVirtualMetacontent(image);
5893     if (blob != (void *) NULL)
5894       goto PerlEnd;
5895
5896   PerlException:
5897     InheritPerlException(exception,perl_exception);
5898     exception=DestroyExceptionInfo(exception);
5899     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5900
5901   PerlEnd:
5902     RETVAL = blob;
5903   }
5904   OUTPUT:
5905     RETVAL
5906 \f
5907 #
5908 ###############################################################################
5909 #                                                                             #
5910 #                                                                             #
5911 #                                                                             #
5912 #   H i s t o g r a m                                                         #
5913 #                                                                             #
5914 #                                                                             #
5915 #                                                                             #
5916 ###############################################################################
5917 #
5918 #
5919 void
5920 Histogram(ref,...)
5921   Image::Magick ref=NO_INIT
5922   ALIAS:
5923     HistogramImage = 1
5924     histogram      = 2
5925     histogramimage = 3
5926   PPCODE:
5927   {
5928     AV
5929       *av;
5930
5931     char
5932       message[MaxTextExtent];
5933
5934     PixelPacket
5935       *histogram;
5936
5937     ExceptionInfo
5938       *exception;
5939
5940     Image
5941       *image;
5942
5943     register ssize_t
5944       i;
5945
5946     ssize_t
5947       count;
5948
5949     struct PackageInfo
5950       *info;
5951
5952     SV
5953       *perl_exception,
5954       *reference;
5955
5956     size_t
5957       number_colors;
5958
5959     PERL_UNUSED_VAR(ref);
5960     PERL_UNUSED_VAR(ix);
5961     exception=AcquireExceptionInfo();
5962     perl_exception=newSVpv("",0);
5963     av=NULL;
5964     if (sv_isobject(ST(0)) == 0)
5965       {
5966         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5967           PackageName);
5968         goto PerlException;
5969       }
5970     reference=SvRV(ST(0));
5971     av=newAV();
5972     SvREFCNT_dec(av);
5973     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5974     if (image == (Image *) NULL)
5975       {
5976         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5977           PackageName);
5978         goto PerlException;
5979       }
5980     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
5981     count=0;
5982     for ( ; image; image=image->next)
5983     {
5984       histogram=GetImageHistogram(image,&number_colors,&image->exception);
5985       if (histogram == (PixelPacket *) NULL)
5986         continue;
5987       count+=(ssize_t) number_colors;
5988       EXTEND(sp,6*count);
5989       for (i=0; i < (ssize_t) number_colors; i++)
5990       {
5991         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
5992           histogram[i].red);
5993         PUSHs(sv_2mortal(newSVpv(message,0)));
5994         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
5995           histogram[i].green);
5996         PUSHs(sv_2mortal(newSVpv(message,0)));
5997         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
5998           histogram[i].blue);
5999         PUSHs(sv_2mortal(newSVpv(message,0)));
6000         if (image->colorspace == CMYKColorspace)
6001           {
6002             (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
6003               histogram[i].black);
6004             PUSHs(sv_2mortal(newSVpv(message,0)));
6005           }
6006         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
6007           histogram[i].alpha);
6008         PUSHs(sv_2mortal(newSVpv(message,0)));
6009         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
6010           histogram[i].count);
6011         PUSHs(sv_2mortal(newSVpv(message,0)));
6012       }
6013       histogram=(PixelPacket *) RelinquishMagickMemory(histogram);
6014     }
6015
6016   PerlException:
6017     InheritPerlException(exception,perl_exception);
6018     exception=DestroyExceptionInfo(exception);
6019     SvREFCNT_dec(perl_exception);
6020   }
6021 \f
6022 #
6023 ###############################################################################
6024 #                                                                             #
6025 #                                                                             #
6026 #                                                                             #
6027 #   G e t P i x e l                                                           #
6028 #                                                                             #
6029 #                                                                             #
6030 #                                                                             #
6031 ###############################################################################
6032 #
6033 #
6034 void
6035 GetPixel(ref,...)
6036   Image::Magick ref=NO_INIT
6037   ALIAS:
6038     getpixel = 1
6039     getPixel = 2
6040   PPCODE:
6041   {
6042     AV
6043       *av;
6044
6045     char
6046       *attribute;
6047
6048     ExceptionInfo
6049       *exception;
6050
6051     Image
6052       *image;
6053
6054     MagickBooleanType
6055       normalize;
6056
6057     RectangleInfo
6058       region;
6059
6060     register const Quantum
6061       *p;
6062
6063     register ssize_t
6064       i;
6065
6066     ssize_t
6067       option;
6068
6069     struct PackageInfo
6070       *info;
6071
6072     SV
6073       *perl_exception,
6074       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6075
6076     PERL_UNUSED_VAR(ref);
6077     PERL_UNUSED_VAR(ix);
6078     exception=AcquireExceptionInfo();
6079     perl_exception=newSVpv("",0);
6080     reference=SvRV(ST(0));
6081     av=(AV *) reference;
6082     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6083       exception);
6084     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6085     if (image == (Image *) NULL)
6086       {
6087         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6088           PackageName);
6089         goto PerlException;
6090       }
6091     normalize=MagickTrue;
6092     region.x=0;
6093     region.y=0;
6094     region.width=image->columns;
6095     region.height=1;
6096     if (items == 1)
6097       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6098     for (i=2; i < items; i+=2)
6099     {
6100       attribute=(char *) SvPV(ST(i-1),na);
6101       switch (*attribute)
6102       {
6103         case 'C':
6104         case 'c':
6105         {
6106           if (LocaleCompare(attribute,"channel") == 0)
6107             {
6108               ssize_t
6109                 option;
6110
6111               option=ParseChannelOption(SvPV(ST(i),na));
6112               if (option < 0)
6113                 {
6114                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6115                     SvPV(ST(i),na));
6116                   return;
6117                 }
6118               SetPixelChannelMap(image,(ChannelType) option);
6119               break;
6120             }
6121           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6122             attribute);
6123           break;
6124         }
6125         case 'g':
6126         case 'G':
6127         {
6128           if (LocaleCompare(attribute,"geometry") == 0)
6129             {
6130               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6131               break;
6132             }
6133           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6134             attribute);
6135           break;
6136         }
6137         case 'N':
6138         case 'n':
6139         {
6140           if (LocaleCompare(attribute,"normalize") == 0)
6141             {
6142               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6143                 SvPV(ST(i),na));
6144               if (option < 0)
6145                 {
6146                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6147                     SvPV(ST(i),na));
6148                   break;
6149                 }
6150              normalize=option != 0 ? MagickTrue : MagickFalse;
6151              break;
6152             }
6153           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6154             attribute);
6155           break;
6156         }
6157         case 'x':
6158         case 'X':
6159         {
6160           if (LocaleCompare(attribute,"x") == 0)
6161             {
6162               region.x=SvIV(ST(i));
6163               break;
6164             }
6165           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6166             attribute);
6167           break;
6168         }
6169         case 'y':
6170         case 'Y':
6171         {
6172           if (LocaleCompare(attribute,"y") == 0)
6173             {
6174               region.y=SvIV(ST(i));
6175               break;
6176             }
6177           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6178             attribute);
6179           break;
6180         }
6181         default:
6182         {
6183           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6184             attribute);
6185           break;
6186         }
6187       }
6188     }
6189     p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6190     if (p == (const Quantum *) NULL)
6191       PUSHs(&sv_undef);
6192     else
6193       {
6194         double
6195           scale;
6196
6197         scale=1.0;
6198         if (normalize != MagickFalse)
6199           scale=1.0/QuantumRange;
6200         if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
6201           PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6202         if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6203           PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6204         if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6205           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6206         if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6207             (image->colorspace == CMYKColorspace))
6208           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6209         if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
6210           PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6211       }
6212
6213   PerlException:
6214     InheritPerlException(exception,perl_exception);
6215     exception=DestroyExceptionInfo(exception);
6216     SvREFCNT_dec(perl_exception);
6217   }
6218 \f
6219 #
6220 ###############################################################################
6221 #                                                                             #
6222 #                                                                             #
6223 #                                                                             #
6224 #   G e t P i x e l s                                                         #
6225 #                                                                             #
6226 #                                                                             #
6227 #                                                                             #
6228 ###############################################################################
6229 #
6230 #
6231 void
6232 GetPixels(ref,...)
6233   Image::Magick ref=NO_INIT
6234   ALIAS:
6235     getpixels = 1
6236     getPixels = 2
6237   PPCODE:
6238   {
6239     AV
6240       *av;
6241
6242     char
6243       *attribute;
6244
6245     const char
6246       *map;
6247
6248     ExceptionInfo
6249       *exception;
6250
6251     Image
6252       *image;
6253
6254     MagickBooleanType
6255       normalize,
6256       status;
6257
6258     RectangleInfo
6259       region;
6260
6261     register ssize_t
6262       i;
6263
6264     ssize_t
6265       option;
6266
6267     struct PackageInfo
6268       *info;
6269
6270     SV
6271       *perl_exception,
6272       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6273
6274     PERL_UNUSED_VAR(ref);
6275     PERL_UNUSED_VAR(ix);
6276     exception=AcquireExceptionInfo();
6277     perl_exception=newSVpv("",0);
6278     reference=SvRV(ST(0));
6279     av=(AV *) reference;
6280     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6281       exception);
6282     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6283     if (image == (Image *) NULL)
6284       {
6285         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6286           PackageName);
6287         goto PerlException;
6288       }
6289     map="RGB";
6290     if (image->matte != MagickFalse)
6291       map="RGBA";
6292     if (image->colorspace == CMYKColorspace)
6293       {
6294         map="CMYK";
6295         if (image->matte != MagickFalse)
6296           map="CMYKA";
6297       }
6298     normalize=MagickFalse;
6299     region.x=0;
6300     region.y=0;
6301     region.width=image->columns;
6302     region.height=1;
6303     if (items == 1)
6304       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6305     for (i=2; i < items; i+=2)
6306     {
6307       attribute=(char *) SvPV(ST(i-1),na);
6308       switch (*attribute)
6309       {
6310         case 'g':
6311         case 'G':
6312         {
6313           if (LocaleCompare(attribute,"geometry") == 0)
6314             {
6315               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6316               break;
6317             }
6318           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6319             attribute);
6320           break;
6321         }
6322         case 'H':
6323         case 'h':
6324         {
6325           if (LocaleCompare(attribute,"height") == 0)
6326             {
6327               region.height=SvIV(ST(i));
6328               break;
6329             }
6330           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6331             attribute);
6332           break;
6333         }
6334         case 'M':
6335         case 'm':
6336         {
6337           if (LocaleCompare(attribute,"map") == 0)
6338             {
6339               map=SvPV(ST(i),na);
6340               break;
6341             }
6342           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6343             attribute);
6344           break;
6345         }
6346         case 'N':
6347         case 'n':
6348         {
6349           if (LocaleCompare(attribute,"normalize") == 0)
6350             {
6351               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6352                 SvPV(ST(i),na));
6353               if (option < 0)
6354                 {
6355                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6356                     SvPV(ST(i),na));
6357                   break;
6358                 }
6359              normalize=option != 0 ? MagickTrue : MagickFalse;
6360              break;
6361             }
6362           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6363             attribute);
6364           break;
6365         }
6366         case 'W':
6367         case 'w':
6368         {
6369           if (LocaleCompare(attribute,"width") == 0)
6370             {
6371               region.width=SvIV(ST(i));
6372               break;
6373             }
6374           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6375             attribute);
6376           break;
6377         }
6378         case 'x':
6379         case 'X':
6380         {
6381           if (LocaleCompare(attribute,"x") == 0)
6382             {
6383               region.x=SvIV(ST(i));
6384               break;
6385             }
6386           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6387             attribute);
6388           break;
6389         }
6390         case 'y':
6391         case 'Y':
6392         {
6393           if (LocaleCompare(attribute,"y") == 0)
6394             {
6395               region.y=SvIV(ST(i));
6396               break;
6397             }
6398           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6399             attribute);
6400           break;
6401         }
6402         default:
6403         {
6404           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6405             attribute);
6406           break;
6407         }
6408       }
6409     }
6410     if (normalize != MagickFalse)
6411       {
6412         float
6413           *pixels;
6414
6415         pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6416           region.height*sizeof(*pixels));
6417         if (pixels == (float *) NULL)
6418           {
6419             ThrowPerlException(exception,ResourceLimitError,
6420               "MemoryAllocationFailed",PackageName);
6421             goto PerlException;
6422           }
6423         status=ExportImagePixels(image,region.x,region.y,region.width,
6424           region.height,map,FloatPixel,pixels,exception);
6425         if (status == MagickFalse)
6426           PUSHs(&sv_undef);
6427         else
6428           {
6429             EXTEND(sp,strlen(map)*region.width*region.height);
6430             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6431               PUSHs(sv_2mortal(newSVnv(pixels[i])));
6432           }
6433         pixels=(float *) RelinquishMagickMemory(pixels);
6434       }
6435     else
6436       {
6437         Quantum
6438           *pixels;
6439
6440         pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6441           region.height*sizeof(*pixels));
6442         if (pixels == (Quantum *) NULL)
6443           {
6444             ThrowPerlException(exception,ResourceLimitError,
6445               "MemoryAllocationFailed",PackageName);
6446             goto PerlException;
6447           }
6448         status=ExportImagePixels(image,region.x,region.y,region.width,
6449           region.height,map,QuantumPixel,pixels,exception);
6450         if (status == MagickFalse)
6451           PUSHs(&sv_undef);
6452         else
6453           {
6454             EXTEND(sp,strlen(map)*region.width*region.height);
6455             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6456               PUSHs(sv_2mortal(newSViv(pixels[i])));
6457           }
6458         pixels=(Quantum *) RelinquishMagickMemory(pixels);
6459       }
6460
6461   PerlException:
6462     InheritPerlException(exception,perl_exception);
6463     exception=DestroyExceptionInfo(exception);
6464     SvREFCNT_dec(perl_exception);
6465   }
6466 \f
6467 #
6468 ###############################################################################
6469 #                                                                             #
6470 #                                                                             #
6471 #                                                                             #
6472 #   I m a g e T o B l o b                                                     #
6473 #                                                                             #
6474 #                                                                             #
6475 #                                                                             #
6476 ###############################################################################
6477 #
6478 #
6479 void
6480 ImageToBlob(ref,...)
6481   Image::Magick ref=NO_INIT
6482   ALIAS:
6483     ImageToBlob  = 1
6484     imagetoblob  = 2
6485     toblob       = 3
6486     blob         = 4
6487   PPCODE:
6488   {
6489     char
6490       filename[MaxTextExtent];
6491
6492     ExceptionInfo
6493       *exception;
6494
6495     Image
6496       *image,
6497       *next;
6498
6499     register ssize_t
6500       i;
6501
6502     struct PackageInfo
6503       *info,
6504       *package_info;
6505
6506     size_t
6507       length;
6508
6509     ssize_t
6510       scene;
6511
6512     SV
6513       *perl_exception,
6514       *reference;
6515
6516     void
6517       *blob;
6518
6519     PERL_UNUSED_VAR(ref);
6520     PERL_UNUSED_VAR(ix);
6521     exception=AcquireExceptionInfo();
6522     perl_exception=newSVpv("",0);
6523     package_info=(struct PackageInfo *) NULL;
6524     if (sv_isobject(ST(0)) == 0)
6525       {
6526         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6527           PackageName);
6528         goto PerlException;
6529       }
6530     reference=SvRV(ST(0));
6531     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6532     if (image == (Image *) NULL)
6533       {
6534         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6535           PackageName);
6536         goto PerlException;
6537       }
6538     package_info=ClonePackageInfo(info,exception);
6539     for (i=2; i < items; i+=2)
6540       SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6541     (void) CopyMagickString(filename,package_info->image_info->filename,
6542       MaxTextExtent);
6543     scene=0;
6544     for (next=image; next; next=next->next)
6545     {
6546       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
6547       next->scene=scene++;
6548     }
6549     SetImageInfo(package_info->image_info,(unsigned int)
6550       GetImageListLength(image),&image->exception);
6551     EXTEND(sp,(ssize_t) GetImageListLength(image));
6552     for ( ; image; image=image->next)
6553     {
6554       length=0;
6555       blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6556       if (blob != (char *) NULL)
6557         {
6558           PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6559           blob=(unsigned char *) RelinquishMagickMemory(blob);
6560         }
6561       if (package_info->image_info->adjoin)
6562         break;
6563     }
6564
6565   PerlException:
6566     if (package_info != (struct PackageInfo *) NULL)
6567       DestroyPackageInfo(package_info);
6568     InheritPerlException(exception,perl_exception);
6569     exception=DestroyExceptionInfo(exception);
6570     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6571   }
6572 \f
6573 #
6574 ###############################################################################
6575 #                                                                             #
6576 #                                                                             #
6577 #                                                                             #
6578 #   L a y e r s                                                               #
6579 #                                                                             #
6580 #                                                                             #
6581 #                                                                             #
6582 ###############################################################################
6583 #
6584 #
6585 void
6586 Layers(ref,...)
6587   Image::Magick ref=NO_INIT
6588   ALIAS:
6589     Layers                = 1
6590     layers           = 2
6591     OptimizeImageLayers   = 3
6592     optimizelayers        = 4
6593     optimizeimagelayers   = 5
6594   PPCODE:
6595   {
6596     AV
6597       *av;
6598
6599     char
6600       *attribute;
6601
6602     CompositeOperator
6603       compose;
6604
6605     ExceptionInfo
6606       *exception;
6607
6608     HV
6609       *hv;
6610
6611     Image
6612       *image,
6613       *layers;
6614
6615     ImageLayerMethod
6616       method;
6617
6618     register ssize_t
6619       i;
6620
6621     ssize_t
6622       option,
6623       sp;
6624
6625     struct PackageInfo
6626       *info;
6627
6628     SV
6629       *av_reference,
6630       *perl_exception,
6631       *reference,
6632       *rv,
6633       *sv;
6634
6635     PERL_UNUSED_VAR(ref);
6636     PERL_UNUSED_VAR(ix);
6637     exception=AcquireExceptionInfo();
6638     perl_exception=newSVpv("",0);
6639     sv=NULL;
6640     if (sv_isobject(ST(0)) == 0)
6641       {
6642         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6643           PackageName);
6644         goto PerlException;
6645       }
6646     reference=SvRV(ST(0));
6647     hv=SvSTASH(reference);
6648     av=newAV();
6649     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
6650     SvREFCNT_dec(av);
6651     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6652     if (image == (Image *) NULL)
6653       {
6654         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6655           PackageName);
6656         goto PerlException;
6657       }
6658     compose=image->compose;
6659     method=OptimizeLayer;
6660     for (i=2; i < items; i+=2)
6661     {
6662       attribute=(char *) SvPV(ST(i-1),na);
6663       switch (*attribute)
6664       {
6665         case 'C':
6666         case 'c':
6667         {
6668           if (LocaleCompare(attribute,"compose") == 0)
6669             {
6670               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
6671                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
6672               if (sp < 0)
6673                 {
6674                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6675                     SvPV(ST(i),na));
6676                   break;
6677                 }
6678               compose=(CompositeOperator) sp;
6679               break;
6680             }
6681           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6682             attribute);
6683           break;
6684         }
6685         case 'M':
6686         case 'm':
6687         {
6688           if (LocaleCompare(attribute,"method") == 0)
6689             {
6690               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
6691                 SvPV(ST(i),na));
6692               if (option < 0)
6693                 {
6694                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6695                     SvPV(ST(i),na));
6696                   break;
6697                 }
6698               method=(ImageLayerMethod) option;
6699               break;
6700             }
6701           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6702             attribute);
6703           break;
6704         }
6705         default:
6706         {
6707           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6708             attribute);
6709           break;
6710         }
6711       }
6712     }
6713     layers=(Image *) NULL;
6714     switch (method)
6715     {
6716       case CompareAnyLayer:
6717       case CompareClearLayer:
6718       case CompareOverlayLayer:
6719       default:
6720       {
6721         layers=CompareImagesLayers(image,method,exception);
6722         break;
6723       }
6724       case MergeLayer:
6725       case FlattenLayer:
6726       case MosaicLayer:
6727       {
6728         layers=MergeImageLayers(image,method,exception);
6729         break;
6730       }
6731       case DisposeLayer:
6732       {
6733         layers=DisposeImages(image,exception);
6734         break;
6735       }
6736       case OptimizeImageLayer:
6737       {
6738         layers=OptimizeImageLayers(image,exception);
6739         break;
6740       }
6741       case OptimizePlusLayer:
6742       {
6743         layers=OptimizePlusImageLayers(image,exception);
6744         break;
6745       }
6746       case OptimizeTransLayer:
6747       {
6748         OptimizeImageTransparency(image,exception);
6749         InheritException(&(image->exception),exception);
6750         break;
6751       }
6752       case RemoveDupsLayer:
6753       {
6754         RemoveDuplicateLayers(&image,exception);
6755         InheritException(&(image->exception),exception);
6756         break;
6757       }
6758       case RemoveZeroLayer:
6759       {
6760         RemoveZeroDelayLayers(&image,exception);
6761         InheritException(&(image->exception),exception);
6762         break;
6763       }
6764       case OptimizeLayer:
6765       {
6766         QuantizeInfo
6767           *quantize_info;
6768
6769         /*
6770           General Purpose, GIF Animation Optimizer.
6771         */
6772         layers=CoalesceImages(image,exception);
6773         if (layers == (Image *) NULL)
6774           break;
6775         InheritException(&(layers->exception),exception);
6776         image=layers;
6777         layers=OptimizeImageLayers(image,exception);
6778         if (layers == (Image *) NULL)
6779           break;
6780         InheritException(&(layers->exception),exception);
6781         image=DestroyImageList(image);
6782         image=layers;
6783         layers=(Image *) NULL;
6784         OptimizeImageTransparency(image,exception);
6785         InheritException(&(image->exception),exception);
6786         quantize_info=AcquireQuantizeInfo(info->image_info);
6787         (void) RemapImages(quantize_info,image,(Image *) NULL,exception);
6788         quantize_info=DestroyQuantizeInfo(quantize_info);
6789         break;
6790       }
6791       case CompositeLayer:
6792       {
6793         Image
6794           *source;
6795
6796         RectangleInfo
6797           geometry;
6798
6799         /*
6800           Split image sequence at the first 'NULL:' image.
6801         */
6802         source=image;
6803         while (source != (Image *) NULL)
6804         {
6805           source=GetNextImageInList(source);
6806           if ((source != (Image *) NULL) &&
6807               (LocaleCompare(source->magick,"NULL") == 0))
6808             break;
6809         }
6810         if (source != (Image *) NULL)
6811           {
6812             if ((GetPreviousImageInList(source) == (Image *) NULL) ||
6813                 (GetNextImageInList(source) == (Image *) NULL))
6814               source=(Image *) NULL;
6815             else
6816               {
6817                 /*
6818                   Separate the two lists, junk the null: image.
6819                 */
6820                 source=SplitImageList(source->previous);
6821                 DeleteImageFromList(&source);
6822               }
6823           }
6824         if (source == (Image *) NULL)
6825           {
6826             (void) ThrowMagickException(exception,GetMagickModule(),
6827               OptionError,"MissingNullSeparator","layers Composite");
6828             break;
6829           }
6830         /*
6831           Adjust offset with gravity and virtual canvas.
6832         */
6833         SetGeometry(image,&geometry);
6834         (void) ParseAbsoluteGeometry(image->geometry,&geometry);
6835         geometry.width=source->page.width != 0 ? source->page.width :
6836           source->columns;
6837         geometry.height=source->page.height != 0 ? source->page.height :
6838           source->rows;
6839         GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
6840           image->columns,image->page.height != 0 ? image->page.height :
6841           image->rows,image->gravity,&geometry);
6842         CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
6843         source=DestroyImageList(source);
6844         InheritException(&(image->exception),exception);
6845         break;
6846       }
6847     }
6848     if (layers != (Image *) NULL)
6849       {
6850         InheritException(&(layers->exception),exception);
6851         image=layers;
6852       }
6853     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
6854       goto PerlException;
6855     for ( ; image; image=image->next)
6856     {
6857       AddImageToRegistry(sv,image);
6858       rv=newRV(sv);
6859       av_push(av,sv_bless(rv,hv));
6860       SvREFCNT_dec(sv);
6861     }
6862     exception=DestroyExceptionInfo(exception);
6863     ST(0)=av_reference;
6864     SvREFCNT_dec(perl_exception);
6865     XSRETURN(1);
6866
6867   PerlException:
6868     InheritPerlException(exception,perl_exception);
6869     exception=DestroyExceptionInfo(exception);
6870     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
6871     SvPOK_on(perl_exception);
6872     ST(0)=sv_2mortal(perl_exception);
6873     XSRETURN(1);
6874   }
6875 \f
6876 #
6877 ###############################################################################
6878 #                                                                             #
6879 #                                                                             #
6880 #                                                                             #
6881 #   M a g i c k T o M i m e                                                   #
6882 #                                                                             #
6883 #                                                                             #
6884 #                                                                             #
6885 ###############################################################################
6886 #
6887 #
6888 SV *
6889 MagickToMime(ref,name)
6890   Image::Magick ref=NO_INIT
6891   char *name
6892   ALIAS:
6893     magicktomime = 1
6894   CODE:
6895   {
6896     char
6897       *mime;
6898
6899     PERL_UNUSED_VAR(ref);
6900     PERL_UNUSED_VAR(ix);
6901     mime=MagickToMime(name);
6902     RETVAL=newSVpv(mime,0);
6903     mime=(char *) RelinquishMagickMemory(mime);
6904   }
6905   OUTPUT:
6906     RETVAL
6907 \f
6908 #
6909 ###############################################################################
6910 #                                                                             #
6911 #                                                                             #
6912 #                                                                             #
6913 #   M o g r i f y                                                             #
6914 #                                                                             #
6915 #                                                                             #
6916 #                                                                             #
6917 ###############################################################################
6918 #
6919 #
6920 void
6921 Mogrify(ref,...)
6922   Image::Magick ref=NO_INIT
6923   ALIAS:
6924     Comment            =   1
6925     CommentImage       =   2
6926     Label              =   3
6927     LabelImage         =   4
6928     AddNoise           =   5
6929     AddNoiseImage      =   6
6930     Colorize           =   7
6931     ColorizeImage      =   8
6932     Border             =   9
6933     BorderImage        =  10
6934     Blur               =  11
6935     BlurImage          =  12
6936     Chop               =  13
6937     ChopImage          =  14
6938     Crop               =  15
6939     CropImage          =  16
6940     Despeckle          =  17
6941     DespeckleImage     =  18
6942     Edge               =  19
6943     EdgeImage          =  20
6944     Emboss             =  21
6945     EmbossImage        =  22
6946     Enhance            =  23
6947     EnhanceImage       =  24
6948     Flip               =  25
6949     FlipImage          =  26
6950     Flop               =  27
6951     FlopImage          =  28
6952     Frame              =  29
6953     FrameImage         =  30
6954     Implode            =  31
6955     ImplodeImage       =  32
6956     Magnify            =  33
6957     MagnifyImage       =  34
6958     MedianFilter       =  35
6959     MedianConvolveImage  =  36
6960     Minify             =  37
6961     MinifyImage        =  38
6962     OilPaint           =  39
6963     OilPaintImage      =  40
6964     ReduceNoise        =  41
6965     ReduceNoiseImage   =  42
6966     Roll               =  43
6967     RollImage          =  44
6968     Rotate             =  45
6969     RotateImage        =  46
6970     Sample             =  47
6971     SampleImage        =  48
6972     Scale              =  49
6973     ScaleImage         =  50
6974     Shade              =  51
6975     ShadeImage         =  52
6976     Sharpen            =  53
6977     SharpenImage       =  54
6978     Shear              =  55
6979     ShearImage         =  56
6980     Spread             =  57
6981     SpreadImage        =  58
6982     Swirl              =  59
6983     SwirlImage         =  60
6984     Resize             =  61
6985     ResizeImage        =  62
6986     Zoom               =  63
6987     ZoomImage          =  64
6988     Annotate           =  65
6989     AnnotateImage      =  66
6990     ColorFloodfill     =  67
6991     ColorFloodfillImage=  68
6992     Composite          =  69
6993     CompositeImage     =  70
6994     Contrast           =  71
6995     ContrastImage      =  72
6996     CycleColormap      =  73
6997     CycleColormapImage =  74
6998     Draw               =  75
6999     DrawImage          =  76
7000     Equalize           =  77
7001     EqualizeImage      =  78
7002     Gamma              =  79
7003     GammaImage         =  80
7004     Map                =  81
7005     MapImage           =  82
7006     MatteFloodfill     =  83
7007     MatteFloodfillImage=  84
7008     Modulate           =  85
7009     ModulateImage      =  86
7010     Negate             =  87
7011     NegateImage        =  88
7012     Normalize          =  89
7013     NormalizeImage     =  90
7014     NumberColors       =  91
7015     NumberColorsImage  =  92
7016     Opaque             =  93
7017     OpaqueImage        =  94
7018     Quantize           =  95
7019     QuantizeImage      =  96
7020     Raise              =  97
7021     RaiseImage         =  98
7022     Segment            =  99
7023     SegmentImage       = 100
7024     Signature          = 101
7025     SignatureImage     = 102
7026     Solarize           = 103
7027     SolarizeImage      = 104
7028     Sync               = 105
7029     SyncImage          = 106
7030     Texture            = 107
7031     TextureImage       = 108
7032     Evaluate           = 109
7033     EvaluateImage      = 110
7034     Transparent        = 111
7035     TransparentImage   = 112
7036     Threshold          = 113
7037     ThresholdImage     = 114
7038     Charcoal           = 115
7039     CharcoalImage      = 116
7040     Trim               = 117
7041     TrimImage          = 118
7042     Wave               = 119
7043     WaveImage          = 120
7044     Separate           = 121
7045     SeparateImage      = 122
7046     Stereo             = 125
7047     StereoImage        = 126
7048     Stegano            = 127
7049     SteganoImage       = 128
7050     Deconstruct        = 129
7051     DeconstructImage   = 130
7052     GaussianBlur       = 131
7053     GaussianBlurImage  = 132
7054     Convolve           = 133
7055     ConvolveImage      = 134
7056     Profile            = 135
7057     ProfileImage       = 136
7058     UnsharpMask        = 137
7059     UnsharpMaskImage   = 138
7060     MotionBlur         = 139
7061     MotionBlurImage    = 140
7062     OrderedDither      = 141
7063     OrderedDitherImage = 142
7064     Shave              = 143
7065     ShaveImage         = 144
7066     Level              = 145
7067     LevelImage         = 146
7068     Clip               = 147
7069     ClipImage          = 148
7070     AffineTransform    = 149
7071     AffineTransformImage = 150
7072     Difference         = 151
7073     DifferenceImage    = 152
7074     AdaptiveThreshold  = 153
7075     AdaptiveThresholdImage = 154
7076     Resample           = 155
7077     ResampleImage      = 156
7078     Describe           = 157
7079     DescribeImage      = 158
7080     BlackThreshold     = 159
7081     BlackThresholdImage= 160
7082     WhiteThreshold     = 161
7083     WhiteThresholdImage= 162
7084     RadialBlur         = 163
7085     RadialBlurImage    = 164
7086     Thumbnail          = 165
7087     ThumbnailImage     = 166
7088     Strip              = 167
7089     StripImage         = 168
7090     Tint               = 169
7091     TintImage          = 170
7092     Channel            = 171
7093     ChannelImage       = 172
7094     Splice             = 173
7095     SpliceImage        = 174
7096     Posterize          = 175
7097     PosterizeImage     = 176
7098     Shadow             = 177
7099     ShadowImage        = 178
7100     Identify           = 179
7101     IdentifyImage      = 180
7102     SepiaTone          = 181
7103     SepiaToneImage     = 182
7104     SigmoidalContrast  = 183
7105     SigmoidalContrastImage = 184
7106     Extent             = 185
7107     ExtentImage        = 186
7108     Vignette           = 187
7109     VignetteImage      = 188
7110     ContrastStretch    = 189
7111     ContrastStretchImage = 190
7112     Sans0              = 191
7113     Sans0Image         = 192
7114     Sans1              = 193
7115     Sans1Image         = 194
7116     AdaptiveSharpen    = 195
7117     AdaptiveSharpenImage = 196
7118     Transpose          = 197
7119     TransposeImage     = 198
7120     Transverse         = 199
7121     TransverseImage    = 200
7122     AutoOrient         = 201
7123     AutoOrientImage    = 202
7124     AdaptiveBlur       = 203
7125     AdaptiveBlurImage  = 204
7126     Sketch             = 205
7127     SketchImage        = 206
7128     UniqueColors       = 207
7129     UniqueColorsImage  = 208
7130     AdaptiveResize     = 209
7131     AdaptiveResizeImage= 210
7132     ClipMask           = 211
7133     ClipMaskImage      = 212
7134     LinearStretch      = 213
7135     LinearStretchImage = 214
7136     RecolorImage       = 215
7137     Recolor            = 216
7138     Mask               = 217
7139     MaskImage          = 218
7140     Polaroid           = 219
7141     PolaroidImage      = 220
7142     FloodfillPaint     = 221
7143     FloodfillPaintImage= 222
7144     Distort            = 223
7145     DistortImage       = 224
7146     Clut               = 225
7147     ClutImage          = 226
7148     LiquidRescale      = 227
7149     LiquidRescaleImage = 228
7150     Encipher           = 229
7151     EncipherImage      = 230
7152     Decipher           = 231
7153     DecipherImage      = 232
7154     Deskew             = 233
7155     DeskewImage        = 234
7156     Remap              = 235
7157     RemapImage         = 236
7158     SparseColor        = 237
7159     SparseColorImage   = 238
7160     Function           = 239
7161     FunctionImage      = 240
7162     SelectiveBlur      = 241
7163     SelectiveBlurImage = 242
7164     HaldClut           = 243
7165     HaldClutImage      = 244
7166     BlueShift          = 245
7167     BlueShiftImage     = 246
7168     ForwardFourierTransform  = 247
7169     ForwardFourierTransformImage = 248
7170     InverseFourierTransform = 249
7171     InverseFourierTransformImage = 250
7172     ColorDecisionList  = 251
7173     ColorDecisionListImage = 252
7174     AutoGamma          = 253
7175     AutoGammaImage     = 254
7176     AutoLevel          = 255
7177     AutoLevelImage     = 256
7178     LevelColors        = 257
7179     LevelImageColors   = 258
7180     Clamp              = 259
7181     ClampImage         = 260
7182     BrightnessContrast = 263
7183     BrightnessContrastImage = 264
7184     Morphology         = 265
7185     MorphologyImage    = 266
7186     ColorMatrix        = 267
7187     ColorMatrixImage   = 268
7188     Color              = 269
7189     ColorImage         = 270
7190     Mode               = 271
7191     ModeImage          = 272
7192     Statistic          = 273
7193     StatisticImage     = 274
7194     MogrifyRegion      = 666
7195   PPCODE:
7196   {
7197     AffineMatrix
7198       affine,
7199       current;
7200
7201     char
7202       attribute_flag[MaxArguments],
7203       message[MaxTextExtent];
7204
7205     ChannelType
7206       channel,
7207       channel_mask;
7208
7209     CompositeOperator
7210       compose;
7211
7212     const char
7213       *attribute,
7214       *value;
7215
7216     double
7217       angle;
7218
7219     ExceptionInfo
7220       *exception;
7221
7222     GeometryInfo
7223       geometry_info;
7224
7225     Image
7226       *image,
7227       *next,
7228       *region_image;
7229
7230     MagickBooleanType
7231       status;
7232
7233     MagickStatusType
7234       flags;
7235
7236     PixelPacket
7237       fill_color;
7238
7239     RectangleInfo
7240       geometry,
7241       region_info;
7242
7243     register ssize_t
7244       i;
7245
7246     ssize_t
7247       base,
7248       j,
7249       number_images;
7250
7251     struct Methods
7252       *rp;
7253
7254     struct PackageInfo
7255       *info;
7256
7257     SV
7258       *perl_exception,
7259       **pv,
7260       *reference,
7261       **reference_vector;
7262
7263     struct ArgumentList
7264       argument_list[MaxArguments];
7265
7266     PERL_UNUSED_VAR(ref);
7267     PERL_UNUSED_VAR(ix);
7268     exception=AcquireExceptionInfo();
7269     perl_exception=newSVpv("",0);
7270     reference_vector=NULL;
7271     region_image=NULL;
7272     number_images=0;
7273     base=2;
7274     if (sv_isobject(ST(0)) == 0)
7275       {
7276         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7277           PackageName);
7278         goto PerlException;
7279       }
7280     reference=SvRV(ST(0));
7281     region_info.width=0;
7282     region_info.height=0;
7283     region_info.x=0;
7284     region_info.y=0;
7285     region_image=(Image *) NULL;
7286     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7287     if (ix && (ix != 666))
7288       {
7289         /*
7290           Called as Method(...)
7291         */
7292         ix=(ix+1)/2;
7293         rp=(&Methods[ix-1]);
7294         attribute=rp->name;
7295       }
7296     else
7297       {
7298         /*
7299           Called as Mogrify("Method",...)
7300         */
7301         attribute=(char *) SvPV(ST(1),na);
7302         if (ix)
7303           {
7304             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7305             attribute=(char *) SvPV(ST(2),na);
7306             base++;
7307           }
7308         for (rp=Methods; ; rp++)
7309         {
7310           if (rp >= EndOf(Methods))
7311             {
7312               ThrowPerlException(exception,OptionError,
7313                 "UnrecognizedPerlMagickMethod",attribute);
7314               goto PerlException;
7315             }
7316           if (strEQcase(attribute,rp->name))
7317             break;
7318         }
7319         ix=rp-Methods+1;
7320         base++;
7321       }
7322     if (image == (Image *) NULL)
7323       {
7324         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7325         goto PerlException;
7326       }
7327     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7328     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7329     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7330     {
7331       Arguments
7332         *pp,
7333         *qq;
7334
7335       ssize_t
7336         ssize_test;
7337
7338       struct ArgumentList
7339         *al;
7340
7341       SV
7342         *sv;
7343
7344       sv=NULL;
7345       ssize_test=0;
7346       pp=(Arguments *) NULL;
7347       qq=rp->arguments;
7348       if (i == items)
7349         {
7350           pp=rp->arguments,
7351           sv=ST(i-1);
7352         }
7353       else
7354         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7355         {
7356           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7357             break;
7358           if (strEQcase(attribute,qq->method) > ssize_test)
7359             {
7360               pp=qq;
7361               ssize_test=strEQcase(attribute,qq->method);
7362             }
7363         }
7364       if (pp == (Arguments *) NULL)
7365         {
7366           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7367             attribute);
7368           goto continue_outer_loop;
7369         }
7370       al=(&argument_list[pp-rp->arguments]);
7371       switch (pp->type)
7372       {
7373         case ArrayReference:
7374         {
7375           if (SvTYPE(sv) != SVt_RV)
7376             {
7377               (void) FormatLocaleString(message,MaxTextExtent,
7378                 "invalid %.60s value",pp->method);
7379               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7380               goto continue_outer_loop;
7381             }
7382           al->array_reference=SvRV(sv);
7383           break;
7384         }
7385         case RealReference:
7386         {
7387           al->real_reference=SvNV(sv);
7388           break;
7389         }
7390         case FileReference:
7391         {
7392           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7393           break;
7394         }
7395         case ImageReference:
7396         {
7397           if (!sv_isobject(sv) ||
7398               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7399                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7400             {
7401               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7402                 PackageName);
7403               goto PerlException;
7404             }
7405           break;
7406         }
7407         case IntegerReference:
7408         {
7409           al->integer_reference=SvIV(sv);
7410           break;
7411         }
7412         case StringReference:
7413         {
7414           al->string_reference=(char *) SvPV(sv,al->length);
7415           if (sv_isobject(sv))
7416             al->image_reference=SetupList(aTHX_ SvRV(sv),
7417               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7418           break;
7419         }
7420         default:
7421         {
7422           /*
7423             Is a string; look up name.
7424           */
7425           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7426             {
7427               al->string_reference=(char *) SvPV(sv,al->length);
7428               al->integer_reference=(-1);
7429               break;
7430             }
7431           al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7432             MagickFalse,SvPV(sv,na));
7433           if (pp->type == MagickChannelOptions)
7434             al->integer_reference=ParseChannelOption(SvPV(sv,na));
7435           if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7436             {
7437               (void) FormatLocaleString(message,MaxTextExtent,
7438                 "invalid %.60s value",pp->method);
7439               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7440               goto continue_outer_loop;
7441             }
7442           break;
7443         }
7444       }
7445       attribute_flag[pp-rp->arguments]++;
7446       continue_outer_loop: ;
7447     }
7448     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7449     pv=reference_vector;
7450     SetGeometryInfo(&geometry_info);
7451     channel=DefaultChannels;
7452     for (next=image; next; next=next->next)
7453     {
7454       image=next;
7455       SetGeometry(image,&geometry);
7456       if ((region_info.width*region_info.height) != 0)
7457         {
7458           region_image=image;
7459           image=CropImage(image,&region_info,exception);
7460         }
7461       switch (ix)
7462       {
7463         default:
7464         {
7465           (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double) ix);
7466           ThrowPerlException(exception,OptionError,
7467             "UnrecognizedPerlMagickMethod",message);
7468           goto PerlException;
7469         }
7470         case 1:  /* Comment */
7471         {
7472           if (attribute_flag[0] == 0)
7473             argument_list[0].string_reference=(char *) NULL;
7474           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7475             info ? info->image_info : (ImageInfo *) NULL,image,
7476             argument_list[0].string_reference,exception));
7477           break;
7478         }
7479         case 2:  /* Label */
7480         {
7481           if (attribute_flag[0] == 0)
7482             argument_list[0].string_reference=(char *) NULL;
7483           (void) SetImageProperty(image,"label",InterpretImageProperties(
7484             info ? info->image_info : (ImageInfo *) NULL,image,
7485             argument_list[0].string_reference,exception));
7486           break;
7487         }
7488         case 3:  /* AddNoise */
7489         {
7490           if (attribute_flag[0] == 0)
7491             argument_list[0].integer_reference=UniformNoise;
7492           if (attribute_flag[1] != 0)
7493             channel=(ChannelType) argument_list[1].integer_reference;
7494           channel_mask=SetPixelChannelMask(image,channel);
7495           image=AddNoiseImage(image,(NoiseType)
7496             argument_list[0].integer_reference,exception);
7497           if (image != (Image *) NULL)
7498             (void) SetPixelChannelMask(image,channel_mask);
7499           break;
7500         }
7501         case 4:  /* Colorize */
7502         {
7503           PixelPacket
7504             target;
7505
7506           (void) GetOneVirtualPixel(image,0,0,&target,exception);
7507           if (attribute_flag[0] != 0)
7508             (void) QueryColorDatabase(argument_list[0].string_reference,&target,
7509               exception);
7510           if (attribute_flag[1] == 0)
7511             argument_list[1].string_reference="100%";
7512           image=ColorizeImage(image,argument_list[1].string_reference,target,
7513             exception);
7514           break;
7515         }
7516         case 5:  /* Border */
7517         {
7518           geometry.width=0;
7519           geometry.height=0;
7520           if (attribute_flag[0] != 0)
7521             {
7522               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7523                 &geometry,exception);
7524               if ((flags & HeightValue) == 0)
7525                 geometry.height=geometry.width;
7526             }
7527           if (attribute_flag[1] != 0)
7528             geometry.width=argument_list[1].integer_reference;
7529           if (attribute_flag[2] != 0)
7530             geometry.height=argument_list[2].integer_reference;
7531           if (attribute_flag[3] != 0)
7532             QueryColorDatabase(argument_list[3].string_reference,
7533               &image->border_color,exception);
7534           if (attribute_flag[4] != 0)
7535             QueryColorDatabase(argument_list[4].string_reference,
7536               &image->border_color,exception);
7537           if (attribute_flag[5] != 0)
7538             QueryColorDatabase(argument_list[5].string_reference,
7539               &image->border_color,exception);
7540           if (attribute_flag[6] != 0)
7541             image->compose=(CompositeOperator) argument_list[6].integer_reference;
7542           image=BorderImage(image,&geometry,exception);
7543           break;
7544         }
7545         case 6:  /* Blur */
7546         {
7547           if (attribute_flag[0] != 0)
7548             {
7549               flags=ParseGeometry(argument_list[0].string_reference,
7550                 &geometry_info);
7551               if ((flags & SigmaValue) == 0)
7552                 geometry_info.sigma=1.0;
7553             }
7554           if (attribute_flag[1] != 0)
7555             geometry_info.rho=argument_list[1].real_reference;
7556           if (attribute_flag[2] != 0)
7557             geometry_info.sigma=argument_list[2].real_reference;
7558           if (attribute_flag[3] != 0)
7559             geometry_info.xi=argument_list[3].real_reference;
7560           if (attribute_flag[4] != 0)
7561             channel=(ChannelType) argument_list[4].integer_reference;
7562           channel_mask=SetPixelChannelMask(image,channel);
7563           image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
7564             geometry_info.xi,exception);
7565           if (image != (Image *) NULL)
7566             (void) SetPixelChannelMask(image,channel_mask);
7567           break;
7568         }
7569         case 7:  /* Chop */
7570         {
7571           if (attribute_flag[0] != 0)
7572             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7573               &geometry,exception);
7574           if (attribute_flag[1] != 0)
7575             geometry.width=argument_list[1].integer_reference;
7576           if (attribute_flag[2] != 0)
7577             geometry.height=argument_list[2].integer_reference;
7578           if (attribute_flag[3] != 0)
7579             geometry.x=argument_list[3].integer_reference;
7580           if (attribute_flag[4] != 0)
7581             geometry.y=argument_list[4].integer_reference;
7582           image=ChopImage(image,&geometry,exception);
7583           break;
7584         }
7585         case 8:  /* Crop */
7586         {
7587           if (attribute_flag[6] != 0)
7588             image->gravity=(GravityType) argument_list[6].integer_reference;
7589           if (attribute_flag[0] != 0)
7590             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7591               &geometry,exception);
7592           if (attribute_flag[1] != 0)
7593             geometry.width=argument_list[1].integer_reference;
7594           if (attribute_flag[2] != 0)
7595             geometry.height=argument_list[2].integer_reference;
7596           if (attribute_flag[3] != 0)
7597             geometry.x=argument_list[3].integer_reference;
7598           if (attribute_flag[4] != 0)
7599             geometry.y=argument_list[4].integer_reference;
7600           if (attribute_flag[5] != 0)
7601             image->fuzz=
7602               SiPrefixToDouble(argument_list[5].string_reference,QuantumRange);
7603           image=CropImage(image,&geometry,exception);
7604           break;
7605         }
7606         case 9:  /* Despeckle */
7607         {
7608           image=DespeckleImage(image,exception);
7609           break;
7610         }
7611         case 10:  /* Edge */
7612         {
7613           if (attribute_flag[0] != 0)
7614             geometry_info.rho=argument_list[0].real_reference;
7615           image=EdgeImage(image,geometry_info.rho,geometry_info.sigma,
7616             exception);
7617           break;
7618         }
7619         case 11:  /* Emboss */
7620         {
7621           if (attribute_flag[0] != 0)
7622             {
7623               flags=ParseGeometry(argument_list[0].string_reference,
7624                 &geometry_info);
7625               if ((flags & SigmaValue) == 0)
7626                 geometry_info.sigma=1.0;
7627             }
7628           if (attribute_flag[1] != 0)
7629             geometry_info.rho=argument_list[1].real_reference;
7630           if (attribute_flag[2] != 0)
7631             geometry_info.sigma=argument_list[2].real_reference;
7632           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
7633             exception);
7634           break;
7635         }
7636         case 12:  /* Enhance */
7637         {
7638           image=EnhanceImage(image,exception);
7639           break;
7640         }
7641         case 13:  /* Flip */
7642         {
7643           image=FlipImage(image,exception);
7644           break;
7645         }
7646         case 14:  /* Flop */
7647         {
7648           image=FlopImage(image,exception);
7649           break;
7650         }
7651         case 15:  /* Frame */
7652         {
7653           FrameInfo
7654             frame_info;
7655
7656           if (attribute_flag[0] != 0)
7657             {
7658               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7659                 &geometry,exception);
7660               if ((flags & HeightValue) == 0)
7661                 geometry.height=geometry.width;
7662               frame_info.width=geometry.width;
7663               frame_info.height=geometry.height;
7664               frame_info.outer_bevel=geometry.x;
7665               frame_info.inner_bevel=geometry.y;
7666             }
7667           if (attribute_flag[1] != 0)
7668             frame_info.width=argument_list[1].integer_reference;
7669           if (attribute_flag[2] != 0)
7670             frame_info.height=argument_list[2].integer_reference;
7671           if (attribute_flag[3] != 0)
7672             frame_info.inner_bevel=argument_list[3].integer_reference;
7673           if (attribute_flag[4] != 0)
7674             frame_info.outer_bevel=argument_list[4].integer_reference;
7675           if (attribute_flag[5] != 0)
7676             QueryColorDatabase(argument_list[5].string_reference,&fill_color,
7677               exception);
7678           if (attribute_flag[6] != 0)
7679             QueryColorDatabase(argument_list[6].string_reference,&fill_color,
7680               exception);
7681           frame_info.x=(ssize_t) frame_info.width;
7682           frame_info.y=(ssize_t) frame_info.height;
7683           frame_info.width=image->columns+2*frame_info.x;
7684           frame_info.height=image->rows+2*frame_info.y;
7685           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
7686             image->matte_color=fill_color;
7687           if (attribute_flag[7] != 0)
7688             image->compose=(CompositeOperator) argument_list[7].integer_reference;
7689           image=FrameImage(image,&frame_info,exception);
7690           break;
7691         }
7692         case 16:  /* Implode */
7693         {
7694           if (attribute_flag[0] == 0)
7695             argument_list[0].real_reference=0.5;
7696           if (attribute_flag[1] != 0)
7697             image->interpolate=(InterpolatePixelMethod)
7698               argument_list[1].integer_reference;
7699           image=ImplodeImage(image,argument_list[0].real_reference,
7700             exception);
7701           break;
7702         }
7703         case 17:  /* Magnify */
7704         {
7705           image=MagnifyImage(image,exception);
7706           break;
7707         }
7708         case 18:  /* MedianFilter */
7709         {
7710           if (attribute_flag[0] != 0)
7711             {
7712               flags=ParseGeometry(argument_list[0].string_reference,
7713                 &geometry_info);
7714               if ((flags & SigmaValue) == 0)
7715                 geometry_info.sigma=geometry_info.rho;
7716             }
7717           if (attribute_flag[1] != 0)
7718             geometry_info.rho=argument_list[1].real_reference;
7719           if (attribute_flag[2] != 0)
7720             geometry_info.sigma=argument_list[2].real_reference;
7721           if (attribute_flag[3] != 0)
7722             channel=(ChannelType) argument_list[3].integer_reference;
7723           channel_mask=SetPixelChannelMask(image,channel);
7724           image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
7725             (size_t) geometry_info.sigma,exception);
7726           if (image != (Image *) NULL)
7727             (void) SetPixelChannelMask(image,channel_mask);
7728           break;
7729         }
7730         case 19:  /* Minify */
7731         {
7732           image=MinifyImage(image,exception);
7733           break;
7734         }
7735         case 20:  /* OilPaint */
7736         {
7737           if (attribute_flag[0] == 0)
7738             argument_list[0].real_reference=0.0;
7739           if (attribute_flag[1] == 0)
7740             argument_list[1].real_reference=1.0;
7741           image=OilPaintImage(image,argument_list[0].real_reference,
7742             argument_list[1].real_reference,exception);
7743           break;
7744         }
7745         case 21:  /* ReduceNoise */
7746         {
7747           if (attribute_flag[0] != 0)
7748             {
7749               flags=ParseGeometry(argument_list[0].string_reference,
7750                 &geometry_info);
7751               if ((flags & SigmaValue) == 0)
7752                 geometry_info.sigma=1.0;
7753             }
7754           if (attribute_flag[1] != 0)
7755             geometry_info.rho=argument_list[1].real_reference;
7756           if (attribute_flag[2] != 0)
7757             geometry_info.sigma=argument_list[2].real_reference;
7758           if (attribute_flag[3] != 0)
7759             channel=(ChannelType) argument_list[3].integer_reference;
7760           channel_mask=SetPixelChannelMask(image,channel);
7761           image=StatisticImage(image,NonpeakStatistic,(size_t)
7762             geometry_info.rho,(size_t) geometry_info.sigma,exception);
7763           if (image != (Image *) NULL)
7764             (void) SetPixelChannelMask(image,channel_mask);
7765           break;
7766         }
7767         case 22:  /* Roll */
7768         {
7769           if (attribute_flag[0] != 0)
7770             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7771               &geometry,exception);
7772           if (attribute_flag[1] != 0)
7773             geometry.x=argument_list[1].integer_reference;
7774           if (attribute_flag[2] != 0)
7775             geometry.y=argument_list[2].integer_reference;
7776           image=RollImage(image,geometry.x,geometry.y,exception);
7777           break;
7778         }
7779         case 23:  /* Rotate */
7780         {
7781           if (attribute_flag[0] == 0)
7782             argument_list[0].real_reference=90.0;
7783           if (attribute_flag[1] != 0)
7784             QueryColorDatabase(argument_list[1].string_reference,
7785               &image->background_color,exception);
7786           if (attribute_flag[2] != 0)
7787             QueryColorDatabase(argument_list[2].string_reference,
7788               &image->background_color,exception);
7789           if (attribute_flag[3] != 0)
7790             QueryColorDatabase(argument_list[3].string_reference,
7791               &image->background_color,exception);
7792           image=RotateImage(image,argument_list[0].real_reference,exception);
7793           break;
7794         }
7795         case 24:  /* Sample */
7796         {
7797           if (attribute_flag[0] != 0)
7798             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7799               &geometry,exception);
7800           if (attribute_flag[1] != 0)
7801             geometry.width=argument_list[1].integer_reference;
7802           if (attribute_flag[2] != 0)
7803             geometry.height=argument_list[2].integer_reference;
7804           image=SampleImage(image,geometry.width,geometry.height,exception);
7805           break;
7806         }
7807         case 25:  /* Scale */
7808         {
7809           if (attribute_flag[0] != 0)
7810             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7811               &geometry,exception);
7812           if (attribute_flag[1] != 0)
7813             geometry.width=argument_list[1].integer_reference;
7814           if (attribute_flag[2] != 0)
7815             geometry.height=argument_list[2].integer_reference;
7816           image=ScaleImage(image,geometry.width,geometry.height,exception);
7817           break;
7818         }
7819         case 26:  /* Shade */
7820         {
7821           if (attribute_flag[0] != 0)
7822             {
7823               flags=ParseGeometry(argument_list[0].string_reference,
7824                 &geometry_info);
7825               if ((flags & SigmaValue) == 0)
7826                 geometry_info.sigma=0.0;
7827             }
7828           if (attribute_flag[1] != 0)
7829             geometry_info.rho=argument_list[1].real_reference;
7830           if (attribute_flag[2] != 0)
7831             geometry_info.sigma=argument_list[2].real_reference;
7832           image=ShadeImage(image,
7833             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
7834             geometry_info.rho,geometry_info.sigma,exception);
7835           break;
7836         }
7837         case 27:  /* Sharpen */
7838         {
7839           if (attribute_flag[0] != 0)
7840             {
7841               flags=ParseGeometry(argument_list[0].string_reference,
7842                 &geometry_info);
7843               if ((flags & SigmaValue) == 0)
7844                 geometry_info.sigma=1.0;
7845             }
7846           if (attribute_flag[1] != 0)
7847             geometry_info.rho=argument_list[1].real_reference;
7848           if (attribute_flag[2] != 0)
7849             geometry_info.sigma=argument_list[2].real_reference;
7850           if (attribute_flag[3] != 0)
7851             geometry_info.xi=argument_list[3].real_reference;
7852           if (attribute_flag[4] != 0)
7853             channel=(ChannelType) argument_list[4].integer_reference;
7854           channel_mask=SetPixelChannelMask(image,channel);
7855           image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
7856             geometry_info.xi,exception);
7857           if (image != (Image *) NULL)
7858             (void) SetPixelChannelMask(image,channel_mask);
7859           break;
7860         }
7861         case 28:  /* Shear */
7862         {
7863           if (attribute_flag[0] != 0)
7864             {
7865               flags=ParseGeometry(argument_list[0].string_reference,
7866                 &geometry_info);
7867               if ((flags & SigmaValue) == 0)
7868                 geometry_info.sigma=geometry_info.rho;
7869             }
7870           if (attribute_flag[1] != 0)
7871             geometry_info.rho=argument_list[1].real_reference;
7872           if (attribute_flag[2] != 0)
7873             geometry_info.sigma=argument_list[2].real_reference;
7874           if (attribute_flag[3] != 0)
7875             QueryColorDatabase(argument_list[3].string_reference,
7876               &image->background_color,exception);
7877           if (attribute_flag[4] != 0)
7878             QueryColorDatabase(argument_list[4].string_reference,
7879               &image->background_color,exception);
7880           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
7881             exception);
7882           break;
7883         }
7884         case 29:  /* Spread */
7885         {
7886           if (attribute_flag[0] == 0)
7887             argument_list[0].real_reference=1.0;
7888           image=SpreadImage(image,argument_list[0].real_reference,exception);
7889           break;
7890         }
7891         case 30:  /* Swirl */
7892         {
7893           if (attribute_flag[0] == 0)
7894             argument_list[0].real_reference=50.0;
7895           if (attribute_flag[1] != 0)
7896             image->interpolate=(InterpolatePixelMethod)
7897               argument_list[1].integer_reference;
7898           image=SwirlImage(image,argument_list[0].real_reference,exception);
7899           break;
7900         }
7901         case 31:  /* Resize */
7902         case 32:  /* Zoom */
7903         {
7904           if (attribute_flag[0] != 0)
7905             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7906               &geometry,exception);
7907           if (attribute_flag[1] != 0)
7908             geometry.width=argument_list[1].integer_reference;
7909           if (attribute_flag[2] != 0)
7910             geometry.height=argument_list[2].integer_reference;
7911           if (attribute_flag[3] == 0)
7912             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
7913           if (attribute_flag[4] != 0)
7914             SetImageArtifact(image,"filter:support",
7915               argument_list[4].string_reference);
7916           if (attribute_flag[5] == 0)
7917             argument_list[5].real_reference=1.0;
7918           image=ResizeImage(image,geometry.width,geometry.height,
7919             (FilterTypes) argument_list[3].integer_reference,
7920             argument_list[5].real_reference,exception);
7921           break;
7922         }
7923         case 33:  /* Annotate */
7924         {
7925           DrawInfo
7926             *draw_info;
7927
7928           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
7929             (DrawInfo *) NULL);
7930           if (attribute_flag[0] != 0)
7931             {
7932               char
7933                 *text;
7934
7935               text=InterpretImageProperties(info ? info->image_info :
7936                 (ImageInfo *) NULL,image,argument_list[0].string_reference,
7937                 exception);
7938               (void) CloneString(&draw_info->text,text);
7939               text=DestroyString(text);
7940             }
7941           if (attribute_flag[1] != 0)
7942             (void) CloneString(&draw_info->font,
7943               argument_list[1].string_reference);
7944           if (attribute_flag[2] != 0)
7945             draw_info->pointsize=argument_list[2].real_reference;
7946           if (attribute_flag[3] != 0)
7947             (void) CloneString(&draw_info->density,
7948               argument_list[3].string_reference);
7949           if (attribute_flag[4] != 0)
7950             (void) QueryColorDatabase(argument_list[4].string_reference,
7951               &draw_info->undercolor,exception);
7952           if (attribute_flag[5] != 0)
7953             {
7954               (void) QueryColorDatabase(argument_list[5].string_reference,
7955                 &draw_info->stroke,exception);
7956               if (argument_list[5].image_reference != (Image *) NULL)
7957                 draw_info->stroke_pattern=CloneImage(
7958                   argument_list[5].image_reference,0,0,MagickTrue,exception);
7959             }
7960           if (attribute_flag[6] != 0)
7961             {
7962               (void) QueryColorDatabase(argument_list[6].string_reference,
7963                 &draw_info->fill,exception);
7964               if (argument_list[6].image_reference != (Image *) NULL)
7965                 draw_info->fill_pattern=CloneImage(
7966                   argument_list[6].image_reference,0,0,MagickTrue,exception);
7967             }
7968           if (attribute_flag[7] != 0)
7969             {
7970               (void) CloneString(&draw_info->geometry,
7971                 argument_list[7].string_reference);
7972               flags=ParsePageGeometry(image,argument_list[7].string_reference,
7973                 &geometry,exception);
7974               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
7975                 geometry_info.sigma=geometry_info.xi;
7976             }
7977           if (attribute_flag[8] != 0)
7978             (void) QueryColorDatabase(argument_list[8].string_reference,
7979               &draw_info->fill,exception);
7980           if (attribute_flag[11] != 0)
7981             draw_info->gravity=(GravityType) argument_list[11].integer_reference;
7982           if (attribute_flag[25] != 0)
7983             {
7984               AV
7985                 *av;
7986
7987               av=(AV *) argument_list[25].array_reference;
7988               if ((av_len(av) != 3) && (av_len(av) != 5))
7989                 {
7990                   ThrowPerlException(exception,OptionError,
7991                     "affine matrix must have 4 or 6 elements",PackageName);
7992                   goto PerlException;
7993                 }
7994               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
7995               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
7996               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
7997               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
7998               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
7999                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8000                 {
8001                   ThrowPerlException(exception,OptionError,
8002                     "affine matrix is singular",PackageName);
8003                    goto PerlException;
8004                 }
8005               if (av_len(av) == 5)
8006                 {
8007                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8008                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8009                 }
8010             }
8011           for (j=12; j < 17; j++)
8012           {
8013             if (attribute_flag[j] == 0)
8014               continue;
8015             value=argument_list[j].string_reference;
8016             angle=argument_list[j].real_reference;
8017             current=draw_info->affine;
8018             GetAffineMatrix(&affine);
8019             switch (j)
8020             {
8021               case 12:
8022               {
8023                 /*
8024                   Translate.
8025                 */
8026                 flags=ParseGeometry(value,&geometry_info);
8027                 affine.tx=geometry_info.xi;
8028                 affine.ty=geometry_info.psi;
8029                 if ((flags & PsiValue) == 0)
8030                   affine.ty=affine.tx;
8031                 break;
8032               }
8033               case 13:
8034               {
8035                 /*
8036                   Scale.
8037                 */
8038                 flags=ParseGeometry(value,&geometry_info);
8039                 affine.sx=geometry_info.rho;
8040                 affine.sy=geometry_info.sigma;
8041                 if ((flags & SigmaValue) == 0)
8042                   affine.sy=affine.sx;
8043                 break;
8044               }
8045               case 14:
8046               {
8047                 /*
8048                   Rotate.
8049                 */
8050                 if (angle == 0.0)
8051                   break;
8052                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8053                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8054                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8055                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8056                 break;
8057               }
8058               case 15:
8059               {
8060                 /*
8061                   SkewX.
8062                 */
8063                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8064                 break;
8065               }
8066               case 16:
8067               {
8068                 /*
8069                   SkewY.
8070                 */
8071                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8072                 break;
8073               }
8074             }
8075             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8076             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8077             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8078             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8079             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8080               current.tx;
8081             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8082               current.ty;
8083           }
8084           if (attribute_flag[9] == 0)
8085             argument_list[9].real_reference=0.0;
8086           if (attribute_flag[10] == 0)
8087             argument_list[10].real_reference=0.0;
8088           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8089             {
8090               char
8091                 geometry[MaxTextExtent];
8092
8093               (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
8094                 (double) argument_list[9].real_reference+draw_info->affine.tx,
8095                 (double) argument_list[10].real_reference+draw_info->affine.ty);
8096               (void) CloneString(&draw_info->geometry,geometry);
8097             }
8098           if (attribute_flag[17] != 0)
8099             draw_info->stroke_width=argument_list[17].real_reference;
8100           if (attribute_flag[18] != 0)
8101             {
8102               draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8103                 MagickTrue : MagickFalse;
8104               draw_info->stroke_antialias=draw_info->text_antialias;
8105             }
8106           if (attribute_flag[19] != 0)
8107             (void) CloneString(&draw_info->family,
8108               argument_list[19].string_reference);
8109           if (attribute_flag[20] != 0)
8110             draw_info->style=(StyleType) argument_list[20].integer_reference;
8111           if (attribute_flag[21] != 0)
8112             draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8113           if (attribute_flag[22] != 0)
8114             draw_info->weight=argument_list[22].integer_reference;
8115           if (attribute_flag[23] != 0)
8116             draw_info->align=(AlignType) argument_list[23].integer_reference;
8117           if (attribute_flag[24] != 0)
8118             (void) CloneString(&draw_info->encoding,
8119               argument_list[24].string_reference);
8120           if (attribute_flag[25] != 0)
8121             draw_info->fill_pattern=CloneImage(
8122               argument_list[25].image_reference,0,0,MagickTrue,exception);
8123           if (attribute_flag[26] != 0)
8124             draw_info->fill_pattern=CloneImage(
8125               argument_list[26].image_reference,0,0,MagickTrue,exception);
8126           if (attribute_flag[27] != 0)
8127             draw_info->stroke_pattern=CloneImage(
8128               argument_list[27].image_reference,0,0,MagickTrue,exception);
8129           if (attribute_flag[29] != 0)
8130             draw_info->kerning=argument_list[29].real_reference;
8131           if (attribute_flag[30] != 0)
8132             draw_info->interline_spacing=argument_list[30].real_reference;
8133           if (attribute_flag[31] != 0)
8134             draw_info->interword_spacing=argument_list[31].real_reference;
8135           if (attribute_flag[32] != 0)
8136             draw_info->direction=(DirectionType)
8137               argument_list[32].integer_reference;
8138           (void) AnnotateImage(image,draw_info,exception);
8139           draw_info=DestroyDrawInfo(draw_info);
8140           break;
8141         }
8142         case 34:  /* ColorFloodfill */
8143         {
8144           DrawInfo
8145             *draw_info;
8146
8147           MagickBooleanType
8148             invert;
8149
8150           PixelInfo
8151             target;
8152
8153           draw_info=CloneDrawInfo(info ? info->image_info :
8154             (ImageInfo *) NULL,(DrawInfo *) NULL);
8155           if (attribute_flag[0] != 0)
8156             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8157               &geometry,exception);
8158           if (attribute_flag[1] != 0)
8159             geometry.x=argument_list[1].integer_reference;
8160           if (attribute_flag[2] != 0)
8161             geometry.y=argument_list[2].integer_reference;
8162           if (attribute_flag[3] != 0)
8163             (void) QueryColorDatabase(argument_list[3].string_reference,
8164               &draw_info->fill,exception);
8165           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
8166             exception);
8167           invert=MagickFalse;
8168           if (attribute_flag[4] != 0)
8169             {
8170               QueryMagickColor(argument_list[4].string_reference,&target,
8171                 exception);
8172               invert=MagickTrue;
8173             }
8174           if (attribute_flag[5] != 0)
8175             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
8176               QuantumRange);
8177           if (attribute_flag[6] != 0)
8178             invert=(MagickBooleanType) argument_list[6].integer_reference;
8179           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8180             geometry.y,invert,exception);
8181           draw_info=DestroyDrawInfo(draw_info);
8182           break;
8183         }
8184         case 35:  /* Composite */
8185         {
8186           char
8187             composite_geometry[MaxTextExtent];
8188
8189           Image
8190             *composite_image,
8191             *rotate_image;
8192
8193           compose=OverCompositeOp;
8194           if (attribute_flag[0] != 0)
8195             composite_image=argument_list[0].image_reference;
8196           else
8197             {
8198               ThrowPerlException(exception,OptionError,
8199                 "CompositeImageRequired",PackageName);
8200               goto PerlException;
8201             }
8202           /*
8203             Parameter Handling used for BOTH normal and tiled composition.
8204           */
8205           if (attribute_flag[1] != 0) /* compose */
8206             compose=(CompositeOperator) argument_list[1].integer_reference;
8207           if (attribute_flag[6] != 0) /* opacity  */
8208             {
8209               if (compose != DissolveCompositeOp)
8210                 (void) SetImageOpacity(composite_image,(Quantum)
8211                   SiPrefixToDouble(argument_list[6].string_reference,
8212                   QuantumRange));
8213               else
8214                 {
8215                   CacheView
8216                     *composite_view;
8217
8218                   double
8219                     opacity;
8220
8221                   MagickBooleanType
8222                     sync;
8223
8224                   register ssize_t
8225                     x;
8226
8227                   register Quantum
8228                     *q;
8229
8230                   ssize_t
8231                     y;
8232
8233                   /*
8234                     Handle dissolve composite operator (patch by
8235                     Kevin A. McGrail).
8236                   */
8237                   (void) CloneString(&image->geometry,
8238                     argument_list[6].string_reference);
8239                   opacity=(Quantum) SiPrefixToDouble(
8240                     argument_list[6].string_reference,QuantumRange);
8241                   if (composite_image->matte != MagickTrue)
8242                     (void) SetImageOpacity(composite_image,OpaqueAlpha);
8243                   composite_view=AcquireCacheView(composite_image);
8244                   for (y=0; y < (ssize_t) composite_image->rows ; y++)
8245                   {
8246                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8247                       composite_image->columns,1,exception);
8248                     for (x=0; x < (ssize_t) composite_image->columns; x++)
8249                     {
8250                       if (GetPixelAlpha(image,q) == OpaqueAlpha)
8251                         SetPixelAlpha(composite_image,ClampToQuantum(opacity),q);
8252                       q+=GetPixelChannels(composite_image);
8253                     }
8254                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8255                     if (sync == MagickFalse)
8256                       break;
8257                   }
8258                   composite_view=DestroyCacheView(composite_view);
8259                 }
8260             }
8261           if (attribute_flag[9] != 0)    /* "color=>" */
8262             QueryColorDatabase(argument_list[9].string_reference,
8263               &composite_image->background_color,exception);
8264           if (attribute_flag[12] != 0) /* "interpolate=>" */
8265             image->interpolate=(InterpolatePixelMethod)
8266               argument_list[12].integer_reference;
8267           if (attribute_flag[13] != 0)   /* "args=>" */
8268             (void) SetImageArtifact(composite_image,"compose:args",
8269               argument_list[13].string_reference);
8270           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8271             (void) SetImageArtifact(composite_image,"compose:args",
8272               argument_list[14].string_reference);
8273           /*
8274             Tiling Composition (with orthogonal rotate).
8275           */
8276           rotate_image=(Image *) NULL;
8277           if (attribute_flag[8] != 0)   /* "rotate=>" */
8278             {
8279                /*
8280                  Rotate image.
8281                */
8282                rotate_image=RotateImage(composite_image,
8283                  argument_list[8].real_reference,exception);
8284                if (rotate_image == (Image *) NULL)
8285                  break;
8286             }
8287           if (attribute_flag[7] && argument_list[7].integer_reference) /* tile */
8288             {
8289               ssize_t
8290                 x,
8291                 y;
8292
8293               /*
8294                 Tile the composite image.
8295               */
8296              if (attribute_flag[8] != 0)   /* "tile=>" */
8297                (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8298                  "false");
8299              else
8300                (void) SetImageArtifact(composite_image,
8301                  "compose:outside-overlay","false");
8302              for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8303                 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8304                 {
8305                   if (attribute_flag[8] != 0) /* rotate */
8306                     (void) CompositeImage(image,compose,rotate_image,x,y);
8307                   else
8308                     (void) CompositeImage(image,compose,composite_image,x,y);
8309                 }
8310               if (attribute_flag[8] != 0) /* rotate */
8311                 rotate_image=DestroyImage(rotate_image);
8312               break;
8313             }
8314           /*
8315             Parameter Handling used used ONLY for normal composition.
8316           */
8317           if (attribute_flag[5] != 0) /* gravity */
8318             image->gravity=(GravityType) argument_list[5].integer_reference;
8319           if (attribute_flag[2] != 0) /* geometry offset */
8320             {
8321               SetGeometry(image,&geometry);
8322               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8323                 &geometry);
8324               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8325                 &geometry);
8326             }
8327           if (attribute_flag[3] != 0) /* x offset */
8328             geometry.x=argument_list[3].integer_reference;
8329           if (attribute_flag[4] != 0) /* y offset */
8330             geometry.y=argument_list[4].integer_reference;
8331           if (attribute_flag[10] != 0) /* mask */
8332             {
8333               if ((image->compose == DisplaceCompositeOp) ||
8334                   (image->compose == DistortCompositeOp))
8335                 {
8336                   /*
8337                     Merge Y displacement into X displacement image.
8338                   */
8339                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8340                     &image->exception);
8341                   (void) CompositeImage(composite_image,CopyGreenCompositeOp,
8342                     argument_list[10].image_reference,0,0);
8343                 }
8344               else
8345                 {
8346                   /*
8347                     Set a blending mask for the composition.
8348                   */
8349                   image->mask=CloneImage(argument_list[10].image_reference,0,0,
8350                     MagickTrue,&image->exception);
8351                   (void) NegateImage(image->mask,MagickFalse,exception);
8352                 }
8353             }
8354           if (attribute_flag[11] != 0) /* channel */
8355             channel=(ChannelType) argument_list[11].integer_reference;
8356           /*
8357             Composite two images (normal composition).
8358           */
8359           (void) FormatLocaleString(composite_geometry,MaxTextExtent,
8360             "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8361             (double) composite_image->rows,(double) geometry.x,(double)
8362             geometry.y);
8363           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8364             exception);
8365           channel_mask=SetPixelChannelMask(image,channel);
8366           if (attribute_flag[8] == 0) /* no rotate */
8367             CompositeImage(image,compose,composite_image,geometry.x,geometry.y);
8368           else
8369             {
8370               /*
8371                 Position adjust rotated image then composite.
8372               */
8373               geometry.x-=(ssize_t) (rotate_image->columns-
8374                 composite_image->columns)/2;
8375               geometry.y-=(ssize_t) (rotate_image->rows-
8376                 composite_image->rows)/2;
8377               CompositeImage(image,compose,rotate_image,geometry.x,geometry.y);
8378               rotate_image=DestroyImage(rotate_image);
8379             }
8380           if (attribute_flag[10] != 0) /* mask */
8381             {
8382               if ((image->compose == DisplaceCompositeOp) ||
8383                   (image->compose == DistortCompositeOp))
8384                 composite_image=DestroyImage(composite_image);
8385               else
8386                 image->mask=DestroyImage(image->mask);
8387             }
8388           (void) SetPixelChannelMask(image,channel_mask);
8389           break;
8390         }
8391         case 36:  /* Contrast */
8392         {
8393           if (attribute_flag[0] == 0)
8394             argument_list[0].integer_reference=0;
8395           (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8396             MagickTrue : MagickFalse,exception);
8397           break;
8398         }
8399         case 37:  /* CycleColormap */
8400         {
8401           if (attribute_flag[0] == 0)
8402             argument_list[0].integer_reference=6;
8403           (void) CycleColormapImage(image,argument_list[0].integer_reference,
8404             exception);
8405           break;
8406         }
8407         case 38:  /* Draw */
8408         {
8409           DrawInfo
8410             *draw_info;
8411
8412           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8413             (DrawInfo *) NULL);
8414           (void) CloneString(&draw_info->primitive,"point");
8415           if (attribute_flag[0] != 0)
8416             {
8417               if (argument_list[0].integer_reference < 0)
8418                 (void) CloneString(&draw_info->primitive,
8419                   argument_list[0].string_reference);
8420               else
8421                 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8422                   MagickPrimitiveOptions,argument_list[0].integer_reference));
8423             }
8424           if (attribute_flag[1] != 0)
8425             {
8426               if (LocaleCompare(draw_info->primitive,"path") == 0)
8427                 {
8428                   (void) ConcatenateString(&draw_info->primitive," '");
8429                   ConcatenateString(&draw_info->primitive,
8430                     argument_list[1].string_reference);
8431                   (void) ConcatenateString(&draw_info->primitive,"'");
8432                 }
8433               else
8434                 {
8435                   (void) ConcatenateString(&draw_info->primitive," ");
8436                   ConcatenateString(&draw_info->primitive,
8437                     argument_list[1].string_reference);
8438                 }
8439             }
8440           if (attribute_flag[2] != 0)
8441             {
8442               (void) ConcatenateString(&draw_info->primitive," ");
8443               (void) ConcatenateString(&draw_info->primitive,
8444                 CommandOptionToMnemonic(MagickMethodOptions,
8445                 argument_list[2].integer_reference));
8446             }
8447           if (attribute_flag[3] != 0)
8448             {
8449               (void) QueryColorDatabase(argument_list[3].string_reference,
8450                 &draw_info->stroke,exception);
8451               if (argument_list[3].image_reference != (Image *) NULL)
8452                 draw_info->stroke_pattern=CloneImage(
8453                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8454             }
8455           if (attribute_flag[4] != 0)
8456             {
8457               (void) QueryColorDatabase(argument_list[4].string_reference,
8458                 &draw_info->fill,exception);
8459               if (argument_list[4].image_reference != (Image *) NULL)
8460                 draw_info->fill_pattern=CloneImage(
8461                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8462             }
8463           if (attribute_flag[5] != 0)
8464             draw_info->stroke_width=argument_list[5].real_reference;
8465           if (attribute_flag[6] != 0)
8466             (void) CloneString(&draw_info->font,
8467               argument_list[6].string_reference);
8468           if (attribute_flag[7] != 0)
8469             (void) QueryColorDatabase(argument_list[7].string_reference,
8470               &draw_info->border_color,exception);
8471           if (attribute_flag[8] != 0)
8472             draw_info->affine.tx=argument_list[8].real_reference;
8473           if (attribute_flag[9] != 0)
8474             draw_info->affine.ty=argument_list[9].real_reference;
8475           if (attribute_flag[20] != 0)
8476             {
8477               AV
8478                 *av;
8479
8480               av=(AV *) argument_list[20].array_reference;
8481               if ((av_len(av) != 3) && (av_len(av) != 5))
8482                 {
8483                   ThrowPerlException(exception,OptionError,
8484                     "affine matrix must have 4 or 6 elements",PackageName);
8485                   goto PerlException;
8486                 }
8487               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8488               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8489               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8490               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8491               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8492                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8493                 {
8494                   ThrowPerlException(exception,OptionError,
8495                     "affine matrix is singular",PackageName);
8496                    goto PerlException;
8497                 }
8498               if (av_len(av) == 5)
8499                 {
8500                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8501                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8502                 }
8503             }
8504           for (j=10; j < 15; j++)
8505           {
8506             if (attribute_flag[j] == 0)
8507               continue;
8508             value=argument_list[j].string_reference;
8509             angle=argument_list[j].real_reference;
8510             current=draw_info->affine;
8511             GetAffineMatrix(&affine);
8512             switch (j)
8513             {
8514               case 10:
8515               {
8516                 /*
8517                   Translate.
8518                 */
8519                 flags=ParseGeometry(value,&geometry_info);
8520                 affine.tx=geometry_info.xi;
8521                 affine.ty=geometry_info.psi;
8522                 if ((flags & PsiValue) == 0)
8523                   affine.ty=affine.tx;
8524                 break;
8525               }
8526               case 11:
8527               {
8528                 /*
8529                   Scale.
8530                 */
8531                 flags=ParseGeometry(value,&geometry_info);
8532                 affine.sx=geometry_info.rho;
8533                 affine.sy=geometry_info.sigma;
8534                 if ((flags & SigmaValue) == 0)
8535                   affine.sy=affine.sx;
8536                 break;
8537               }
8538               case 12:
8539               {
8540                 /*
8541                   Rotate.
8542                 */
8543                 if (angle == 0.0)
8544                   break;
8545                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8546                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8547                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8548                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8549                 break;
8550               }
8551               case 13:
8552               {
8553                 /*
8554                   SkewX.
8555                 */
8556                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8557                 break;
8558               }
8559               case 14:
8560               {
8561                 /*
8562                   SkewY.
8563                 */
8564                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8565                 break;
8566               }
8567             }
8568             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8569             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8570             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8571             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8572             draw_info->affine.tx=
8573               current.sx*affine.tx+current.ry*affine.ty+current.tx;
8574             draw_info->affine.ty=
8575               current.rx*affine.tx+current.sy*affine.ty+current.ty;
8576           }
8577           if (attribute_flag[15] != 0)
8578             draw_info->fill_pattern=CloneImage(
8579               argument_list[15].image_reference,0,0,MagickTrue,exception);
8580           if (attribute_flag[16] != 0)
8581             draw_info->pointsize=argument_list[16].real_reference;
8582           if (attribute_flag[17] != 0)
8583             {
8584               draw_info->stroke_antialias=argument_list[17].integer_reference != 0
8585                 ? MagickTrue : MagickFalse;
8586               draw_info->text_antialias=draw_info->stroke_antialias;
8587             }
8588           if (attribute_flag[18] != 0)
8589             (void) CloneString(&draw_info->density,
8590               argument_list[18].string_reference);
8591           if (attribute_flag[19] != 0)
8592             draw_info->stroke_width=argument_list[19].real_reference;
8593           if (attribute_flag[21] != 0)
8594             draw_info->dash_offset=argument_list[21].real_reference;
8595           if (attribute_flag[22] != 0)
8596             {
8597               AV
8598                 *av;
8599
8600               av=(AV *) argument_list[22].array_reference;
8601               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
8602                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
8603               if (draw_info->dash_pattern != (double *) NULL)
8604                 {
8605                   for (i=0; i <= av_len(av); i++)
8606                     draw_info->dash_pattern[i]=(double)
8607                       SvNV(*(av_fetch(av,i,0)));
8608                   draw_info->dash_pattern[i]=0.0;
8609                 }
8610             }
8611           if (attribute_flag[23] != 0)
8612             image->interpolate=(InterpolatePixelMethod)
8613               argument_list[23].integer_reference;
8614           if ((attribute_flag[24] != 0) &&
8615               (draw_info->fill_pattern != (Image *) NULL))
8616             flags=ParsePageGeometry(draw_info->fill_pattern,
8617               argument_list[24].string_reference,
8618               &draw_info->fill_pattern->tile_offset,exception);
8619           if (attribute_flag[25] != 0)
8620             {
8621               (void) ConcatenateString(&draw_info->primitive," '");
8622               (void) ConcatenateString(&draw_info->primitive,
8623                 argument_list[25].string_reference);
8624               (void) ConcatenateString(&draw_info->primitive,"'");
8625             }
8626           if (attribute_flag[26] != 0)
8627             draw_info->fill_pattern=CloneImage(
8628               argument_list[26].image_reference,0,0,MagickTrue,exception);
8629           if (attribute_flag[27] != 0)
8630             draw_info->stroke_pattern=CloneImage(
8631               argument_list[27].image_reference,0,0,MagickTrue,exception);
8632           if (attribute_flag[28] != 0)
8633             (void) CloneString(&draw_info->primitive,
8634               argument_list[28].string_reference);
8635           if (attribute_flag[29] != 0)
8636             draw_info->kerning=argument_list[29].real_reference;
8637           if (attribute_flag[30] != 0)
8638             draw_info->interline_spacing=argument_list[30].real_reference;
8639           if (attribute_flag[31] != 0)
8640             draw_info->interword_spacing=argument_list[31].real_reference;
8641           if (attribute_flag[32] != 0)
8642             draw_info->direction=(DirectionType)
8643               argument_list[32].integer_reference;
8644           DrawImage(image,draw_info,exception);
8645           draw_info=DestroyDrawInfo(draw_info);
8646           break;
8647         }
8648         case 39:  /* Equalize */
8649         {
8650           if (attribute_flag[0] != 0)
8651             channel=(ChannelType) argument_list[0].integer_reference;
8652           channel_mask=SetPixelChannelMask(image,channel);
8653           EqualizeImage(image,exception);
8654           (void) SetPixelChannelMask(image,channel_mask);
8655           break;
8656         }
8657         case 40:  /* Gamma */
8658         {
8659           if (attribute_flag[1] != 0)
8660             channel=(ChannelType) argument_list[1].integer_reference;
8661           if (attribute_flag[2] == 0)
8662             argument_list[2].real_reference=1.0;
8663           if (attribute_flag[3] == 0)
8664             argument_list[3].real_reference=1.0;
8665           if (attribute_flag[4] == 0)
8666             argument_list[4].real_reference=1.0;
8667           if (attribute_flag[0] == 0)
8668             {
8669               (void) FormatLocaleString(message,MaxTextExtent,
8670                 "%.15g,%.15g,%.15g",(double) argument_list[2].real_reference,
8671                 (double) argument_list[3].real_reference,
8672                 (double) argument_list[4].real_reference);
8673               argument_list[0].string_reference=message;
8674             }
8675           (void) GammaImage(image,InterpretLocaleValue(
8676             argument_list[0].string_reference,(char **) NULL),exception);
8677           break;
8678         }
8679         case 41:  /* Map */
8680         {
8681           QuantizeInfo
8682             *quantize_info;
8683
8684           if (attribute_flag[0] == 0)
8685             {
8686               ThrowPerlException(exception,OptionError,"MapImageRequired",
8687                 PackageName);
8688               goto PerlException;
8689             }
8690           quantize_info=AcquireQuantizeInfo(info->image_info);
8691           if (attribute_flag[1] != 0)
8692             quantize_info->dither=(MagickBooleanType)
8693               argument_list[1].integer_reference;
8694           if (attribute_flag[2] != 0)
8695             quantize_info->dither_method=(DitherMethod)
8696               argument_list[2].integer_reference;
8697           (void) RemapImages(quantize_info,image,
8698             argument_list[0].image_reference,exception);
8699           quantize_info=DestroyQuantizeInfo(quantize_info);
8700           break;
8701         }
8702         case 42:  /* MatteFloodfill */
8703         {
8704           DrawInfo
8705             *draw_info;
8706
8707           MagickBooleanType
8708             invert;
8709
8710           PixelInfo
8711             target;
8712
8713           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8714             (DrawInfo *) NULL);
8715           if (attribute_flag[0] != 0)
8716             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8717               &geometry,exception);
8718           if (attribute_flag[1] != 0)
8719             geometry.x=argument_list[1].integer_reference;
8720           if (attribute_flag[2] != 0)
8721             geometry.y=argument_list[2].integer_reference;
8722           if (image->matte == MagickFalse)
8723             (void) SetImageOpacity(image,OpaqueAlpha);
8724           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
8725             exception);
8726           if (attribute_flag[4] != 0)
8727             QueryMagickColor(argument_list[4].string_reference,&target,
8728               exception);
8729           if (attribute_flag[3] != 0)
8730             target.alpha=SiPrefixToDouble(argument_list[3].string_reference,
8731               QuantumRange);
8732           if (attribute_flag[5] != 0)
8733             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
8734               QuantumRange);
8735           invert=MagickFalse;
8736           if (attribute_flag[6] != 0)
8737             invert=(MagickBooleanType) argument_list[6].integer_reference;
8738           channel_mask=SetPixelChannelMask(image,AlphaChannel);
8739           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8740             geometry.y,invert,exception);
8741           (void) SetPixelChannelMask(image,channel_mask);
8742           draw_info=DestroyDrawInfo(draw_info);
8743           break;
8744         }
8745         case 43:  /* Modulate */
8746         {
8747           char
8748             modulate[MaxTextExtent];
8749
8750           geometry_info.rho=100.0;
8751           geometry_info.sigma=100.0;
8752           geometry_info.xi=100.0;
8753           if (attribute_flag[0] != 0)
8754             (void)ParseGeometry(argument_list[0].string_reference,
8755               &geometry_info);
8756           if (attribute_flag[1] != 0)
8757             geometry_info.xi=argument_list[1].real_reference;
8758           if (attribute_flag[2] != 0)
8759             geometry_info.sigma=argument_list[2].real_reference;
8760           if (attribute_flag[3] != 0)
8761             {
8762               geometry_info.sigma=argument_list[3].real_reference;
8763               SetImageArtifact(image,"modulate:colorspace","HWB");
8764             }
8765           if (attribute_flag[4] != 0)
8766             {
8767               geometry_info.rho=argument_list[4].real_reference;
8768               SetImageArtifact(image,"modulate:colorspace","HSB");
8769             }
8770           if (attribute_flag[5] != 0)
8771             {
8772               geometry_info.sigma=argument_list[5].real_reference;
8773               SetImageArtifact(image,"modulate:colorspace","HSL");
8774             }
8775           if (attribute_flag[6] != 0)
8776             {
8777               geometry_info.rho=argument_list[6].real_reference;
8778               SetImageArtifact(image,"modulate:colorspace","HWB");
8779             }
8780           (void) FormatLocaleString(modulate,MaxTextExtent,"%.15g,%.15g,%.15g",
8781             geometry_info.rho,geometry_info.sigma,geometry_info.xi);
8782           (void) ModulateImage(image,modulate,exception);
8783           break;
8784         }
8785         case 44:  /* Negate */
8786         {
8787           if (attribute_flag[0] == 0)
8788             argument_list[0].integer_reference=0;
8789           if (attribute_flag[1] != 0)
8790             channel=(ChannelType) argument_list[1].integer_reference;
8791           channel_mask=SetPixelChannelMask(image,channel);
8792           (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
8793             MagickTrue : MagickFalse,exception);
8794           (void) SetPixelChannelMask(image,channel_mask);
8795           break;
8796         }
8797         case 45:  /* Normalize */
8798         {
8799           if (attribute_flag[0] != 0)
8800             channel=(ChannelType) argument_list[0].integer_reference;
8801           channel_mask=SetPixelChannelMask(image,channel);
8802           NormalizeImage(image,exception);
8803           (void) SetPixelChannelMask(image,channel_mask);
8804           break;
8805         }
8806         case 46:  /* NumberColors */
8807           break;
8808         case 47:  /* Opaque */
8809         {
8810           MagickBooleanType
8811             invert;
8812
8813           PixelInfo
8814             fill_color,
8815             target;
8816
8817           (void) QueryMagickColor("none",&target,exception);
8818           (void) QueryMagickColor("none",&fill_color,exception);
8819           if (attribute_flag[0] != 0)
8820             (void) QueryMagickColor(argument_list[0].string_reference,
8821               &target,exception);
8822           if (attribute_flag[1] != 0)
8823             (void) QueryMagickColor(argument_list[1].string_reference,
8824               &fill_color,exception);
8825           if (attribute_flag[2] != 0)
8826             image->fuzz=SiPrefixToDouble(argument_list[2].string_reference,
8827               QuantumRange);
8828           if (attribute_flag[3] != 0)
8829             channel=(ChannelType) argument_list[3].integer_reference;
8830           invert=MagickFalse;
8831           if (attribute_flag[4] != 0)
8832             invert=(MagickBooleanType) argument_list[4].integer_reference;
8833           channel_mask=SetPixelChannelMask(image,channel);
8834           (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
8835           (void) SetPixelChannelMask(image,channel_mask);
8836           break;
8837         }
8838         case 48:  /* Quantize */
8839         {
8840           QuantizeInfo
8841             *quantize_info;
8842
8843           quantize_info=AcquireQuantizeInfo(info->image_info);
8844           if (attribute_flag[0] != 0)
8845             quantize_info->number_colors=(size_t)
8846               argument_list[0].integer_reference;
8847           if (attribute_flag[1] != 0)
8848             quantize_info->tree_depth=(size_t)
8849               argument_list[1].integer_reference;
8850           if (attribute_flag[2] != 0)
8851             quantize_info->colorspace=(ColorspaceType)
8852               argument_list[2].integer_reference;
8853           if (attribute_flag[3] != 0)
8854             quantize_info->dither=argument_list[3].integer_reference != 0 ?
8855               MagickTrue : MagickFalse;
8856           if (attribute_flag[4] != 0)
8857             quantize_info->measure_error=
8858               argument_list[4].integer_reference != 0 ? MagickTrue : MagickFalse;
8859           if (attribute_flag[5] != 0)
8860             (void) QueryColorDatabase(argument_list[5].string_reference,
8861               &image->transparent_color,exception);
8862           if (attribute_flag[5] && argument_list[5].integer_reference)
8863             {
8864               (void) QuantizeImages(quantize_info,image,exception);
8865               goto PerlException;
8866             }
8867           if (attribute_flag[6] != 0)
8868             quantize_info->dither_method=(DitherMethod)
8869               argument_list[6].integer_reference;
8870           if ((image->storage_class == DirectClass) ||
8871               (image->colors > quantize_info->number_colors) ||
8872               (quantize_info->colorspace == GRAYColorspace))
8873             (void) QuantizeImage(quantize_info,image,exception);
8874           else
8875             CompressImageColormap(image,exception);
8876           quantize_info=DestroyQuantizeInfo(quantize_info);
8877           break;
8878         }
8879         case 49:  /* Raise */
8880         {
8881           if (attribute_flag[0] != 0)
8882             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8883               &geometry,exception);
8884           if (attribute_flag[1] != 0)
8885             geometry.width=argument_list[1].integer_reference;
8886           if (attribute_flag[2] != 0)
8887             geometry.height=argument_list[2].integer_reference;
8888           if (attribute_flag[3] == 0)
8889             argument_list[3].integer_reference=1;
8890           (void) RaiseImage(image,&geometry,
8891             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8892             exception);
8893           break;
8894         }
8895         case 50:  /* Segment */
8896         {
8897           ColorspaceType
8898             colorspace;
8899
8900           double
8901             cluster_threshold,
8902             smoothing_threshold;
8903
8904           MagickBooleanType
8905             verbose;
8906
8907           cluster_threshold=1.0;
8908           smoothing_threshold=1.5;
8909           colorspace=RGBColorspace;
8910           verbose=MagickFalse;
8911           if (attribute_flag[0] != 0)
8912             {
8913               flags=ParseGeometry(argument_list[0].string_reference,
8914                 &geometry_info);
8915               cluster_threshold=geometry_info.rho;
8916               if (flags & SigmaValue)
8917                 smoothing_threshold=geometry_info.sigma;
8918             }
8919           if (attribute_flag[1] != 0)
8920             cluster_threshold=argument_list[1].real_reference;
8921           if (attribute_flag[2] != 0)
8922             smoothing_threshold=argument_list[2].real_reference;
8923           if (attribute_flag[3] != 0)
8924             colorspace=(ColorspaceType) argument_list[3].integer_reference;
8925           if (attribute_flag[4] != 0)
8926             verbose=argument_list[4].integer_reference != 0 ?
8927               MagickTrue : MagickFalse;
8928           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
8929             smoothing_threshold,exception);
8930           break;
8931         }
8932         case 51:  /* Signature */
8933         {
8934           (void) SignatureImage(image,exception);
8935           break;
8936         }
8937         case 52:  /* Solarize */
8938         {
8939           geometry_info.rho=QuantumRange/2.0;
8940           if (attribute_flag[0] != 0)
8941             flags=ParseGeometry(argument_list[0].string_reference,
8942               &geometry_info);
8943           if (attribute_flag[1] != 0)
8944             geometry_info.rho=SiPrefixToDouble(
8945              argument_list[1].string_reference,QuantumRange);
8946           (void) SolarizeImage(image,geometry_info.rho,exception);
8947           break;
8948         }
8949         case 53:  /* Sync */
8950         {
8951           (void) SyncImage(image);
8952           break;
8953         }
8954         case 54:  /* Texture */
8955         {
8956           if (attribute_flag[0] == 0)
8957             break;
8958           TextureImage(image,argument_list[0].image_reference);
8959           break;
8960         }
8961         case 55:  /* Evalute */
8962         {
8963           MagickEvaluateOperator
8964             op;
8965
8966           op=SetEvaluateOperator;
8967           if (attribute_flag[0] == MagickFalse)
8968             argument_list[0].real_reference=0.0;
8969           if (attribute_flag[1] != MagickFalse)
8970             op=(MagickEvaluateOperator) argument_list[1].integer_reference;
8971           if (attribute_flag[2] != MagickFalse)
8972             channel=(ChannelType) argument_list[2].integer_reference;
8973           channel_mask=SetPixelChannelMask(image,channel);
8974           (void) EvaluateImage(image,op,argument_list[0].real_reference,
8975             exception);
8976           (void) SetPixelChannelMask(image,channel_mask);
8977           break;
8978         }
8979         case 56:  /* Transparent */
8980         {
8981           double
8982             opacity;
8983
8984           MagickBooleanType
8985             invert;
8986
8987           PixelInfo
8988             target;
8989
8990           (void) QueryMagickColor("none",&target,exception);
8991           if (attribute_flag[0] != 0)
8992             (void) QueryMagickColor(argument_list[0].string_reference,&target,
8993               exception);
8994           opacity=TransparentAlpha;
8995           if (attribute_flag[1] != 0)
8996             opacity=SiPrefixToDouble(argument_list[1].string_reference,
8997               QuantumRange);
8998           if (attribute_flag[2] != 0)
8999             image->fuzz=SiPrefixToDouble(argument_list[2].string_reference,
9000               QuantumRange);
9001           if (attribute_flag[3] == 0)
9002             argument_list[3].integer_reference=0;
9003           invert=MagickFalse;
9004           if (attribute_flag[3] != 0)
9005             invert=(MagickBooleanType) argument_list[3].integer_reference;
9006           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9007             invert,exception);
9008           break;
9009         }
9010         case 57:  /* Threshold */
9011         {
9012           double
9013             threshold;
9014
9015           if (attribute_flag[0] == 0)
9016             argument_list[0].string_reference="50%";
9017           if (attribute_flag[1] != 0)
9018             channel=(ChannelType) argument_list[1].integer_reference;
9019           threshold=SiPrefixToDouble(argument_list[0].string_reference,
9020             QuantumRange);
9021           channel_mask=SetPixelChannelMask(image,channel);
9022           (void) BilevelImage(image,threshold);
9023           (void) SetPixelChannelMask(image,channel_mask);
9024           break;
9025         }
9026         case 58:  /* Charcoal */
9027         {
9028           if (attribute_flag[0] != 0)
9029             {
9030               flags=ParseGeometry(argument_list[0].string_reference,
9031                 &geometry_info);
9032               if ((flags & SigmaValue) == 0)
9033                 geometry_info.sigma=1.0;
9034             }
9035           if (attribute_flag[1] != 0)
9036             geometry_info.rho=argument_list[1].real_reference;
9037           if (attribute_flag[2] != 0)
9038             geometry_info.sigma=argument_list[2].real_reference;
9039           if (attribute_flag[3] != 0)
9040             geometry_info.xi=argument_list[3].real_reference;
9041           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9042             geometry_info.xi,exception);
9043           break;
9044         }
9045         case 59:  /* Trim */
9046         {
9047           if (attribute_flag[0] != 0)
9048             image->fuzz=SiPrefixToDouble(argument_list[0].string_reference,
9049               QuantumRange);
9050           image=TrimImage(image,exception);
9051           break;
9052         }
9053         case 60:  /* Wave */
9054         {
9055           if (attribute_flag[0] != 0)
9056             {
9057               flags=ParseGeometry(argument_list[0].string_reference,
9058                 &geometry_info);
9059               if ((flags & SigmaValue) == 0)
9060                 geometry_info.sigma=1.0;
9061             }
9062           if (attribute_flag[1] != 0)
9063             geometry_info.rho=argument_list[1].real_reference;
9064           if (attribute_flag[2] != 0)
9065             geometry_info.sigma=argument_list[2].real_reference;
9066           if (attribute_flag[3] != 0)
9067             image->interpolate=(InterpolatePixelMethod)
9068               argument_list[3].integer_reference;
9069           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9070             exception);
9071           break;
9072         }
9073         case 61:  /* Separate */
9074         {
9075           if (attribute_flag[0] != 0)
9076             channel=(ChannelType) argument_list[0].integer_reference;
9077           channel_mask=SetPixelChannelMask(image,channel);
9078           (void) SeparateImage(image);
9079           (void) SetPixelChannelMask(image,channel_mask);
9080           break;
9081         }
9082         case 63:  /* Stereo */
9083         {
9084           if (attribute_flag[0] == 0)
9085             {
9086               ThrowPerlException(exception,OptionError,"StereoImageRequired",
9087                 PackageName);
9088               goto PerlException;
9089             }
9090           if (attribute_flag[1] != 0)
9091             geometry.x=argument_list[1].integer_reference;
9092           if (attribute_flag[2] != 0)
9093             geometry.y=argument_list[2].integer_reference;
9094           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9095             geometry.x,geometry.y,exception);
9096           break;
9097         }
9098         case 64:  /* Stegano */
9099         {
9100           if (attribute_flag[0] == 0)
9101             {
9102               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9103                 PackageName);
9104               goto PerlException;
9105             }
9106           if (attribute_flag[1] == 0)
9107             argument_list[1].integer_reference=0;
9108           image->offset=argument_list[1].integer_reference;
9109           image=SteganoImage(image,argument_list[0].image_reference,exception);
9110           break;
9111         }
9112         case 65:  /* Deconstruct */
9113         {
9114           image=CompareImagesLayers(image,CompareAnyLayer,exception);
9115           break;
9116         }
9117         case 66:  /* GaussianBlur */
9118         {
9119           if (attribute_flag[0] != 0)
9120             {
9121               flags=ParseGeometry(argument_list[0].string_reference,
9122                 &geometry_info);
9123               if ((flags & SigmaValue) == 0)
9124                 geometry_info.sigma=1.0;
9125             }
9126           if (attribute_flag[1] != 0)
9127             geometry_info.rho=argument_list[1].real_reference;
9128           if (attribute_flag[2] != 0)
9129             geometry_info.sigma=argument_list[2].real_reference;
9130           if (attribute_flag[3] != 0)
9131             geometry_info.xi=argument_list[3].real_reference;
9132           if (attribute_flag[4] != 0)
9133             channel=(ChannelType) argument_list[4].integer_reference;
9134           channel_mask=SetPixelChannelMask(image,channel);
9135           image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9136             geometry_info.xi,exception);
9137           if (image != (Image *) NULL)
9138             (void) SetPixelChannelMask(image,channel_mask);
9139           break;
9140         }
9141         case 67:  /* Convolve */
9142         {
9143           KernelInfo
9144             *kernel;
9145
9146           kernel=(KernelInfo *) NULL;
9147           if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9148             break;
9149           if (attribute_flag[0] != 0)
9150             {
9151               AV
9152                 *av;
9153
9154               size_t
9155                 order;
9156
9157               kernel=AcquireKernelInfo((const char *) NULL);
9158               if (kernel == (KernelInfo *) NULL)
9159                 break;
9160               av=(AV *) argument_list[0].array_reference;
9161               order=(size_t) sqrt(av_len(av)+1);
9162               kernel->width=order;
9163               kernel->height=order;
9164               kernel->values=(double *) AcquireQuantumMemory(order,order*
9165                 sizeof(*kernel->values));
9166               if (kernel->values == (double *) NULL)
9167                 {
9168                   kernel=DestroyKernelInfo(kernel);
9169                   ThrowPerlException(exception,ResourceLimitFatalError,
9170                     "MemoryAllocationFailed",PackageName);
9171                   goto PerlException;
9172                 }
9173               for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9174                 kernel->values[j]=(double) SvNV(*(av_fetch(av,j,0)));
9175               for ( ; j < (ssize_t) (order*order); j++)
9176                 kernel->values[j]=0.0;
9177             }
9178           if (attribute_flag[1] != 0)
9179             channel=(ChannelType) argument_list[1].integer_reference;
9180           if (attribute_flag[2] != 0)
9181             image->bias=SiPrefixToDouble(argument_list[2].string_reference,
9182               QuantumRange);
9183           if (attribute_flag[3] != 0)
9184             {
9185               kernel=AcquireKernelInfo(argument_list[3].string_reference);
9186               if (kernel == (KernelInfo *) NULL)
9187                 break;
9188             }
9189           channel_mask=SetPixelChannelMask(image,channel);
9190           kernel->bias=image->bias;
9191           image=ConvolveImage(image,kernel,exception);
9192           if (image != (Image *) NULL)
9193             (void) SetPixelChannelMask(image,channel_mask);
9194           kernel=DestroyKernelInfo(kernel);
9195           break;
9196         }
9197         case 68:  /* Profile */
9198         {
9199           const char
9200             *name;
9201
9202           Image
9203             *profile_image;
9204
9205           ImageInfo
9206             *profile_info;
9207
9208           StringInfo
9209             *profile;
9210
9211           name="*";
9212           if (attribute_flag[0] != 0)
9213             name=argument_list[0].string_reference;
9214           if (attribute_flag[2] != 0)
9215             image->rendering_intent=(RenderingIntent)
9216               argument_list[2].integer_reference;
9217           if (attribute_flag[3] != 0)
9218             image->black_point_compensation=
9219               argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9220           if (attribute_flag[1] != 0)
9221             {
9222               if (argument_list[1].length == 0)
9223                 {
9224                   /*
9225                     Remove a profile from the image.
9226                   */
9227                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9228                     MagickTrue);
9229                   break;
9230                 }
9231               /*
9232                 Associate user supplied profile with the image.
9233               */
9234               profile=AcquireStringInfo(argument_list[1].length);
9235               SetStringInfoDatum(profile,(const unsigned char *)
9236                 argument_list[1].string_reference);
9237               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9238                 (size_t) GetStringInfoLength(profile),MagickFalse);
9239               profile=DestroyStringInfo(profile);
9240               break;
9241             }
9242           /*
9243             Associate a profile with the image.
9244           */
9245           profile_info=
9246             CloneImageInfo(info ? info->image_info : (ImageInfo *) NULL);
9247           (void) CopyMagickString(profile_info->filename,name,MaxTextExtent);
9248           profile_image=ReadImages(profile_info,&image->exception);
9249           if (profile_image == (Image *) NULL)
9250             break;
9251           ResetImageProfileIterator(profile_image);
9252           name=GetNextImageProfile(profile_image);
9253           while (name != (const char *) NULL)
9254           {
9255             const StringInfo
9256               *profile;
9257
9258             profile=GetImageProfile(profile_image,name);
9259             if (profile != (const StringInfo *) NULL)
9260               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9261                 (size_t) GetStringInfoLength(profile),MagickFalse);
9262             name=GetNextImageProfile(profile_image);
9263           }
9264           profile_image=DestroyImage(profile_image);
9265           profile_info=DestroyImageInfo(profile_info);
9266           break;
9267         }
9268         case 69:  /* UnsharpMask */
9269         {
9270           if (attribute_flag[0] != 0)
9271             {
9272               flags=ParseGeometry(argument_list[0].string_reference,
9273                 &geometry_info);
9274               if ((flags & SigmaValue) == 0)
9275                 geometry_info.sigma=1.0;
9276               if ((flags & XiValue) == 0)
9277                 geometry_info.xi=1.0;
9278               if ((flags & PsiValue) == 0)
9279                 geometry_info.psi=0.5;
9280             }
9281           if (attribute_flag[1] != 0)
9282             geometry_info.rho=argument_list[1].real_reference;
9283           if (attribute_flag[2] != 0)
9284             geometry_info.sigma=argument_list[2].real_reference;
9285           if (attribute_flag[3] != 0)
9286             geometry_info.xi=argument_list[3].real_reference;
9287           if (attribute_flag[4] != 0)
9288             geometry_info.psi=argument_list[4].real_reference;
9289           if (attribute_flag[5] != 0)
9290             channel=(ChannelType) argument_list[5].integer_reference;
9291           channel_mask=SetPixelChannelMask(image,channel);
9292           image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9293             geometry_info.xi,geometry_info.psi,exception);
9294           if (image != (Image *) NULL)
9295             (void) SetPixelChannelMask(image,channel_mask);
9296           break;
9297         }
9298         case 70:  /* MotionBlur */
9299         {
9300           if (attribute_flag[0] != 0)
9301             {
9302               flags=ParseGeometry(argument_list[0].string_reference,
9303                 &geometry_info);
9304               if ((flags & SigmaValue) == 0)
9305                 geometry_info.sigma=1.0;
9306               if ((flags & XiValue) == 0)
9307                 geometry_info.xi=1.0;
9308             }
9309           if (attribute_flag[1] != 0)
9310             geometry_info.rho=argument_list[1].real_reference;
9311           if (attribute_flag[2] != 0)
9312             geometry_info.sigma=argument_list[2].real_reference;
9313           if (attribute_flag[3] != 0)
9314             geometry_info.xi=argument_list[3].real_reference;
9315           if (attribute_flag[4] != 0)
9316             geometry_info.psi=argument_list[4].real_reference;
9317           if (attribute_flag[5] != 0)
9318             channel=(ChannelType) argument_list[5].integer_reference;
9319           channel_mask=SetPixelChannelMask(image,channel);
9320           image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9321             geometry_info.xi,geometry_info.psi,exception);
9322           if (image != (Image *) NULL)
9323             (void) SetPixelChannelMask(image,channel_mask);
9324           break;
9325         }
9326         case 71:  /* OrderedDither */
9327         {
9328           if (attribute_flag[0] == 0)
9329             argument_list[0].string_reference="o8x8";
9330           if (attribute_flag[1] != 0)
9331             channel=(ChannelType) argument_list[1].integer_reference;
9332           channel_mask=SetPixelChannelMask(image,channel);
9333           (void) OrderedPosterizeImage(image,argument_list[0].string_reference,
9334             exception);
9335           (void) SetPixelChannelMask(image,channel_mask);
9336           break;
9337         }
9338         case 72:  /* Shave */
9339         {
9340           if (attribute_flag[0] != 0)
9341             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9342               &geometry,exception);
9343           if (attribute_flag[1] != 0)
9344             geometry.width=argument_list[1].integer_reference;
9345           if (attribute_flag[2] != 0)
9346             geometry.height=argument_list[2].integer_reference;
9347           image=ShaveImage(image,&geometry,exception);
9348           break;
9349         }
9350         case 73:  /* Level */
9351         {
9352           double
9353             black_point,
9354             gamma,
9355             white_point;
9356
9357           black_point=0.0;
9358           white_point=(MagickRealType) image->columns*image->rows;
9359           gamma=1.0;
9360           if (attribute_flag[0] != 0)
9361             {
9362               flags=ParseGeometry(argument_list[0].string_reference,
9363                 &geometry_info);
9364               black_point=geometry_info.rho;
9365               if ((flags & SigmaValue) != 0)
9366                 white_point=geometry_info.sigma;
9367               if ((flags & XiValue) != 0)
9368                 gamma=geometry_info.xi;
9369               if ((flags & PercentValue) != 0)
9370                 {
9371                   black_point*=(double) (QuantumRange/100.0);
9372                   white_point*=(double) (QuantumRange/100.0);
9373                 }
9374               if ((flags & SigmaValue) == 0)
9375                 white_point=(double) QuantumRange-black_point;
9376             }
9377           if (attribute_flag[1] != 0)
9378             black_point=argument_list[1].real_reference;
9379           if (attribute_flag[2] != 0)
9380             white_point=argument_list[2].real_reference;
9381           if (attribute_flag[3] != 0)
9382             gamma=argument_list[3].real_reference;
9383           if (attribute_flag[4] != 0)
9384             channel=(ChannelType) argument_list[4].integer_reference;
9385           if (attribute_flag[5] != 0)
9386             {
9387               argument_list[0].real_reference=argument_list[5].real_reference;
9388               attribute_flag[0]=attribute_flag[5];
9389             }
9390           channel_mask=SetPixelChannelMask(image,channel);
9391           (void) LevelImage(image,black_point,white_point,gamma,exception);
9392           (void) SetPixelChannelMask(image,channel_mask);
9393           break;
9394         }
9395         case 74:  /* Clip */
9396         {
9397           if (attribute_flag[0] == 0)
9398             argument_list[0].string_reference="#1";
9399           if (attribute_flag[1] == 0)
9400             argument_list[1].integer_reference=MagickTrue;
9401           (void) ClipImagePath(image,argument_list[0].string_reference,
9402             argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse,
9403             exception);
9404           break;
9405         }
9406         case 75:  /* AffineTransform */
9407         {
9408           DrawInfo
9409             *draw_info;
9410
9411           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9412             (DrawInfo *) NULL);
9413           if (attribute_flag[0] != 0)
9414             {
9415               AV
9416                 *av;
9417
9418               av=(AV *) argument_list[0].array_reference;
9419               if ((av_len(av) != 3) && (av_len(av) != 5))
9420                 {
9421                   ThrowPerlException(exception,OptionError,
9422                     "affine matrix must have 4 or 6 elements",PackageName);
9423                   goto PerlException;
9424                 }
9425               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9426               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9427               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9428               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9429               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9430                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9431                 {
9432                   ThrowPerlException(exception,OptionError,
9433                     "affine matrix is singular",PackageName);
9434                    goto PerlException;
9435                 }
9436               if (av_len(av) == 5)
9437                 {
9438                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9439                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9440                 }
9441             }
9442           for (j=1; j < 6; j++)
9443           {
9444             if (attribute_flag[j] == 0)
9445               continue;
9446             value=argument_list[j].string_reference;
9447             angle=argument_list[j].real_reference;
9448             current=draw_info->affine;
9449             GetAffineMatrix(&affine);
9450             switch (j)
9451             {
9452               case 1:
9453               {
9454                 /*
9455                   Translate.
9456                 */
9457                 flags=ParseGeometry(value,&geometry_info);
9458                 affine.tx=geometry_info.xi;
9459                 affine.ty=geometry_info.psi;
9460                 if ((flags & PsiValue) == 0)
9461                   affine.ty=affine.tx;
9462                 break;
9463               }
9464               case 2:
9465               {
9466                 /*
9467                   Scale.
9468                 */
9469                 flags=ParseGeometry(value,&geometry_info);
9470                 affine.sx=geometry_info.rho;
9471                 affine.sy=geometry_info.sigma;
9472                 if ((flags & SigmaValue) == 0)
9473                   affine.sy=affine.sx;
9474                 break;
9475               }
9476               case 3:
9477               {
9478                 /*
9479                   Rotate.
9480                 */
9481                 if (angle == 0.0)
9482                   break;
9483                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9484                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9485                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9486                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9487                 break;
9488               }
9489               case 4:
9490               {
9491                 /*
9492                   SkewX.
9493                 */
9494                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9495                 break;
9496               }
9497               case 5:
9498               {
9499                 /*
9500                   SkewY.
9501                 */
9502                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9503                 break;
9504               }
9505             }
9506             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9507             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9508             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9509             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9510             draw_info->affine.tx=
9511               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9512             draw_info->affine.ty=
9513               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9514           }
9515           if (attribute_flag[6] != 0)
9516             image->interpolate=(InterpolatePixelMethod)
9517               argument_list[6].integer_reference;
9518           if (attribute_flag[7] != 0)
9519             QueryColorDatabase(argument_list[7].string_reference,
9520               &image->background_color,exception);
9521           image=AffineTransformImage(image,&draw_info->affine,exception);
9522           draw_info=DestroyDrawInfo(draw_info);
9523           break;
9524         }
9525         case 76:  /* Difference */
9526         {
9527           if (attribute_flag[0] == 0)
9528             {
9529               ThrowPerlException(exception,OptionError,
9530                 "ReferenceImageRequired",PackageName);
9531               goto PerlException;
9532             }
9533           if (attribute_flag[1] != 0)
9534             image->fuzz=SiPrefixToDouble(argument_list[1].string_reference,
9535               QuantumRange);
9536           (void) IsImagesEqual(image,argument_list[0].image_reference,
9537             exception);
9538           break;
9539         }
9540         case 77:  /* AdaptiveThreshold */
9541         {
9542           if (attribute_flag[0] != 0)
9543             {
9544               flags=ParseGeometry(argument_list[0].string_reference,
9545                 &geometry_info);
9546               if ((flags & PercentValue) != 0)
9547                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9548             }
9549           if (attribute_flag[1] != 0)
9550             geometry_info.rho=argument_list[1].integer_reference;
9551           if (attribute_flag[2] != 0)
9552             geometry_info.sigma=argument_list[2].integer_reference;
9553           if (attribute_flag[3] != 0)
9554             geometry_info.xi=argument_list[3].integer_reference;;
9555           image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
9556             (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
9557           break;
9558         }
9559         case 78:  /* Resample */
9560         {
9561           size_t
9562             height,
9563             width;
9564
9565           if (attribute_flag[0] != 0)
9566             {
9567               flags=ParseGeometry(argument_list[0].string_reference,
9568                 &geometry_info);
9569               if ((flags & SigmaValue) == 0)
9570                 geometry_info.sigma=geometry_info.rho;
9571             }
9572           if (attribute_flag[1] != 0)
9573             geometry_info.rho=argument_list[1].real_reference;
9574           if (attribute_flag[2] != 0)
9575             geometry_info.sigma=argument_list[2].real_reference;
9576           if (attribute_flag[3] == 0)
9577             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
9578           if (attribute_flag[4] == 0)
9579             SetImageArtifact(image,"filter:support",
9580               argument_list[4].string_reference);
9581           if (attribute_flag[5] != 0)
9582             argument_list[5].real_reference=1.0;
9583           width=(size_t) (geometry_info.rho*image->columns/
9584             (image->x_resolution == 0.0 ? 72.0 : image->x_resolution)+0.5);
9585           height=(size_t) (geometry_info.sigma*image->rows/
9586             (image->y_resolution == 0.0 ? 72.0 : image->y_resolution)+0.5);
9587           image=ResizeImage(image,width,height,(FilterTypes)
9588             argument_list[3].integer_reference,argument_list[5].real_reference,
9589             exception);
9590           if (image != (Image *) NULL)
9591             {
9592               image->x_resolution=geometry_info.rho;
9593               image->y_resolution=geometry_info.sigma;
9594             }
9595           break;
9596         }
9597         case 79:  /* Describe */
9598         {
9599           if (attribute_flag[0] == 0)
9600             argument_list[0].file_reference=(FILE *) NULL;
9601           if (attribute_flag[1] != 0)
9602             (void) SetImageArtifact(image,"identify:features",
9603               argument_list[1].string_reference);
9604           (void) IdentifyImage(image,argument_list[0].file_reference,
9605             MagickTrue,exception);
9606           break;
9607         }
9608         case 80:  /* BlackThreshold */
9609         {
9610           if (attribute_flag[0] == 0)
9611             argument_list[0].string_reference="50%";
9612           if (attribute_flag[2] != 0)
9613             channel=(ChannelType) argument_list[2].integer_reference;
9614           channel_mask=SetPixelChannelMask(image,channel);
9615           BlackThresholdImage(image,argument_list[0].string_reference,
9616             exception);
9617           (void) SetPixelChannelMask(image,channel_mask);
9618           break;
9619         }
9620         case 81:  /* WhiteThreshold */
9621         {
9622           if (attribute_flag[0] == 0)
9623             argument_list[0].string_reference="50%";
9624           if (attribute_flag[2] != 0)
9625             channel=(ChannelType) argument_list[2].integer_reference;
9626           channel_mask=SetPixelChannelMask(image,channel);
9627           WhiteThresholdImage(image,argument_list[0].string_reference,
9628             exception);
9629           (void) SetPixelChannelMask(image,channel_mask);
9630           break;
9631         }
9632         case 82:  /* RadialBlur */
9633         {
9634           if (attribute_flag[0] != 0)
9635             {
9636               flags=ParseGeometry(argument_list[0].string_reference,
9637                 &geometry_info);
9638             }
9639           if (attribute_flag[1] != 0)
9640             geometry_info.rho=argument_list[1].real_reference;
9641           if (attribute_flag[2] != 0)
9642             geometry_info.sigma=argument_list[2].real_reference;
9643           if (attribute_flag[3] != 0)
9644             channel=(ChannelType) argument_list[3].integer_reference;
9645           channel_mask=SetPixelChannelMask(image,channel);
9646           image=RadialBlurImage(image,geometry_info.rho,geometry_info.sigma,
9647             exception);
9648           if (image != (Image *) NULL)
9649             (void) SetPixelChannelMask(image,channel_mask);
9650           break;
9651         }
9652         case 83:  /* Thumbnail */
9653         {
9654           if (attribute_flag[0] != 0)
9655             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
9656               &geometry,exception);
9657           if (attribute_flag[1] != 0)
9658             geometry.width=argument_list[1].integer_reference;
9659           if (attribute_flag[2] != 0)
9660             geometry.height=argument_list[2].integer_reference;
9661           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
9662           break;
9663         }
9664         case 84:  /* Strip */
9665         {
9666           (void) StripImage(image);
9667           break;
9668         }
9669         case 85:  /* Tint */
9670         {
9671           PixelPacket
9672             target;
9673
9674           (void) GetOneVirtualPixel(image,0,0,&target,exception);
9675           if (attribute_flag[0] != 0)
9676             (void) QueryColorDatabase(argument_list[0].string_reference,&target,
9677               exception);
9678           if (attribute_flag[1] == 0)
9679             argument_list[1].string_reference="100";
9680           image=TintImage(image,argument_list[1].string_reference,target,
9681             exception);
9682           break;
9683         }
9684         case 86:  /* Channel */
9685         {
9686           if (attribute_flag[0] != 0)
9687             channel=(ChannelType) argument_list[0].integer_reference;
9688           channel_mask=SetPixelChannelMask(image,channel);
9689           (void) SeparateImage(image);
9690           (void) SetPixelChannelMask(image,channel_mask);
9691           break;
9692         }
9693         case 87:  /* Splice */
9694         {
9695           if (attribute_flag[0] != 0)
9696             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
9697               &geometry,exception);
9698           if (attribute_flag[1] != 0)
9699             geometry.width=argument_list[1].integer_reference;
9700           if (attribute_flag[2] != 0)
9701             geometry.height=argument_list[2].integer_reference;
9702           if (attribute_flag[3] != 0)
9703             geometry.x=argument_list[3].integer_reference;
9704           if (attribute_flag[4] != 0)
9705             geometry.y=argument_list[4].integer_reference;
9706           if (attribute_flag[5] != 0)
9707             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
9708               QuantumRange);
9709           if (attribute_flag[6] != 0)
9710             (void) QueryColorDatabase(argument_list[6].string_reference,
9711               &image->background_color,exception);
9712           if (attribute_flag[7] != 0)
9713             image->gravity=(GravityType) argument_list[7].integer_reference;
9714           image=SpliceImage(image,&geometry,exception);
9715           break;
9716         }
9717         case 88:  /* Posterize */
9718         {
9719           if (attribute_flag[0] == 0)
9720             argument_list[0].integer_reference=3;
9721           if (attribute_flag[1] == 0)
9722             argument_list[1].integer_reference=0;
9723           (void) PosterizeImage(image,argument_list[0].integer_reference,
9724             argument_list[1].integer_reference ? MagickTrue : MagickFalse,
9725             exception);
9726           break;
9727         }
9728         case 89:  /* Shadow */
9729         {
9730           if (attribute_flag[0] != 0)
9731             {
9732               flags=ParseGeometry(argument_list[0].string_reference,
9733                 &geometry_info);
9734               if ((flags & SigmaValue) == 0)
9735                 geometry_info.sigma=1.0;
9736               if ((flags & XiValue) == 0)
9737                 geometry_info.xi=4.0;
9738               if ((flags & PsiValue) == 0)
9739                 geometry_info.psi=4.0;
9740             }
9741           if (attribute_flag[1] != 0)
9742             geometry_info.rho=argument_list[1].real_reference;
9743           if (attribute_flag[2] != 0)
9744             geometry_info.sigma=argument_list[2].real_reference;
9745           if (attribute_flag[3] != 0)
9746             geometry_info.xi=argument_list[3].integer_reference;
9747           if (attribute_flag[4] != 0)
9748             geometry_info.psi=argument_list[4].integer_reference;
9749           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
9750             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-
9751             0.5),exception);
9752           break;
9753         }
9754         case 90:  /* Identify */
9755         {
9756           if (attribute_flag[0] == 0)
9757             argument_list[0].file_reference=(FILE *) NULL;
9758           if (attribute_flag[1] != 0)
9759             (void) SetImageArtifact(image,"identify:features",
9760               argument_list[1].string_reference);
9761           if ((attribute_flag[2] != 0) &&
9762               (argument_list[2].integer_reference != 0))
9763             (void) SetImageArtifact(image,"identify:unique","true");
9764           (void) IdentifyImage(image,argument_list[0].file_reference,
9765             MagickTrue,exception);
9766           break;
9767         }
9768         case 91:  /* SepiaTone */
9769         {
9770           if (attribute_flag[0] == 0)
9771             argument_list[0].real_reference=80.0*QuantumRange/100.0;
9772           image=SepiaToneImage(image,argument_list[0].real_reference,
9773             exception);
9774           break;
9775         }
9776         case 92:  /* SigmoidalContrast */
9777         {
9778           MagickBooleanType
9779             sharpen;
9780
9781           if (attribute_flag[0] != 0)
9782             {
9783               flags=ParseGeometry(argument_list[0].string_reference,
9784                 &geometry_info);
9785               if ((flags & SigmaValue) == 0)
9786                 geometry_info.sigma=QuantumRange/2.0;
9787               if ((flags & PercentValue) != 0)
9788                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
9789             }
9790           if (attribute_flag[1] != 0)
9791             geometry_info.rho=argument_list[1].real_reference;
9792           if (attribute_flag[2] != 0)
9793             geometry_info.sigma=argument_list[2].real_reference;
9794           if (attribute_flag[3] != 0)
9795             channel=(ChannelType) argument_list[3].integer_reference;
9796           sharpen=MagickTrue;
9797           if (attribute_flag[4] != 0)
9798             sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
9799               MagickFalse;
9800           channel_mask=SetPixelChannelMask(image,channel);
9801           (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
9802             geometry_info.sigma,exception);
9803           (void) SetPixelChannelMask(image,channel_mask);
9804           break;
9805         }
9806         case 93:  /* Extent */
9807         {
9808           if (attribute_flag[7] != 0)
9809             image->gravity=(GravityType) argument_list[7].integer_reference;
9810           if (attribute_flag[0] != 0)
9811             {
9812               int
9813                 flags;
9814
9815               flags=ParseGravityGeometry(image,
9816                 argument_list[0].string_reference,&geometry,exception);
9817               (void) flags;
9818               if (geometry.width == 0)
9819                 geometry.width=image->columns;
9820               if (geometry.height == 0)
9821                 geometry.height=image->rows;
9822             }
9823           if (attribute_flag[1] != 0)
9824             geometry.width=argument_list[1].integer_reference;
9825           if (attribute_flag[2] != 0)
9826             geometry.height=argument_list[2].integer_reference;
9827           if (attribute_flag[3] != 0)
9828             geometry.x=argument_list[3].integer_reference;
9829           if (attribute_flag[4] != 0)
9830             geometry.y=argument_list[4].integer_reference;
9831           if (attribute_flag[5] != 0)
9832             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
9833               QuantumRange);
9834           if (attribute_flag[6] != 0)
9835             (void) QueryColorDatabase(argument_list[6].string_reference,
9836               &image->background_color,exception);
9837           image=ExtentImage(image,&geometry,exception);
9838           break;
9839         }
9840         case 94:  /* Vignette */
9841         {
9842           if (attribute_flag[0] != 0)
9843             {
9844               flags=ParseGeometry(argument_list[0].string_reference,
9845                 &geometry_info);
9846               if ((flags & SigmaValue) == 0)
9847                 geometry_info.sigma=1.0;
9848               if ((flags & XiValue) == 0)
9849                 geometry_info.xi=0.1*image->columns;
9850               if ((flags & PsiValue) == 0)
9851                 geometry_info.psi=0.1*image->rows;
9852             }
9853           if (attribute_flag[1] != 0)
9854             geometry_info.rho=argument_list[1].real_reference;
9855           if (attribute_flag[2] != 0)
9856             geometry_info.sigma=argument_list[2].real_reference;
9857           if (attribute_flag[3] != 0)
9858             geometry_info.xi=argument_list[3].integer_reference;
9859           if (attribute_flag[4] != 0)
9860             geometry_info.psi=argument_list[4].integer_reference;
9861           if (attribute_flag[5] != 0)
9862             (void) QueryColorDatabase(argument_list[5].string_reference,
9863               &image->background_color,exception);
9864           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
9865             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-
9866             0.5),exception);
9867           break;
9868         }
9869         case 95:  /* ContrastStretch */
9870         {
9871           double
9872             black_point,
9873             white_point;
9874
9875           black_point=0.0;
9876           white_point=(MagickRealType) image->columns*image->rows;
9877           if (attribute_flag[0] != 0)
9878             {
9879               flags=ParseGeometry(argument_list[0].string_reference,
9880                 &geometry_info);
9881               black_point=geometry_info.rho;
9882               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
9883                 black_point;
9884               if ((flags & PercentValue) != 0)
9885                 {
9886                   black_point*=(double) image->columns*image->rows/100.0;
9887                   white_point*=(double) image->columns*image->rows/100.0;
9888                 }
9889               white_point=(MagickRealType) image->columns*image->rows-
9890                 white_point;
9891             }
9892           if (attribute_flag[1] != 0)
9893             black_point=argument_list[1].real_reference;
9894           if (attribute_flag[2] != 0)
9895             white_point=argument_list[2].real_reference;
9896           if (attribute_flag[4] != 0)
9897             channel=(ChannelType) argument_list[4].integer_reference;
9898           channel_mask=SetPixelChannelMask(image,channel);
9899           (void) ContrastStretchImage(image,black_point,white_point,exception);
9900           (void) SetPixelChannelMask(image,channel_mask);
9901           break;
9902         }
9903         case 96:  /* Sans0 */
9904         {
9905           break;
9906         }
9907         case 97:  /* Sans1 */
9908         {
9909           break;
9910         }
9911         case 98:  /* AdaptiveSharpen */
9912         {
9913           if (attribute_flag[0] != 0)
9914             {
9915               flags=ParseGeometry(argument_list[0].string_reference,
9916                 &geometry_info);
9917               if ((flags & SigmaValue) == 0)
9918                 geometry_info.sigma=1.0;
9919               if ((flags & XiValue) == 0)
9920                 geometry_info.xi=0.0;
9921             }
9922           if (attribute_flag[1] != 0)
9923             geometry_info.rho=argument_list[1].real_reference;
9924           if (attribute_flag[2] != 0)
9925             geometry_info.sigma=argument_list[2].real_reference;
9926           if (attribute_flag[3] != 0)
9927             geometry_info.xi=argument_list[3].real_reference;
9928           if (attribute_flag[4] != 0)
9929             channel=(ChannelType) argument_list[4].integer_reference;
9930           channel_mask=SetPixelChannelMask(image,channel);
9931           image=AdaptiveSharpenImage(image,geometry_info.rho,
9932             geometry_info.sigma,geometry_info.xi,exception);
9933           if (image != (Image *) NULL)
9934             (void) SetPixelChannelMask(image,channel_mask);
9935           break;
9936         }
9937         case 99:  /* Transpose */
9938         {
9939           image=TransposeImage(image,exception);
9940           break;
9941         }
9942         case 100:  /* Tranverse */
9943         {
9944           image=TransverseImage(image,exception);
9945           break;
9946         }
9947         case 101:  /* AutoOrient */
9948         {
9949           switch (image->orientation)
9950           {
9951             case TopRightOrientation:
9952             {
9953               image=FlopImage(image,exception);
9954               break;
9955             }
9956             case BottomRightOrientation:
9957             {
9958               image=RotateImage(image,180.0,exception);
9959               break;
9960             }
9961             case BottomLeftOrientation:
9962             {
9963               image=FlipImage(image,exception);
9964               break;
9965             }
9966             case LeftTopOrientation:
9967             {
9968               image=TransposeImage(image,exception);
9969               break;
9970             }
9971             case RightTopOrientation:
9972             {
9973               image=RotateImage(image,90.0,exception);
9974               break;
9975             }
9976             case RightBottomOrientation:
9977             {
9978               image=TransverseImage(image,exception);
9979               break;
9980             }
9981             case LeftBottomOrientation:
9982             {
9983               image=RotateImage(image,270.0,exception);
9984               break;
9985             }
9986             default:
9987               break;
9988           }
9989           break;
9990         }
9991         case 102:  /* AdaptiveBlur */
9992         {
9993           if (attribute_flag[0] != 0)
9994             {
9995               flags=ParseGeometry(argument_list[0].string_reference,
9996                 &geometry_info);
9997               if ((flags & SigmaValue) == 0)
9998                 geometry_info.sigma=1.0;
9999               if ((flags & XiValue) == 0)
10000                 geometry_info.xi=0.0;
10001             }
10002           if (attribute_flag[1] != 0)
10003             geometry_info.rho=argument_list[1].real_reference;
10004           if (attribute_flag[2] != 0)
10005             geometry_info.sigma=argument_list[2].real_reference;
10006           if (attribute_flag[3] != 0)
10007             geometry_info.xi=argument_list[3].real_reference;
10008           if (attribute_flag[4] != 0)
10009             channel=(ChannelType) argument_list[4].integer_reference;
10010           channel_mask=SetPixelChannelMask(image,channel);
10011           image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10012             geometry_info.xi,exception);
10013           if (image != (Image *) NULL)
10014             (void) SetPixelChannelMask(image,channel_mask);
10015           break;
10016         }
10017         case 103:  /* Sketch */
10018         {
10019           if (attribute_flag[0] != 0)
10020             {
10021               flags=ParseGeometry(argument_list[0].string_reference,
10022                 &geometry_info);
10023               if ((flags & SigmaValue) == 0)
10024                 geometry_info.sigma=1.0;
10025               if ((flags & XiValue) == 0)
10026                 geometry_info.xi=1.0;
10027             }
10028           if (attribute_flag[1] != 0)
10029             geometry_info.rho=argument_list[1].real_reference;
10030           if (attribute_flag[2] != 0)
10031             geometry_info.sigma=argument_list[2].real_reference;
10032           if (attribute_flag[3] != 0)
10033             geometry_info.xi=argument_list[3].real_reference;
10034           if (attribute_flag[4] != 0)
10035             geometry_info.psi=argument_list[4].real_reference;
10036           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10037             geometry_info.xi,geometry_info.psi,exception);
10038           break;
10039         }
10040         case 104:  /* UniqueColors */
10041         {
10042           image=UniqueImageColors(image,exception);
10043           break;
10044         }
10045         case 105:  /* AdaptiveResize */
10046         {
10047           if (attribute_flag[0] != 0)
10048             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10049               &geometry,exception);
10050           if (attribute_flag[1] != 0)
10051             geometry.width=argument_list[1].integer_reference;
10052           if (attribute_flag[2] != 0)
10053             geometry.height=argument_list[2].integer_reference;
10054           if (attribute_flag[3] != 0)
10055             image->filter=(FilterTypes) argument_list[4].integer_reference;
10056           if (attribute_flag[4] != 0)
10057             SetImageArtifact(image,"filter:support",
10058               argument_list[4].string_reference);
10059           if (attribute_flag[5] != 0)
10060             image->blur=argument_list[5].real_reference;
10061           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10062             exception);
10063           break;
10064         }
10065         case 106:  /* ClipMask */
10066         {
10067           if (attribute_flag[0] == 0)
10068             {
10069               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10070                 PackageName);
10071               goto PerlException;
10072             }
10073           image->clip_mask=CloneImage(argument_list[0].image_reference,0,0,
10074             MagickTrue,exception);
10075           (void) NegateImage(image->clip_mask,MagickFalse,exception);
10076           break;
10077         }
10078         case 107:  /* LinearStretch */
10079         {
10080            double
10081              black_point,
10082              white_point;
10083
10084            black_point=0.0;
10085            white_point=(MagickRealType) image->columns*image->rows;
10086            if (attribute_flag[0] != 0)
10087              {
10088                flags=ParseGeometry(argument_list[0].string_reference,
10089                  &geometry_info);
10090                if ((flags & SigmaValue) != 0)
10091                   white_point=geometry_info.sigma;
10092                if ((flags & PercentValue) != 0)
10093                  {
10094                    black_point*=(double) image->columns*image->rows/100.0;
10095                    white_point*=(double) image->columns*image->rows/100.0;
10096                  }
10097                if ((flags & SigmaValue) == 0)
10098                  white_point=(double) image->columns*image->rows-black_point;
10099              }
10100           if (attribute_flag[1] != 0)
10101             black_point=argument_list[1].real_reference;
10102           if (attribute_flag[2] != 0)
10103             white_point=argument_list[2].real_reference;
10104           (void) LinearStretchImage(image,black_point,white_point,exception);
10105           break;
10106         }
10107         case 109:  /* Mask */
10108         {
10109           if (attribute_flag[0] == 0)
10110             {
10111               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10112                 PackageName);
10113               goto PerlException;
10114             }
10115           image->mask=CloneImage(argument_list[0].image_reference,0,0,
10116             MagickTrue,exception);
10117           (void) NegateImage(image->mask,MagickFalse,exception);
10118           break;
10119         }
10120         case 110:  /* Polaroid */
10121         {
10122           DrawInfo
10123             *draw_info;
10124
10125           double
10126             angle;
10127
10128           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10129             (DrawInfo *) NULL);
10130           if (attribute_flag[0] != 0)
10131             (void) SetImageProperty(image,"caption",InterpretImageProperties(
10132               info ? info->image_info : (ImageInfo *) NULL,image,
10133               argument_list[0].string_reference,exception));
10134           angle=0.0;
10135           if (attribute_flag[1] != 0)
10136             angle=argument_list[1].real_reference;
10137           if (attribute_flag[2] != 0)
10138             (void) CloneString(&draw_info->font,
10139               argument_list[2].string_reference);
10140           if (attribute_flag[3] != 0)
10141             (void) QueryColorDatabase(argument_list[3].string_reference,
10142               &draw_info->stroke,exception);
10143           if (attribute_flag[4] != 0)
10144             (void) QueryColorDatabase(argument_list[4].string_reference,
10145               &draw_info->fill,exception);
10146           if (attribute_flag[5] != 0)
10147             draw_info->stroke_width=argument_list[5].real_reference;
10148           if (attribute_flag[6] != 0)
10149             draw_info->pointsize=argument_list[6].real_reference;
10150           if (attribute_flag[7] != 0)
10151             draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10152           if (attribute_flag[8] != 0)
10153             (void) QueryColorDatabase(argument_list[8].string_reference,
10154               &image->background_color,exception);
10155           image=PolaroidImage(image,draw_info,angle,exception);
10156           draw_info=DestroyDrawInfo(draw_info);
10157           break;
10158         }
10159         case 111:  /* FloodfillPaint */
10160         {
10161           DrawInfo
10162             *draw_info;
10163
10164           MagickBooleanType
10165             invert;
10166
10167           PixelInfo
10168             target;
10169
10170           draw_info=CloneDrawInfo(info ? info->image_info :
10171             (ImageInfo *) NULL,(DrawInfo *) NULL);
10172           if (attribute_flag[0] != 0)
10173             flags=ParsePageGeometry(image,argument_list[0].string_reference,
10174               &geometry,exception);
10175           if (attribute_flag[1] != 0)
10176             geometry.x=argument_list[1].integer_reference;
10177           if (attribute_flag[2] != 0)
10178             geometry.y=argument_list[2].integer_reference;
10179           if (attribute_flag[3] != 0)
10180             (void) QueryColorDatabase(argument_list[3].string_reference,
10181               &draw_info->fill,exception);
10182           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
10183             exception);
10184           if (attribute_flag[4] != 0)
10185             QueryMagickColor(argument_list[4].string_reference,&target,
10186               exception);
10187           if (attribute_flag[5] != 0)
10188             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
10189               QuantumRange);
10190           if (attribute_flag[6] != 0)
10191             channel=(ChannelType) argument_list[6].integer_reference;
10192           invert=MagickFalse;
10193           if (attribute_flag[7] != 0)
10194             invert=(MagickBooleanType) argument_list[7].integer_reference;
10195           channel_mask=SetPixelChannelMask(image,channel);
10196           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10197             geometry.y,invert,exception);
10198           (void) SetPixelChannelMask(image,channel_mask);
10199           draw_info=DestroyDrawInfo(draw_info);
10200           break;
10201         }
10202         case 112:  /* Distort */
10203         {
10204           AV
10205             *av;
10206
10207           double
10208             *coordinates;
10209
10210           DistortImageMethod
10211             method;
10212
10213           size_t
10214             number_coordinates;
10215
10216           VirtualPixelMethod
10217             virtual_pixel;
10218
10219           if (attribute_flag[0] == 0)
10220             break;
10221           method=UndefinedDistortion;
10222           if (attribute_flag[1] != 0)
10223             method=(DistortImageMethod) argument_list[1].integer_reference;
10224           av=(AV *) argument_list[0].array_reference;
10225           number_coordinates=(size_t) av_len(av)+1;
10226           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10227             sizeof(*coordinates));
10228           if (coordinates == (double *) NULL)
10229             {
10230               ThrowPerlException(exception,ResourceLimitFatalError,
10231                 "MemoryAllocationFailed",PackageName);
10232               goto PerlException;
10233             }
10234           for (j=0; j < (ssize_t) number_coordinates; j++)
10235             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10236           virtual_pixel=UndefinedVirtualPixelMethod;
10237           if (attribute_flag[2] != 0)
10238             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10239               argument_list[2].integer_reference);
10240           image=DistortImage(image,method,number_coordinates,coordinates,
10241             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10242             exception);
10243           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10244             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10245           coordinates=(double *) RelinquishMagickMemory(coordinates);
10246           break;
10247         }
10248         case 113:  /* Clut */
10249         {
10250           if (attribute_flag[0] == 0)
10251             {
10252               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10253                 PackageName);
10254               goto PerlException;
10255             }
10256           if (attribute_flag[1] != 0)
10257             channel=(ChannelType) argument_list[1].integer_reference;
10258           channel_mask=SetPixelChannelMask(image,channel);
10259           (void) ClutImage(image,argument_list[0].image_reference,exception);
10260           (void) SetPixelChannelMask(image,channel_mask);
10261           break;
10262         }
10263         case 114:  /* LiquidRescale */
10264         {
10265           if (attribute_flag[0] != 0)
10266             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10267               &geometry,exception);
10268           if (attribute_flag[1] != 0)
10269             geometry.width=argument_list[1].integer_reference;
10270           if (attribute_flag[2] != 0)
10271             geometry.height=argument_list[2].integer_reference;
10272           if (attribute_flag[3] == 0)
10273             argument_list[3].real_reference=1.0;
10274           if (attribute_flag[4] == 0)
10275             argument_list[4].real_reference=0.0;
10276           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10277             argument_list[3].real_reference,argument_list[4].real_reference,
10278             exception);
10279           break;
10280         }
10281         case 115:  /* EncipherImage */
10282         {
10283           (void) EncipherImage(image,argument_list[0].string_reference,
10284             exception);
10285           break;
10286         }
10287         case 116:  /* DecipherImage */
10288         {
10289           (void) DecipherImage(image,argument_list[0].string_reference,
10290             exception);
10291           break;
10292         }
10293         case 117:  /* Deskew */
10294         {
10295           geometry_info.rho=QuantumRange/2.0;
10296           if (attribute_flag[0] != 0)
10297             flags=ParseGeometry(argument_list[0].string_reference,
10298               &geometry_info);
10299           if (attribute_flag[1] != 0)
10300             geometry_info.rho=SiPrefixToDouble(
10301               argument_list[1].string_reference,QuantumRange);
10302           image=DeskewImage(image,geometry_info.rho,exception);
10303           break;
10304         }
10305         case 118:  /* Remap */
10306         {
10307           QuantizeInfo
10308             *quantize_info;
10309
10310           if (attribute_flag[0] == 0)
10311             {
10312               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10313                 PackageName);
10314               goto PerlException;
10315             }
10316           quantize_info=AcquireQuantizeInfo(info->image_info);
10317           if (attribute_flag[1] != 0)
10318             quantize_info->dither=(MagickBooleanType)
10319               argument_list[1].integer_reference;
10320           if (attribute_flag[2] != 0)
10321             quantize_info->dither_method=(DitherMethod)
10322               argument_list[2].integer_reference;
10323           (void) RemapImages(quantize_info,image,
10324             argument_list[0].image_reference,exception);
10325           quantize_info=DestroyQuantizeInfo(quantize_info);
10326           break;
10327         }
10328         case 119:  /* SparseColor */
10329         {
10330           AV
10331             *av;
10332
10333           double
10334             *coordinates;
10335
10336           SparseColorMethod
10337             method;
10338
10339           size_t
10340             number_coordinates;
10341
10342           VirtualPixelMethod
10343             virtual_pixel;
10344
10345           if (attribute_flag[0] == 0)
10346             break;
10347           method=UndefinedColorInterpolate;
10348           if (attribute_flag[1] != 0)
10349             method=(SparseColorMethod) argument_list[1].integer_reference;
10350           av=(AV *) argument_list[0].array_reference;
10351           number_coordinates=(size_t) av_len(av)+1;
10352           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10353             sizeof(*coordinates));
10354           if (coordinates == (double *) NULL)
10355             {
10356               ThrowPerlException(exception,ResourceLimitFatalError,
10357                 "MemoryAllocationFailed",PackageName);
10358               goto PerlException;
10359             }
10360           for (j=0; j < (ssize_t) number_coordinates; j++)
10361             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10362           virtual_pixel=UndefinedVirtualPixelMethod;
10363           if (attribute_flag[2] != 0)
10364             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10365               argument_list[2].integer_reference);
10366           if (attribute_flag[3] != 0)
10367             channel=(ChannelType) argument_list[3].integer_reference;
10368           channel_mask=SetPixelChannelMask(image,channel);
10369           image=SparseColorImage(image,method,number_coordinates,coordinates,
10370             exception);
10371           if (image != (Image *) NULL)
10372             (void) SetPixelChannelMask(image,channel_mask);
10373           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10374             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10375           coordinates=(double *) RelinquishMagickMemory(coordinates);
10376           break;
10377         }
10378         case 120:  /* Function */
10379         {
10380           AV
10381             *av;
10382
10383           double
10384             *parameters;
10385
10386           MagickFunction
10387             function;
10388
10389           size_t
10390             number_parameters;
10391
10392           VirtualPixelMethod
10393             virtual_pixel;
10394
10395           if (attribute_flag[0] == 0)
10396             break;
10397           function=UndefinedFunction;
10398           if (attribute_flag[1] != 0)
10399             function=(MagickFunction) argument_list[1].integer_reference;
10400           av=(AV *) argument_list[0].array_reference;
10401           number_parameters=(size_t) av_len(av)+1;
10402           parameters=(double *) AcquireQuantumMemory(number_parameters,
10403             sizeof(*parameters));
10404           if (parameters == (double *) NULL)
10405             {
10406               ThrowPerlException(exception,ResourceLimitFatalError,
10407                 "MemoryAllocationFailed",PackageName);
10408               goto PerlException;
10409             }
10410           for (j=0; j < (ssize_t) number_parameters; j++)
10411             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10412           virtual_pixel=UndefinedVirtualPixelMethod;
10413           if (attribute_flag[2] != 0)
10414             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10415               argument_list[2].integer_reference);
10416           (void) FunctionImage(image,function,number_parameters,parameters,
10417             exception);
10418           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10419             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10420           parameters=(double *) RelinquishMagickMemory(parameters);
10421           break;
10422         }
10423         case 121:  /* SelectiveBlur */
10424         {
10425           if (attribute_flag[0] != 0)
10426             {
10427               flags=ParseGeometry(argument_list[0].string_reference,
10428                 &geometry_info);
10429               if ((flags & SigmaValue) == 0)
10430                 geometry_info.sigma=1.0;
10431               if ((flags & PercentValue) != 0)
10432                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10433             }
10434           if (attribute_flag[1] != 0)
10435             geometry_info.rho=argument_list[1].real_reference;
10436           if (attribute_flag[2] != 0)
10437             geometry_info.sigma=argument_list[2].real_reference;
10438           if (attribute_flag[3] != 0)
10439             geometry_info.xi=argument_list[3].integer_reference;;
10440           if (attribute_flag[4] != 0)
10441             geometry_info.psi=argument_list[4].integer_reference;;
10442           if (attribute_flag[5] != 0)
10443             channel=(ChannelType) argument_list[5].integer_reference;
10444           channel_mask=SetPixelChannelMask(image,channel);
10445           image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10446             geometry_info.xi,geometry_info.psi,exception);
10447           if (image != (Image *) NULL)
10448             (void) SetPixelChannelMask(image,channel_mask);
10449           break;
10450         }
10451         case 122:  /* HaldClut */
10452         {
10453           if (attribute_flag[0] == 0)
10454             {
10455               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10456                 PackageName);
10457               goto PerlException;
10458             }
10459           if (attribute_flag[1] != 0)
10460             channel=(ChannelType) argument_list[1].integer_reference;
10461           channel_mask=SetPixelChannelMask(image,channel);
10462           (void) HaldClutImage(image,argument_list[0].image_reference,
10463             exception);
10464           (void) SetPixelChannelMask(image,channel_mask);
10465           break;
10466         }
10467         case 123:  /* BlueShift */
10468         {
10469           if (attribute_flag[0] != 0)
10470             (void) ParseGeometry(argument_list[0].string_reference,
10471               &geometry_info);
10472           image=BlueShiftImage(image,geometry_info.rho,exception);
10473           break;
10474         }
10475         case 124:  /* ForwardFourierTransformImage */
10476         {
10477           image=ForwardFourierTransformImage(image,
10478             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10479             exception);
10480           break;
10481         }
10482         case 125:  /* InverseFourierTransformImage */
10483         {
10484           image=InverseFourierTransformImage(image,image->next,
10485             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10486             exception);
10487           break;
10488         }
10489         case 126:  /* ColorDecisionList */
10490         {
10491           if (attribute_flag[0] == 0)
10492             argument_list[0].string_reference=(char *) NULL;
10493           (void) ColorDecisionListImage(image,
10494             argument_list[0].string_reference,exception);
10495           break;
10496         }
10497         case 127:  /* AutoGamma */
10498         {
10499           if (attribute_flag[0] != 0)
10500             channel=(ChannelType) argument_list[0].integer_reference;
10501           channel_mask=SetPixelChannelMask(image,channel);
10502           (void) AutoGammaImage(image,exception);
10503           (void) SetPixelChannelMask(image,channel_mask);
10504           break;
10505         }
10506         case 128:  /* AutoLevel */
10507         {
10508           if (attribute_flag[0] != 0)
10509             channel=(ChannelType) argument_list[0].integer_reference;
10510           channel_mask=SetPixelChannelMask(image,channel);
10511           (void) AutoLevelImage(image,exception);
10512           (void) SetPixelChannelMask(image,channel_mask);
10513           break;
10514         }
10515         case 129:  /* LevelColors */
10516         {
10517           PixelInfo
10518             black_point,
10519             white_point;
10520
10521           (void) QueryMagickColor("#000000",&black_point,exception);
10522           (void) QueryMagickColor("#ffffff",&white_point,exception);
10523           if (attribute_flag[1] != 0)
10524              (void) QueryMagickColor(argument_list[1].string_reference,
10525                &black_point,exception);
10526           if (attribute_flag[2] != 0)
10527              (void) QueryMagickColor(argument_list[2].string_reference,
10528                &white_point,exception);
10529           if (attribute_flag[3] != 0)
10530             channel=(ChannelType) argument_list[3].integer_reference;
10531           channel_mask=SetPixelChannelMask(image,channel);
10532           (void) LevelImageColors(image,&black_point,&white_point,
10533             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10534             exception);
10535           (void) SetPixelChannelMask(image,channel_mask);
10536           break;
10537         }
10538         case 130:  /* Clamp */
10539         {
10540           if (attribute_flag[0] != 0)
10541             channel=(ChannelType) argument_list[0].integer_reference;
10542           channel_mask=SetPixelChannelMask(image,channel);
10543           (void) ClampImage(image);
10544           (void) SetPixelChannelMask(image,channel_mask);
10545           break;
10546         }
10547         case 132:  /* BrightnessContrast */
10548         {
10549           double
10550             brightness,
10551             contrast;
10552
10553           brightness=0.0;
10554           contrast=0.0;
10555           if (attribute_flag[0] != 0)
10556             {
10557               flags=ParseGeometry(argument_list[0].string_reference,
10558                 &geometry_info);
10559               brightness=geometry_info.rho;
10560               if ((flags & SigmaValue) == 0)
10561                 contrast=geometry_info.sigma;
10562             }
10563           if (attribute_flag[1] != 0)
10564             brightness=argument_list[1].real_reference;
10565           if (attribute_flag[2] != 0)
10566             contrast=argument_list[2].real_reference;
10567           if (attribute_flag[4] != 0)
10568             channel=(ChannelType) argument_list[4].integer_reference;
10569           channel_mask=SetPixelChannelMask(image,channel);
10570           (void) BrightnessContrastImage(image,brightness,contrast,exception);
10571           (void) SetPixelChannelMask(image,channel_mask);
10572           break;
10573         }
10574         case 133:  /* Morphology */
10575         {
10576           KernelInfo
10577             *kernel;
10578
10579           MorphologyMethod
10580             method;
10581
10582           ssize_t
10583             iterations;
10584
10585           if (attribute_flag[0] == 0)
10586             break;
10587           kernel=AcquireKernelInfo(argument_list[0].string_reference);
10588           if (kernel == (KernelInfo *) NULL)
10589             break;
10590           if (attribute_flag[1] != 0)
10591             channel=(ChannelType) argument_list[1].integer_reference;
10592           method=UndefinedMorphology;
10593           if (attribute_flag[2] != 0)
10594             method=argument_list[2].integer_reference;
10595           iterations=1;
10596           if (attribute_flag[3] != 0)
10597             iterations=argument_list[4].integer_reference;
10598           channel_mask=SetPixelChannelMask(image,channel);
10599           image=MorphologyImage(image,method,iterations,kernel,exception);
10600           if (image != (Image *) NULL)
10601             (void) SetPixelChannelMask(image,channel_mask);
10602           kernel=DestroyKernelInfo(kernel);
10603           break;
10604         }
10605         case 108:  /* Recolor */
10606         case 134:  /* ColorMatrix */
10607         {
10608           AV
10609             *av;
10610
10611           double
10612             *color_matrix;
10613
10614           KernelInfo
10615             *kernel_info;
10616
10617           size_t
10618             order;
10619
10620           if (attribute_flag[0] == 0)
10621             break;
10622           av=(AV *) argument_list[0].array_reference;
10623           if (av == (AV *) NULL)
10624             break;
10625           order=(size_t) sqrt(av_len(av)+1);
10626           color_matrix=(double *) AcquireQuantumMemory(order,order*
10627             sizeof(*color_matrix));
10628           if (color_matrix == (double *) NULL)
10629             {
10630               ThrowPerlException(exception,ResourceLimitFatalError,
10631                 "MemoryAllocationFailed",PackageName);
10632               goto PerlException;
10633            }
10634           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10635             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10636           for ( ; j < (ssize_t) (order*order); j++)
10637             color_matrix[j]=0.0;
10638           kernel_info=AcquireKernelInfo((const char *) NULL);
10639           if (kernel_info == (KernelInfo *) NULL)
10640             break;
10641           kernel_info->width=order;
10642           kernel_info->height=order;
10643           kernel_info->values=color_matrix;
10644           image=ColorMatrixImage(image,kernel_info,exception);
10645           kernel_info->values=(double *) NULL;
10646           kernel_info=DestroyKernelInfo(kernel_info);
10647           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10648           break;
10649         }
10650         case 135:  /* Color */
10651         {
10652           PixelInfo
10653             color;
10654
10655           (void) QueryMagickColor("none",&color,exception);
10656           if (attribute_flag[0] != 0)
10657             (void) QueryMagickColor(argument_list[0].string_reference,
10658               &color,exception);
10659           (void) SetImageColor(image,&color);
10660           break;
10661         }
10662         case 136:  /* Mode */
10663         {
10664           if (attribute_flag[0] != 0)
10665             {
10666               flags=ParseGeometry(argument_list[0].string_reference,
10667                 &geometry_info);
10668               if ((flags & SigmaValue) == 0)
10669                 geometry_info.sigma=1.0;
10670             }
10671           if (attribute_flag[1] != 0)
10672             geometry_info.rho=argument_list[1].real_reference;
10673           if (attribute_flag[2] != 0)
10674             geometry_info.sigma=argument_list[2].real_reference;
10675           if (attribute_flag[3] != 0)
10676             channel=(ChannelType) argument_list[3].integer_reference;
10677           channel_mask=SetPixelChannelMask(image,channel);
10678           image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
10679             (size_t) geometry_info.sigma,exception);
10680           if (image != (Image *) NULL)
10681             (void) SetPixelChannelMask(image,channel_mask);
10682           break;
10683         }
10684         case 137:  /* Statistic */
10685         {
10686           StatisticType
10687             statistic;
10688
10689           statistic=UndefinedStatistic;
10690           if (attribute_flag[0] != 0)
10691             {
10692               flags=ParseGeometry(argument_list[0].string_reference,
10693                 &geometry_info);
10694               if ((flags & SigmaValue) == 0)
10695                 geometry_info.sigma=1.0;
10696             }
10697           if (attribute_flag[1] != 0)
10698             geometry_info.rho=argument_list[1].real_reference;
10699           if (attribute_flag[2] != 0)
10700             geometry_info.sigma=argument_list[2].real_reference;
10701           if (attribute_flag[3] != 0)
10702             channel=(ChannelType) argument_list[3].integer_reference;
10703           if (attribute_flag[4] != 0)
10704             statistic=(StatisticType) argument_list[4].integer_reference;
10705           channel_mask=SetPixelChannelMask(image,channel);
10706           image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
10707             (size_t) geometry_info.sigma,exception);
10708           if (image != (Image *) NULL)
10709             (void) SetPixelChannelMask(image,channel_mask);
10710           break;
10711         }
10712       }
10713       if (next != (Image *) NULL)
10714         (void) CatchImageException(next);
10715       if (region_image != (Image *) NULL)
10716         {
10717           /*
10718             Composite region.
10719           */ 
10720           status=CompositeImage(region_image,CopyCompositeOp,image,
10721             region_info.x,region_info.y);
10722           (void) status;
10723           (void) CatchImageException(region_image);
10724           image=DestroyImage(image);
10725           image=region_image;
10726         }
10727       if (image != (Image *) NULL)
10728         {
10729           number_images++;
10730           if (next && (next != image))
10731             {
10732               image->next=next->next;
10733               if (image->next != (Image *) NULL)
10734                 image->next->previous=image;
10735               DeleteImageFromRegistry(*pv,next);
10736             }
10737           sv_setiv(*pv,(IV) image);
10738           next=image;
10739         }
10740       if (*pv)
10741         pv++;
10742     }
10743
10744   PerlException:
10745     if (reference_vector)
10746       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
10747     InheritPerlException(exception,perl_exception);
10748     exception=DestroyExceptionInfo(exception);
10749     sv_setiv(perl_exception,(IV) number_images);
10750     SvPOK_on(perl_exception);
10751     ST(0)=sv_2mortal(perl_exception);
10752     XSRETURN(1);
10753   }
10754 \f
10755 #
10756 ###############################################################################
10757 #                                                                             #
10758 #                                                                             #
10759 #                                                                             #
10760 #   M o n t a g e                                                             #
10761 #                                                                             #
10762 #                                                                             #
10763 #                                                                             #
10764 ###############################################################################
10765 #
10766 #
10767 void
10768 Montage(ref,...)
10769   Image::Magick ref=NO_INIT
10770   ALIAS:
10771     MontageImage  = 1
10772     montage       = 2
10773     montageimage  = 3
10774   PPCODE:
10775   {
10776     AV
10777       *av;
10778
10779     char
10780       *attribute;
10781
10782     ExceptionInfo
10783       *exception;
10784
10785     HV
10786       *hv;
10787
10788     Image
10789       *image,
10790       *next;
10791
10792     PixelInfo
10793       transparent_color;
10794
10795     MontageInfo
10796       *montage_info;
10797
10798     register ssize_t
10799       i;
10800
10801     ssize_t
10802       sp;
10803
10804     struct PackageInfo
10805       *info;
10806
10807     SV
10808       *av_reference,
10809       *perl_exception,
10810       *reference,
10811       *rv,
10812       *sv;
10813
10814     PERL_UNUSED_VAR(ref);
10815     PERL_UNUSED_VAR(ix);
10816     exception=AcquireExceptionInfo();
10817     perl_exception=newSVpv("",0);
10818     sv=NULL;
10819     attribute=NULL;
10820     if (sv_isobject(ST(0)) == 0)
10821       {
10822         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
10823           PackageName);
10824         goto PerlException;
10825       }
10826     reference=SvRV(ST(0));
10827     hv=SvSTASH(reference);
10828     av=newAV();
10829     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
10830     SvREFCNT_dec(av);
10831     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
10832     if (image == (Image *) NULL)
10833       {
10834         ThrowPerlException(exception,OptionError,"NoImagesDefined",
10835           PackageName);
10836         goto PerlException;
10837       }
10838     /*
10839       Get options.
10840     */
10841     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
10842     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
10843     (void) QueryMagickColor("none",&transparent_color,exception);
10844     for (i=2; i < items; i+=2)
10845     {
10846       attribute=(char *) SvPV(ST(i-1),na);
10847       switch (*attribute)
10848       {
10849         case 'B':
10850         case 'b':
10851         {
10852           if (LocaleCompare(attribute,"background") == 0)
10853             {
10854               (void) QueryColorDatabase(SvPV(ST(i),na),
10855                 &montage_info->background_color,exception);
10856               for (next=image; next; next=next->next)
10857                 next->background_color=montage_info->background_color;
10858               break;
10859             }
10860           if (LocaleCompare(attribute,"border") == 0)
10861             {
10862               montage_info->border_width=SvIV(ST(i));
10863               break;
10864             }
10865           if (LocaleCompare(attribute,"bordercolor") == 0)
10866             {
10867               (void) QueryColorDatabase(SvPV(ST(i),na),
10868                 &montage_info->border_color,exception);
10869               for (next=image; next; next=next->next)
10870                 next->border_color=montage_info->border_color;
10871               break;
10872             }
10873           if (LocaleCompare(attribute,"borderwidth") == 0)
10874             {
10875               montage_info->border_width=SvIV(ST(i));
10876               break;
10877             }
10878           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10879             attribute);
10880           break;
10881         }
10882         case 'C':
10883         case 'c':
10884         {
10885           if (LocaleCompare(attribute,"compose") == 0)
10886             {
10887               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
10888                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
10889               if (sp < 0)
10890                 {
10891                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
10892                     SvPV(ST(i),na));
10893                   break;
10894                 }
10895               for (next=image; next; next=next->next)
10896                 next->compose=(CompositeOperator) sp;
10897               break;
10898             }
10899           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10900             attribute);
10901           break;
10902         }
10903         case 'F':
10904         case 'f':
10905         {
10906           if (LocaleCompare(attribute,"fill") == 0)
10907             {
10908               (void) QueryColorDatabase(SvPV(ST(i),na),&montage_info->fill,
10909                 exception);
10910               break;
10911             }
10912           if (LocaleCompare(attribute,"font") == 0)
10913             {
10914               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
10915               break;
10916             }
10917           if (LocaleCompare(attribute,"frame") == 0)
10918             {
10919               char
10920                 *p;
10921
10922               p=SvPV(ST(i),na);
10923               if (IsGeometry(p) == MagickFalse)
10924                 {
10925                   ThrowPerlException(exception,OptionError,"MissingGeometry",
10926                     p);
10927                   break;
10928                 }
10929               (void) CloneString(&montage_info->frame,p);
10930               if (*p == '\0')
10931                 montage_info->frame=(char *) NULL;
10932               break;
10933             }
10934           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10935             attribute);
10936           break;
10937         }
10938         case 'G':
10939         case 'g':
10940         {
10941           if (LocaleCompare(attribute,"geometry") == 0)
10942             {
10943               char
10944                 *p;
10945
10946               p=SvPV(ST(i),na);
10947               if (IsGeometry(p) == MagickFalse)
10948                 {
10949                   ThrowPerlException(exception,OptionError,"MissingGeometry",
10950                     p);
10951                   break;
10952                 }
10953              (void) CloneString(&montage_info->geometry,p);
10954              if (*p == '\0')
10955                montage_info->geometry=(char *) NULL;
10956              break;
10957            }
10958          if (LocaleCompare(attribute,"gravity") == 0)
10959            {
10960              ssize_t
10961                in;
10962
10963              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
10964                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
10965              if (in < 0)
10966                {
10967                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
10968                    SvPV(ST(i),na));
10969                  return;
10970                }
10971              montage_info->gravity=(GravityType) in;
10972              for (next=image; next; next=next->next)
10973                next->gravity=(GravityType) in;
10974              break;
10975            }
10976           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10977             attribute);
10978           break;
10979         }
10980         case 'L':
10981         case 'l':
10982         {
10983           if (LocaleCompare(attribute,"label") == 0)
10984             {
10985               for (next=image; next; next=next->next)
10986                 (void) SetImageProperty(next,"label",InterpretImageProperties(
10987                   info ? info->image_info : (ImageInfo *) NULL,next,
10988                   SvPV(ST(i),na),exception));
10989               break;
10990             }
10991           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10992             attribute);
10993           break;
10994         }
10995         case 'M':
10996         case 'm':
10997         {
10998           if (LocaleCompare(attribute,"mattecolor") == 0)
10999             {
11000               (void) QueryColorDatabase(SvPV(ST(i),na),
11001                 &montage_info->matte_color,exception);
11002               for (next=image; next; next=next->next)
11003                 next->matte_color=montage_info->matte_color;
11004               break;
11005             }
11006           if (LocaleCompare(attribute,"mode") == 0)
11007             {
11008               ssize_t
11009                 in;
11010
11011               in=!SvPOK(ST(i)) ? SvIV(ST(i)) :
11012                 ParseCommandOption(MagickModeOptions,MagickFalse,SvPV(ST(i),na));
11013               switch (in)
11014               {
11015                 default:
11016                 {
11017                   ThrowPerlException(exception,OptionError,
11018                     "UnrecognizedModeType",SvPV(ST(i),na));
11019                   break;
11020                 }
11021                 case FrameMode:
11022                 {
11023                   (void) CloneString(&montage_info->frame,"15x15+3+3");
11024                   montage_info->shadow=MagickTrue;
11025                   break;
11026                 }
11027                 case UnframeMode:
11028                 {
11029                   montage_info->frame=(char *) NULL;
11030                   montage_info->shadow=MagickFalse;
11031                   montage_info->border_width=0;
11032                   break;
11033                 }
11034                 case ConcatenateMode:
11035                 {
11036                   montage_info->frame=(char *) NULL;
11037                   montage_info->shadow=MagickFalse;
11038                   (void) CloneString(&montage_info->geometry,"+0+0");
11039                   montage_info->border_width=0;
11040                 }
11041               }
11042               break;
11043             }
11044           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11045             attribute);
11046           break;
11047         }
11048         case 'P':
11049         case 'p':
11050         {
11051           if (LocaleCompare(attribute,"pointsize") == 0)
11052             {
11053               montage_info->pointsize=SvIV(ST(i));
11054               break;
11055             }
11056           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11057             attribute);
11058           break;
11059         }
11060         case 'S':
11061         case 's':
11062         {
11063           if (LocaleCompare(attribute,"shadow") == 0)
11064             {
11065               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11066                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11067               if (sp < 0)
11068                 {
11069                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11070                     SvPV(ST(i),na));
11071                   break;
11072                 }
11073              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11074              break;
11075             }
11076           if (LocaleCompare(attribute,"stroke") == 0)
11077             {
11078               (void) QueryColorDatabase(SvPV(ST(i),na),&montage_info->stroke,
11079                 exception);
11080               break;
11081             }
11082           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11083             attribute);
11084           break;
11085         }
11086         case 'T':
11087         case 't':
11088         {
11089           if (LocaleCompare(attribute,"texture") == 0)
11090             {
11091               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11092               break;
11093             }
11094           if (LocaleCompare(attribute,"tile") == 0)
11095             {
11096               char *p=SvPV(ST(i),na);
11097               if (IsGeometry(p) == MagickFalse)
11098                 {
11099                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11100                     p);
11101                   break;
11102                 }
11103               (void) CloneString(&montage_info->tile,p);
11104               if (*p == '\0')
11105                 montage_info->tile=(char *) NULL;
11106               break;
11107             }
11108           if (LocaleCompare(attribute,"title") == 0)
11109             {
11110               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11111               break;
11112             }
11113           if (LocaleCompare(attribute,"transparent") == 0)
11114             {
11115               PixelInfo
11116                 transparent_color;
11117
11118               QueryMagickColor(SvPV(ST(i),na),&transparent_color,exception);
11119               for (next=image; next; next=next->next)
11120                 (void) TransparentPaintImage(next,&transparent_color,
11121                   TransparentAlpha,MagickFalse,exception);
11122               break;
11123             }
11124           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11125             attribute);
11126           break;
11127         }
11128         default:
11129         {
11130           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11131             attribute);
11132           break;
11133         }
11134       }
11135     }
11136     image=MontageImageList(info->image_info,montage_info,image,exception);
11137     montage_info=DestroyMontageInfo(montage_info);
11138     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11139       goto PerlException;
11140     if (transparent_color.alpha != TransparentAlpha)
11141       for (next=image; next; next=next->next)
11142         (void) TransparentPaintImage(next,&transparent_color,
11143           TransparentAlpha,MagickFalse,exception);
11144     for (  ; image; image=image->next)
11145     {
11146       AddImageToRegistry(sv,image);
11147       rv=newRV(sv);
11148       av_push(av,sv_bless(rv,hv));
11149       SvREFCNT_dec(sv);
11150     }
11151     exception=DestroyExceptionInfo(exception);
11152     ST(0)=av_reference;
11153     SvREFCNT_dec(perl_exception);
11154     XSRETURN(1);
11155
11156   PerlException:
11157     InheritPerlException(exception,perl_exception);
11158     exception=DestroyExceptionInfo(exception);
11159     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11160     SvPOK_on(perl_exception);
11161     ST(0)=sv_2mortal(perl_exception);
11162     XSRETURN(1);
11163   }
11164 \f
11165 #
11166 ###############################################################################
11167 #                                                                             #
11168 #                                                                             #
11169 #                                                                             #
11170 #   M o r p h                                                                 #
11171 #                                                                             #
11172 #                                                                             #
11173 #                                                                             #
11174 ###############################################################################
11175 #
11176 #
11177 void
11178 Morph(ref,...)
11179   Image::Magick ref=NO_INIT
11180   ALIAS:
11181     MorphImage  = 1
11182     morph       = 2
11183     morphimage  = 3
11184   PPCODE:
11185   {
11186     AV
11187       *av;
11188
11189     char
11190       *attribute;
11191
11192     ExceptionInfo
11193       *exception;
11194
11195     HV
11196       *hv;
11197
11198     Image
11199       *image;
11200
11201     register ssize_t
11202       i;
11203
11204     ssize_t
11205       number_frames;
11206
11207     struct PackageInfo
11208       *info;
11209
11210     SV
11211       *av_reference,
11212       *perl_exception,
11213       *reference,
11214       *rv,
11215       *sv;
11216
11217     PERL_UNUSED_VAR(ref);
11218     PERL_UNUSED_VAR(ix);
11219     exception=AcquireExceptionInfo();
11220     perl_exception=newSVpv("",0);
11221     sv=NULL;
11222     av=NULL;
11223     attribute=NULL;
11224     if (sv_isobject(ST(0)) == 0)
11225       {
11226         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11227           PackageName);
11228         goto PerlException;
11229       }
11230     reference=SvRV(ST(0));
11231     hv=SvSTASH(reference);
11232     av=newAV();
11233     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11234     SvREFCNT_dec(av);
11235     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11236     if (image == (Image *) NULL)
11237       {
11238         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11239           PackageName);
11240         goto PerlException;
11241       }
11242     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11243     /*
11244       Get attribute.
11245     */
11246     number_frames=30;
11247     for (i=2; i < items; i+=2)
11248     {
11249       attribute=(char *) SvPV(ST(i-1),na);
11250       switch (*attribute)
11251       {
11252         case 'F':
11253         case 'f':
11254         {
11255           if (LocaleCompare(attribute,"frames") == 0)
11256             {
11257               number_frames=SvIV(ST(i));
11258               break;
11259             }
11260           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11261             attribute);
11262           break;
11263         }
11264         default:
11265         {
11266           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11267             attribute);
11268           break;
11269         }
11270       }
11271     }
11272     image=MorphImages(image,number_frames,exception);
11273     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11274       goto PerlException;
11275     for ( ; image; image=image->next)
11276     {
11277       AddImageToRegistry(sv,image);
11278       rv=newRV(sv);
11279       av_push(av,sv_bless(rv,hv));
11280       SvREFCNT_dec(sv);
11281     }
11282     exception=DestroyExceptionInfo(exception);
11283     ST(0)=av_reference;
11284     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11285     XSRETURN(1);
11286
11287   PerlException:
11288     InheritPerlException(exception,perl_exception);
11289     exception=DestroyExceptionInfo(exception);
11290     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11291     SvPOK_on(perl_exception);
11292     ST(0)=sv_2mortal(perl_exception);
11293     XSRETURN(1);
11294   }
11295 \f
11296 #
11297 ###############################################################################
11298 #                                                                             #
11299 #                                                                             #
11300 #                                                                             #
11301 #   M o s a i c                                                               #
11302 #                                                                             #
11303 #                                                                             #
11304 #                                                                             #
11305 ###############################################################################
11306 #
11307 #
11308 void
11309 Mosaic(ref)
11310   Image::Magick ref=NO_INIT
11311   ALIAS:
11312     MosaicImage   = 1
11313     mosaic        = 2
11314     mosaicimage   = 3
11315   PPCODE:
11316   {
11317     AV
11318       *av;
11319
11320     ExceptionInfo
11321       *exception;
11322
11323     HV
11324       *hv;
11325
11326     Image
11327       *image;
11328
11329     struct PackageInfo
11330       *info;
11331
11332     SV
11333       *perl_exception,
11334       *reference,
11335       *rv,
11336       *sv;
11337
11338     PERL_UNUSED_VAR(ref);
11339     PERL_UNUSED_VAR(ix);
11340     exception=AcquireExceptionInfo();
11341     perl_exception=newSVpv("",0);
11342     sv=NULL;
11343     if (sv_isobject(ST(0)) == 0)
11344       {
11345         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11346           PackageName);
11347         goto PerlException;
11348       }
11349     reference=SvRV(ST(0));
11350     hv=SvSTASH(reference);
11351     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11352     if (image == (Image *) NULL)
11353       {
11354         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11355           PackageName);
11356         goto PerlException;
11357       }
11358     image=MergeImageLayers(image,MosaicLayer,exception);
11359     /*
11360       Create blessed Perl array for the returned image.
11361     */
11362     av=newAV();
11363     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11364     SvREFCNT_dec(av);
11365     AddImageToRegistry(sv,image);
11366     rv=newRV(sv);
11367     av_push(av,sv_bless(rv,hv));
11368     SvREFCNT_dec(sv);
11369     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11370     (void) CopyMagickString(info->image_info->filename,image->filename,
11371       MaxTextExtent);
11372     SetImageInfo(info->image_info,0,&image->exception);
11373     exception=DestroyExceptionInfo(exception);
11374     SvREFCNT_dec(perl_exception);
11375     XSRETURN(1);
11376
11377   PerlException:
11378     InheritPerlException(exception,perl_exception);
11379     exception=DestroyExceptionInfo(exception);
11380     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11381     SvPOK_on(perl_exception);  /* return messages in string context */
11382     ST(0)=sv_2mortal(perl_exception);
11383     XSRETURN(1);
11384   }
11385 \f
11386 #
11387 ###############################################################################
11388 #                                                                             #
11389 #                                                                             #
11390 #                                                                             #
11391 #   P i n g                                                                   #
11392 #                                                                             #
11393 #                                                                             #
11394 #                                                                             #
11395 ###############################################################################
11396 #
11397 #
11398 void
11399 Ping(ref,...)
11400   Image::Magick ref=NO_INIT
11401   ALIAS:
11402     PingImage  = 1
11403     ping       = 2
11404     pingimage  = 3
11405   PPCODE:
11406   {
11407     AV
11408       *av;
11409
11410     char
11411       **keep,
11412       **list;
11413
11414     ExceptionInfo
11415       *exception;
11416
11417     Image
11418       *image,
11419       *next;
11420
11421     int
11422       n;
11423
11424     MagickBooleanType
11425       status;
11426
11427     register char
11428       **p;
11429
11430     register ssize_t
11431       i;
11432
11433     ssize_t
11434       ac;
11435
11436     STRLEN
11437       *length;
11438
11439     struct PackageInfo
11440       *info,
11441       *package_info;
11442
11443     SV
11444       *perl_exception,
11445       *reference;
11446
11447     size_t
11448       count;
11449
11450     PERL_UNUSED_VAR(ref);
11451     PERL_UNUSED_VAR(ix);
11452     exception=AcquireExceptionInfo();
11453     perl_exception=newSVpv("",0);
11454     package_info=(struct PackageInfo *) NULL;
11455     ac=(items < 2) ? 1 : items-1;
11456     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
11457     keep=list;
11458     length=(STRLEN *) NULL;
11459     if (list == (char **) NULL)
11460       {
11461         ThrowPerlException(exception,ResourceLimitError,
11462           "MemoryAllocationFailed",PackageName);
11463         goto PerlException;
11464       }
11465     keep=list;
11466     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
11467     if (length == (STRLEN *) NULL)
11468       {
11469         ThrowPerlException(exception,ResourceLimitError,
11470           "MemoryAllocationFailed",PackageName);
11471         goto PerlException;
11472       }
11473     if (sv_isobject(ST(0)) == 0)
11474       {
11475         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11476           PackageName);
11477         goto PerlException;
11478       }
11479     reference=SvRV(ST(0));
11480     if (SvTYPE(reference) != SVt_PVAV)
11481       {
11482         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11483           PackageName);
11484         goto PerlException;
11485       }
11486     av=(AV *) reference;
11487     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11488       exception);
11489     package_info=ClonePackageInfo(info,exception);
11490     n=1;
11491     if (items <= 1)
11492       *list=(char *) (*package_info->image_info->filename ?
11493         package_info->image_info->filename : "XC:black");
11494     else
11495       for (n=0, i=0; i < ac; i++)
11496       {
11497         list[n]=(char *) SvPV(ST(i+1),length[n]);
11498         if ((items >= 3) && strEQcase(list[n],"blob"))
11499           {
11500             void
11501               *blob;
11502
11503             i++;
11504             blob=(void *) (SvPV(ST(i+1),length[n]));
11505             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
11506           }
11507         if ((items >= 3) && strEQcase(list[n],"filename"))
11508           continue;
11509         if ((items >= 3) && strEQcase(list[n],"file"))
11510           {
11511             FILE
11512               *file;
11513
11514             PerlIO
11515               *io_info;
11516
11517             i++;
11518             io_info=IoIFP(sv_2io(ST(i+1)));
11519             if (io_info == (PerlIO *) NULL)
11520               {
11521                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11522                   PackageName);
11523                 continue;
11524               }
11525             file=PerlIO_findFILE(io_info);
11526             if (file == (FILE *) NULL)
11527               {
11528                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11529                   PackageName);
11530                 continue;
11531               }
11532             SetImageInfoFile(package_info->image_info,file);
11533           }
11534         if ((items >= 3) && strEQcase(list[n],"magick"))
11535           continue;
11536         n++;
11537       }
11538     list[n]=(char *) NULL;
11539     keep=list;
11540     status=ExpandFilenames(&n,&list);
11541     if (status == MagickFalse)
11542       {
11543         ThrowPerlException(exception,ResourceLimitError,
11544           "MemoryAllocationFailed",PackageName);
11545         goto PerlException;
11546       }
11547     count=0;
11548     for (i=0; i < n; i++)
11549     {
11550       (void) CopyMagickString(package_info->image_info->filename,list[i],
11551         MaxTextExtent);
11552       image=PingImage(package_info->image_info,exception);
11553       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11554         break;
11555       if ((package_info->image_info->file != (FILE *) NULL) ||
11556           (package_info->image_info->blob != (void *) NULL))
11557         DisassociateImageStream(image);
11558       count+=GetImageListLength(image);
11559       EXTEND(sp,4*count);
11560       for (next=image; next; next=next->next)
11561       {
11562         PUSHs(sv_2mortal(newSViv(next->columns)));
11563         PUSHs(sv_2mortal(newSViv(next->rows)));
11564         PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
11565         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
11566       }
11567       image=DestroyImageList(image);
11568     }
11569     /*
11570       Free resources.
11571     */
11572     for (i=0; i < n; i++)
11573       if (list[i] != (char *) NULL)
11574         for (p=keep; list[i] != *p++; )
11575           if (*p == NULL)
11576             {
11577               list[i]=(char *) RelinquishMagickMemory(list[i]);
11578               break;
11579             }
11580
11581   PerlException:
11582     if (package_info != (struct PackageInfo *) NULL)
11583       DestroyPackageInfo(package_info);
11584     if (list && (list != keep))
11585       list=(char **) RelinquishMagickMemory(list);
11586     if (keep)
11587       keep=(char **) RelinquishMagickMemory(keep);
11588     if (length)
11589       length=(STRLEN *) RelinquishMagickMemory(length);
11590     InheritPerlException(exception,perl_exception);
11591     exception=DestroyExceptionInfo(exception);
11592     SvREFCNT_dec(perl_exception);  /* throw away all errors */
11593   }
11594 \f
11595 #
11596 ###############################################################################
11597 #                                                                             #
11598 #                                                                             #
11599 #                                                                             #
11600 #   P r e v i e w                                                             #
11601 #                                                                             #
11602 #                                                                             #
11603 #                                                                             #
11604 ###############################################################################
11605 #
11606 #
11607 void
11608 Preview(ref,...)
11609   Image::Magick ref=NO_INIT
11610   ALIAS:
11611     PreviewImage = 1
11612     preview      = 2
11613     previewimage = 3
11614   PPCODE:
11615   {
11616     AV
11617       *av;
11618
11619     ExceptionInfo
11620       *exception;
11621
11622     HV
11623       *hv;
11624
11625     Image
11626       *image,
11627       *preview_image;
11628
11629     PreviewType
11630       preview_type;
11631
11632     struct PackageInfo
11633       *info;
11634
11635     SV
11636       *av_reference,
11637       *perl_exception,
11638       *reference,
11639       *rv,
11640       *sv;
11641
11642     PERL_UNUSED_VAR(ref);
11643     PERL_UNUSED_VAR(ix);
11644     exception=AcquireExceptionInfo();
11645     perl_exception=newSVpv("",0);
11646     sv=NULL;
11647     av=NULL;
11648     if (sv_isobject(ST(0)) == 0)
11649       {
11650         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11651           PackageName);
11652         goto PerlException;
11653       }
11654     reference=SvRV(ST(0));
11655     hv=SvSTASH(reference);
11656     av=newAV();
11657     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11658     SvREFCNT_dec(av);
11659     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11660     if (image == (Image *) NULL)
11661       {
11662         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11663           PackageName);
11664         goto PerlException;
11665       }
11666     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11667     preview_type=GammaPreview;
11668     if (items > 1)
11669       preview_type=(PreviewType)
11670         ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
11671     for ( ; image; image=image->next)
11672     {
11673       preview_image=PreviewImage(image,preview_type,exception);
11674       if (preview_image == (Image *) NULL)
11675         goto PerlException;
11676       AddImageToRegistry(sv,preview_image);
11677       rv=newRV(sv);
11678       av_push(av,sv_bless(rv,hv));
11679       SvREFCNT_dec(sv);
11680     }
11681     exception=DestroyExceptionInfo(exception);
11682     ST(0)=av_reference;
11683     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11684     XSRETURN(1);
11685
11686   PerlException:
11687     InheritPerlException(exception,perl_exception);
11688     exception=DestroyExceptionInfo(exception);
11689     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11690     SvPOK_on(perl_exception);
11691     ST(0)=sv_2mortal(perl_exception);
11692     XSRETURN(1);
11693   }
11694 \f
11695 #
11696 ###############################################################################
11697 #                                                                             #
11698 #                                                                             #
11699 #                                                                             #
11700 #   Q u e r y C o l o r                                                       #
11701 #                                                                             #
11702 #                                                                             #
11703 #                                                                             #
11704 ###############################################################################
11705 #
11706 #
11707 void
11708 QueryColor(ref,...)
11709   Image::Magick ref=NO_INIT
11710   ALIAS:
11711     querycolor = 1
11712   PPCODE:
11713   {
11714     char
11715       *name;
11716
11717     ExceptionInfo
11718       *exception;
11719
11720     PixelInfo
11721       color;
11722
11723     register ssize_t
11724       i;
11725
11726     SV
11727       *perl_exception;
11728
11729     PERL_UNUSED_VAR(ref);
11730     PERL_UNUSED_VAR(ix);
11731     exception=AcquireExceptionInfo();
11732     perl_exception=newSVpv("",0);
11733     if (items == 1)
11734       {
11735         const ColorInfo
11736           **colorlist;
11737
11738         size_t
11739           colors;
11740
11741         colorlist=GetColorInfoList("*",&colors,exception);
11742         EXTEND(sp,colors);
11743         for (i=0; i < (ssize_t) colors; i++)
11744         {
11745           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
11746         }
11747         colorlist=(const ColorInfo **)
11748           RelinquishMagickMemory((ColorInfo **) colorlist);
11749         goto PerlException;
11750       }
11751     EXTEND(sp,5*items);
11752     for (i=1; i < items; i++)
11753     {
11754       name=(char *) SvPV(ST(i),na);
11755       if (QueryMagickColor(name,&color,exception) == MagickFalse)
11756         {
11757           PUSHs(&sv_undef);
11758           continue;
11759         }
11760       PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
11761       PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
11762       PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
11763       if (color.colorspace == CMYKColorspace)
11764         PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
11765       if (color.matte != MagickFalse)
11766         PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
11767     }
11768
11769   PerlException:
11770     InheritPerlException(exception,perl_exception);
11771     exception=DestroyExceptionInfo(exception);
11772     SvREFCNT_dec(perl_exception);
11773   }
11774 \f
11775 #
11776 ###############################################################################
11777 #                                                                             #
11778 #                                                                             #
11779 #                                                                             #
11780 #   Q u e r y C o l o r N a m e                                               #
11781 #                                                                             #
11782 #                                                                             #
11783 #                                                                             #
11784 ###############################################################################
11785 #
11786 #
11787 void
11788 QueryColorname(ref,...)
11789   Image::Magick ref=NO_INIT
11790   ALIAS:
11791     querycolorname = 1
11792   PPCODE:
11793   {
11794     AV
11795       *av;
11796
11797     char
11798       message[MaxTextExtent];
11799
11800     ExceptionInfo
11801       *exception;
11802
11803     Image
11804       *image;
11805
11806     PixelPacket
11807       target_color;
11808
11809     register ssize_t
11810       i;
11811
11812     struct PackageInfo
11813       *info;
11814
11815     SV
11816       *perl_exception,
11817       *reference;  /* reference is the SV* of ref=SvIV(reference) */
11818
11819     PERL_UNUSED_VAR(ref);
11820     PERL_UNUSED_VAR(ix);
11821     exception=AcquireExceptionInfo();
11822     perl_exception=newSVpv("",0);
11823     reference=SvRV(ST(0));
11824     av=(AV *) reference;
11825     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11826       exception);
11827     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11828     if (image == (Image *) NULL)
11829       {
11830         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11831           PackageName);
11832         goto PerlException;
11833       }
11834     EXTEND(sp,items);
11835     for (i=1; i < items; i++)
11836     {
11837       (void) QueryColorDatabase(SvPV(ST(i),na),&target_color,exception);
11838       (void) QueryColorname(image,&target_color,SVGCompliance,message,
11839         exception);
11840       PUSHs(sv_2mortal(newSVpv(message,0)));
11841     }
11842
11843   PerlException:
11844     InheritPerlException(exception,perl_exception);
11845     exception=DestroyExceptionInfo(exception);
11846     SvREFCNT_dec(perl_exception);
11847   }
11848 \f
11849 #
11850 ###############################################################################
11851 #                                                                             #
11852 #                                                                             #
11853 #                                                                             #
11854 #   Q u e r y F o n t                                                         #
11855 #                                                                             #
11856 #                                                                             #
11857 #                                                                             #
11858 ###############################################################################
11859 #
11860 #
11861 void
11862 QueryFont(ref,...)
11863   Image::Magick ref=NO_INIT
11864   ALIAS:
11865     queryfont = 1
11866   PPCODE:
11867   {
11868     char
11869       *name,
11870       message[MaxTextExtent];
11871
11872     ExceptionInfo
11873       *exception;
11874
11875     register ssize_t
11876       i;
11877
11878     SV
11879       *perl_exception;
11880
11881     volatile const TypeInfo
11882       *type_info;
11883
11884     PERL_UNUSED_VAR(ref);
11885     PERL_UNUSED_VAR(ix);
11886     exception=AcquireExceptionInfo();
11887     perl_exception=newSVpv("",0);
11888     if (items == 1)
11889       {
11890         const TypeInfo
11891           **typelist;
11892
11893         size_t
11894           types;
11895
11896         typelist=GetTypeInfoList("*",&types,exception);
11897         EXTEND(sp,types);
11898         for (i=0; i < (ssize_t) types; i++)
11899         {
11900           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
11901         }
11902         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
11903           typelist);
11904         goto PerlException;
11905       }
11906     EXTEND(sp,10*items);
11907     for (i=1; i < items; i++)
11908     {
11909       name=(char *) SvPV(ST(i),na);
11910       type_info=GetTypeInfo(name,exception);
11911       if (type_info == (TypeInfo *) NULL)
11912         {
11913           PUSHs(&sv_undef);
11914           continue;
11915         }
11916       if (type_info->name == (char *) NULL)
11917         PUSHs(&sv_undef);
11918       else
11919         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
11920       if (type_info->description == (char *) NULL)
11921         PUSHs(&sv_undef);
11922       else
11923         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
11924       if (type_info->family == (char *) NULL)
11925         PUSHs(&sv_undef);
11926       else
11927         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
11928       if (type_info->style == UndefinedStyle)
11929         PUSHs(&sv_undef);
11930       else
11931         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
11932           type_info->style),0)));
11933       if (type_info->stretch == UndefinedStretch)
11934         PUSHs(&sv_undef);
11935       else
11936         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
11937           type_info->stretch),0)));
11938       (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
11939         type_info->weight);
11940       PUSHs(sv_2mortal(newSVpv(message,0)));
11941       if (type_info->encoding == (char *) NULL)
11942         PUSHs(&sv_undef);
11943       else
11944         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
11945       if (type_info->foundry == (char *) NULL)
11946         PUSHs(&sv_undef);
11947       else
11948         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
11949       if (type_info->format == (char *) NULL)
11950         PUSHs(&sv_undef);
11951       else
11952         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
11953       if (type_info->metrics == (char *) NULL)
11954         PUSHs(&sv_undef);
11955       else
11956         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
11957       if (type_info->glyphs == (char *) NULL)
11958         PUSHs(&sv_undef);
11959       else
11960         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
11961     }
11962
11963   PerlException:
11964     InheritPerlException(exception,perl_exception);
11965     exception=DestroyExceptionInfo(exception);
11966     SvREFCNT_dec(perl_exception);
11967   }
11968 \f
11969 #
11970 ###############################################################################
11971 #                                                                             #
11972 #                                                                             #
11973 #                                                                             #
11974 #   Q u e r y F o n t M e t r i c s                                           #
11975 #                                                                             #
11976 #                                                                             #
11977 #                                                                             #
11978 ###############################################################################
11979 #
11980 #
11981 void
11982 QueryFontMetrics(ref,...)
11983   Image::Magick ref=NO_INIT
11984   ALIAS:
11985     queryfontmetrics = 1
11986   PPCODE:
11987   {
11988     AffineMatrix
11989       affine,
11990       current;
11991
11992     AV
11993       *av;
11994
11995     char
11996       *attribute;
11997
11998     double
11999       x,
12000       y;
12001
12002     DrawInfo
12003       *draw_info;
12004
12005     ExceptionInfo
12006       *exception;
12007
12008     GeometryInfo
12009       geometry_info;
12010
12011     Image
12012       *image;
12013
12014     MagickBooleanType
12015       status;
12016
12017     MagickStatusType
12018       flags;
12019
12020     register ssize_t
12021       i;
12022
12023     ssize_t
12024       type;
12025
12026     struct PackageInfo
12027       *info,
12028       *package_info;
12029
12030     SV
12031       *perl_exception,
12032       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12033
12034     TypeMetric
12035       metrics;
12036
12037     PERL_UNUSED_VAR(ref);
12038     PERL_UNUSED_VAR(ix);
12039     exception=AcquireExceptionInfo();
12040     package_info=(struct PackageInfo *) NULL;
12041     perl_exception=newSVpv("",0);
12042     reference=SvRV(ST(0));
12043     av=(AV *) reference;
12044     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12045       exception);
12046     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12047     if (image == (Image *) NULL)
12048       {
12049         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12050           PackageName);
12051         goto PerlException;
12052       }
12053     package_info=ClonePackageInfo(info,exception);
12054     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12055     CloneString(&draw_info->text,"");
12056     current=draw_info->affine;
12057     GetAffineMatrix(&affine);
12058     x=0.0;
12059     y=0.0;
12060     EXTEND(sp,7*items);
12061     for (i=2; i < items; i+=2)
12062     {
12063       attribute=(char *) SvPV(ST(i-1),na);
12064       switch (*attribute)
12065       {
12066         case 'A':
12067         case 'a':
12068         {
12069           if (LocaleCompare(attribute,"antialias") == 0)
12070             {
12071               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12072                 SvPV(ST(i),na));
12073               if (type < 0)
12074                 {
12075                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12076                     SvPV(ST(i),na));
12077                   break;
12078                 }
12079               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12080               break;
12081             }
12082           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12083             attribute);
12084           break;
12085         }
12086         case 'd':
12087         case 'D':
12088         {
12089           if (LocaleCompare(attribute,"density") == 0)
12090             {
12091               CloneString(&draw_info->density,SvPV(ST(i),na));
12092               break;
12093             }
12094           if (LocaleCompare(attribute,"direction") == 0)
12095             {
12096               draw_info->direction=(DirectionType) ParseCommandOption(
12097                 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12098               break;
12099             }
12100           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12101             attribute);
12102           break;
12103         }
12104         case 'e':
12105         case 'E':
12106         {
12107           if (LocaleCompare(attribute,"encoding") == 0)
12108             {
12109               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12110               break;
12111             }
12112           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12113             attribute);
12114           break;
12115         }
12116         case 'f':
12117         case 'F':
12118         {
12119           if (LocaleCompare(attribute,"family") == 0)
12120             {
12121               CloneString(&draw_info->family,SvPV(ST(i),na));
12122               break;
12123             }
12124           if (LocaleCompare(attribute,"fill") == 0)
12125             {
12126               if (info)
12127                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->fill,
12128                   &image->exception);
12129               break;
12130             }
12131           if (LocaleCompare(attribute,"font") == 0)
12132             {
12133               CloneString(&draw_info->font,SvPV(ST(i),na));
12134               break;
12135             }
12136           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12137             attribute);
12138           break;
12139         }
12140         case 'g':
12141         case 'G':
12142         {
12143           if (LocaleCompare(attribute,"geometry") == 0)
12144             {
12145               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12146               break;
12147             }
12148           if (LocaleCompare(attribute,"gravity") == 0)
12149             {
12150               draw_info->gravity=(GravityType) ParseCommandOption(
12151                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12152               break;
12153             }
12154           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12155             attribute);
12156           break;
12157         }
12158         case 'i':
12159         case 'I':
12160         {
12161           if (LocaleCompare(attribute,"interline-spacing") == 0)
12162             {
12163               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12164               draw_info->interline_spacing=geometry_info.rho;
12165               break;
12166             }
12167           if (LocaleCompare(attribute,"interword-spacing") == 0)
12168             {
12169               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12170               draw_info->interword_spacing=geometry_info.rho;
12171               break;
12172             }
12173           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12174             attribute);
12175           break;
12176         }
12177         case 'k':
12178         case 'K':
12179         {
12180           if (LocaleCompare(attribute,"kerning") == 0)
12181             {
12182               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12183               draw_info->kerning=geometry_info.rho;
12184               break;
12185             }
12186           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12187             attribute);
12188           break;
12189         }
12190         case 'p':
12191         case 'P':
12192         {
12193           if (LocaleCompare(attribute,"pointsize") == 0)
12194             {
12195               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12196               draw_info->pointsize=geometry_info.rho;
12197               break;
12198             }
12199           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12200             attribute);
12201           break;
12202         }
12203         case 'r':
12204         case 'R':
12205         {
12206           if (LocaleCompare(attribute,"rotate") == 0)
12207             {
12208               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12209               affine.rx=geometry_info.rho;
12210               affine.ry=geometry_info.sigma;
12211               if ((flags & SigmaValue) == 0)
12212                 affine.ry=affine.rx;
12213               break;
12214             }
12215           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12216             attribute);
12217           break;
12218         }
12219         case 's':
12220         case 'S':
12221         {
12222           if (LocaleCompare(attribute,"scale") == 0)
12223             {
12224               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12225               affine.sx=geometry_info.rho;
12226               affine.sy=geometry_info.sigma;
12227               if ((flags & SigmaValue) == 0)
12228                 affine.sy=affine.sx;
12229               break;
12230             }
12231           if (LocaleCompare(attribute,"skew") == 0)
12232             {
12233               double
12234                 x_angle,
12235                 y_angle;
12236
12237               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12238               x_angle=geometry_info.rho;
12239               y_angle=geometry_info.sigma;
12240               if ((flags & SigmaValue) == 0)
12241                 y_angle=x_angle;
12242               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12243               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12244               break;
12245             }
12246           if (LocaleCompare(attribute,"stroke") == 0)
12247             {
12248               if (info)
12249                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->stroke,
12250                   &image->exception);
12251               break;
12252             }
12253           if (LocaleCompare(attribute,"style") == 0)
12254             {
12255               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12256                 SvPV(ST(i),na));
12257               if (type < 0)
12258                 {
12259                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12260                     SvPV(ST(i),na));
12261                   break;
12262                 }
12263               draw_info->style=(StyleType) type;
12264               break;
12265             }
12266           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12267             attribute);
12268           break;
12269         }
12270         case 't':
12271         case 'T':
12272         {
12273           if (LocaleCompare(attribute,"text") == 0)
12274             {
12275               CloneString(&draw_info->text,SvPV(ST(i),na));
12276               break;
12277             }
12278           if (LocaleCompare(attribute,"translate") == 0)
12279             {
12280               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12281               affine.tx=geometry_info.rho;
12282               affine.ty=geometry_info.sigma;
12283               if ((flags & SigmaValue) == 0)
12284                 affine.ty=affine.tx;
12285               break;
12286             }
12287           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12288             attribute);
12289           break;
12290         }
12291         case 'w':
12292         case 'W':
12293         {
12294           if (LocaleCompare(attribute,"weight") == 0)
12295             {
12296               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12297               draw_info->weight=(size_t) geometry_info.rho;
12298               break;
12299             }
12300           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12301             attribute);
12302           break;
12303         }
12304         case 'x':
12305         case 'X':
12306         {
12307           if (LocaleCompare(attribute,"x") == 0)
12308             {
12309               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12310               x=geometry_info.rho;
12311               break;
12312             }
12313           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12314             attribute);
12315           break;
12316         }
12317         case 'y':
12318         case 'Y':
12319         {
12320           if (LocaleCompare(attribute,"y") == 0)
12321             {
12322               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12323               y=geometry_info.rho;
12324               break;
12325             }
12326           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12327             attribute);
12328           break;
12329         }
12330         default:
12331         {
12332           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12333             attribute);
12334           break;
12335         }
12336       }
12337     }
12338     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12339     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12340     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12341     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12342     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12343     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12344     if (draw_info->geometry == (char *) NULL)
12345       {
12346         draw_info->geometry=AcquireString((char *) NULL);
12347         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12348           "%.15g,%.15g",x,y);
12349       }
12350     status=GetTypeMetrics(image,draw_info,&metrics,exception);
12351     (void) CatchImageException(image);
12352     if (status == MagickFalse)
12353       PUSHs(&sv_undef);
12354     else
12355       {
12356         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12357         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12358         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12359         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12360         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12361         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12362         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12363         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12364         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12365         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12366         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12367         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12368         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12369       }
12370     draw_info=DestroyDrawInfo(draw_info);
12371
12372   PerlException:
12373     if (package_info != (struct PackageInfo *) NULL)
12374       DestroyPackageInfo(package_info);
12375     InheritPerlException(exception,perl_exception);
12376     exception=DestroyExceptionInfo(exception);
12377     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12378   }
12379 \f
12380 #
12381 ###############################################################################
12382 #                                                                             #
12383 #                                                                             #
12384 #                                                                             #
12385 #   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                         #
12386 #                                                                             #
12387 #                                                                             #
12388 #                                                                             #
12389 ###############################################################################
12390 #
12391 #
12392 void
12393 QueryMultilineFontMetrics(ref,...)
12394   Image::Magick ref=NO_INIT
12395   ALIAS:
12396     querymultilinefontmetrics = 1
12397   PPCODE:
12398   {
12399     AffineMatrix
12400       affine,
12401       current;
12402
12403     AV
12404       *av;
12405
12406     char
12407       *attribute;
12408
12409     double
12410       x,
12411       y;
12412
12413     DrawInfo
12414       *draw_info;
12415
12416     ExceptionInfo
12417       *exception;
12418
12419     GeometryInfo
12420       geometry_info;
12421
12422     Image
12423       *image;
12424
12425     MagickBooleanType
12426       status;
12427
12428     MagickStatusType
12429       flags;
12430
12431     register ssize_t
12432       i;
12433
12434     ssize_t
12435       type;
12436
12437     struct PackageInfo
12438       *info,
12439       *package_info;
12440
12441     SV
12442       *perl_exception,
12443       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12444
12445     TypeMetric
12446       metrics;
12447
12448     PERL_UNUSED_VAR(ref);
12449     PERL_UNUSED_VAR(ix);
12450     exception=AcquireExceptionInfo();
12451     package_info=(struct PackageInfo *) NULL;
12452     perl_exception=newSVpv("",0);
12453     reference=SvRV(ST(0));
12454     av=(AV *) reference;
12455     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12456       exception);
12457     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12458     if (image == (Image *) NULL)
12459       {
12460         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12461           PackageName);
12462         goto PerlException;
12463       }
12464     package_info=ClonePackageInfo(info,exception);
12465     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12466     CloneString(&draw_info->text,"");
12467     current=draw_info->affine;
12468     GetAffineMatrix(&affine);
12469     x=0.0;
12470     y=0.0;
12471     EXTEND(sp,7*items);
12472     for (i=2; i < items; i+=2)
12473     {
12474       attribute=(char *) SvPV(ST(i-1),na);
12475       switch (*attribute)
12476       {
12477         case 'A':
12478         case 'a':
12479         {
12480           if (LocaleCompare(attribute,"antialias") == 0)
12481             {
12482               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12483                 SvPV(ST(i),na));
12484               if (type < 0)
12485                 {
12486                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12487                     SvPV(ST(i),na));
12488                   break;
12489                 }
12490               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12491               break;
12492             }
12493           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12494             attribute);
12495           break;
12496         }
12497         case 'd':
12498         case 'D':
12499         {
12500           if (LocaleCompare(attribute,"density") == 0)
12501             {
12502               CloneString(&draw_info->density,SvPV(ST(i),na));
12503               break;
12504             }
12505           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12506             attribute);
12507           break;
12508         }
12509         case 'e':
12510         case 'E':
12511         {
12512           if (LocaleCompare(attribute,"encoding") == 0)
12513             {
12514               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12515               break;
12516             }
12517           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12518             attribute);
12519           break;
12520         }
12521         case 'f':
12522         case 'F':
12523         {
12524           if (LocaleCompare(attribute,"family") == 0)
12525             {
12526               CloneString(&draw_info->family,SvPV(ST(i),na));
12527               break;
12528             }
12529           if (LocaleCompare(attribute,"fill") == 0)
12530             {
12531               if (info)
12532                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->fill,
12533                   &image->exception);
12534               break;
12535             }
12536           if (LocaleCompare(attribute,"font") == 0)
12537             {
12538               CloneString(&draw_info->font,SvPV(ST(i),na));
12539               break;
12540             }
12541           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12542             attribute);
12543           break;
12544         }
12545         case 'g':
12546         case 'G':
12547         {
12548           if (LocaleCompare(attribute,"geometry") == 0)
12549             {
12550               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12551               break;
12552             }
12553           if (LocaleCompare(attribute,"gravity") == 0)
12554             {
12555               draw_info->gravity=(GravityType) ParseCommandOption(
12556                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12557               break;
12558             }
12559           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12560             attribute);
12561           break;
12562         }
12563         case 'p':
12564         case 'P':
12565         {
12566           if (LocaleCompare(attribute,"pointsize") == 0)
12567             {
12568               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12569               draw_info->pointsize=geometry_info.rho;
12570               break;
12571             }
12572           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12573             attribute);
12574           break;
12575         }
12576         case 'r':
12577         case 'R':
12578         {
12579           if (LocaleCompare(attribute,"rotate") == 0)
12580             {
12581               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12582               affine.rx=geometry_info.rho;
12583               affine.ry=geometry_info.sigma;
12584               if ((flags & SigmaValue) == 0)
12585                 affine.ry=affine.rx;
12586               break;
12587             }
12588           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12589             attribute);
12590           break;
12591         }
12592         case 's':
12593         case 'S':
12594         {
12595           if (LocaleCompare(attribute,"scale") == 0)
12596             {
12597               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12598               affine.sx=geometry_info.rho;
12599               affine.sy=geometry_info.sigma;
12600               if ((flags & SigmaValue) == 0)
12601                 affine.sy=affine.sx;
12602               break;
12603             }
12604           if (LocaleCompare(attribute,"skew") == 0)
12605             {
12606               double
12607                 x_angle,
12608                 y_angle;
12609
12610               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12611               x_angle=geometry_info.rho;
12612               y_angle=geometry_info.sigma;
12613               if ((flags & SigmaValue) == 0)
12614                 y_angle=x_angle;
12615               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12616               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12617               break;
12618             }
12619           if (LocaleCompare(attribute,"stroke") == 0)
12620             {
12621               if (info)
12622                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->stroke,
12623                   &image->exception);
12624               break;
12625             }
12626           if (LocaleCompare(attribute,"style") == 0)
12627             {
12628               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12629                 SvPV(ST(i),na));
12630               if (type < 0)
12631                 {
12632                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12633                     SvPV(ST(i),na));
12634                   break;
12635                 }
12636               draw_info->style=(StyleType) type;
12637               break;
12638             }
12639           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12640             attribute);
12641           break;
12642         }
12643         case 't':
12644         case 'T':
12645         {
12646           if (LocaleCompare(attribute,"text") == 0)
12647             {
12648               CloneString(&draw_info->text,SvPV(ST(i),na));
12649               break;
12650             }
12651           if (LocaleCompare(attribute,"translate") == 0)
12652             {
12653               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12654               affine.tx=geometry_info.rho;
12655               affine.ty=geometry_info.sigma;
12656               if ((flags & SigmaValue) == 0)
12657                 affine.ty=affine.tx;
12658               break;
12659             }
12660           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12661             attribute);
12662           break;
12663         }
12664         case 'w':
12665         case 'W':
12666         {
12667           if (LocaleCompare(attribute,"weight") == 0)
12668             {
12669               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12670               draw_info->weight=(size_t) geometry_info.rho;
12671               break;
12672             }
12673           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12674             attribute);
12675           break;
12676         }
12677         case 'x':
12678         case 'X':
12679         {
12680           if (LocaleCompare(attribute,"x") == 0)
12681             {
12682               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12683               x=geometry_info.rho;
12684               break;
12685             }
12686           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12687             attribute);
12688           break;
12689         }
12690         case 'y':
12691         case 'Y':
12692         {
12693           if (LocaleCompare(attribute,"y") == 0)
12694             {
12695               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12696               y=geometry_info.rho;
12697               break;
12698             }
12699           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12700             attribute);
12701           break;
12702         }
12703         default:
12704         {
12705           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12706             attribute);
12707           break;
12708         }
12709       }
12710     }
12711     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12712     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12713     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12714     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12715     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12716     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12717     if (draw_info->geometry == (char *) NULL)
12718       {
12719         draw_info->geometry=AcquireString((char *) NULL);
12720         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12721           "%.15g,%.15g",x,y);
12722       }
12723     status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
12724     (void) CatchException(exception);
12725     if (status == MagickFalse)
12726       PUSHs(&sv_undef);
12727     else
12728       {
12729         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12730         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12731         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12732         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12733         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12734         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12735         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12736         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12737         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12738         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12739         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12740         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12741         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12742       }
12743     draw_info=DestroyDrawInfo(draw_info);
12744
12745   PerlException:
12746     if (package_info != (struct PackageInfo *) NULL)
12747       DestroyPackageInfo(package_info);
12748     InheritPerlException(exception,perl_exception);
12749     exception=DestroyExceptionInfo(exception);
12750     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12751   }
12752 \f
12753 #
12754 ###############################################################################
12755 #                                                                             #
12756 #                                                                             #
12757 #                                                                             #
12758 #   Q u e r y F o r m a t                                                     #
12759 #                                                                             #
12760 #                                                                             #
12761 #                                                                             #
12762 ###############################################################################
12763 #
12764 #
12765 void
12766 QueryFormat(ref,...)
12767   Image::Magick ref=NO_INIT
12768   ALIAS:
12769     queryformat = 1
12770   PPCODE:
12771   {
12772     char
12773       *name;
12774
12775     ExceptionInfo
12776       *exception;
12777
12778     register ssize_t
12779       i;
12780
12781     SV
12782       *perl_exception;
12783
12784     volatile const MagickInfo
12785       *magick_info;
12786
12787     PERL_UNUSED_VAR(ref);
12788     PERL_UNUSED_VAR(ix);
12789     exception=AcquireExceptionInfo();
12790     perl_exception=newSVpv("",0);
12791     if (items == 1)
12792       {
12793         char
12794           format[MaxTextExtent];
12795
12796         const MagickInfo
12797           **format_list;
12798
12799         size_t
12800           types;
12801
12802         format_list=GetMagickInfoList("*",&types,exception);
12803         EXTEND(sp,types);
12804         for (i=0; i < (ssize_t) types; i++)
12805         {
12806           (void) CopyMagickString(format,format_list[i]->name,MaxTextExtent);
12807           LocaleLower(format);
12808           PUSHs(sv_2mortal(newSVpv(format,0)));
12809         }
12810         format_list=(const MagickInfo **)
12811           RelinquishMagickMemory((MagickInfo *) format_list);
12812         goto PerlException;
12813       }
12814     EXTEND(sp,8*items);
12815     for (i=1; i < items; i++)
12816     {
12817       name=(char *) SvPV(ST(i),na);
12818       magick_info=GetMagickInfo(name,exception);
12819       if (magick_info == (const MagickInfo *) NULL)
12820         {
12821           PUSHs(&sv_undef);
12822           continue;
12823         }
12824       PUSHs(sv_2mortal(newSViv(magick_info->adjoin)));
12825       PUSHs(sv_2mortal(newSViv(magick_info->blob_support)));
12826       PUSHs(sv_2mortal(newSViv(magick_info->raw)));
12827       PUSHs(sv_2mortal(newSViv((long) magick_info->decoder)));
12828       PUSHs(sv_2mortal(newSViv((long) magick_info->encoder)));
12829       if (magick_info->description == (char *) NULL)
12830         PUSHs(&sv_undef);
12831       else
12832         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
12833       if (magick_info->module == (char *) NULL)
12834         PUSHs(&sv_undef);
12835       else
12836         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
12837     }
12838
12839   PerlException:
12840     InheritPerlException(exception,perl_exception);
12841     exception=DestroyExceptionInfo(exception);
12842     SvREFCNT_dec(perl_exception);
12843   }
12844 \f
12845 #
12846 ###############################################################################
12847 #                                                                             #
12848 #                                                                             #
12849 #                                                                             #
12850 #   Q u e r y O p t i o n                                                     #
12851 #                                                                             #
12852 #                                                                             #
12853 #                                                                             #
12854 ###############################################################################
12855 #
12856 #
12857 void
12858 QueryOption(ref,...)
12859   Image::Magick ref=NO_INIT
12860   ALIAS:
12861     queryoption = 1
12862   PPCODE:
12863   {
12864     char
12865       **options;
12866
12867     ExceptionInfo
12868       *exception;
12869
12870     register ssize_t
12871       i;
12872
12873     ssize_t
12874       j,
12875       option;
12876
12877     SV
12878       *perl_exception;
12879
12880     PERL_UNUSED_VAR(ref);
12881     PERL_UNUSED_VAR(ix);
12882     exception=AcquireExceptionInfo();
12883     perl_exception=newSVpv("",0);
12884     EXTEND(sp,8*items);
12885     for (i=1; i < items; i++)
12886     {
12887       option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
12888         SvPV(ST(i),na));
12889       options=GetCommandOptions((CommandOption) option);
12890       if (options == (char **) NULL)
12891         PUSHs(&sv_undef);
12892       else
12893         {
12894           for (j=0; options[j] != (char *) NULL; j++)
12895             PUSHs(sv_2mortal(newSVpv(options[j],0)));
12896           options=DestroyStringList(options);
12897         }
12898     }
12899
12900     InheritPerlException(exception,perl_exception);
12901     exception=DestroyExceptionInfo(exception);
12902     SvREFCNT_dec(perl_exception);
12903   }
12904 \f
12905 #
12906 ###############################################################################
12907 #                                                                             #
12908 #                                                                             #
12909 #                                                                             #
12910 #   R e a d                                                                   #
12911 #                                                                             #
12912 #                                                                             #
12913 #                                                                             #
12914 ###############################################################################
12915 #
12916 #
12917 void
12918 Read(ref,...)
12919   Image::Magick ref=NO_INIT
12920   ALIAS:
12921     ReadImage  = 1
12922     read       = 2
12923     readimage  = 3
12924   PPCODE:
12925   {
12926     AV
12927       *av;
12928
12929     char
12930       **keep,
12931       **list;
12932
12933     ExceptionInfo
12934       *exception;
12935
12936     HV
12937       *hv;
12938
12939     Image
12940       *image;
12941
12942     int
12943       n;
12944
12945     MagickBooleanType
12946       status;
12947
12948     register char
12949       **p;
12950
12951     register ssize_t
12952       i;
12953
12954     ssize_t
12955       ac,
12956       number_images;
12957
12958     STRLEN
12959       *length;
12960
12961     struct PackageInfo
12962       *info,
12963       *package_info;
12964
12965     SV
12966       *perl_exception,  /* Perl variable for storing messages */
12967       *reference,
12968       *rv,
12969       *sv;
12970
12971     PERL_UNUSED_VAR(ref);
12972     PERL_UNUSED_VAR(ix);
12973     exception=AcquireExceptionInfo();
12974     perl_exception=newSVpv("",0);
12975     sv=NULL;
12976     package_info=(struct PackageInfo *) NULL;
12977     number_images=0;
12978     ac=(items < 2) ? 1 : items-1;
12979     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
12980     keep=list;
12981     length=(STRLEN *) NULL;
12982     if (list == (char **) NULL)
12983       {
12984         ThrowPerlException(exception,ResourceLimitError,
12985           "MemoryAllocationFailed",PackageName);
12986         goto PerlException;
12987       }
12988     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
12989     if (length == (STRLEN *) NULL)
12990       {
12991         ThrowPerlException(exception,ResourceLimitError,
12992           "MemoryAllocationFailed",PackageName);
12993         goto PerlException;
12994       }
12995     if (sv_isobject(ST(0)) == 0)
12996       {
12997         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12998           PackageName);
12999         goto PerlException;
13000       }
13001     reference=SvRV(ST(0));
13002     hv=SvSTASH(reference);
13003     if (SvTYPE(reference) != SVt_PVAV)
13004       {
13005         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13006           PackageName);
13007         goto PerlException;
13008       }
13009     av=(AV *) reference;
13010     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13011       exception);
13012     package_info=ClonePackageInfo(info,exception);
13013     n=1;
13014     if (items <= 1)
13015       *list=(char *) (*package_info->image_info->filename ?
13016         package_info->image_info->filename : "XC:black");
13017     else
13018       for (n=0, i=0; i < ac; i++)
13019       {
13020         list[n]=(char *) SvPV(ST(i+1),length[n]);
13021         if ((items >= 3) && strEQcase(list[n],"blob"))
13022           {
13023             void
13024               *blob;
13025
13026             i++;
13027             blob=(void *) (SvPV(ST(i+1),length[n]));
13028             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13029           }
13030         if ((items >= 3) && strEQcase(list[n],"filename"))
13031           continue;
13032         if ((items >= 3) && strEQcase(list[n],"file"))
13033           {
13034             FILE
13035               *file;
13036
13037             PerlIO
13038               *io_info;
13039
13040             i++;
13041             io_info=IoIFP(sv_2io(ST(i+1)));
13042             if (io_info == (PerlIO *) NULL)
13043               {
13044                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13045                   PackageName);
13046                 continue;
13047               }
13048             file=PerlIO_findFILE(io_info);
13049             if (file == (FILE *) NULL)
13050               {
13051                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13052                   PackageName);
13053                 continue;
13054               }
13055             SetImageInfoFile(package_info->image_info,file);
13056           }
13057         if ((items >= 3) && strEQcase(list[n],"magick"))
13058           continue;
13059         n++;
13060       }
13061     list[n]=(char *) NULL;
13062     keep=list;
13063     status=ExpandFilenames(&n,&list);
13064     if (status == MagickFalse)
13065       {
13066         ThrowPerlException(exception,ResourceLimitError,
13067           "MemoryAllocationFailed",PackageName);
13068         goto PerlException;
13069       }
13070     number_images=0;
13071     for (i=0; i < n; i++)
13072     {
13073       if ((package_info->image_info->file != (FILE *) NULL) ||
13074           (package_info->image_info->blob != (void *) NULL))
13075         {
13076           image=ReadImages(package_info->image_info,exception);
13077           if (image != (Image *) NULL)
13078             DisassociateImageStream(image);
13079         }
13080       else
13081         {
13082           (void) CopyMagickString(package_info->image_info->filename,list[i],
13083             MaxTextExtent);
13084           image=ReadImages(package_info->image_info,exception);
13085         }
13086       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
13087         break;
13088       for ( ; image; image=image->next)
13089       {
13090         AddImageToRegistry(sv,image);
13091         rv=newRV(sv);
13092         av_push(av,sv_bless(rv,hv));
13093         SvREFCNT_dec(sv);
13094         number_images++;
13095       }
13096     }
13097     /*
13098       Free resources.
13099     */
13100     for (i=0; i < n; i++)
13101       if (list[i] != (char *) NULL)
13102         for (p=keep; list[i] != *p++; )
13103           if (*p == (char *) NULL)
13104             {
13105               list[i]=(char *) RelinquishMagickMemory(list[i]);
13106               break;
13107             }
13108
13109   PerlException:
13110     if (package_info != (struct PackageInfo *) NULL)
13111       DestroyPackageInfo(package_info);
13112     if (list && (list != keep))
13113       list=(char **) RelinquishMagickMemory(list);
13114     if (keep)
13115       keep=(char **) RelinquishMagickMemory(keep);
13116     if (length)
13117       length=(STRLEN *) RelinquishMagickMemory(length);
13118     InheritPerlException(exception,perl_exception);
13119     exception=DestroyExceptionInfo(exception);
13120     sv_setiv(perl_exception,(IV) number_images);
13121     SvPOK_on(perl_exception);
13122     ST(0)=sv_2mortal(perl_exception);
13123     XSRETURN(1);
13124   }
13125 \f
13126 #
13127 ###############################################################################
13128 #                                                                             #
13129 #                                                                             #
13130 #                                                                             #
13131 #   R e m o t e                                                               #
13132 #                                                                             #
13133 #                                                                             #
13134 #                                                                             #
13135 ###############################################################################
13136 #
13137 #
13138 void
13139 Remote(ref,...)
13140   Image::Magick ref=NO_INIT
13141   ALIAS:
13142     RemoteCommand  = 1
13143     remote         = 2
13144     remoteCommand  = 3
13145   PPCODE:
13146   {
13147     AV
13148       *av;
13149
13150     ExceptionInfo
13151       *exception;
13152
13153     register ssize_t
13154       i;
13155
13156     SV
13157       *perl_exception,
13158       *reference;
13159
13160     struct PackageInfo
13161       *info;
13162
13163     PERL_UNUSED_VAR(ref);
13164     PERL_UNUSED_VAR(ix);
13165     exception=AcquireExceptionInfo();
13166     perl_exception=newSVpv("",0);
13167     reference=SvRV(ST(0));
13168     av=(AV *) reference;
13169     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13170       exception);
13171     for (i=1; i < items; i++)
13172       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13173         SvPV(ST(i),na),exception);
13174     InheritPerlException(exception,perl_exception);
13175     exception=DestroyExceptionInfo(exception);
13176     SvREFCNT_dec(perl_exception);    /* throw away all errors */
13177   }
13178 \f
13179 #
13180 ###############################################################################
13181 #                                                                             #
13182 #                                                                             #
13183 #                                                                             #
13184 #   S e t                                                                     #
13185 #                                                                             #
13186 #                                                                             #
13187 #                                                                             #
13188 ###############################################################################
13189 #
13190 #
13191 void
13192 Set(ref,...)
13193   Image::Magick ref=NO_INIT
13194   ALIAS:
13195     SetAttributes  = 1
13196     SetAttribute   = 2
13197     set            = 3
13198     setattributes  = 4
13199     setattribute   = 5
13200   PPCODE:
13201   {
13202     ExceptionInfo
13203       *exception;
13204
13205     Image
13206       *image;
13207
13208     register ssize_t
13209       i;
13210
13211     struct PackageInfo
13212       *info;
13213
13214     SV
13215       *perl_exception,
13216       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13217
13218     PERL_UNUSED_VAR(ref);
13219     PERL_UNUSED_VAR(ix);
13220     exception=AcquireExceptionInfo();
13221     perl_exception=newSVpv("",0);
13222     if (sv_isobject(ST(0)) == 0)
13223       {
13224         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13225           PackageName);
13226         goto PerlException;
13227       }
13228     reference=SvRV(ST(0));
13229     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13230     if (items == 2)
13231       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13232     else
13233       for (i=2; i < items; i+=2)
13234         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13235
13236   PerlException:
13237     InheritPerlException(exception,perl_exception);
13238     exception=DestroyExceptionInfo(exception);
13239     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13240     SvPOK_on(perl_exception);
13241     ST(0)=sv_2mortal(perl_exception);
13242     XSRETURN(1);
13243   }
13244 \f
13245 #
13246 ###############################################################################
13247 #                                                                             #
13248 #                                                                             #
13249 #                                                                             #
13250 #   S e t P i x e l                                                           #
13251 #                                                                             #
13252 #                                                                             #
13253 #                                                                             #
13254 ###############################################################################
13255 #
13256 #
13257 void
13258 SetPixel(ref,...)
13259   Image::Magick ref=NO_INIT
13260   ALIAS:
13261     setpixel = 1
13262     setPixel = 2
13263   PPCODE:
13264   {
13265     AV
13266       *av;
13267
13268     char
13269       *attribute;
13270
13271     ChannelType
13272       channel,
13273       channel_mask;
13274
13275     ExceptionInfo
13276       *exception;
13277
13278     Image
13279       *image;
13280
13281     MagickBooleanType
13282       normalize;
13283
13284     RectangleInfo
13285       region;
13286
13287     register ssize_t
13288       i;
13289
13290     register Quantum
13291       *q;
13292
13293     ssize_t
13294       option;
13295
13296     struct PackageInfo
13297       *info;
13298
13299     SV
13300       *perl_exception,
13301       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13302
13303     PERL_UNUSED_VAR(ref);
13304     PERL_UNUSED_VAR(ix);
13305     exception=AcquireExceptionInfo();
13306     perl_exception=newSVpv("",0);
13307     reference=SvRV(ST(0));
13308     av=(AV *) reference;
13309     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13310       exception);
13311     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13312     if (image == (Image *) NULL)
13313       {
13314         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13315           PackageName);
13316         goto PerlException;
13317       }
13318     av=(AV *) NULL;
13319     normalize=MagickTrue;
13320     region.x=0;
13321     region.y=0;
13322     region.width=image->columns;
13323     region.height=1;
13324     if (items == 1)
13325       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13326     channel=DefaultChannels;
13327     for (i=2; i < items; i+=2)
13328     {
13329       attribute=(char *) SvPV(ST(i-1),na);
13330       switch (*attribute)
13331       {
13332         case 'C':
13333         case 'c':
13334         {
13335           if (LocaleCompare(attribute,"channel") == 0)
13336             {
13337               ssize_t
13338                 option;
13339
13340               option=ParseChannelOption(SvPV(ST(i),na));
13341               if (option < 0)
13342                 {
13343                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13344                     SvPV(ST(i),na));
13345                   return;
13346                 }
13347               channel=(ChannelType) option;
13348               break;
13349             }
13350           if (LocaleCompare(attribute,"color") == 0)
13351             {
13352               if (SvTYPE(ST(i)) != SVt_RV)
13353                 {
13354                   char
13355                     message[MaxTextExtent];
13356
13357                   (void) FormatLocaleString(message,MaxTextExtent,
13358                     "invalid %.60s value",attribute);
13359                   ThrowPerlException(exception,OptionError,message,
13360                     SvPV(ST(i),na));
13361                 }
13362               av=(AV *) SvRV(ST(i));
13363               break;
13364             }
13365           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13366             attribute);
13367           break;
13368         }
13369         case 'g':
13370         case 'G':
13371         {
13372           if (LocaleCompare(attribute,"geometry") == 0)
13373             {
13374               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
13375               break;
13376             }
13377           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13378             attribute);
13379           break;
13380         }
13381         case 'N':
13382         case 'n':
13383         {
13384           if (LocaleCompare(attribute,"normalize") == 0)
13385             {
13386               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13387                 SvPV(ST(i),na));
13388               if (option < 0)
13389                 {
13390                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13391                     SvPV(ST(i),na));
13392                   break;
13393                 }
13394              normalize=option != 0 ? MagickTrue : MagickFalse;
13395              break;
13396             }
13397           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13398             attribute);
13399           break;
13400         }
13401         case 'x':
13402         case 'X':
13403         {
13404           if (LocaleCompare(attribute,"x") == 0)
13405             {
13406               region.x=SvIV(ST(i));
13407               break;
13408             }
13409           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13410             attribute);
13411           break;
13412         }
13413         case 'y':
13414         case 'Y':
13415         {
13416           if (LocaleCompare(attribute,"y") == 0)
13417             {
13418               region.y=SvIV(ST(i));
13419               break;
13420             }
13421           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13422             attribute);
13423           break;
13424         }
13425         default:
13426         {
13427           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13428             attribute);
13429           break;
13430         }
13431       }
13432     }
13433     (void) SetImageStorageClass(image,DirectClass,exception);
13434     channel_mask=SetPixelChannelMask(image,channel);
13435     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
13436     if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
13437         (SvTYPE(av) != SVt_PVAV))
13438       PUSHs(&sv_undef);
13439     else
13440       {
13441         double
13442           scale;
13443
13444         register ssize_t
13445           i;
13446
13447         i=0;
13448         scale=1.0;
13449         if (normalize != MagickFalse)
13450           scale=QuantumRange;
13451         if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
13452             (i <= av_len(av)))
13453           {
13454             SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
13455               av_fetch(av,i,0)))),q);
13456             i++;
13457           }
13458         if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
13459             (i <= av_len(av)))
13460           {
13461             SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
13462               av_fetch(av,i,0)))),q);
13463             i++;
13464           }
13465         if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
13466             (i <= av_len(av)))
13467           {
13468             SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
13469               av_fetch(av,i,0)))),q);
13470             i++;
13471           }
13472         if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
13473             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
13474           {
13475             SetPixelBlack(image,ClampToQuantum(scale*
13476               SvNV(*(av_fetch(av,i,0)))),q);
13477             i++;
13478           }
13479         if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
13480             (i <= av_len(av)))
13481           {
13482             SetPixelAlpha(image,ClampToQuantum(scale*
13483               SvNV(*(av_fetch(av,i,0)))),q);
13484             i++;
13485           }
13486         (void) SyncAuthenticPixels(image,exception);
13487       }
13488     (void) SetPixelChannelMask(image,channel_mask);
13489
13490   PerlException:
13491     InheritPerlException(exception,perl_exception);
13492     exception=DestroyExceptionInfo(exception);
13493     SvREFCNT_dec(perl_exception);
13494   }
13495 \f
13496 #
13497 ###############################################################################
13498 #                                                                             #
13499 #                                                                             #
13500 #                                                                             #
13501 #   S m u s h                                                                 #
13502 #                                                                             #
13503 #                                                                             #
13504 #                                                                             #
13505 ###############################################################################
13506 #
13507 #
13508 void
13509 Smush(ref,...)
13510   Image::Magick ref=NO_INIT
13511   ALIAS:
13512     SmushImage  = 1
13513     smush       = 2
13514     smushimage  = 3
13515   PPCODE:
13516   {
13517     AV
13518       *av;
13519
13520     char
13521       *attribute;
13522
13523     ExceptionInfo
13524       *exception;
13525
13526     HV
13527       *hv;
13528
13529     Image
13530       *image;
13531
13532     register ssize_t
13533       i;
13534
13535     ssize_t
13536       offset,
13537       stack;
13538
13539     struct PackageInfo
13540       *info;
13541
13542     SV
13543       *av_reference,
13544       *perl_exception,
13545       *reference,
13546       *rv,
13547       *sv;
13548
13549     PERL_UNUSED_VAR(ref);
13550     PERL_UNUSED_VAR(ix);
13551     exception=AcquireExceptionInfo();
13552     perl_exception=newSVpv("",0);
13553     sv=NULL;
13554     attribute=NULL;
13555     av=NULL;
13556     if (sv_isobject(ST(0)) == 0)
13557       {
13558         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13559           PackageName);
13560         goto PerlException;
13561       }
13562     reference=SvRV(ST(0));
13563     hv=SvSTASH(reference);
13564     av=newAV();
13565     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13566     SvREFCNT_dec(av);
13567     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13568     if (image == (Image *) NULL)
13569       {
13570         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13571           PackageName);
13572         goto PerlException;
13573       }
13574     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13575     /*
13576       Get options.
13577     */
13578     offset=0;
13579     stack=MagickTrue;
13580     for (i=2; i < items; i+=2)
13581     {
13582       attribute=(char *) SvPV(ST(i-1),na);
13583       switch (*attribute)
13584       {
13585         case 'O':
13586         case 'o':
13587         {
13588           if (LocaleCompare(attribute,"offset") == 0)
13589             {
13590               offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
13591               break;
13592             }
13593           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13594             attribute);
13595           break;
13596         }
13597         case 'S':
13598         case 's':
13599         {
13600           if (LocaleCompare(attribute,"stack") == 0)
13601             {
13602               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13603                 SvPV(ST(i),na));
13604               if (stack < 0)
13605                 {
13606                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13607                     SvPV(ST(i),na));
13608                   return;
13609                 }
13610               break;
13611             }
13612           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13613             attribute);
13614           break;
13615         }
13616         default:
13617         {
13618           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13619             attribute);
13620           break;
13621         }
13622       }
13623     }
13624     image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
13625       exception);
13626     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
13627       goto PerlException;
13628     for ( ; image; image=image->next)
13629     {
13630       AddImageToRegistry(sv,image);
13631       rv=newRV(sv);
13632       av_push(av,sv_bless(rv,hv));
13633       SvREFCNT_dec(sv);
13634     }
13635     exception=DestroyExceptionInfo(exception);
13636     ST(0)=av_reference;
13637     SvREFCNT_dec(perl_exception);
13638     XSRETURN(1);
13639
13640   PerlException:
13641     InheritPerlException(exception,perl_exception);
13642     exception=DestroyExceptionInfo(exception);
13643     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
13644     SvPOK_on(perl_exception);
13645     ST(0)=sv_2mortal(perl_exception);
13646     XSRETURN(1);
13647   }
13648 \f
13649 #
13650 ###############################################################################
13651 #                                                                             #
13652 #                                                                             #
13653 #                                                                             #
13654 #   S t a t i s t i c s                                                       #
13655 #                                                                             #
13656 #                                                                             #
13657 #                                                                             #
13658 ###############################################################################
13659 #
13660 #
13661 void
13662 Statistics(ref,...)
13663   Image::Magick ref=NO_INIT
13664   ALIAS:
13665     StatisticsImage = 1
13666     statistics      = 2
13667     statisticsimage = 3
13668   PPCODE:
13669   {
13670 #define ChannelStatistics(channel) \
13671 { \
13672   (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
13673     (double) channel_statistics[channel].depth); \
13674   PUSHs(sv_2mortal(newSVpv(message,0))); \
13675   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13676     channel_statistics[channel].minima/scale); \
13677   PUSHs(sv_2mortal(newSVpv(message,0))); \
13678   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13679     channel_statistics[channel].maxima/scale); \
13680   PUSHs(sv_2mortal(newSVpv(message,0))); \
13681   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13682     channel_statistics[channel].mean/scale); \
13683   PUSHs(sv_2mortal(newSVpv(message,0))); \
13684   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13685     channel_statistics[channel].standard_deviation/scale); \
13686   PUSHs(sv_2mortal(newSVpv(message,0))); \
13687   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13688     channel_statistics[channel].kurtosis); \
13689   PUSHs(sv_2mortal(newSVpv(message,0))); \
13690   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13691     channel_statistics[channel].skewness); \
13692   PUSHs(sv_2mortal(newSVpv(message,0))); \
13693 }
13694
13695     AV
13696       *av;
13697
13698     char
13699       message[MaxTextExtent];
13700
13701     ChannelStatistics
13702       *channel_statistics;
13703
13704     double
13705       scale;
13706
13707     ExceptionInfo
13708       *exception;
13709
13710     Image
13711       *image;
13712
13713     ssize_t
13714       count;
13715
13716     struct PackageInfo
13717       *info;
13718
13719     SV
13720       *perl_exception,
13721       *reference;
13722
13723     PERL_UNUSED_VAR(ref);
13724     PERL_UNUSED_VAR(ix);
13725     exception=AcquireExceptionInfo();
13726     perl_exception=newSVpv("",0);
13727     av=NULL;
13728     if (sv_isobject(ST(0)) == 0)
13729       {
13730         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13731           PackageName);
13732         goto PerlException;
13733       }
13734     reference=SvRV(ST(0));
13735     av=newAV();
13736     SvREFCNT_dec(av);
13737     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13738     if (image == (Image *) NULL)
13739       {
13740         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13741           PackageName);
13742         goto PerlException;
13743       }
13744     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13745     count=0;
13746     for ( ; image; image=image->next)
13747     {
13748       channel_statistics=GetImageStatistics(image,&image->exception);
13749       if (channel_statistics == (ChannelStatistics *) NULL)
13750         continue;
13751       count++;
13752       EXTEND(sp,35*count);
13753       scale=(double) QuantumRange;
13754       ChannelStatistics(RedChannel);
13755       ChannelStatistics(GreenChannel);
13756       ChannelStatistics(BlueChannel);
13757       if (image->colorspace == CMYKColorspace)
13758         ChannelStatistics(BlackChannel);
13759       if (image->matte != MagickFalse)
13760         ChannelStatistics(AlphaChannel);
13761       channel_statistics=(ChannelStatistics *)
13762         RelinquishMagickMemory(channel_statistics);
13763     }
13764
13765   PerlException:
13766     InheritPerlException(exception,perl_exception);
13767     exception=DestroyExceptionInfo(exception);
13768     SvREFCNT_dec(perl_exception);
13769   }
13770 \f
13771 #
13772 ###############################################################################
13773 #                                                                             #
13774 #                                                                             #
13775 #                                                                             #
13776 #   S y n c A u t h e n t i c P i x e l s                                     #
13777 #                                                                             #
13778 #                                                                             #
13779 #                                                                             #
13780 ###############################################################################
13781 #
13782 #
13783 void
13784 SyncAuthenticPixels(ref,...)
13785   Image::Magick ref = NO_INIT
13786   ALIAS:
13787     Syncauthenticpixels = 1
13788     SyncImagePixels = 2
13789     syncimagepixels = 3
13790   CODE:
13791   {
13792     ExceptionInfo
13793       *exception;
13794
13795     Image
13796       *image;
13797
13798     MagickBooleanType
13799       status;
13800
13801     struct PackageInfo
13802       *info;
13803
13804     SV
13805       *perl_exception,
13806       *reference;
13807
13808     PERL_UNUSED_VAR(ref);
13809     PERL_UNUSED_VAR(ix);
13810     exception=AcquireExceptionInfo();
13811     perl_exception=newSVpv("",0);
13812     if (sv_isobject(ST(0)) == 0)
13813       {
13814         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13815           PackageName);
13816         goto PerlException;
13817       }
13818
13819     reference=SvRV(ST(0));
13820     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13821     if (image == (Image *) NULL)
13822       {
13823         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13824           PackageName);
13825         goto PerlException;
13826       }
13827
13828     status=SyncAuthenticPixels(image,exception);
13829     if (status != MagickFalse)
13830       return;
13831     InheritException(exception,&image->exception);
13832
13833   PerlException:
13834     InheritPerlException(exception,perl_exception);
13835     exception=DestroyExceptionInfo(exception);
13836     SvREFCNT_dec(perl_exception);  /* throw away all errors */
13837   }
13838 \f
13839 #
13840 ###############################################################################
13841 #                                                                             #
13842 #                                                                             #
13843 #                                                                             #
13844 #   T r a n s f o r m                                                         #
13845 #                                                                             #
13846 #                                                                             #
13847 #                                                                             #
13848 ###############################################################################
13849 #
13850 #
13851 void
13852 Transform(ref,...)
13853   Image::Magick ref=NO_INIT
13854   ALIAS:
13855     TransformImage = 1
13856     transform      = 2
13857     transformimage = 3
13858   PPCODE:
13859   {
13860     AV
13861       *av;
13862
13863     char
13864       *attribute,
13865       *crop_geometry,
13866       *geometry;
13867
13868     ExceptionInfo
13869       *exception;
13870
13871     HV
13872       *hv;
13873
13874     Image
13875       *clone,
13876       *image;
13877
13878     register ssize_t
13879       i;
13880
13881     struct PackageInfo
13882       *info;
13883
13884     SV
13885       *av_reference,
13886       *perl_exception,
13887       *reference,
13888       *rv,
13889       *sv;
13890
13891     PERL_UNUSED_VAR(ref);
13892     PERL_UNUSED_VAR(ix);
13893     exception=AcquireExceptionInfo();
13894     perl_exception=newSVpv("",0);
13895     sv=NULL;
13896     av=NULL;
13897     attribute=NULL;
13898     if (sv_isobject(ST(0)) == 0)
13899       {
13900         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13901           PackageName);
13902         goto PerlException;
13903       }
13904     reference=SvRV(ST(0));
13905     hv=SvSTASH(reference);
13906     av=newAV();
13907     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13908     SvREFCNT_dec(av);
13909     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13910     if (image == (Image *) NULL)
13911       {
13912         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13913           PackageName);
13914         goto PerlException;
13915       }
13916     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13917     /*
13918       Get attribute.
13919     */
13920     crop_geometry=(char *) NULL;
13921     geometry=(char *) NULL;
13922     for (i=2; i < items; i+=2)
13923     {
13924       attribute=(char *) SvPV(ST(i-1),na);
13925       switch (*attribute)
13926       {
13927         case 'c':
13928         case 'C':
13929         {
13930           if (LocaleCompare(attribute,"crop") == 0)
13931             {
13932               crop_geometry=SvPV(ST(i),na);
13933               break;
13934             }
13935           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13936             attribute);
13937           break;
13938         }
13939         case 'g':
13940         case 'G':
13941         {
13942           if (LocaleCompare(attribute,"geometry") == 0)
13943             {
13944               geometry=SvPV(ST(i),na);
13945               break;
13946             }
13947          if (LocaleCompare(attribute,"gravity") == 0)
13948            {
13949              Image
13950                *next;
13951
13952              ssize_t
13953                in;
13954
13955              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
13956                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13957              if (in < 0)
13958                {
13959                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
13960                    SvPV(ST(i),na));
13961                  return;
13962                }
13963              for (next=image; next; next=next->next)
13964                next->gravity=(GravityType) in;
13965              break;
13966            }
13967           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13968             attribute);
13969           break;
13970         }
13971         default:
13972         {
13973           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13974             attribute);
13975           break;
13976         }
13977       }
13978     }
13979     for ( ; image; image=image->next)
13980     {
13981       clone=CloneImage(image,0,0,MagickTrue,exception);
13982       if ((clone == (Image *) NULL) || (exception->severity >= ErrorException))
13983         goto PerlException;
13984       TransformImage(&clone,crop_geometry,geometry);
13985       for ( ; clone; clone=clone->next)
13986       {
13987         AddImageToRegistry(sv,clone);
13988         rv=newRV(sv);
13989         av_push(av,sv_bless(rv,hv));
13990         SvREFCNT_dec(sv);
13991       }
13992     }
13993     exception=DestroyExceptionInfo(exception);
13994     ST(0)=av_reference;
13995     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13996     XSRETURN(1);
13997
13998   PerlException:
13999     InheritPerlException(exception,perl_exception);
14000     exception=DestroyExceptionInfo(exception);
14001     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14002     SvPOK_on(perl_exception);
14003     ST(0)=sv_2mortal(perl_exception);
14004     XSRETURN(1);
14005   }
14006 \f
14007 #
14008 ###############################################################################
14009 #                                                                             #
14010 #                                                                             #
14011 #                                                                             #
14012 #   W r i t e                                                                 #
14013 #                                                                             #
14014 #                                                                             #
14015 #                                                                             #
14016 ###############################################################################
14017 #
14018 #
14019 void
14020 Write(ref,...)
14021   Image::Magick ref=NO_INIT
14022   ALIAS:
14023     WriteImage    = 1
14024     write         = 2
14025     writeimage    = 3
14026   PPCODE:
14027   {
14028     char
14029       filename[MaxTextExtent];
14030
14031     ExceptionInfo
14032       *exception;
14033
14034     Image
14035       *image,
14036       *next;
14037
14038     register ssize_t
14039       i;
14040
14041     ssize_t
14042       number_images,
14043       scene;
14044
14045     struct PackageInfo
14046       *info,
14047       *package_info;
14048
14049     SV
14050       *perl_exception,
14051       *reference;
14052
14053     PERL_UNUSED_VAR(ref);
14054     PERL_UNUSED_VAR(ix);
14055     exception=AcquireExceptionInfo();
14056     perl_exception=newSVpv("",0);
14057     number_images=0;
14058     package_info=(struct PackageInfo *) NULL;
14059     if (sv_isobject(ST(0)) == 0)
14060       {
14061         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14062           PackageName);
14063         goto PerlException;
14064       }
14065     reference=SvRV(ST(0));
14066     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14067     if (image == (Image *) NULL)
14068       {
14069         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14070           PackageName);
14071         goto PerlException;
14072       }
14073     package_info=ClonePackageInfo(info,exception);
14074     if (items == 2)
14075       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14076     else
14077       if (items > 2)
14078         for (i=2; i < items; i+=2)
14079           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14080             exception);
14081     (void) CopyMagickString(filename,package_info->image_info->filename,
14082       MaxTextExtent);
14083     scene=0;
14084     for (next=image; next; next=next->next)
14085     {
14086       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
14087       next->scene=scene++;
14088     }
14089     SetImageInfo(package_info->image_info,(unsigned int)
14090       GetImageListLength(image),&image->exception);
14091     for (next=image; next; next=next->next)
14092     {
14093       (void) WriteImage(package_info->image_info,next,exception);
14094       number_images++;
14095       if (package_info->image_info->adjoin)
14096         break;
14097     }
14098
14099   PerlException:
14100     if (package_info != (struct PackageInfo *) NULL)
14101       DestroyPackageInfo(package_info);
14102     InheritPerlException(exception,perl_exception);
14103     exception=DestroyExceptionInfo(exception);
14104     sv_setiv(perl_exception,(IV) number_images);
14105     SvPOK_on(perl_exception);
14106     ST(0)=sv_2mortal(perl_exception);
14107     XSRETURN(1);
14108   }