]> granicus.if.org Git - imagemagick/blob - PerlMagick/Magick.xs
spelling typo
[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(WIN32)
52 #define MagickExport
53 #endif
54
55 #if defined(__cplusplus) || defined(c_plusplus)
56 extern "C" {
57 #endif
58
59 #define PERL_NO_GET_CONTEXT
60 #include "EXTERN.h"
61 #include "perl.h"
62 #include "XSUB.h"
63 #include <math.h>
64 #include <magick/MagickCore.h>
65 #undef tainted
66
67 #if defined(__cplusplus) || defined(c_plusplus)
68 }
69 #endif
70 \f
71 /*
72   Define declarations.
73 */
74 #ifndef aTHX_
75 #define aTHX_
76 #define pTHX_
77 #define dTHX
78 #endif
79 #define DegreesToRadians(x)  (MagickPI*(x)/180.0)
80 #define EndOf(array)  (&array[NumberOf(array)])
81 #define MagickPI  3.14159265358979323846264338327950288419716939937510
82 #define MaxArguments  33
83 #ifndef na
84 #define na  PL_na
85 #endif
86 #define NumberOf(array)  (sizeof(array)/sizeof(*array))
87 #define PackageName   "Image::Magick"
88 #if PERL_VERSION <= 6
89 #define PerlIO  FILE
90 #define PerlIO_importFILE(f, fl)  (f)
91 #define PerlIO_findFILE(f)  NULL
92 #endif
93 #ifndef sv_undef
94 #define sv_undef  PL_sv_undef
95 #endif
96
97 #define AddImageToRegistry(sv,image) \
98 { \
99   if (magick_registry != (SplayTreeInfo *) NULL) \
100     { \
101       (void) AddValueToSplayTree(magick_registry,image,image); \
102       (sv)=newSViv((IV) image); \
103     } \
104 }
105
106 #define DeleteImageFromRegistry(reference,image) \
107 { \
108   if (magick_registry != (SplayTreeInfo *) NULL) \
109     { \
110       if (GetImageReferenceCount(image) == 1) \
111        (void) DeleteNodeByValueFromSplayTree(magick_registry,image); \
112       image=DestroyImage(image); \
113       sv_setiv(reference,0); \
114     } \
115 }
116
117 #define InheritPerlException(exception,perl_exception) \
118 { \
119   char \
120     message[MaxTextExtent]; \
121  \
122   if ((exception)->severity != UndefinedException) \
123     { \
124       (void) FormatMagickString(message,MaxTextExtent,"Exception %d: %s%s%s%s",\
125         (exception)->severity, (exception)->reason ? \
126         GetLocaleExceptionMessage((exception)->severity,(exception)->reason) : \
127         "Unknown", (exception)->description ? " (" : "", \
128         (exception)->description ? GetLocaleExceptionMessage( \
129         (exception)->severity,(exception)->description) : "", \
130         (exception)->description ? ")" : ""); \
131       if ((perl_exception) != (SV *) NULL) \
132         { \
133           if (SvCUR(perl_exception)) \
134             sv_catpv(perl_exception,"\n"); \
135           sv_catpv(perl_exception,message); \
136         } \
137     } \
138 }
139
140 #define ThrowPerlException(exception,severity,tag,reason) \
141   (void) ThrowMagickException(exception,GetMagickModule(),severity, \
142     tag,"`%s'",reason); \
143 \f
144 /*
145   Typedef and structure declarations.
146 */
147 typedef enum
148 {
149   ArrayReference = (~0),
150   RealReference = (~0)-1,
151   FileReference = (~0)-2,
152   ImageReference = (~0)-3,
153   IntegerReference = (~0)-4,
154   StringReference = (~0)-5
155 } MagickReference;
156
157 typedef struct _Arguments
158 {
159   const char
160     *method;
161
162   ssize_t
163     type;
164 } Arguments;
165
166 struct ArgumentList
167 {
168   ssize_t
169     integer_reference;
170
171   MagickRealType
172     real_reference;
173
174   const char
175     *string_reference;
176
177   Image
178     *image_reference;
179
180   SV
181     *array_reference;
182
183   FILE
184     *file_reference;
185
186   size_t
187     length;
188 };
189
190 struct PackageInfo
191 {
192   ImageInfo
193     *image_info;
194 };
195
196 typedef void
197   *Image__Magick;  /* data type for the Image::Magick package */
198 \f
199 /*
200   Static declarations.
201 */
202 static struct
203   Methods
204   {
205     const char
206       *name;
207
208     Arguments
209       arguments[MaxArguments];
210   } Methods[] =
211   {
212     { "Comment", { {"comment", StringReference} } },
213     { "Label", { {"label", StringReference} } },
214     { "AddNoise", { {"noise", MagickNoiseOptions},
215       {"channel", MagickChannelOptions} } },
216     { "Colorize", { {"fill", StringReference}, {"opacity", StringReference} } },
217     { "Border", { {"geometry", StringReference}, {"width", IntegerReference},
218       {"height", IntegerReference}, {"fill", StringReference},
219       {"bordercolor", StringReference}, {"color", StringReference},
220       {"compose", MagickComposeOptions} } },
221     { "Blur", { {"geometry", StringReference}, {"radius", RealReference},
222       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
223     { "Chop", { {"geometry", StringReference}, {"width", IntegerReference},
224       {"height", IntegerReference}, {"x", IntegerReference},
225       {"y", IntegerReference} } },
226     { "Crop", { {"geometry", StringReference}, {"width", IntegerReference},
227       {"height", IntegerReference}, {"x", IntegerReference},
228       {"y", IntegerReference}, {"fuzz", StringReference},
229       {"gravity", MagickGravityOptions} } },
230     { "Despeckle", },
231     { "Edge", { {"radius", RealReference} } },
232     { "Emboss", { {"geometry", StringReference}, {"radius", RealReference},
233       {"sigma", RealReference} } },
234     { "Enhance", },
235     { "Flip", },
236     { "Flop", },
237     { "Frame", { {"geometry", StringReference}, {"width", IntegerReference},
238       {"height", IntegerReference}, {"inner", IntegerReference},
239       {"outer", IntegerReference}, {"fill", StringReference},
240       {"color", StringReference}, {"compose", MagickComposeOptions} } },
241     { "Implode", { {"amount", RealReference},
242       {"interpolate", MagickInterpolateOptions} } },
243     { "Magnify", },
244     { "MedianFilter", { {"geometry", StringReference},
245       {"width", IntegerReference},{"height", IntegerReference},
246       {"channel", MagickChannelOptions} } },
247     { "Minify", },
248     { "OilPaint", { {"radius", RealReference} } },
249     { "ReduceNoise", { {"geometry", StringReference},
250       {"width", IntegerReference},{"height", IntegerReference},
251       {"channel", MagickChannelOptions} } },
252     { "Roll", { {"geometry", StringReference}, {"x", IntegerReference},
253       {"y", IntegerReference} } },
254     { "Rotate", { {"degrees", RealReference}, {"fill", StringReference},
255       {"color", StringReference}, {"background", StringReference} } },
256     { "Sample", { {"geometry", StringReference}, {"width", IntegerReference},
257       {"height", IntegerReference} } },
258     { "Scale", { {"geometry", StringReference}, {"width", IntegerReference},
259       {"height", IntegerReference} } },
260     { "Shade", { {"geometry", StringReference}, {"azimuth", RealReference},
261       {"elevation", RealReference}, {"gray", MagickBooleanOptions} } },
262     { "Sharpen", { {"geometry", StringReference}, {"radius", RealReference},
263       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
264     { "Shear", { {"geometry", StringReference}, {"x", RealReference},
265       {"y", RealReference}, { "fill", StringReference},
266       {"color", StringReference} } },
267     { "Spread", { {"radius", RealReference} } },
268     { "Swirl", { {"degrees", RealReference},
269       {"interpolate", MagickInterpolateOptions} } },
270     { "Resize", { {"geometry", StringReference}, {"width", IntegerReference},
271       {"height", IntegerReference}, {"filter", MagickFilterOptions},
272       {"support", StringReference }, {"blur", RealReference } } },
273     { "Zoom", { {"geometry", StringReference}, {"width", IntegerReference},
274       {"height", IntegerReference}, {"filter", MagickFilterOptions},
275       {"support", RealReference }, {"blur", RealReference } } },
276     { "Annotate", { {"text", StringReference}, {"font", StringReference},
277       {"pointsize", RealReference}, {"density", StringReference},
278       {"undercolor", StringReference}, {"stroke", StringReference},
279       {"fill", StringReference}, {"geometry", StringReference},
280       {"pen", StringReference}, {"x", RealReference},
281       {"y", RealReference}, {"gravity", MagickGravityOptions},
282       {"translate", StringReference}, {"scale", StringReference},
283       {"rotate", RealReference}, {"skewX", RealReference},
284       {"skewY", RealReference}, {"strokewidth", RealReference},
285       {"antialias", MagickBooleanOptions}, {"family", StringReference},
286       {"style", MagickStyleOptions}, {"stretch", MagickStretchOptions},
287       {"weight", IntegerReference}, {"align", MagickAlignOptions},
288       {"encoding", StringReference}, {"affine", ArrayReference},
289       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
290       {"tile", ImageReference}, {"kerning", RealReference},
291       {"interline-spacing", RealReference},
292       {"interword-spacing", RealReference},
293       {"direction", MagickDirectionOptions} } },
294     { "ColorFloodfill", { {"geometry", StringReference},
295       {"x", IntegerReference}, {"y", IntegerReference},
296       {"fill", StringReference}, {"bordercolor", StringReference},
297       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
298     { "Composite", { {"image", ImageReference},
299       {"compose", MagickComposeOptions}, {"geometry", StringReference},
300       {"x", IntegerReference}, {"y", IntegerReference},
301       {"gravity", MagickGravityOptions}, {"opacity", StringReference},
302       {"tile", MagickBooleanOptions}, {"rotate", RealReference},
303       {"color", StringReference}, {"mask", ImageReference},
304       {"channel", MagickChannelOptions},
305       {"interpolate", MagickInterpolateOptions}, {"args", StringReference},
306       {"blend", StringReference} } },
307     { "Contrast", { {"sharpen", MagickBooleanOptions} } },
308     { "CycleColormap", { {"display", IntegerReference} } },
309     { "Draw", { {"primitive", MagickPrimitiveOptions},
310       {"points", StringReference}, {"method", MagickMethodOptions},
311       {"stroke", StringReference}, {"fill", StringReference},
312       {"strokewidth", RealReference}, {"font", StringReference},
313       {"bordercolor", StringReference}, {"x", RealReference},
314       {"y", RealReference}, {"translate", StringReference},
315       {"scale", StringReference}, {"rotate", RealReference},
316       {"skewX", RealReference}, {"skewY", RealReference},
317       {"tile", ImageReference}, {"pointsize", RealReference},
318       {"antialias", MagickBooleanOptions}, {"density", StringReference},
319       {"linewidth", RealReference}, {"affine", ArrayReference},
320       {"stroke-dashoffset", RealReference},
321       {"stroke-dasharray", ArrayReference},
322       {"interpolate", MagickInterpolateOptions},
323       {"origin", StringReference}, {"text", StringReference},
324       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
325       {"vector-graphics", StringReference}, {"kerning", RealReference},
326       {"interline-spacing", RealReference},
327       {"interword-spacing", RealReference},
328       {"direction", MagickDirectionOptions} } },
329     { "Equalize", { {"channel", MagickChannelOptions} } },
330     { "Gamma", { {"gamma", StringReference}, {"channel", MagickChannelOptions},
331       {"red", RealReference}, {"green", RealReference},
332       {"blue", RealReference} } },
333     { "Map", { {"image", ImageReference}, {"dither", MagickBooleanOptions},
334       {"dither-method", MagickDitherOptions} } },
335     { "MatteFloodfill", { {"geometry", StringReference},
336       {"x", IntegerReference}, {"y", IntegerReference},
337       {"opacity", StringReference}, {"bordercolor", StringReference},
338       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
339     { "Modulate", { {"factor", StringReference}, {"hue", RealReference},
340       {"saturation", RealReference}, {"whiteness", RealReference},
341       {"brightness", RealReference}, {"lightness", RealReference},
342       {"blackness", RealReference} } },
343     { "Negate", { {"gray", MagickBooleanOptions},
344       {"channel", MagickChannelOptions} } },
345     { "Normalize", { {"channel", MagickChannelOptions} } },
346     { "NumberColors", },
347     { "Opaque", { {"color", StringReference}, {"fill", StringReference},
348       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
349       {"invert", MagickBooleanOptions} } },
350     { "Quantize", { {"colors", IntegerReference},
351       {"treedepth", IntegerReference}, {"colorspace", MagickColorspaceOptions},
352       {"dither", MagickBooleanOptions}, {"measure", MagickBooleanOptions},
353       {"global", MagickBooleanOptions}, {"transparent-color", StringReference},
354       {"dither-method", MagickDitherOptions} } },
355     { "Raise", { {"geometry", StringReference}, {"width", IntegerReference},
356       {"height", IntegerReference}, {"raise", MagickBooleanOptions} } },
357     { "Segment", { {"geometry", StringReference},
358       {"cluster-threshold", RealReference},
359       {"smoothing-threshold", RealReference},
360       {"colorspace", MagickColorspaceOptions},
361       {"verbose", MagickBooleanOptions} } },
362     { "Signature", },
363     { "Solarize", { {"geometry", StringReference},
364       {"threshold", StringReference} } },
365     { "Sync", },
366     { "Texture", { {"texture", ImageReference} } },
367     { "Evaluate", { {"value", RealReference},
368       {"operator", MagickEvaluateOptions},
369       {"channel", MagickChannelOptions} } },
370     { "Transparent", { {"color", StringReference}, {"opacity", StringReference},
371       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
372     { "Threshold", { {"threshold", StringReference},
373       {"channel", MagickChannelOptions} } },
374     { "Charcoal", { {"geometry", StringReference}, {"radius", RealReference},
375       {"sigma", RealReference} } },
376     { "Trim", { {"fuzz", StringReference} } },
377     { "Wave", { {"geometry", StringReference}, {"amplitude", RealReference},
378       {"wavelength", RealReference},
379       {"interpolate", MagickInterpolateOptions} } },
380     { "Separate", { {"channel", MagickChannelOptions} } },
381     { "Condense", },
382     { "Stereo", { {"image", ImageReference}, {"x", IntegerReference},
383       {"y", IntegerReference} } },
384     { "Stegano", { {"image", ImageReference}, {"offset", IntegerReference} } },
385     { "Deconstruct", },
386     { "GaussianBlur", { {"geometry", StringReference},
387       {"radius", RealReference}, {"sigma", RealReference},
388       {"channel", MagickChannelOptions} } },
389     { "Convolve", { {"coefficients", ArrayReference},
390       {"channel", MagickChannelOptions}, {"bias", StringReference} } },
391     { "Profile", { {"name", StringReference}, {"profile", StringReference},
392       { "rendering-intent", MagickIntentOptions},
393       { "black-point-compensation", MagickBooleanOptions} } },
394     { "UnsharpMask", { {"geometry", StringReference},
395       {"radius", RealReference}, {"sigma", RealReference},
396       {"amount", RealReference}, {"threshold", RealReference},
397       {"channel", MagickChannelOptions} } },
398     { "MotionBlur", { {"geometry", StringReference},
399       {"radius", RealReference}, {"sigma", RealReference},
400       {"angle", RealReference}, {"channel", MagickChannelOptions} } },
401     { "OrderedDither", { {"threshold", StringReference},
402       {"channel", MagickChannelOptions} } },
403     { "Shave", { {"geometry", StringReference}, {"width", IntegerReference},
404       {"height", IntegerReference} } },
405     { "Level", { {"levels", StringReference}, {"black-point", RealReference},
406       {"white-point", RealReference}, {"gamma", RealReference},
407       {"channel", MagickChannelOptions}, {"level", StringReference} } },
408     { "Clip", { {"id", StringReference}, {"inside", MagickBooleanOptions} } },
409     { "AffineTransform", { {"affine", ArrayReference},
410       {"translate", StringReference}, {"scale", StringReference},
411       {"rotate", RealReference}, {"skewX", RealReference},
412       {"skewY", RealReference}, {"interpolate", MagickInterpolateOptions},
413       {"background", StringReference} } },
414     { "Difference", { {"image", ImageReference}, {"fuzz", StringReference} } },
415     { "AdaptiveThreshold", { {"geometry", StringReference},
416       {"width", IntegerReference}, {"height", IntegerReference},
417       {"offset", IntegerReference} } },
418     { "Resample", { {"density", StringReference}, {"x", RealReference},
419       {"y", RealReference}, {"filter", MagickFilterOptions},
420       {"support", RealReference }, {"blur", RealReference } } },
421     { "Describe", { {"file", FileReference} } },
422     { "BlackThreshold", { {"threshold", StringReference},
423       {"channel", MagickChannelOptions} } },
424     { "WhiteThreshold", { {"threshold", StringReference},
425       {"channel", MagickChannelOptions} } },
426     { "RadialBlur", { {"geometry", StringReference}, {"angle", RealReference},
427       {"channel", MagickChannelOptions} } },
428     { "Thumbnail", { {"geometry", StringReference}, {"width", IntegerReference},
429       {"height", IntegerReference} } },
430     { "Strip", },
431     { "Tint", { {"fill", StringReference}, {"opacity", StringReference} } },
432     { "Channel", { {"channel", MagickChannelOptions} } },
433     { "Splice", { {"geometry", StringReference}, {"width", IntegerReference},
434       {"height", IntegerReference}, {"x", IntegerReference},
435       {"y", IntegerReference}, {"fuzz", StringReference},
436       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
437     { "Posterize", { {"levels", IntegerReference},
438       {"dither", MagickBooleanOptions} } },
439     { "Shadow", { {"geometry", StringReference}, {"opacity", RealReference},
440       {"sigma", RealReference}, {"x", IntegerReference},
441       {"y", IntegerReference} } },
442     { "Identify", { {"file", FileReference}, {"features", StringReference},
443       {"unique", MagickBooleanOptions} } },
444     { "SepiaTone", { {"threshold", RealReference} } },
445     { "SigmoidalContrast", { {"geometry", StringReference},
446       {"contrast", RealReference}, {"mid-point", RealReference},
447       {"channel", MagickChannelOptions}, {"sharpen", MagickBooleanOptions} } },
448     { "Extent", { {"geometry", StringReference}, {"width", IntegerReference},
449       {"height", IntegerReference}, {"x", IntegerReference},
450       {"y", IntegerReference}, {"fuzz", StringReference},
451       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
452     { "Vignette", { {"geometry", StringReference}, {"radius", RealReference},
453       {"sigma", RealReference}, {"x", IntegerReference},
454       {"y", IntegerReference}, {"background", StringReference} } },
455     { "ContrastStretch", { {"levels", StringReference},
456       {"black-point", RealReference},{"white-point", RealReference},
457       {"channel", MagickChannelOptions} } },
458     { "Sans0", },
459     { "Sans1", },
460     { "AdaptiveSharpen", { {"geometry", StringReference},
461       {"radius", RealReference}, {"sigma", RealReference},
462       {"channel", MagickChannelOptions} } },
463     { "Transpose", },
464     { "Transverse", },
465     { "AutoOrient", },
466     { "AdaptiveBlur", { {"geometry", StringReference},
467       {"radius", RealReference}, {"sigma", RealReference},
468       {"channel", MagickChannelOptions} } },
469     { "Sketch", { {"geometry", StringReference},
470       {"radius", RealReference}, {"sigma", RealReference},
471       {"angle", RealReference} } },
472     { "UniqueColors", },
473     { "AdaptiveResize", { {"geometry", StringReference},
474       {"width", IntegerReference}, {"height", IntegerReference},
475       {"filter", MagickFilterOptions}, {"support", StringReference },
476       {"blur", RealReference } } },
477     { "ClipMask", { {"mask", ImageReference} } },
478     { "LinearStretch", { {"levels", StringReference},
479       {"black-point", RealReference},{"white-point", RealReference} } },
480     { "Recolor", { {"matrix", ArrayReference} } },
481     { "Mask", { {"mask", ImageReference} } },
482     { "Polaroid", { {"caption", StringReference}, {"angle", RealReference},
483       {"font", StringReference}, {"stroke", StringReference},
484       {"fill", StringReference}, {"strokewidth", RealReference},
485       {"pointsize", RealReference}, {"gravity", MagickGravityOptions},
486       {"background", StringReference} } },
487     { "FloodfillPaint", { {"geometry", StringReference},
488       {"x", IntegerReference}, {"y", IntegerReference},
489       {"fill", StringReference}, {"bordercolor", StringReference},
490       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
491       {"invert", MagickBooleanOptions} } },
492     { "Distort", { {"points", ArrayReference}, {"method", MagickDistortOptions},
493       {"virtual-pixel", MagickVirtualPixelOptions},
494       {"best-fit", MagickBooleanOptions} } },
495     { "Clut", { {"image", ImageReference},
496       {"channel", MagickChannelOptions} } },
497     { "LiquidRescale", { {"geometry", StringReference},
498       {"width", IntegerReference}, {"height", IntegerReference},
499       {"delta-x", RealReference}, {"rigidity", RealReference } } },
500     { "Encipher", { {"passphrase", StringReference} } },
501     { "Decipher", { {"passphrase", StringReference} } },
502     { "Deskew", { {"geometry", StringReference},
503       {"threshold", StringReference} } },
504     { "Remap", { {"image", ImageReference}, {"dither", MagickBooleanOptions},
505       {"dither-method", MagickDitherOptions} } },
506     { "SparseColor", { {"points", ArrayReference},
507       {"method", MagickSparseColorOptions},
508       {"virtual-pixel", MagickVirtualPixelOptions},
509       {"channel", MagickChannelOptions} } },
510     { "Function", { {"parameters", ArrayReference},
511       {"function", MagickFunctionOptions},
512       {"virtual-pixel", MagickVirtualPixelOptions} } },
513     { "SelectiveBlur", { {"geometry", StringReference},
514       {"radius", RealReference}, {"sigma", RealReference},
515       {"threshold", RealReference}, {"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     { "Filter", { {"kernel", StringReference},
530       {"channel", MagickChannelOptions}, {"bias", StringReference} } },
531     { "BrightnessContrast", { {"levels", StringReference},
532       {"brightness", RealReference},{"contrast", RealReference},
533       {"channel", MagickChannelOptions} } },
534     { "Morphology", { {"kernel", StringReference},
535       {"channel", MagickChannelOptions}, {"method", MagickMorphologyOptions},
536       {"iterations", IntegerReference} } },
537     { "ColorMatrix", { {"matrix", ArrayReference} } },
538     { "Color", { {"color", StringReference} } },
539     { "Mode", { {"geometry", StringReference},
540       {"width", IntegerReference},{"height", IntegerReference},
541       {"channel", MagickChannelOptions} } },
542     { "Statistic", { {"geometry", StringReference},
543       {"width", IntegerReference},{"height", IntegerReference},
544       {"channel", MagickChannelOptions}, {"type", MagickStatisticOptions} } }
545   };
546
547 static SplayTreeInfo
548   *magick_registry = (SplayTreeInfo *) NULL;
549 \f
550 /*
551   Forward declarations.
552 */
553 static Image
554   *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
555
556 static ssize_t
557   strEQcase(const char *,const char *);
558 \f
559 /*
560 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
561 %                                                                             %
562 %                                                                             %
563 %                                                                             %
564 %   C l o n e P a c k a g e I n f o                                           %
565 %                                                                             %
566 %                                                                             %
567 %                                                                             %
568 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
569 %
570 %  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
571 %  a new one.
572 %
573 %  The format of the ClonePackageInfo routine is:
574 %
575 %      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
576 %        exception)
577 %
578 %  A description of each parameter follows:
579 %
580 %    o info: a structure of type info.
581 %
582 %    o exception: Return any errors or warnings in this structure.
583 %
584 */
585 static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
586   ExceptionInfo *exception)
587 {
588   struct PackageInfo
589     *clone_info;
590
591   clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
592   if (clone_info == (struct PackageInfo *) NULL)
593     {
594       ThrowPerlException(exception,ResourceLimitError,
595         "UnableToClonePackageInfo",PackageName);
596       return((struct PackageInfo *) NULL);
597     }
598   if (info == (struct PackageInfo *) NULL)
599     {
600       clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
601       return(clone_info);
602     }
603   *clone_info=(*info);
604   clone_info->image_info=CloneImageInfo(info->image_info);
605   return(clone_info);
606 }
607 \f
608 /*
609 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
610 %                                                                             %
611 %                                                                             %
612 %                                                                             %
613 %   c o n s t a n t                                                           %
614 %                                                                             %
615 %                                                                             %
616 %                                                                             %
617 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
618 %
619 %  constant() returns a double value for the specified name.
620 %
621 %  The format of the constant routine is:
622 %
623 %      double constant(char *name,ssize_t sans)
624 %
625 %  A description of each parameter follows:
626 %
627 %    o value: Method constant returns a double value for the specified name.
628 %
629 %    o name: The name of the constant.
630 %
631 %    o sans: This integer value is not used.
632 %
633 */
634 static double constant(char *name,ssize_t sans)
635 {
636   (void) sans;
637   errno=0;
638   switch (*name)
639   {
640     case 'B':
641     {
642       if (strEQ(name,"BlobError"))
643         return(BlobError);
644       if (strEQ(name,"BlobWarning"))
645         return(BlobWarning);
646       break;
647     }
648     case 'C':
649     {
650       if (strEQ(name,"CacheError"))
651         return(CacheError);
652       if (strEQ(name,"CacheWarning"))
653         return(CacheWarning);
654       if (strEQ(name,"CoderError"))
655         return(CoderError);
656       if (strEQ(name,"CoderWarning"))
657         return(CoderWarning);
658       if (strEQ(name,"ConfigureError"))
659         return(ConfigureError);
660       if (strEQ(name,"ConfigureWarning"))
661         return(ConfigureWarning);
662       if (strEQ(name,"CorruptImageError"))
663         return(CorruptImageError);
664       if (strEQ(name,"CorruptImageWarning"))
665         return(CorruptImageWarning);
666       break;
667     }
668     case 'D':
669     {
670       if (strEQ(name,"DelegateError"))
671         return(DelegateError);
672       if (strEQ(name,"DelegateWarning"))
673         return(DelegateWarning);
674       if (strEQ(name,"DrawError"))
675         return(DrawError);
676       if (strEQ(name,"DrawWarning"))
677         return(DrawWarning);
678       break;
679     }
680     case 'E':
681     {
682       if (strEQ(name,"ErrorException"))
683         return(ErrorException);
684       if (strEQ(name,"ExceptionError"))
685         return(CoderError);
686       if (strEQ(name,"ExceptionWarning"))
687         return(CoderWarning);
688       break;
689     }
690     case 'F':
691     {
692       if (strEQ(name,"FatalErrorException"))
693         return(FatalErrorException);
694       if (strEQ(name,"FileOpenError"))
695         return(FileOpenError);
696       if (strEQ(name,"FileOpenWarning"))
697         return(FileOpenWarning);
698       break;
699     }
700     case 'I':
701     {
702       if (strEQ(name,"ImageError"))
703         return(ImageError);
704       if (strEQ(name,"ImageWarning"))
705         return(ImageWarning);
706       break;
707     }
708     case 'M':
709     {
710       if (strEQ(name,"MaxRGB"))
711         return(QuantumRange);
712       if (strEQ(name,"MissingDelegateError"))
713         return(MissingDelegateError);
714       if (strEQ(name,"MissingDelegateWarning"))
715         return(MissingDelegateWarning);
716       if (strEQ(name,"ModuleError"))
717         return(ModuleError);
718       if (strEQ(name,"ModuleWarning"))
719         return(ModuleWarning);
720       break;
721     }
722     case 'O':
723     {
724       if (strEQ(name,"Opaque"))
725         return(OpaqueOpacity);
726       if (strEQ(name,"OptionError"))
727         return(OptionError);
728       if (strEQ(name,"OptionWarning"))
729         return(OptionWarning);
730       break;
731     }
732     case 'Q':
733     {
734       if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
735         return(MAGICKCORE_QUANTUM_DEPTH);
736       if (strEQ(name,"QuantumDepth"))
737         return(QuantumDepth);
738       if (strEQ(name,"QuantumRange"))
739         return(QuantumRange);
740       break;
741     }
742     case 'R':
743     {
744       if (strEQ(name,"ResourceLimitError"))
745         return(ResourceLimitError);
746       if (strEQ(name,"ResourceLimitWarning"))
747         return(ResourceLimitWarning);
748       if (strEQ(name,"RegistryError"))
749         return(RegistryError);
750       if (strEQ(name,"RegistryWarning"))
751         return(RegistryWarning);
752       break;
753     }
754     case 'S':
755     {
756       if (strEQ(name,"StreamError"))
757         return(StreamError);
758       if (strEQ(name,"StreamWarning"))
759         return(StreamWarning);
760       if (strEQ(name,"Success"))
761         return(0);
762       break;
763     }
764     case 'T':
765     {
766       if (strEQ(name,"Transparent"))
767         return(TransparentOpacity);
768       if (strEQ(name,"TypeError"))
769         return(TypeError);
770       if (strEQ(name,"TypeWarning"))
771         return(TypeWarning);
772       break;
773     }
774     case 'W':
775     {
776       if (strEQ(name,"WarningException"))
777         return(WarningException);
778       break;
779     }
780     case 'X':
781     {
782       if (strEQ(name,"XServerError"))
783         return(XServerError);
784       if (strEQ(name,"XServerWarning"))
785         return(XServerWarning);
786       break;
787     }
788   }
789   errno=EINVAL;
790   return(0);
791 }
792 \f
793 /*
794 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
795 %                                                                             %
796 %                                                                             %
797 %                                                                             %
798 %   D e s t r o y P a c k a g e I n f o                                       %
799 %                                                                             %
800 %                                                                             %
801 %                                                                             %
802 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
803 %
804 %  Method DestroyPackageInfo frees a previously created info structure.
805 %
806 %  The format of the DestroyPackageInfo routine is:
807 %
808 %      DestroyPackageInfo(struct PackageInfo *info)
809 %
810 %  A description of each parameter follows:
811 %
812 %    o info: a structure of type info.
813 %
814 */
815 static void DestroyPackageInfo(struct PackageInfo *info)
816 {
817   info->image_info=DestroyImageInfo(info->image_info);
818   info=(struct PackageInfo *) RelinquishMagickMemory(info);
819 }
820 \f
821 /*
822 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
823 %                                                                             %
824 %                                                                             %
825 %                                                                             %
826 %   G e t L i s t                                                             %
827 %                                                                             %
828 %                                                                             %
829 %                                                                             %
830 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
831 %
832 %  Method GetList is recursively called by SetupList to traverse the
833 %  Image__Magick reference.  If building an reference_vector (see SetupList),
834 %  *current is the current position in *reference_vector and *last is the final
835 %  entry in *reference_vector.
836 %
837 %  The format of the GetList routine is:
838 %
839 %      GetList(info)
840 %
841 %  A description of each parameter follows:
842 %
843 %    o info: a structure of type info.
844 %
845 */
846 static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,ssize_t *current,
847   ssize_t *last,ExceptionInfo *exception)
848 {
849   Image
850     *image;
851
852   if (reference == (SV *) NULL)
853     return(NULL);
854   switch (SvTYPE(reference))
855   {
856     case SVt_PVAV:
857     {
858       AV
859         *av;
860
861       Image
862         *head,
863         *previous;
864
865       register ssize_t
866         i;
867
868       ssize_t
869         n;
870
871       /*
872         Array of images.
873       */
874       previous=(Image *) NULL;
875       head=(Image *) NULL;
876       av=(AV *) reference;
877       n=av_len(av);
878       for (i=0; i <= n; i++)
879       {
880         SV
881           **rv;
882
883         rv=av_fetch(av,i,0);
884         if (rv && *rv && sv_isobject(*rv))
885           {
886             image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
887               exception);
888             if (image == (Image *) NULL)
889               continue;
890             if (image == previous)
891               {
892                 image=CloneImage(image,0,0,MagickTrue,exception);
893                 if (image == (Image *) NULL)
894                   return(NULL);
895               }
896             image->previous=previous;
897             *(previous ? &previous->next : &head)=image;
898             for (previous=image; previous->next; previous=previous->next) ;
899           }
900       }
901       return(head);
902     }
903     case SVt_PVMG:
904     {
905       /*
906         Blessed scalar, one image.
907       */
908       image=(Image *) SvIV(reference);
909       if (image == (Image *) NULL)
910         return(NULL);
911       image->previous=(Image *) NULL;
912       image->next=(Image *) NULL;
913       if (reference_vector)
914         {
915           if (*current == *last)
916             {
917               *last+=256;
918               if (*reference_vector == (SV **) NULL)
919                 *reference_vector=(SV **) AcquireQuantumMemory(*last,
920                   sizeof(*reference_vector));
921               else
922                 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
923                   *last,sizeof(*reference_vector));
924             }
925           if (*reference_vector == (SV **) NULL)
926             {
927               ThrowPerlException(exception,ResourceLimitError,
928                 "MemoryAllocationFailed",PackageName);
929               return((Image *) NULL);
930             }
931           (*reference_vector)[*current]=reference;
932           (*reference_vector)[++(*current)]=NULL;
933         }
934       return(image);
935     }
936     default:
937       break;
938   }
939   (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
940     (double) SvTYPE(reference));
941   return((Image *) NULL);
942 }
943 \f
944 /*
945 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
946 %                                                                             %
947 %                                                                             %
948 %                                                                             %
949 %   G e t P a c k a g e I n f o                                               %
950 %                                                                             %
951 %                                                                             %
952 %                                                                             %
953 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
954 %
955 %  Method GetPackageInfo looks up or creates an info structure for the given
956 %  Image__Magick reference.  If it does create a new one, the information in
957 %  package_info is used to initialize it.
958 %
959 %  The format of the GetPackageInfo routine is:
960 %
961 %      struct PackageInfo *GetPackageInfo(void *reference,
962 %        struct PackageInfo *package_info,ExceptionInfo *exception)
963 %
964 %  A description of each parameter follows:
965 %
966 %    o info: a structure of type info.
967 %
968 %    o exception: Return any errors or warnings in this structure.
969 %
970 */
971 static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
972   struct PackageInfo *package_info,ExceptionInfo *exception)
973 {
974   char
975     message[MaxTextExtent];
976
977   struct PackageInfo
978     *clone_info;
979
980   SV
981     *sv;
982
983   (void) FormatMagickString(message,MaxTextExtent,"%s::package%s%p",
984     PackageName,XS_VERSION,reference);
985   sv=perl_get_sv(message,(TRUE | 0x02));
986   if (sv == (SV *) NULL)
987     {
988       ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
989         message);
990       return(package_info);
991     }
992   if (SvREFCNT(sv) == 0)
993     (void) SvREFCNT_inc(sv);
994   if (SvIOKp(sv) && (clone_info=(struct PackageInfo *) SvIV(sv)))
995     return(clone_info);
996   clone_info=ClonePackageInfo(package_info,exception);
997   sv_setiv(sv,(IV) clone_info);
998   return(clone_info);
999 }
1000 \f
1001 /*
1002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1003 %                                                                             %
1004 %                                                                             %
1005 %                                                                             %
1006 %   S e t A t t r i b u t e                                                   %
1007 %                                                                             %
1008 %                                                                             %
1009 %                                                                             %
1010 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1011 %
1012 %  SetAttribute() sets the attribute to the value in sval.  This can change
1013 %  either or both of image or info.
1014 %
1015 %  The format of the SetAttribute routine is:
1016 %
1017 %      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1018 %        SV *sval,ExceptionInfo *exception)
1019 %
1020 %  A description of each parameter follows:
1021 %
1022 %    o list: a list of strings.
1023 %
1024 %    o string: a character string.
1025 %
1026 */
1027
1028 static inline double SiPrefixToDouble(const char *string,const double interval)
1029 {
1030   char
1031     *q;
1032
1033   double
1034     scale,
1035     value;
1036
1037   value=strtod(string,&q);
1038   scale=1000.0;
1039   if ((*q != '\0') && (tolower((int) ((unsigned char) *(q+1))) == 'i'))
1040     scale=1024.0;
1041   switch (tolower((int) ((unsigned char) *q)))
1042   {
1043     case '%': value*=pow(scale,0)*interval/100.0; break;
1044     case 'k': value*=pow(scale,1); break;
1045     case 'm': value*=pow(scale,2); break;
1046     case 'g': value*=pow(scale,3); break;
1047     case 't': value*=pow(scale,4); break;
1048     case 'p': value*=pow(scale,5); break;
1049     case 'e': value*=pow(scale,6); break;
1050     case 'z': value*=pow(scale,7); break;
1051     case 'y': value*=pow(scale,8); break;
1052     default:  break;
1053   }
1054   return(value);
1055 }
1056
1057 static inline double StringToDouble(const char *value)
1058 {
1059   return(strtod(value,(char **) NULL));
1060 }
1061
1062 static inline ssize_t StringToLong(const char *value)
1063 {
1064   return(strtol(value,(char **) NULL,10));
1065 }
1066
1067 static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1068   const char *attribute,SV *sval,ExceptionInfo *exception)
1069 {
1070   GeometryInfo
1071     geometry_info;
1072
1073   long
1074     x,
1075     y;
1076
1077   MagickPixelPacket
1078     pixel;
1079
1080   MagickStatusType
1081     flags;
1082
1083   PixelPacket
1084     *color,
1085     target_color;
1086
1087   ssize_t
1088     sp;
1089
1090   switch (*attribute)
1091   {
1092     case 'A':
1093     case 'a':
1094     {
1095       if (LocaleCompare(attribute,"adjoin") == 0)
1096         {
1097           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1098             SvPV(sval,na)) : SvIV(sval);
1099           if (sp < 0)
1100             {
1101               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1102                 SvPV(sval,na));
1103               break;
1104             }
1105           if (info)
1106             info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1107           break;
1108         }
1109       if (LocaleCompare(attribute,"alpha") == 0)
1110         {
1111           sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaOptions,MagickFalse,
1112             SvPV(sval,na)) : SvIV(sval);
1113           if (sp < 0)
1114             {
1115               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1116                 SvPV(sval,na));
1117               break;
1118             }
1119           for ( ; image; image=image->next)
1120             (void) SetImageAlphaChannel(image,(AlphaChannelType) sp);
1121           break;
1122         }
1123       if (LocaleCompare(attribute,"antialias") == 0)
1124         {
1125           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1126             SvPV(sval,na)) : SvIV(sval);
1127           if (sp < 0)
1128             {
1129               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1130                 SvPV(sval,na));
1131               break;
1132             }
1133           if (info)
1134             info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1135           break;
1136         }
1137       if (LocaleCompare(attribute,"area-limit") == 0)
1138         {
1139           MagickSizeType
1140             limit;
1141
1142           limit=MagickResourceInfinity;
1143           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1144             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1145           (void) SetMagickResourceLimit(AreaResource,limit);
1146           break;
1147         }
1148       if (LocaleCompare(attribute,"attenuate") == 0)
1149         {
1150           if (info)
1151             (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1152           break;
1153         }
1154       if (LocaleCompare(attribute,"authenticate") == 0)
1155         {
1156           if (info)
1157             (void) CloneString(&info->image_info->authenticate,SvPV(sval,na));
1158           break;
1159         }
1160       if (info)
1161         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1162       for ( ; image; image=image->next)
1163         SetImageProperty(image,attribute,SvPV(sval,na));
1164       break;
1165     }
1166     case 'B':
1167     case 'b':
1168     {
1169       if (LocaleCompare(attribute,"background") == 0)
1170         {
1171           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1172           if (info)
1173             info->image_info->background_color=target_color;
1174           for ( ; image; image=image->next)
1175             image->background_color=target_color;
1176           break;
1177         }
1178       if (LocaleCompare(attribute,"bias") == 0)
1179         {
1180           for ( ; image; image=image->next)
1181             image->bias=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1182           break;
1183         }
1184       if (LocaleCompare(attribute,"blue-primary") == 0)
1185         {
1186           for ( ; image; image=image->next)
1187           {
1188             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1189             image->chromaticity.blue_primary.x=geometry_info.rho;
1190             image->chromaticity.blue_primary.y=geometry_info.sigma;
1191             if ((flags & SigmaValue) == 0)
1192               image->chromaticity.blue_primary.y=
1193                 image->chromaticity.blue_primary.x;
1194           }
1195           break;
1196         }
1197       if (LocaleCompare(attribute,"bordercolor") == 0)
1198         {
1199           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1200           if (info)
1201             info->image_info->border_color=target_color;
1202           for ( ; image; image=image->next)
1203             image->border_color=target_color;
1204           break;
1205         }
1206       if (info)
1207         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1208       for ( ; image; image=image->next)
1209         SetImageProperty(image,attribute,SvPV(sval,na));
1210       break;
1211     }
1212     case 'C':
1213     case 'c':
1214     {
1215       if (LocaleCompare(attribute,"cache-threshold") == 0)
1216         {
1217           (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1218             SiPrefixToDouble(SvPV(sval,na),100.0));
1219           (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1220             (2*SiPrefixToDouble(SvPV(sval,na),100.0)));
1221           break;
1222         }
1223       if (LocaleCompare(attribute,"clip-mask") == 0)
1224         {
1225           Image
1226             *clip_mask;
1227
1228           clip_mask=(Image *) NULL;
1229           if (SvPOK(sval))
1230             clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1231           for ( ; image; image=image->next)
1232             SetImageClipMask(image,clip_mask);
1233           break;
1234         }
1235       if (LocaleNCompare(attribute,"colormap",8) == 0)
1236         {
1237           for ( ; image; image=image->next)
1238           {
1239             int
1240               items;
1241
1242             long
1243               i;
1244
1245             if (image->storage_class == DirectClass)
1246               continue;
1247             i=0;
1248             items=sscanf(attribute,"%*[^[][%ld",&i);
1249             if (i > (ssize_t) image->colors)
1250               i%=image->colors;
1251             if ((strchr(SvPV(sval,na),',') == 0) ||
1252                 (strchr(SvPV(sval,na),')') != 0))
1253               QueryColorDatabase(SvPV(sval,na),image->colormap+i,exception);
1254             else
1255               {
1256                 color=image->colormap+i;
1257                 pixel.red=color->red;
1258                 pixel.green=color->green;
1259                 pixel.blue=color->blue;
1260                 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1261                 pixel.red=geometry_info.rho;
1262                 pixel.green=geometry_info.sigma;
1263                 pixel.blue=geometry_info.xi;
1264                 color->red=ClampToQuantum(pixel.red);
1265                 color->green=ClampToQuantum(pixel.green);
1266                 color->blue=ClampToQuantum(pixel.blue);
1267               }
1268           }
1269           break;
1270         }
1271       if (LocaleCompare(attribute,"colorspace") == 0)
1272         {
1273           sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1274             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1275           if (sp < 0)
1276             {
1277               ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1278                 SvPV(sval,na));
1279               break;
1280             }
1281           for ( ; image; image=image->next)
1282             (void) TransformImageColorspace(image,(ColorspaceType) sp);
1283           break;
1284         }
1285       if (LocaleCompare(attribute,"comment") == 0)
1286         {
1287           for ( ; image; image=image->next)
1288             (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1289               info ? info->image_info : (ImageInfo *) NULL,image,
1290               SvPV(sval,na)));
1291           break;
1292         }
1293       if (LocaleCompare(attribute,"compression") == 0)
1294         {
1295           sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1296             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1297           if (sp < 0)
1298             {
1299               ThrowPerlException(exception,OptionError,
1300                 "UnrecognizedImageCompression",SvPV(sval,na));
1301               break;
1302             }
1303           if (info)
1304             info->image_info->compression=(CompressionType) sp;
1305           for ( ; image; image=image->next)
1306             image->compression=(CompressionType) sp;
1307           break;
1308         }
1309       if (info)
1310         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1311       for ( ; image; image=image->next)
1312         SetImageProperty(image,attribute,SvPV(sval,na));
1313       break;
1314     }
1315     case 'D':
1316     case 'd':
1317     {
1318       if (LocaleCompare(attribute,"debug") == 0)
1319         {
1320           SetLogEventMask(SvPV(sval,na));
1321           break;
1322         }
1323       if (LocaleCompare(attribute,"delay") == 0)
1324         {
1325           flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1326           for ( ; image; image=image->next)
1327           {
1328             image->delay=(size_t) floor(geometry_info.rho+0.5);
1329             if ((flags & SigmaValue) != 0)
1330               image->ticks_per_second=(ssize_t)
1331                 floor(geometry_info.sigma+0.5);
1332           }
1333           break;
1334         }
1335       if (LocaleCompare(attribute,"disk-limit") == 0)
1336         {
1337           MagickSizeType
1338             limit;
1339
1340           limit=MagickResourceInfinity;
1341           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1342             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1343           (void) SetMagickResourceLimit(DiskResource,limit);
1344           break;
1345         }
1346       if (LocaleCompare(attribute,"density") == 0)
1347         {
1348           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1349             {
1350               ThrowPerlException(exception,OptionError,"MissingGeometry",
1351                 SvPV(sval,na));
1352               break;
1353             }
1354           if (info)
1355             (void) CloneString(&info->image_info->density,SvPV(sval,na));
1356           for ( ; image; image=image->next)
1357           {
1358             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1359             image->x_resolution=geometry_info.rho;
1360             image->y_resolution=geometry_info.sigma;
1361             if ((flags & SigmaValue) == 0)
1362               image->y_resolution=image->x_resolution;
1363           }
1364           break;
1365         }
1366       if (LocaleCompare(attribute,"depth") == 0)
1367         {
1368           if (info)
1369             info->image_info->depth=SvIV(sval);
1370           for ( ; image; image=image->next)
1371             (void) SetImageDepth(image,SvIV(sval));
1372           break;
1373         }
1374       if (LocaleCompare(attribute,"dispose") == 0)
1375         {
1376           sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1377             SvPV(sval,na)) : SvIV(sval);
1378           if (sp < 0)
1379             {
1380               ThrowPerlException(exception,OptionError,
1381                 "UnrecognizedDisposeMethod",SvPV(sval,na));
1382               break;
1383             }
1384           for ( ; image; image=image->next)
1385             image->dispose=(DisposeType) sp;
1386           break;
1387         }
1388       if (LocaleCompare(attribute,"dither") == 0)
1389         {
1390           if (info)
1391             {
1392               sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1393                 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1394               if (sp < 0)
1395                 {
1396                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
1397                     SvPV(sval,na));
1398                   break;
1399                 }
1400               info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1401             }
1402           break;
1403         }
1404       if (LocaleCompare(attribute,"display") == 0)
1405         {
1406           display:
1407           if (info)
1408             (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1409           break;
1410         }
1411       if (info)
1412         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1413       for ( ; image; image=image->next)
1414         SetImageProperty(image,attribute,SvPV(sval,na));
1415       break;
1416     }
1417     case 'E':
1418     case 'e':
1419     {
1420       if (LocaleCompare(attribute,"endian") == 0)
1421         {
1422           sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1423             SvPV(sval,na)) : SvIV(sval);
1424           if (sp < 0)
1425             {
1426               ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1427                 SvPV(sval,na));
1428               break;
1429             }
1430           if (info)
1431             info->image_info->endian=(EndianType) sp;
1432           for ( ; image; image=image->next)
1433             image->endian=(EndianType) sp;
1434           break;
1435         }
1436       if (LocaleCompare(attribute,"extract") == 0)
1437         {
1438           /*
1439             Set image extract geometry.
1440           */
1441           (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1442           break;
1443         }
1444       if (info)
1445         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1446       for ( ; image; image=image->next)
1447         SetImageProperty(image,attribute,SvPV(sval,na));
1448       break;
1449     }
1450     case 'F':
1451     case 'f':
1452     {
1453       if (LocaleCompare(attribute,"filename") == 0)
1454         {
1455           if (info)
1456             (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1457               MaxTextExtent);
1458           for ( ; image; image=image->next)
1459             (void) CopyMagickString(image->filename,SvPV(sval,na),
1460               MaxTextExtent);
1461           break;
1462         }
1463       if (LocaleCompare(attribute,"file") == 0)
1464         {
1465           FILE
1466             *file;
1467
1468           PerlIO
1469             *io_info;
1470
1471           if (info == (struct PackageInfo *) NULL)
1472             break;
1473           io_info=IoIFP(sv_2io(sval));
1474           if (io_info == (PerlIO *) NULL)
1475             {
1476               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1477                 PackageName);
1478               break;
1479             }
1480           file=PerlIO_findFILE(io_info);
1481           if (file == (FILE *) NULL)
1482             {
1483               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1484                 PackageName);
1485               break;
1486             }
1487           SetImageInfoFile(info->image_info,file);
1488           break;
1489         }
1490       if (LocaleCompare(attribute,"fill") == 0)
1491         {
1492           if (info)
1493             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1494           break;
1495         }
1496       if (LocaleCompare(attribute,"font") == 0)
1497         {
1498           if (info)
1499             (void) CloneString(&info->image_info->font,SvPV(sval,na));
1500           break;
1501         }
1502       if (LocaleCompare(attribute,"foreground") == 0)
1503         break;
1504       if (LocaleCompare(attribute,"fuzz") == 0)
1505         {
1506           if (info)
1507             info->image_info->fuzz=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1508           for ( ; image; image=image->next)
1509             image->fuzz=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1510           break;
1511         }
1512       if (info)
1513         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1514       for ( ; image; image=image->next)
1515         SetImageProperty(image,attribute,SvPV(sval,na));
1516       break;
1517     }
1518     case 'G':
1519     case 'g':
1520     {
1521       if (LocaleCompare(attribute,"gamma") == 0)
1522         {
1523           for ( ; image; image=image->next)
1524             image->gamma=SvNV(sval);
1525           break;
1526         }
1527       if (LocaleCompare(attribute,"gravity") == 0)
1528         {
1529           sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1530             SvPV(sval,na)) : SvIV(sval);
1531           if (sp < 0)
1532             {
1533               ThrowPerlException(exception,OptionError,
1534                 "UnrecognizedGravityType",SvPV(sval,na));
1535               break;
1536             }
1537           if (info)
1538             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1539           for ( ; image; image=image->next)
1540             image->gravity=(GravityType) sp;
1541           break;
1542         }
1543       if (LocaleCompare(attribute,"green-primary") == 0)
1544         {
1545           for ( ; image; image=image->next)
1546           {
1547             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1548             image->chromaticity.green_primary.x=geometry_info.rho;
1549             image->chromaticity.green_primary.y=geometry_info.sigma;
1550             if ((flags & SigmaValue) == 0)
1551               image->chromaticity.green_primary.y=
1552                 image->chromaticity.green_primary.x;
1553           }
1554           break;
1555         }
1556       if (info)
1557         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1558       for ( ; image; image=image->next)
1559         SetImageProperty(image,attribute,SvPV(sval,na));
1560       break;
1561     }
1562     case 'I':
1563     case 'i':
1564     {
1565       if (LocaleNCompare(attribute,"index",5) == 0)
1566         {
1567           IndexPacket
1568             *indexes;
1569
1570           int
1571             items;
1572
1573           long
1574             index;
1575
1576           register PixelPacket
1577             *p;
1578
1579           CacheView
1580             *image_view;
1581
1582           for ( ; image; image=image->next)
1583           {
1584             if (image->storage_class != PseudoClass)
1585               continue;
1586             x=0;
1587             y=0;
1588             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1589             image_view=AcquireCacheView(image);
1590             p=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1591             if (p != (PixelPacket *) NULL)
1592               {
1593                 indexes=GetCacheViewAuthenticIndexQueue(image_view);
1594                 items=sscanf(SvPV(sval,na),"%ld",&index);
1595                 if ((index >= 0) && (index < (ssize_t) image->colors))
1596                   SetIndexPixelComponent(indexes,index);
1597                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1598               }
1599             image_view=DestroyCacheView(image_view);
1600           }
1601           break;
1602         }
1603       if (LocaleCompare(attribute,"iterations") == 0)
1604         {
1605   iterations:
1606           for ( ; image; image=image->next)
1607             image->iterations=SvIV(sval);
1608           break;
1609         }
1610       if (LocaleCompare(attribute,"interlace") == 0)
1611         {
1612           sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1613             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1614           if (sp < 0)
1615             {
1616               ThrowPerlException(exception,OptionError,
1617                 "UnrecognizedInterlaceType",SvPV(sval,na));
1618               break;
1619             }
1620           if (info)
1621             info->image_info->interlace=(InterlaceType) sp;
1622           for ( ; image; image=image->next)
1623             image->interlace=(InterlaceType) sp;
1624           break;
1625         }
1626       if (info)
1627         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1628       for ( ; image; image=image->next)
1629         SetImageProperty(image,attribute,SvPV(sval,na));
1630       break;
1631     }
1632     case 'L':
1633     case 'l':
1634     {
1635       if (LocaleCompare(attribute,"label") == 0)
1636         {
1637           for ( ; image; image=image->next)
1638             (void) SetImageProperty(image,"label",InterpretImageProperties(
1639               info ? info->image_info : (ImageInfo *) NULL,image,
1640               SvPV(sval,na)));
1641           break;
1642         }
1643       if (LocaleCompare(attribute,"loop") == 0)
1644         goto iterations;
1645       if (info)
1646         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1647       for ( ; image; image=image->next)
1648         SetImageProperty(image,attribute,SvPV(sval,na));
1649       break;
1650     }
1651     case 'M':
1652     case 'm':
1653     {
1654       if (LocaleCompare(attribute,"magick") == 0)
1655         {
1656           if (info)
1657             (void) FormatMagickString(info->image_info->filename,MaxTextExtent,
1658               "%s:",SvPV(sval,na));
1659           for ( ; image; image=image->next)
1660             (void) CopyMagickString(image->magick,SvPV(sval,na),MaxTextExtent);
1661           break;
1662         }
1663       if (LocaleCompare(attribute,"map-limit") == 0)
1664         {
1665           MagickSizeType
1666             limit;
1667
1668           limit=MagickResourceInfinity;
1669           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1670             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1671           (void) SetMagickResourceLimit(MapResource,limit);
1672           break;
1673         }
1674       if (LocaleCompare(attribute,"mask") == 0)
1675         {
1676           Image
1677             *mask;
1678
1679           mask=(Image *) NULL;
1680           if (SvPOK(sval))
1681             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1682           for ( ; image; image=image->next)
1683             SetImageMask(image,mask);
1684           break;
1685         }
1686       if (LocaleCompare(attribute,"mattecolor") == 0)
1687         {
1688           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1689           if (info)
1690             info->image_info->matte_color=target_color;
1691           for ( ; image; image=image->next)
1692             image->matte_color=target_color;
1693           break;
1694         }
1695       if (LocaleCompare(attribute,"matte") == 0)
1696         {
1697           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1698             SvPV(sval,na)) : SvIV(sval);
1699           if (sp < 0)
1700             {
1701               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1702                 SvPV(sval,na));
1703               break;
1704             }
1705           for ( ; image; image=image->next)
1706             image->matte=sp != 0 ? MagickTrue : MagickFalse;
1707           break;
1708         }
1709       if (LocaleCompare(attribute,"memory-limit") == 0)
1710         {
1711           MagickSizeType
1712             limit;
1713
1714           limit=MagickResourceInfinity;
1715           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1716             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1717           (void) SetMagickResourceLimit(MemoryResource,limit);
1718           break;
1719         }
1720       if (LocaleCompare(attribute,"monochrome") == 0)
1721         {
1722           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1723             SvPV(sval,na)) : SvIV(sval);
1724           if (sp < 0)
1725             {
1726               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1727                 SvPV(sval,na));
1728               break;
1729             }
1730           if (info)
1731             info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1732           for ( ; image; image=image->next)
1733             (void) SetImageType(image,BilevelType);
1734           break;
1735         }
1736       if (info)
1737         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1738       for ( ; image; image=image->next)
1739         SetImageProperty(image,attribute,SvPV(sval,na));
1740       break;
1741     }
1742     case 'O':
1743     case 'o':
1744     {
1745       if (LocaleCompare(attribute,"option") == 0)
1746         {
1747           if (info)
1748             DefineImageOption(info->image_info,SvPV(sval,na));
1749           break;
1750         }
1751       if (LocaleCompare(attribute,"orientation") == 0)
1752         {
1753           sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1754             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1755           if (sp < 0)
1756             {
1757               ThrowPerlException(exception,OptionError,
1758                 "UnrecognizedOrientationType",SvPV(sval,na));
1759               break;
1760             }
1761           if (info)
1762             info->image_info->orientation=(OrientationType) sp;
1763           for ( ; image; image=image->next)
1764             image->orientation=(OrientationType) sp;
1765           break;
1766         }
1767       if (info)
1768         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1769       for ( ; image; image=image->next)
1770         SetImageProperty(image,attribute,SvPV(sval,na));
1771       break;
1772     }
1773     case 'P':
1774     case 'p':
1775     {
1776       if (LocaleCompare(attribute,"page") == 0)
1777         {
1778           char
1779             *geometry;
1780
1781           geometry=GetPageGeometry(SvPV(sval,na));
1782           if (info)
1783             (void) CloneString(&info->image_info->page,geometry);
1784           for ( ; image; image=image->next)
1785             (void) ParsePageGeometry(image,geometry,&image->page,exception);
1786           geometry=(char *) RelinquishMagickMemory(geometry);
1787           break;
1788         }
1789       if (LocaleCompare(attribute,"pen") == 0)
1790         {
1791           if (info)
1792             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1793           break;
1794         }
1795       if (LocaleNCompare(attribute,"pixel",5) == 0)
1796         {
1797           int
1798             items;
1799
1800           MagickPixelPacket
1801             pixel;
1802
1803           register IndexPacket
1804             *indexes;
1805
1806           register PixelPacket
1807             *q;
1808
1809           CacheView
1810             *image_view;
1811
1812           for ( ; image; image=image->next)
1813           {
1814             if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1815               break;
1816             x=0;
1817             y=0;
1818             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1819             image_view=AcquireCacheView(image);
1820             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1821             indexes=GetCacheViewAuthenticIndexQueue(image_view);
1822             if (q != (PixelPacket *) NULL)
1823               {
1824                 if ((strchr(SvPV(sval,na),',') == 0) ||
1825                     (strchr(SvPV(sval,na),')') != 0))
1826                   QueryMagickColor(SvPV(sval,na),&pixel,exception);
1827                 else
1828                   {
1829                     GetMagickPixelPacket(image,&pixel);
1830                     flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1831                     pixel.red=geometry_info.rho;
1832                     if ((flags & SigmaValue) != 0)
1833                       pixel.green=geometry_info.sigma;
1834                     if ((flags & XiValue) != 0)
1835                       pixel.blue=geometry_info.xi;
1836                     if ((flags & PsiValue) != 0)
1837                       pixel.opacity=geometry_info.psi;
1838                     if ((flags & ChiValue) != 0)
1839                       pixel.index=geometry_info.chi;
1840                   }
1841                 SetRedPixelComponent(q,ClampToQuantum(pixel.red));
1842                 SetGreenPixelComponent(q,ClampToQuantum(pixel.green));
1843                 SetBluePixelComponent(q,ClampToQuantum(pixel.blue));
1844                 SetOpacityPixelComponent(q,ClampToQuantum(pixel.opacity));
1845                 if (((image->colorspace == CMYKColorspace) ||
1846                      (image->storage_class == PseudoClass)) &&
1847                     (indexes != (IndexPacket *) NULL))
1848                   SetIndexPixelComponent(indexes,ClampToQuantum(pixel.index));
1849                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1850               }
1851             image_view=DestroyCacheView(image_view);
1852           }
1853           break;
1854         }
1855       if (LocaleCompare(attribute,"pointsize") == 0)
1856         {
1857           if (info)
1858             {
1859               (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1860               info->image_info->pointsize=geometry_info.rho;
1861             }
1862           break;
1863         }
1864       if (LocaleCompare(attribute,"preview") == 0)
1865         {
1866           sp=SvPOK(sval) ? ParseCommandOption(MagickPreviewOptions,MagickFalse,
1867             SvPV(sval,na)) : SvIV(sval);
1868           if (sp < 0)
1869             {
1870               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1871                 SvPV(sval,na));
1872               break;
1873             }
1874           if (info)
1875             info->image_info->preview_type=(PreviewType) sp;
1876           break;
1877         }
1878       if (info)
1879         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1880       for ( ; image; image=image->next)
1881         SetImageProperty(image,attribute,SvPV(sval,na));
1882       break;
1883     }
1884     case 'Q':
1885     case 'q':
1886     {
1887       if (LocaleCompare(attribute,"quality") == 0)
1888         {
1889           if (info)
1890             info->image_info->quality=SvIV(sval);
1891           for ( ; image; image=image->next)
1892             image->quality=SvIV(sval);
1893           break;
1894         }
1895       if (info)
1896         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1897       for ( ; image; image=image->next)
1898         SetImageProperty(image,attribute,SvPV(sval,na));
1899       break;
1900     }
1901     case 'R':
1902     case 'r':
1903     {
1904       if (LocaleCompare(attribute,"red-primary") == 0)
1905         {
1906           for ( ; image; image=image->next)
1907           {
1908             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1909             image->chromaticity.red_primary.x=geometry_info.rho;
1910             image->chromaticity.red_primary.y=geometry_info.sigma;
1911             if ((flags & SigmaValue) == 0)
1912               image->chromaticity.red_primary.y=
1913                 image->chromaticity.red_primary.x;
1914           }
1915           break;
1916         }
1917       if (LocaleCompare(attribute,"render") == 0)
1918         {
1919           sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1920             SvPV(sval,na)) : SvIV(sval);
1921           if (sp < 0)
1922             {
1923               ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1924                 SvPV(sval,na));
1925               break;
1926             }
1927          for ( ; image; image=image->next)
1928            image->rendering_intent=(RenderingIntent) sp;
1929          break;
1930        }
1931       if (LocaleCompare(attribute,"repage") == 0)
1932         {
1933           RectangleInfo
1934             geometry;
1935
1936           for ( ; image; image=image->next)
1937           {
1938             flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
1939             if ((flags & WidthValue) != 0)
1940               {
1941                 if ((flags & HeightValue) == 0)
1942                   geometry.height=geometry.width;
1943                 image->page.width=geometry.width;
1944                 image->page.height=geometry.height;
1945               }
1946             if ((flags & AspectValue) != 0)
1947               {
1948                 if ((flags & XValue) != 0)
1949                   image->page.x+=geometry.x;
1950                 if ((flags & YValue) != 0)
1951                   image->page.y+=geometry.y;
1952               }
1953             else
1954               {
1955                 if ((flags & XValue) != 0)
1956                   {
1957                     image->page.x=geometry.x;
1958                     if (((flags & WidthValue) != 0) && (geometry.x > 0))
1959                       image->page.width=image->columns+geometry.x;
1960                   }
1961                 if ((flags & YValue) != 0)
1962                   {
1963                     image->page.y=geometry.y;
1964                     if (((flags & HeightValue) != 0) && (geometry.y > 0))
1965                       image->page.height=image->rows+geometry.y;
1966                   }
1967               }
1968           }
1969           break;
1970         }
1971       if (info)
1972         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1973       for ( ; image; image=image->next)
1974         SetImageProperty(image,attribute,SvPV(sval,na));
1975       break;
1976     }
1977     case 'S':
1978     case 's':
1979     {
1980       if (LocaleCompare(attribute,"sampling-factor") == 0)
1981         {
1982           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1983             {
1984               ThrowPerlException(exception,OptionError,"MissingGeometry",
1985                 SvPV(sval,na));
1986               break;
1987             }
1988           if (info)
1989             (void) CloneString(&info->image_info->sampling_factor,
1990               SvPV(sval,na));
1991           break;
1992         }
1993       if (LocaleCompare(attribute,"scene") == 0)
1994         {
1995           for ( ; image; image=image->next)
1996             image->scene=SvIV(sval);
1997           break;
1998         }
1999       if (LocaleCompare(attribute,"subimage") == 0)
2000         {
2001           if (info)
2002             info->image_info->subimage=SvIV(sval);
2003           break;
2004         }
2005       if (LocaleCompare(attribute,"subrange") == 0)
2006         {
2007           if (info)
2008             info->image_info->subrange=SvIV(sval);
2009           break;
2010         }
2011       if (LocaleCompare(attribute,"server") == 0)
2012         goto display;
2013       if (LocaleCompare(attribute,"size") == 0)
2014         {
2015           if (info)
2016             {
2017               if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2018                 {
2019                   ThrowPerlException(exception,OptionError,"MissingGeometry",
2020                     SvPV(sval,na));
2021                   break;
2022                 }
2023               (void) CloneString(&info->image_info->size,SvPV(sval,na));
2024             }
2025           break;
2026         }
2027       if (LocaleCompare(attribute,"stroke") == 0)
2028         {
2029           if (info)
2030             (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2031           break;
2032         }
2033       if (info)
2034         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2035       for ( ; image; image=image->next)
2036         SetImageProperty(image,attribute,SvPV(sval,na));
2037       break;
2038     }
2039     case 'T':
2040     case 't':
2041     {
2042       if (LocaleCompare(attribute,"texture") == 0)
2043         {
2044           if (info)
2045             (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2046           break;
2047         }
2048       if (LocaleCompare(attribute,"thread-limit") == 0)
2049         {
2050           MagickSizeType
2051             limit;
2052
2053           limit=MagickResourceInfinity;
2054           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2055             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
2056           (void) SetMagickResourceLimit(ThreadResource,limit);
2057           break;
2058         }
2059       if (LocaleCompare(attribute,"tile") == 0)
2060         {
2061           if (info)
2062             (void) CloneString(&info->image_info->tile,SvPV(sval,na));
2063           break;
2064         }
2065       if (LocaleCompare(attribute,"tile-offset") == 0)
2066         {
2067           char
2068             *geometry;
2069
2070           geometry=GetPageGeometry(SvPV(sval,na));
2071           if (info)
2072             (void) CloneString(&info->image_info->page,geometry);
2073           for ( ; image; image=image->next)
2074             (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2075               exception);
2076           geometry=(char *) RelinquishMagickMemory(geometry);
2077           break;
2078         }
2079       if (LocaleCompare(attribute,"time-limit") == 0)
2080         {
2081           MagickSizeType
2082             limit;
2083
2084           limit=MagickResourceInfinity;
2085           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2086             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
2087           (void) SetMagickResourceLimit(TimeResource,limit);
2088           break;
2089         }
2090       if (LocaleCompare(attribute,"transparent-color") == 0)
2091         {
2092           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
2093           if (info)
2094             info->image_info->transparent_color=target_color;
2095           for ( ; image; image=image->next)
2096             image->transparent_color=target_color;
2097           break;
2098         }
2099       if (LocaleCompare(attribute,"type") == 0)
2100         {
2101           sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2102             SvPV(sval,na)) : SvIV(sval);
2103           if (sp < 0)
2104             {
2105               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2106                 SvPV(sval,na));
2107               break;
2108             }
2109           if (info)
2110             info->image_info->type=(ImageType) sp;
2111           for ( ; image; image=image->next)
2112             SetImageType(image,(ImageType) sp);
2113           break;
2114         }
2115       if (info)
2116         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2117       for ( ; image; image=image->next)
2118         SetImageProperty(image,attribute,SvPV(sval,na));
2119       break;
2120     }
2121     case 'U':
2122     case 'u':
2123     {
2124       if (LocaleCompare(attribute,"units") == 0)
2125         {
2126           sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2127             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2128           if (sp < 0)
2129             {
2130               ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2131                 SvPV(sval,na));
2132               break;
2133             }
2134           if (info)
2135             info->image_info->units=(ResolutionType) sp;
2136           for ( ; image; image=image->next)
2137           {
2138             ResolutionType
2139               units;
2140
2141             units=(ResolutionType) sp;
2142             if (image->units != units)
2143               switch (image->units)
2144               {
2145                 case UndefinedResolution:
2146                 case PixelsPerInchResolution:
2147                 {
2148                   if (units == PixelsPerCentimeterResolution)
2149                     {
2150                       image->x_resolution*=2.54;
2151                       image->y_resolution*=2.54;
2152                     }
2153                   break;
2154                 }
2155                 case PixelsPerCentimeterResolution:
2156                 {
2157                   if (units == PixelsPerInchResolution)
2158                     {
2159                       image->x_resolution/=2.54;
2160                       image->y_resolution/=2.54;
2161                     }
2162                   break;
2163                 }
2164               }
2165             image->units=units;
2166           }
2167           break;
2168         }
2169       if (info)
2170         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2171       for ( ; image; image=image->next)
2172         SetImageProperty(image,attribute,SvPV(sval,na));
2173       break;
2174     }
2175     case 'V':
2176     case 'v':
2177     {
2178       if (LocaleCompare(attribute,"verbose") == 0)
2179         {
2180           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2181             SvPV(sval,na)) : SvIV(sval);
2182           if (sp < 0)
2183             {
2184               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2185                 SvPV(sval,na));
2186               break;
2187             }
2188           if (info)
2189             info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2190           break;
2191         }
2192       if (LocaleCompare(attribute,"view") == 0)
2193         {
2194           if (info)
2195             (void) CloneString(&info->image_info->view,SvPV(sval,na));
2196           break;
2197         }
2198       if (LocaleCompare(attribute,"virtual-pixel") == 0)
2199         {
2200           sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2201             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2202           if (sp < 0)
2203             {
2204               ThrowPerlException(exception,OptionError,
2205                 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2206               break;
2207             }
2208           if (info)
2209             info->image_info->virtual_pixel_method=(VirtualPixelMethod) sp;
2210           for ( ; image; image=image->next)
2211             SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp);
2212           break;
2213         }
2214       if (info)
2215         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2216       for ( ; image; image=image->next)
2217         SetImageProperty(image,attribute,SvPV(sval,na));
2218       break;
2219     }
2220     case 'W':
2221     case 'w':
2222     {
2223       if (LocaleCompare(attribute,"white-point") == 0)
2224         {
2225           for ( ; image; image=image->next)
2226           {
2227             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2228             image->chromaticity.white_point.x=geometry_info.rho;
2229             image->chromaticity.white_point.y=geometry_info.sigma;
2230             if ((flags & SigmaValue) == 0)
2231               image->chromaticity.white_point.y=
2232                 image->chromaticity.white_point.x;
2233           }
2234           break;
2235         }
2236       if (info)
2237         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2238       for ( ; image; image=image->next)
2239         SetImageProperty(image,attribute,SvPV(sval,na));
2240       break;
2241     }
2242     default:
2243     {
2244       if (info)
2245         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2246       for ( ; image; image=image->next)
2247         SetImageProperty(image,attribute,SvPV(sval,na));
2248       break;
2249     }
2250   }
2251 }
2252 \f
2253 /*
2254 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2255 %                                                                             %
2256 %                                                                             %
2257 %                                                                             %
2258 %   S e t u p L i s t                                                         %
2259 %                                                                             %
2260 %                                                                             %
2261 %                                                                             %
2262 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2263 %
2264 %  Method SetupList returns the list of all the images linked by their
2265 %  image->next and image->previous link lists for use with ImageMagick.  If
2266 %  info is non-NULL, an info structure is returned in *info.  If
2267 %  reference_vector is non-NULL,an array of SV* are returned in
2268 %  *reference_vector.  Reference_vector is used when the images are going to be
2269 %  replaced with new Image*'s.
2270 %
2271 %  The format of the SetupList routine is:
2272 %
2273 %      Image *SetupList(SV *reference,struct PackageInfo **info,
2274 %        SV ***reference_vector,ExceptionInfo *exception)
2275 %
2276 %  A description of each parameter follows:
2277 %
2278 %    o list: a list of strings.
2279 %
2280 %    o string: a character string.
2281 %
2282 %    o exception: Return any errors or warnings in this structure.
2283 %
2284 */
2285 static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2286   SV ***reference_vector,ExceptionInfo *exception)
2287 {
2288   Image
2289     *image;
2290
2291   ssize_t
2292     current,
2293     last;
2294
2295   if (reference_vector)
2296     *reference_vector=NULL;
2297   if (info)
2298     *info=NULL;
2299   current=0;
2300   last=0;
2301   image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2302   if (info && (SvTYPE(reference) == SVt_PVAV))
2303     *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2304       exception);
2305   return(image);
2306 }
2307 \f
2308 /*
2309 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2310 %                                                                             %
2311 %                                                                             %
2312 %                                                                             %
2313 %   s t r E Q c a s e                                                         %
2314 %                                                                             %
2315 %                                                                             %
2316 %                                                                             %
2317 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2318 %
2319 %  strEQcase() compares two strings and returns 0 if they are the
2320 %  same or if the second string runs out first.  The comparison is case
2321 %  insensitive.
2322 %
2323 %  The format of the strEQcase routine is:
2324 %
2325 %      ssize_t strEQcase(const char *p,const char *q)
2326 %
2327 %  A description of each parameter follows:
2328 %
2329 %    o p: a character string.
2330 %
2331 %    o q: a character string.
2332 %
2333 %
2334 */
2335 static ssize_t strEQcase(const char *p,const char *q)
2336 {
2337   char
2338     c;
2339
2340   register ssize_t
2341     i;
2342
2343   for (i=0 ; (c=(*q)) != 0; i++)
2344   {
2345     if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2346         (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2347       return(0);
2348     p++;
2349     q++;
2350   }
2351   return(((*q == 0) && (*p == 0)) ? i : 0);
2352 }
2353 \f
2354 /*
2355 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2356 %                                                                             %
2357 %                                                                             %
2358 %                                                                             %
2359 %   I m a g e : : M a g i c k                                                 %
2360 %                                                                             %
2361 %                                                                             %
2362 %                                                                             %
2363 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2364 %
2365 %
2366 */
2367 MODULE = Image::Magick PACKAGE = Image::Magick
2368
2369 PROTOTYPES: ENABLE
2370
2371 BOOT:
2372   MagickCoreGenesis("PerlMagick",MagickFalse);
2373   SetWarningHandler(NULL);
2374   SetErrorHandler(NULL);
2375   magick_registry=NewSplayTree((int (*)(const void *,const void *))
2376     NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2377
2378 void
2379 UNLOAD()
2380   PPCODE:
2381   {
2382     if (magick_registry != (SplayTreeInfo *) NULL)
2383       magick_registry=DestroySplayTree(magick_registry);
2384     MagickCoreTerminus();
2385   }
2386
2387 double
2388 constant(name,argument)
2389   char *name
2390   ssize_t argument
2391 \f
2392 #
2393 ###############################################################################
2394 #                                                                             #
2395 #                                                                             #
2396 #                                                                             #
2397 #   A n i m a t e                                                             #
2398 #                                                                             #
2399 #                                                                             #
2400 #                                                                             #
2401 ###############################################################################
2402 #
2403 #
2404 void
2405 Animate(ref,...)
2406   Image::Magick ref=NO_INIT
2407   ALIAS:
2408     AnimateImage  = 1
2409     animate       = 2
2410     animateimage  = 3
2411   PPCODE:
2412   {
2413     ExceptionInfo
2414       *exception;
2415
2416     Image
2417       *image;
2418
2419     register ssize_t
2420       i;
2421
2422     struct PackageInfo
2423       *info,
2424       *package_info;
2425
2426     SV
2427       *perl_exception,
2428       *reference;
2429
2430     PERL_UNUSED_VAR(ref);
2431     PERL_UNUSED_VAR(ix);
2432     exception=AcquireExceptionInfo();
2433     perl_exception=newSVpv("",0);
2434     package_info=(struct PackageInfo *) NULL;
2435     if (sv_isobject(ST(0)) == 0)
2436       {
2437         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2438           PackageName);
2439         goto PerlException;
2440       }
2441     reference=SvRV(ST(0));
2442     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2443     if (image == (Image *) NULL)
2444       {
2445         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2446           PackageName);
2447         goto PerlException;
2448       }
2449     package_info=ClonePackageInfo(info,exception);
2450     if (items == 2)
2451       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2452     else
2453       if (items > 2)
2454         for (i=2; i < items; i+=2)
2455           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2456             exception);
2457     (void) AnimateImages(package_info->image_info,image);
2458     (void) CatchImageException(image);
2459     InheritException(exception,&image->exception);
2460
2461   PerlException:
2462     if (package_info != (struct PackageInfo *) NULL)
2463       DestroyPackageInfo(package_info);
2464     InheritPerlException(exception,perl_exception);
2465     exception=DestroyExceptionInfo(exception);
2466     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2467     SvPOK_on(perl_exception);
2468     ST(0)=sv_2mortal(perl_exception);
2469     XSRETURN(1);
2470   }
2471 \f
2472 #
2473 ###############################################################################
2474 #                                                                             #
2475 #                                                                             #
2476 #                                                                             #
2477 #   A p p e n d                                                               #
2478 #                                                                             #
2479 #                                                                             #
2480 #                                                                             #
2481 ###############################################################################
2482 #
2483 #
2484 void
2485 Append(ref,...)
2486   Image::Magick ref=NO_INIT
2487   ALIAS:
2488     AppendImage  = 1
2489     append       = 2
2490     appendimage  = 3
2491   PPCODE:
2492   {
2493     AV
2494       *av;
2495
2496     char
2497       *attribute;
2498
2499     ExceptionInfo
2500       *exception;
2501
2502     HV
2503       *hv;
2504
2505     Image
2506       *image;
2507
2508     register ssize_t
2509       i;
2510
2511     ssize_t
2512       stack;
2513
2514     struct PackageInfo
2515       *info;
2516
2517     SV
2518       *av_reference,
2519       *perl_exception,
2520       *reference,
2521       *rv,
2522       *sv;
2523
2524     PERL_UNUSED_VAR(ref);
2525     PERL_UNUSED_VAR(ix);
2526     exception=AcquireExceptionInfo();
2527     perl_exception=newSVpv("",0);
2528     sv=NULL;
2529     attribute=NULL;
2530     av=NULL;
2531     if (sv_isobject(ST(0)) == 0)
2532       {
2533         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2534           PackageName);
2535         goto PerlException;
2536       }
2537     reference=SvRV(ST(0));
2538     hv=SvSTASH(reference);
2539     av=newAV();
2540     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2541     SvREFCNT_dec(av);
2542     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2543     if (image == (Image *) NULL)
2544       {
2545         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2546           PackageName);
2547         goto PerlException;
2548       }
2549     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2550     /*
2551       Get options.
2552     */
2553     stack=MagickTrue;
2554     for (i=2; i < items; i+=2)
2555     {
2556       attribute=(char *) SvPV(ST(i-1),na);
2557       switch (*attribute)
2558       {
2559         case 'S':
2560         case 's':
2561         {
2562           if (LocaleCompare(attribute,"stack") == 0)
2563             {
2564               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2565                 SvPV(ST(i),na));
2566               if (stack < 0)
2567                 {
2568                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
2569                     SvPV(ST(i),na));
2570                   return;
2571                 }
2572               break;
2573             }
2574           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2575             attribute);
2576           break;
2577         }
2578         default:
2579         {
2580           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2581             attribute);
2582           break;
2583         }
2584       }
2585     }
2586     image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2587     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2588       goto PerlException;
2589     for ( ; image; image=image->next)
2590     {
2591       AddImageToRegistry(sv,image);
2592       rv=newRV(sv);
2593       av_push(av,sv_bless(rv,hv));
2594       SvREFCNT_dec(sv);
2595     }
2596     exception=DestroyExceptionInfo(exception);
2597     ST(0)=av_reference;
2598     SvREFCNT_dec(perl_exception);
2599     XSRETURN(1);
2600
2601   PerlException:
2602     InheritPerlException(exception,perl_exception);
2603     exception=DestroyExceptionInfo(exception);
2604     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2605     SvPOK_on(perl_exception);
2606     ST(0)=sv_2mortal(perl_exception);
2607     XSRETURN(1);
2608   }
2609 \f
2610 #
2611 ###############################################################################
2612 #                                                                             #
2613 #                                                                             #
2614 #                                                                             #
2615 #   A v e r a g e                                                             #
2616 #                                                                             #
2617 #                                                                             #
2618 #                                                                             #
2619 ###############################################################################
2620 #
2621 #
2622 void
2623 Average(ref)
2624   Image::Magick ref=NO_INIT
2625   ALIAS:
2626     AverageImage   = 1
2627     average        = 2
2628     averageimage   = 3
2629   PPCODE:
2630   {
2631     AV
2632       *av;
2633
2634     char
2635       *p;
2636
2637     ExceptionInfo
2638       *exception;
2639
2640     HV
2641       *hv;
2642
2643     Image
2644       *image;
2645
2646     struct PackageInfo
2647       *info;
2648
2649     SV
2650       *perl_exception,
2651       *reference,
2652       *rv,
2653       *sv;
2654
2655     PERL_UNUSED_VAR(ref);
2656     PERL_UNUSED_VAR(ix);
2657     exception=AcquireExceptionInfo();
2658     perl_exception=newSVpv("",0);
2659     sv=NULL;
2660     if (sv_isobject(ST(0)) == 0)
2661       {
2662         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2663           PackageName);
2664         goto PerlException;
2665       }
2666     reference=SvRV(ST(0));
2667     hv=SvSTASH(reference);
2668     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2669     if (image == (Image *) NULL)
2670       {
2671         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2672           PackageName);
2673         goto PerlException;
2674       }
2675     image=EvaluateImages(image,MeanEvaluateOperator,exception);
2676     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2677       goto PerlException;
2678     /*
2679       Create blessed Perl array for the returned image.
2680     */
2681     av=newAV();
2682     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2683     SvREFCNT_dec(av);
2684     AddImageToRegistry(sv,image);
2685     rv=newRV(sv);
2686     av_push(av,sv_bless(rv,hv));
2687     SvREFCNT_dec(sv);
2688     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2689     (void) FormatMagickString(info->image_info->filename,MaxTextExtent,
2690       "average-%.*s",(int) (MaxTextExtent-9),
2691       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2692     (void) CopyMagickString(image->filename,info->image_info->filename,
2693       MaxTextExtent);
2694     SetImageInfo(info->image_info,0,exception);
2695     exception=DestroyExceptionInfo(exception);
2696     SvREFCNT_dec(perl_exception);
2697     XSRETURN(1);
2698
2699   PerlException:
2700     InheritPerlException(exception,perl_exception);
2701     exception=DestroyExceptionInfo(exception);
2702     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2703     SvPOK_on(perl_exception);
2704     ST(0)=sv_2mortal(perl_exception);
2705     XSRETURN(1);
2706   }
2707 \f
2708 #
2709 ###############################################################################
2710 #                                                                             #
2711 #                                                                             #
2712 #                                                                             #
2713 #   B l o b T o I m a g e                                                     #
2714 #                                                                             #
2715 #                                                                             #
2716 #                                                                             #
2717 ###############################################################################
2718 #
2719 #
2720 void
2721 BlobToImage(ref,...)
2722   Image::Magick ref=NO_INIT
2723   ALIAS:
2724     BlobToImage  = 1
2725     blobtoimage  = 2
2726     blobto       = 3
2727   PPCODE:
2728   {
2729     AV
2730       *av;
2731
2732     char
2733       **keep,
2734       **list;
2735
2736     ExceptionInfo
2737       *exception;
2738
2739     HV
2740       *hv;
2741
2742     Image
2743       *image;
2744
2745     register char
2746       **p;
2747
2748     register ssize_t
2749       i;
2750
2751     ssize_t
2752       ac,
2753       n,
2754       number_images;
2755
2756     STRLEN
2757       *length;
2758
2759     struct PackageInfo
2760       *info;
2761
2762     SV
2763       *perl_exception,
2764       *reference,
2765       *rv,
2766       *sv;
2767
2768     PERL_UNUSED_VAR(ref);
2769     PERL_UNUSED_VAR(ix);
2770     exception=AcquireExceptionInfo();
2771     perl_exception=newSVpv("",0);
2772     sv=NULL;
2773     number_images=0;
2774     ac=(items < 2) ? 1 : items-1;
2775     length=(STRLEN *) NULL;
2776     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2777     if (list == (char **) NULL)
2778       {
2779         ThrowPerlException(exception,ResourceLimitError,
2780           "MemoryAllocationFailed",PackageName);
2781         goto PerlException;
2782       }
2783     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2784     if (length == (STRLEN *) NULL)
2785       {
2786         ThrowPerlException(exception,ResourceLimitError,
2787           "MemoryAllocationFailed",PackageName);
2788         goto PerlException;
2789       }
2790     if (sv_isobject(ST(0)) == 0)
2791       {
2792         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2793           PackageName);
2794         goto PerlException;
2795       }
2796     reference=SvRV(ST(0));
2797     hv=SvSTASH(reference);
2798     if (SvTYPE(reference) != SVt_PVAV)
2799       {
2800         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2801           PackageName);
2802         goto PerlException;
2803       }
2804     av=(AV *) reference;
2805     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2806       exception);
2807     n=1;
2808     if (items <= 1)
2809       {
2810         ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2811         goto PerlException;
2812       }
2813     for (n=0, i=0; i < ac; i++)
2814     {
2815       list[n]=(char *) (SvPV(ST(i+1),length[n]));
2816       if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2817         {
2818           list[n]=(char *) (SvPV(ST(i+2),length[n]));
2819           continue;
2820         }
2821       n++;
2822     }
2823     list[n]=(char *) NULL;
2824     keep=list;
2825     for (i=number_images=0; i < n; i++)
2826     {
2827       image=BlobToImage(info->image_info,list[i],length[i],exception);
2828       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2829         break;
2830       for ( ; image; image=image->next)
2831       {
2832         AddImageToRegistry(sv,image);
2833         rv=newRV(sv);
2834         av_push(av,sv_bless(rv,hv));
2835         SvREFCNT_dec(sv);
2836         number_images++;
2837       }
2838     }
2839     /*
2840       Free resources.
2841     */
2842     for (i=0; i < n; i++)
2843       if (list[i] != (char *) NULL)
2844         for (p=keep; list[i] != *p++; )
2845           if (*p == (char *) NULL)
2846             {
2847               list[i]=(char *) RelinquishMagickMemory(list[i]);
2848               break;
2849             }
2850
2851   PerlException:
2852     if (list)
2853       list=(char **) RelinquishMagickMemory(list);
2854     if (length)
2855       length=(STRLEN *) RelinquishMagickMemory(length);
2856     InheritPerlException(exception,perl_exception);
2857     exception=DestroyExceptionInfo(exception);
2858     sv_setiv(perl_exception,(IV) number_images);
2859     SvPOK_on(perl_exception);
2860     ST(0)=sv_2mortal(perl_exception);
2861     XSRETURN(1);
2862   }
2863 \f
2864 #
2865 ###############################################################################
2866 #                                                                             #
2867 #                                                                             #
2868 #                                                                             #
2869 #   C l o n e                                                                 #
2870 #                                                                             #
2871 #                                                                             #
2872 #                                                                             #
2873 ###############################################################################
2874 #
2875 #
2876 void
2877 Clone(ref)
2878   Image::Magick ref=NO_INIT
2879   ALIAS:
2880     CopyImage   = 1
2881     copy        = 2
2882     copyimage   = 3
2883     CloneImage  = 4
2884     clone       = 5
2885     cloneimage  = 6
2886     Clone       = 7
2887   PPCODE:
2888   {
2889     AV
2890       *av;
2891
2892     ExceptionInfo
2893       *exception;
2894
2895     HV
2896       *hv;
2897
2898     Image
2899       *clone,
2900       *image;
2901
2902     struct PackageInfo
2903       *info;
2904
2905     SV
2906       *perl_exception,
2907       *reference,
2908       *rv,
2909       *sv;
2910
2911     PERL_UNUSED_VAR(ref);
2912     PERL_UNUSED_VAR(ix);
2913     exception=AcquireExceptionInfo();
2914     perl_exception=newSVpv("",0);
2915     sv=NULL;
2916     if (sv_isobject(ST(0)) == 0)
2917       {
2918         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2919           PackageName);
2920         goto PerlException;
2921       }
2922     reference=SvRV(ST(0));
2923     hv=SvSTASH(reference);
2924     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2925     if (image == (Image *) NULL)
2926       {
2927         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2928           PackageName);
2929         goto PerlException;
2930       }
2931     /*
2932       Create blessed Perl array for the returned image.
2933     */
2934     av=newAV();
2935     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2936     SvREFCNT_dec(av);
2937     for ( ; image; image=image->next)
2938     {
2939       clone=CloneImage(image,0,0,MagickTrue,exception);
2940       if ((clone == (Image *) NULL) || (exception->severity >= ErrorException))
2941         break;
2942       AddImageToRegistry(sv,clone);
2943       rv=newRV(sv);
2944       av_push(av,sv_bless(rv,hv));
2945       SvREFCNT_dec(sv);
2946     }
2947     exception=DestroyExceptionInfo(exception);
2948     SvREFCNT_dec(perl_exception);
2949     XSRETURN(1);
2950
2951   PerlException:
2952     InheritPerlException(exception,perl_exception);
2953     exception=DestroyExceptionInfo(exception);
2954     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2955     SvPOK_on(perl_exception);
2956     ST(0)=sv_2mortal(perl_exception);
2957     XSRETURN(1);
2958   }
2959 \f
2960 #
2961 ###############################################################################
2962 #                                                                             #
2963 #                                                                             #
2964 #                                                                             #
2965 #   C L O N E                                                                 #
2966 #                                                                             #
2967 #                                                                             #
2968 #                                                                             #
2969 ###############################################################################
2970 #
2971 #
2972 void
2973 CLONE(ref,...)
2974   SV *ref;
2975   CODE:
2976   {
2977     PERL_UNUSED_VAR(ref);
2978     if (magick_registry != (SplayTreeInfo *) NULL)
2979       {
2980         register Image
2981           *p;
2982
2983         ResetSplayTreeIterator(magick_registry);
2984         p=(Image *) GetNextKeyInSplayTree(magick_registry);
2985         while (p != (Image *) NULL)
2986         {
2987           ReferenceImage(p);
2988           p=(Image *) GetNextKeyInSplayTree(magick_registry);
2989         }
2990       }
2991   }
2992 \f
2993 #
2994 ###############################################################################
2995 #                                                                             #
2996 #                                                                             #
2997 #                                                                             #
2998 #   C o a l e s c e                                                           #
2999 #                                                                             #
3000 #                                                                             #
3001 #                                                                             #
3002 ###############################################################################
3003 #
3004 #
3005 void
3006 Coalesce(ref)
3007   Image::Magick ref=NO_INIT
3008   ALIAS:
3009     CoalesceImage   = 1
3010     coalesce        = 2
3011     coalesceimage   = 3
3012   PPCODE:
3013   {
3014     AV
3015       *av;
3016
3017     ExceptionInfo
3018       *exception;
3019
3020     HV
3021       *hv;
3022
3023     Image
3024       *image;
3025
3026     struct PackageInfo
3027       *info;
3028
3029     SV
3030       *av_reference,
3031       *perl_exception,
3032       *reference,
3033       *rv,
3034       *sv;
3035
3036     PERL_UNUSED_VAR(ref);
3037     PERL_UNUSED_VAR(ix);
3038     exception=AcquireExceptionInfo();
3039     perl_exception=newSVpv("",0);
3040     sv=NULL;
3041     if (sv_isobject(ST(0)) == 0)
3042       {
3043         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3044           PackageName);
3045         goto PerlException;
3046       }
3047     reference=SvRV(ST(0));
3048     hv=SvSTASH(reference);
3049     av=newAV();
3050     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3051     SvREFCNT_dec(av);
3052     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3053     if (image == (Image *) NULL)
3054       {
3055         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3056           PackageName);
3057         goto PerlException;
3058       }
3059     image=CoalesceImages(image,exception);
3060     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3061       goto PerlException;
3062     for ( ; image; image=image->next)
3063     {
3064       AddImageToRegistry(sv,image);
3065       rv=newRV(sv);
3066       av_push(av,sv_bless(rv,hv));
3067       SvREFCNT_dec(sv);
3068     }
3069     exception=DestroyExceptionInfo(exception);
3070     ST(0)=av_reference;
3071     SvREFCNT_dec(perl_exception);
3072     XSRETURN(1);
3073
3074   PerlException:
3075     InheritPerlException(exception,perl_exception);
3076     exception=DestroyExceptionInfo(exception);
3077     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3078     SvPOK_on(perl_exception);
3079     ST(0)=sv_2mortal(perl_exception);
3080     XSRETURN(1);
3081   }
3082 \f
3083 #
3084 ###############################################################################
3085 #                                                                             #
3086 #                                                                             #
3087 #                                                                             #
3088 #   C o m p a r e                                                             #
3089 #                                                                             #
3090 #                                                                             #
3091 #                                                                             #
3092 ###############################################################################
3093 #
3094 #
3095 void
3096 Compare(ref,...)
3097   Image::Magick ref=NO_INIT
3098   ALIAS:
3099     CompareImage = 1
3100     compare      = 2
3101     compareimage = 3
3102   PPCODE:
3103   {
3104     AV
3105       *av;
3106
3107     char
3108       *attribute;
3109
3110     ChannelType
3111       channel;
3112
3113     double
3114       distortion;
3115
3116     ExceptionInfo
3117       *exception;
3118
3119     HV
3120       *hv;
3121
3122     Image
3123       *difference_image,
3124       *image,
3125       *reconstruct_image;
3126
3127     MetricType
3128       metric;
3129
3130     register ssize_t
3131       i;
3132
3133     ssize_t
3134       option;
3135
3136     struct PackageInfo
3137       *info;
3138
3139     SV
3140       *av_reference,
3141       *perl_exception,
3142       *reference,
3143       *rv,
3144       *sv;
3145
3146     PERL_UNUSED_VAR(ref);
3147     PERL_UNUSED_VAR(ix);
3148     exception=AcquireExceptionInfo();
3149     perl_exception=newSVpv("",0);
3150     sv=NULL;
3151     av=NULL;
3152     attribute=NULL;
3153     if (sv_isobject(ST(0)) == 0)
3154       {
3155         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3156           PackageName);
3157         goto PerlException;
3158       }
3159     reference=SvRV(ST(0));
3160     hv=SvSTASH(reference);
3161     av=newAV();
3162     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3163     SvREFCNT_dec(av);
3164     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3165     if (image == (Image *) NULL)
3166       {
3167         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3168           PackageName);
3169         goto PerlException;
3170       }
3171     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3172     /*
3173       Get attribute.
3174     */
3175     channel=DefaultChannels;
3176     reconstruct_image=image;
3177     metric=RootMeanSquaredErrorMetric;
3178     for (i=2; i < items; i+=2)
3179     {
3180       attribute=(char *) SvPV(ST(i-1),na);
3181       switch (*attribute)
3182       {
3183         case 'C':
3184         case 'c':
3185         {
3186           if (LocaleCompare(attribute,"channel") == 0)
3187             {
3188               ssize_t
3189                 option;
3190
3191               option=ParseChannelOption(SvPV(ST(i),na));
3192               if (option < 0)
3193                 {
3194                   ThrowPerlException(exception,OptionError,
3195                     "UnrecognizedType",SvPV(ST(i),na));
3196                   return;
3197                 }
3198               channel=(ChannelType) option;
3199               break;
3200             }
3201           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3202             attribute);
3203           break;
3204         }
3205         case 'F':
3206         case 'f':
3207         {
3208           if (LocaleCompare(attribute,"fuzz") == 0)
3209             {
3210               image->fuzz=SiPrefixToDouble(SvPV(ST(i),na),100.0);
3211               break;
3212             }
3213           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3214             attribute);
3215           break;
3216         }
3217         case 'I':
3218         case 'i':
3219         {
3220           if (LocaleCompare(attribute,"image") == 0)
3221             {
3222               reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3223                 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3224               break;
3225             }
3226           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3227             attribute);
3228           break;
3229         }
3230         case 'M':
3231         case 'm':
3232         {
3233           if (LocaleCompare(attribute,"metric") == 0)
3234             {
3235               option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3236                 SvPV(ST(i),na));
3237               if (option < 0)
3238                 {
3239                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3240                     SvPV(ST(i),na));
3241                   break;
3242                 }
3243               metric=(MetricType) option;
3244               break;
3245             }
3246           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3247             attribute);
3248           break;
3249         }
3250         default:
3251         {
3252           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3253             attribute);
3254           break;
3255         }
3256       }
3257     }
3258     difference_image=CompareImageChannels(image,reconstruct_image,channel,
3259       metric,&distortion,exception);
3260     if (difference_image != (Image *) NULL)
3261       {
3262         difference_image->error.mean_error_per_pixel=distortion;
3263         AddImageToRegistry(sv,difference_image);
3264         rv=newRV(sv);
3265         av_push(av,sv_bless(rv,hv));
3266         SvREFCNT_dec(sv);
3267       }
3268     exception=DestroyExceptionInfo(exception);
3269     ST(0)=av_reference;
3270     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3271     XSRETURN(1);
3272
3273   PerlException:
3274     InheritPerlException(exception,perl_exception);
3275     exception=DestroyExceptionInfo(exception);
3276     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3277     SvPOK_on(perl_exception);
3278     ST(0)=sv_2mortal(perl_exception);
3279     XSRETURN(1);
3280   }
3281 \f
3282 #
3283 ###############################################################################
3284 #                                                                             #
3285 #                                                                             #
3286 #                                                                             #
3287 #   C o m p a r e L a y e r s                                                 #
3288 #                                                                             #
3289 #                                                                             #
3290 #                                                                             #
3291 ###############################################################################
3292 #
3293 #
3294 void
3295 CompareLayers(ref)
3296   Image::Magick ref=NO_INIT
3297   ALIAS:
3298     CompareImageLayers   = 1
3299     comparelayers        = 2
3300     compareimagelayers   = 3
3301   PPCODE:
3302   {
3303     AV
3304       *av;
3305
3306     char
3307       *attribute;
3308
3309     ExceptionInfo
3310       *exception;
3311
3312     HV
3313       *hv;
3314
3315     Image
3316       *image;
3317
3318     ImageLayerMethod
3319       method;
3320
3321     register ssize_t
3322       i;
3323
3324     ssize_t
3325       option;
3326
3327     struct PackageInfo
3328       *info;
3329
3330     SV
3331       *av_reference,
3332       *perl_exception,
3333       *reference,
3334       *rv,
3335       *sv;
3336
3337     PERL_UNUSED_VAR(ref);
3338     PERL_UNUSED_VAR(ix);
3339     exception=AcquireExceptionInfo();
3340     perl_exception=newSVpv("",0);
3341     sv=NULL;
3342     if (sv_isobject(ST(0)) == 0)
3343       {
3344         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3345           PackageName);
3346         goto PerlException;
3347       }
3348     reference=SvRV(ST(0));
3349     hv=SvSTASH(reference);
3350     av=newAV();
3351     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3352     SvREFCNT_dec(av);
3353     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3354     if (image == (Image *) NULL)
3355       {
3356         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3357           PackageName);
3358         goto PerlException;
3359       }
3360     method=CompareAnyLayer;
3361     for (i=2; i < items; i+=2)
3362     {
3363       attribute=(char *) SvPV(ST(i-1),na);
3364       switch (*attribute)
3365       {
3366         case 'M':
3367         case 'm':
3368         {
3369           if (LocaleCompare(attribute,"method") == 0)
3370             {
3371               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3372                 SvPV(ST(i),na));
3373               if (option < 0)
3374                 {
3375                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3376                     SvPV(ST(i),na));
3377                   break;
3378                 }
3379                method=(ImageLayerMethod) option;
3380               break;
3381             }
3382           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3383             attribute);
3384           break;
3385         }
3386         default:
3387         {
3388           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3389             attribute);
3390           break;
3391         }
3392       }
3393     }
3394     image=CompareImageLayers(image,method,exception);
3395     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3396       goto PerlException;
3397     for ( ; image; image=image->next)
3398     {
3399       AddImageToRegistry(sv,image);
3400       rv=newRV(sv);
3401       av_push(av,sv_bless(rv,hv));
3402       SvREFCNT_dec(sv);
3403     }
3404     exception=DestroyExceptionInfo(exception);
3405     ST(0)=av_reference;
3406     SvREFCNT_dec(perl_exception);
3407     XSRETURN(1);
3408
3409   PerlException:
3410     InheritPerlException(exception,perl_exception);
3411     exception=DestroyExceptionInfo(exception);
3412     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3413     SvPOK_on(perl_exception);
3414     ST(0)=sv_2mortal(perl_exception);
3415     XSRETURN(1);
3416   }
3417 \f
3418 #
3419 ###############################################################################
3420 #                                                                             #
3421 #                                                                             #
3422 #                                                                             #
3423 #   D e s t r o y                                                             #
3424 #                                                                             #
3425 #                                                                             #
3426 #                                                                             #
3427 ###############################################################################
3428 #
3429 #
3430 void
3431 DESTROY(ref)
3432   Image::Magick ref=NO_INIT
3433   PPCODE:
3434   {
3435     SV
3436       *reference;
3437
3438     PERL_UNUSED_VAR(ref);
3439     if (sv_isobject(ST(0)) == 0)
3440       croak("ReferenceIsNotMyType");
3441     reference=SvRV(ST(0));
3442     switch (SvTYPE(reference))
3443     {
3444       case SVt_PVAV:
3445       {
3446         char
3447           message[MaxTextExtent];
3448
3449         const SV
3450           *key;
3451
3452         HV
3453           *hv;
3454
3455         GV
3456           **gvp;
3457
3458         struct PackageInfo
3459           *info;
3460
3461         SV
3462           *sv;
3463
3464         /*
3465           Array (AV *) reference
3466         */
3467         (void) FormatMagickString(message,MaxTextExtent,"package%s%p",
3468           XS_VERSION,reference);
3469         hv=gv_stashpv(PackageName, FALSE);
3470         if (!hv)
3471           break;
3472         gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3473         if (!gvp)
3474           break;
3475         sv=GvSV(*gvp);
3476         if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3477           {
3478             info=(struct PackageInfo *) SvIV(sv);
3479             DestroyPackageInfo(info);
3480           }
3481         key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3482         break;
3483       }
3484       case SVt_PVMG:
3485       {
3486         Image
3487           *image;
3488
3489         /*
3490           Blessed scalar = (Image *) SvIV(reference)
3491         */
3492         image=(Image *) SvIV(reference);
3493         if (image != (Image *) NULL)
3494           DeleteImageFromRegistry(reference,image);
3495         break;
3496       }
3497       default:
3498         break;
3499     }
3500   }
3501 \f
3502 #
3503 ###############################################################################
3504 #                                                                             #
3505 #                                                                             #
3506 #                                                                             #
3507 #   D i s p l a y                                                             #
3508 #                                                                             #
3509 #                                                                             #
3510 #                                                                             #
3511 ###############################################################################
3512 #
3513 #
3514 void
3515 Display(ref,...)
3516   Image::Magick ref=NO_INIT
3517   ALIAS:
3518     DisplayImage  = 1
3519     display       = 2
3520     displayimage  = 3
3521   PPCODE:
3522   {
3523     ExceptionInfo
3524       *exception;
3525
3526     Image
3527       *image;
3528
3529     register ssize_t
3530       i;
3531
3532     struct PackageInfo
3533       *info,
3534       *package_info;
3535
3536     SV
3537       *perl_exception,
3538       *reference;
3539
3540     PERL_UNUSED_VAR(ref);
3541     PERL_UNUSED_VAR(ix);
3542     exception=AcquireExceptionInfo();
3543     perl_exception=newSVpv("",0);
3544     package_info=(struct PackageInfo *) NULL;
3545     if (sv_isobject(ST(0)) == 0)
3546       {
3547         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3548           PackageName);
3549         goto PerlException;
3550       }
3551     reference=SvRV(ST(0));
3552     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3553     if (image == (Image *) NULL)
3554       {
3555         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3556           PackageName);
3557         goto PerlException;
3558       }
3559     package_info=ClonePackageInfo(info,exception);
3560     if (items == 2)
3561       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3562     else
3563       if (items > 2)
3564         for (i=2; i < items; i+=2)
3565           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3566             exception);
3567     (void) DisplayImages(package_info->image_info,image);
3568     (void) CatchImageException(image);
3569     InheritException(exception,&image->exception);
3570
3571   PerlException:
3572     if (package_info != (struct PackageInfo *) NULL)
3573       DestroyPackageInfo(package_info);
3574     InheritPerlException(exception,perl_exception);
3575     exception=DestroyExceptionInfo(exception);
3576     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3577     SvPOK_on(perl_exception);
3578     ST(0)=sv_2mortal(perl_exception);
3579     XSRETURN(1);
3580   }
3581 \f
3582 #
3583 ###############################################################################
3584 #                                                                             #
3585 #                                                                             #
3586 #                                                                             #
3587 #   E v a l u a t e I m a g e s                                               #
3588 #                                                                             #
3589 #                                                                             #
3590 #                                                                             #
3591 ###############################################################################
3592 #
3593 #
3594 void
3595 EvaluateImages(ref)
3596   Image::Magick ref=NO_INIT
3597   ALIAS:
3598     EvaluateImages   = 1
3599     evaluateimages   = 2
3600   PPCODE:
3601   {
3602     AV
3603       *av;
3604
3605     char
3606       *attribute,
3607       *p;
3608
3609     ExceptionInfo
3610       *exception;
3611
3612     HV
3613       *hv;
3614
3615     Image
3616       *image;
3617
3618     MagickEvaluateOperator
3619       op;
3620
3621     register ssize_t
3622       i;
3623
3624     struct PackageInfo
3625       *info;
3626
3627     SV
3628       *perl_exception,
3629       *reference,
3630       *rv,
3631       *sv;
3632
3633     PERL_UNUSED_VAR(ref);
3634     PERL_UNUSED_VAR(ix);
3635     exception=AcquireExceptionInfo();
3636     perl_exception=newSVpv("",0);
3637     sv=NULL;
3638     if (sv_isobject(ST(0)) == 0)
3639       {
3640         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3641           PackageName);
3642         goto PerlException;
3643       }
3644     reference=SvRV(ST(0));
3645     hv=SvSTASH(reference);
3646     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3647     if (image == (Image *) NULL)
3648       {
3649         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3650           PackageName);
3651         goto PerlException;
3652       }
3653     op=MeanEvaluateOperator;
3654     if (items == 2)
3655       {
3656         ssize_t
3657           in;
3658
3659         in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
3660           SvPV(ST(1),na));
3661         if (in < 0)
3662           {
3663             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3664               SvPV(ST(1),na));
3665             return;
3666           }
3667         op=(MagickEvaluateOperator) in;
3668       }
3669     else
3670       for (i=2; i < items; i+=2)
3671       {
3672         attribute=(char *) SvPV(ST(i-1),na);
3673         switch (*attribute)
3674         {
3675           case 'O':
3676           case 'o':
3677           {
3678             if (LocaleCompare(attribute,"operator") == 0)
3679               {
3680                 ssize_t
3681                   in;
3682
3683                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3684                   MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
3685                 if (in < 0)
3686                   {
3687                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3688                       SvPV(ST(i),na));
3689                     return;
3690                   }
3691                 op=(MagickEvaluateOperator) in;
3692                 break;
3693               }
3694             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3695               attribute);
3696             break;
3697           }
3698           default:
3699           {
3700             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3701               attribute);
3702             break;
3703           }
3704         }
3705       }
3706     image=EvaluateImages(image,op,exception);
3707     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3708       goto PerlException;
3709     /*
3710       Create blessed Perl array for the returned image.
3711     */
3712     av=newAV();
3713     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3714     SvREFCNT_dec(av);
3715     AddImageToRegistry(sv,image);
3716     rv=newRV(sv);
3717     av_push(av,sv_bless(rv,hv));
3718     SvREFCNT_dec(sv);
3719     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3720     (void) FormatMagickString(info->image_info->filename,MaxTextExtent,
3721       "evaluate-%.*s",(int) (MaxTextExtent-9),
3722       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3723     (void) CopyMagickString(image->filename,info->image_info->filename,
3724       MaxTextExtent);
3725     SetImageInfo(info->image_info,0,exception);
3726     exception=DestroyExceptionInfo(exception);
3727     SvREFCNT_dec(perl_exception);
3728     XSRETURN(1);
3729
3730   PerlException:
3731     InheritPerlException(exception,perl_exception);
3732     exception=DestroyExceptionInfo(exception);
3733     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3734     SvPOK_on(perl_exception);
3735     ST(0)=sv_2mortal(perl_exception);
3736     XSRETURN(1);
3737   }
3738 \f
3739 #
3740 ###############################################################################
3741 #                                                                             #
3742 #                                                                             #
3743 #                                                                             #
3744 #   F e a t u r e s                                                           #
3745 #                                                                             #
3746 #                                                                             #
3747 #                                                                             #
3748 ###############################################################################
3749 #
3750 #
3751 void
3752 Features(ref,...)
3753   Image::Magick ref=NO_INIT
3754   ALIAS:
3755     FeaturesImage = 1
3756     features      = 2
3757     featuresimage = 3
3758   PPCODE:
3759   {
3760 #define ChannelFeatures(channel,direction) \
3761 { \
3762   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3763     channel_features[channel].angular_second_moment[direction]); \
3764   PUSHs(sv_2mortal(newSVpv(message,0))); \
3765   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3766     channel_features[channel].contrast[direction]); \
3767   PUSHs(sv_2mortal(newSVpv(message,0))); \
3768   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3769     channel_features[channel].contrast[direction]); \
3770   PUSHs(sv_2mortal(newSVpv(message,0))); \
3771   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3772     channel_features[channel].variance_sum_of_squares[direction]); \
3773   PUSHs(sv_2mortal(newSVpv(message,0))); \
3774   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3775     channel_features[channel].inverse_difference_moment[direction]); \
3776   PUSHs(sv_2mortal(newSVpv(message,0))); \
3777   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3778     channel_features[channel].sum_average[direction]); \
3779   PUSHs(sv_2mortal(newSVpv(message,0))); \
3780   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3781     channel_features[channel].sum_variance[direction]); \
3782   PUSHs(sv_2mortal(newSVpv(message,0))); \
3783   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3784     channel_features[channel].sum_entropy[direction]); \
3785   PUSHs(sv_2mortal(newSVpv(message,0))); \
3786   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3787     channel_features[channel].entropy[direction]); \
3788   PUSHs(sv_2mortal(newSVpv(message,0))); \
3789   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3790     channel_features[channel].difference_variance[direction]); \
3791   PUSHs(sv_2mortal(newSVpv(message,0))); \
3792   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3793     channel_features[channel].difference_entropy[direction]); \
3794   PUSHs(sv_2mortal(newSVpv(message,0))); \
3795   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3796     channel_features[channel].measure_of_correlation_1[direction]); \
3797   PUSHs(sv_2mortal(newSVpv(message,0))); \
3798   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3799     channel_features[channel].measure_of_correlation_2[direction]); \
3800   PUSHs(sv_2mortal(newSVpv(message,0))); \
3801   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
3802     channel_features[channel].maximum_correlation_coefficient[direction]); \
3803   PUSHs(sv_2mortal(newSVpv(message,0))); \
3804 }
3805
3806     AV
3807       *av;
3808
3809     char
3810       *attribute,
3811       message[MaxTextExtent];
3812
3813     ChannelFeatures
3814       *channel_features;
3815
3816     double
3817       distance;
3818
3819     ExceptionInfo
3820       *exception;
3821
3822     HV
3823       *hv;
3824
3825     Image
3826       *image;
3827
3828     register ssize_t
3829       i;
3830
3831     ssize_t
3832       count;
3833
3834     struct PackageInfo
3835       *info;
3836
3837     SV
3838       *av_reference,
3839       *perl_exception,
3840       *reference;
3841
3842     PERL_UNUSED_VAR(ref);
3843     PERL_UNUSED_VAR(ix);
3844     exception=AcquireExceptionInfo();
3845     perl_exception=newSVpv("",0);
3846     av=NULL;
3847     if (sv_isobject(ST(0)) == 0)
3848       {
3849         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3850           PackageName);
3851         goto PerlException;
3852       }
3853     reference=SvRV(ST(0));
3854     hv=SvSTASH(reference);
3855     av=newAV();
3856     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3857     SvREFCNT_dec(av);
3858     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3859     if (image == (Image *) NULL)
3860       {
3861         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3862           PackageName);
3863         goto PerlException;
3864       }
3865     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3866     distance=1;
3867     for (i=2; i < items; i+=2)
3868     {
3869       attribute=(char *) SvPV(ST(i-1),na);
3870       switch (*attribute)
3871       {
3872         case 'D':
3873         case 'd':
3874         {
3875           if (LocaleCompare(attribute,"distance") == 0)
3876             {
3877               distance=StringToLong((char *) SvPV(ST(1),na));
3878               break;
3879             }
3880           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3881             attribute);
3882           break;
3883         }
3884         default:
3885         {
3886           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3887             attribute);
3888           break;
3889         }
3890       }
3891     }
3892     count=0;
3893     for ( ; image; image=image->next)
3894     {
3895       channel_features=GetImageChannelFeatures(image,distance,
3896         &image->exception);
3897       if (channel_features == (ChannelFeatures *) NULL)
3898         continue;
3899       count++;
3900       EXTEND(sp,75*count);
3901       for (i=0; i < 4; i++)
3902       {
3903         ChannelFeatures(RedChannel,i);
3904         ChannelFeatures(GreenChannel,i);
3905         ChannelFeatures(BlueChannel,i);
3906         if (image->colorspace == CMYKColorspace)
3907           ChannelFeatures(IndexChannel,i);
3908         if (image->matte != MagickFalse)
3909           ChannelFeatures(OpacityChannel,i);
3910       }
3911       channel_features=(ChannelFeatures *)
3912         RelinquishMagickMemory(channel_features);
3913     }
3914
3915   PerlException:
3916     InheritPerlException(exception,perl_exception);
3917     exception=DestroyExceptionInfo(exception);
3918     SvREFCNT_dec(perl_exception);
3919   }
3920 \f
3921 #
3922 ###############################################################################
3923 #                                                                             #
3924 #                                                                             #
3925 #                                                                             #
3926 #   F l a t t e n                                                             #
3927 #                                                                             #
3928 #                                                                             #
3929 #                                                                             #
3930 ###############################################################################
3931 #
3932 #
3933 void
3934 Flatten(ref)
3935   Image::Magick ref=NO_INIT
3936   ALIAS:
3937     FlattenImage   = 1
3938     flatten        = 2
3939     flattenimage   = 3
3940   PPCODE:
3941   {
3942     AV
3943       *av;
3944
3945     char
3946       *attribute,
3947       *p;
3948
3949     ExceptionInfo
3950       *exception;
3951
3952     HV
3953       *hv;
3954
3955     Image
3956       *image;
3957
3958     PixelPacket
3959       background_color;
3960
3961     register ssize_t
3962       i;
3963
3964     struct PackageInfo
3965       *info;
3966
3967     SV
3968       *perl_exception,
3969       *reference,
3970       *rv,
3971       *sv;
3972
3973     PERL_UNUSED_VAR(ref);
3974     PERL_UNUSED_VAR(ix);
3975     exception=AcquireExceptionInfo();
3976     perl_exception=newSVpv("",0);
3977     sv=NULL;
3978     if (sv_isobject(ST(0)) == 0)
3979       {
3980         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3981           PackageName);
3982         goto PerlException;
3983       }
3984     reference=SvRV(ST(0));
3985     hv=SvSTASH(reference);
3986     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3987     if (image == (Image *) NULL)
3988       {
3989         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3990           PackageName);
3991         goto PerlException;
3992       }
3993     background_color=image->background_color;
3994     if (items == 2)
3995       (void) QueryColorDatabase((char *) SvPV(ST(1),na),&background_color,
3996         exception);
3997     else
3998       for (i=2; i < items; i+=2)
3999       {
4000         attribute=(char *) SvPV(ST(i-1),na);
4001         switch (*attribute)
4002         {
4003           case 'B':
4004           case 'b':
4005           {
4006             if (LocaleCompare(attribute,"background") == 0)
4007               {
4008                 (void) QueryColorDatabase((char *) SvPV(ST(1),na),
4009                   &background_color,exception);
4010                 break;
4011               }
4012             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4013               attribute);
4014             break;
4015           }
4016           default:
4017           {
4018             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4019               attribute);
4020             break;
4021           }
4022         }
4023       }
4024     image->background_color=background_color;
4025     image=MergeImageLayers(image,FlattenLayer,exception);
4026     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
4027       goto PerlException;
4028     /*
4029       Create blessed Perl array for the returned image.
4030     */
4031     av=newAV();
4032     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4033     SvREFCNT_dec(av);
4034     AddImageToRegistry(sv,image);
4035     rv=newRV(sv);
4036     av_push(av,sv_bless(rv,hv));
4037     SvREFCNT_dec(sv);
4038     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4039     (void) FormatMagickString(info->image_info->filename,MaxTextExtent,
4040       "flatten-%.*s",(int) (MaxTextExtent-9),
4041       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4042     (void) CopyMagickString(image->filename,info->image_info->filename,
4043       MaxTextExtent);
4044     SetImageInfo(info->image_info,0,exception);
4045     exception=DestroyExceptionInfo(exception);
4046     SvREFCNT_dec(perl_exception);
4047     XSRETURN(1);
4048
4049   PerlException:
4050     InheritPerlException(exception,perl_exception);
4051     exception=DestroyExceptionInfo(exception);
4052     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4053     SvPOK_on(perl_exception);  /* return messages in string context */
4054     ST(0)=sv_2mortal(perl_exception);
4055     XSRETURN(1);
4056   }
4057 \f
4058 #
4059 ###############################################################################
4060 #                                                                             #
4061 #                                                                             #
4062 #                                                                             #
4063 #   F x                                                                       #
4064 #                                                                             #
4065 #                                                                             #
4066 #                                                                             #
4067 ###############################################################################
4068 #
4069 #
4070 void
4071 Fx(ref,...)
4072   Image::Magick ref=NO_INIT
4073   ALIAS:
4074     FxImage  = 1
4075     fx       = 2
4076     fximage  = 3
4077   PPCODE:
4078   {
4079     AV
4080       *av;
4081
4082     char
4083       *attribute,
4084       expression[MaxTextExtent];
4085
4086     ChannelType
4087       channel;
4088
4089     ExceptionInfo
4090       *exception;
4091
4092     HV
4093       *hv;
4094
4095     Image
4096       *image;
4097
4098     register ssize_t
4099       i;
4100
4101     struct PackageInfo
4102       *info;
4103
4104     SV
4105       *av_reference,
4106       *perl_exception,
4107       *reference,
4108       *rv,
4109       *sv;
4110
4111     PERL_UNUSED_VAR(ref);
4112     PERL_UNUSED_VAR(ix);
4113     exception=AcquireExceptionInfo();
4114     perl_exception=newSVpv("",0);
4115     sv=NULL;
4116     attribute=NULL;
4117     av=NULL;
4118     if (sv_isobject(ST(0)) == 0)
4119       {
4120         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4121           PackageName);
4122         goto PerlException;
4123       }
4124     reference=SvRV(ST(0));
4125     hv=SvSTASH(reference);
4126     av=newAV();
4127     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4128     SvREFCNT_dec(av);
4129     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4130     if (image == (Image *) NULL)
4131       {
4132         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4133           PackageName);
4134         goto PerlException;
4135       }
4136     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4137     /*
4138       Get options.
4139     */
4140     channel=DefaultChannels;
4141     (void) CopyMagickString(expression,"u",MaxTextExtent);
4142     if (items == 2)
4143       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MaxTextExtent);
4144     else
4145       for (i=2; i < items; i+=2)
4146       {
4147         attribute=(char *) SvPV(ST(i-1),na);
4148         switch (*attribute)
4149         {
4150           case 'C':
4151           case 'c':
4152           {
4153             if (LocaleCompare(attribute,"channel") == 0)
4154               {
4155                 ssize_t
4156                   option;
4157
4158                 option=ParseChannelOption(SvPV(ST(i),na));
4159                 if (option < 0)
4160                   {
4161                     ThrowPerlException(exception,OptionError,
4162                       "UnrecognizedType",SvPV(ST(i),na));
4163                     return;
4164                   }
4165                 channel=(ChannelType) option;
4166                 break;
4167               }
4168             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4169               attribute);
4170             break;
4171           }
4172           case 'E':
4173           case 'e':
4174           {
4175             if (LocaleCompare(attribute,"expression") == 0)
4176               {
4177                 (void) CopyMagickString(expression,SvPV(ST(i),na),
4178                   MaxTextExtent);
4179                 break;
4180               }
4181             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4182               attribute);
4183             break;
4184           }
4185           default:
4186           {
4187             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4188               attribute);
4189             break;
4190           }
4191         }
4192       }
4193     image=FxImageChannel(image,channel,expression,exception);
4194     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
4195       goto PerlException;
4196     for ( ; image; image=image->next)
4197     {
4198       AddImageToRegistry(sv,image);
4199       rv=newRV(sv);
4200       av_push(av,sv_bless(rv,hv));
4201       SvREFCNT_dec(sv);
4202     }
4203     exception=DestroyExceptionInfo(exception);
4204     ST(0)=av_reference;
4205     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4206     XSRETURN(1);
4207
4208   PerlException:
4209     InheritPerlException(exception,perl_exception);
4210     exception=DestroyExceptionInfo(exception);
4211     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4212     SvPOK_on(perl_exception);
4213     ST(0)=sv_2mortal(perl_exception);
4214     XSRETURN(1);
4215   }
4216 \f
4217 #
4218 ###############################################################################
4219 #                                                                             #
4220 #                                                                             #
4221 #                                                                             #
4222 #   G e t                                                                     #
4223 #                                                                             #
4224 #                                                                             #
4225 #                                                                             #
4226 ###############################################################################
4227 #
4228 #
4229 void
4230 Get(ref,...)
4231   Image::Magick ref=NO_INIT
4232   ALIAS:
4233     GetAttributes = 1
4234     GetAttribute  = 2
4235     get           = 3
4236     getattributes = 4
4237     getattribute  = 5
4238   PPCODE:
4239   {
4240     char
4241       *attribute,
4242       color[MaxTextExtent];
4243
4244     const char
4245       *value;
4246
4247     ExceptionInfo
4248       *exception;
4249
4250     Image
4251       *image;
4252
4253     long
4254       j;
4255
4256     register ssize_t
4257       i;
4258
4259     struct PackageInfo
4260       *info;
4261
4262     SV
4263       *perl_exception,
4264       *reference,
4265       *s;
4266
4267     PERL_UNUSED_VAR(ref);
4268     PERL_UNUSED_VAR(ix);
4269     exception=AcquireExceptionInfo();
4270     perl_exception=newSVpv("",0);
4271     if (sv_isobject(ST(0)) == 0)
4272       {
4273         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4274           PackageName);
4275         XSRETURN_EMPTY;
4276       }
4277     reference=SvRV(ST(0));
4278     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4279     if (image == (Image *) NULL && !info)
4280       XSRETURN_EMPTY;
4281     EXTEND(sp,items);
4282     for (i=1; i < items; i++)
4283     {
4284       attribute=(char *) SvPV(ST(i),na);
4285       s=NULL;
4286       switch (*attribute)
4287       {
4288         case 'A':
4289         case 'a':
4290         {
4291           if (LocaleCompare(attribute,"adjoin") == 0)
4292             {
4293               if (info)
4294                 s=newSViv((ssize_t) info->image_info->adjoin);
4295               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4296               continue;
4297             }
4298           if (LocaleCompare(attribute,"antialias") == 0)
4299             {
4300               if (info)
4301                 s=newSViv((ssize_t) info->image_info->antialias);
4302               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4303               continue;
4304             }
4305           if (LocaleCompare(attribute,"area") == 0)
4306             {
4307               s=newSViv(GetMagickResource(AreaResource));
4308               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4309               continue;
4310             }
4311           if (LocaleCompare(attribute,"attenuate") == 0)
4312             {
4313               const char
4314                 *value;
4315
4316               value=GetImageProperty(image,attribute);
4317               if (value != (const char *) NULL)
4318                 s=newSVpv(value,0);
4319               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4320               continue;
4321             }
4322           if (LocaleCompare(attribute,"authenticate") == 0)
4323             {
4324               if (info)
4325                 s=newSVpv(info->image_info->authenticate,0);
4326               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4327               continue;
4328             }
4329           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4330             attribute);
4331           break;
4332         }
4333         case 'B':
4334         case 'b':
4335         {
4336           if (LocaleCompare(attribute,"background") == 0)
4337             {
4338               if (image == (Image *) NULL)
4339                 break;
4340               (void) FormatMagickString(color,MaxTextExtent,QuantumFormat ","
4341                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4342                 image->background_color.red,image->background_color.green,
4343                 image->background_color.blue,image->background_color.opacity);
4344               s=newSVpv(color,0);
4345               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4346               continue;
4347             }
4348           if (LocaleCompare(attribute,"base-columns") == 0)
4349             {
4350               if (image != (Image *) NULL)
4351                 s=newSViv((ssize_t) image->magick_columns);
4352               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4353               continue;
4354             }
4355           if (LocaleCompare(attribute,"base-filename") == 0)
4356             {
4357               if (image != (Image *) NULL)
4358                 s=newSVpv(image->magick_filename,0);
4359               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4360               continue;
4361             }
4362           if (LocaleCompare(attribute,"base-height") == 0)
4363             {
4364               if (image != (Image *) NULL)
4365                 s=newSViv((ssize_t) image->magick_rows);
4366               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4367               continue;
4368             }
4369           if (LocaleCompare(attribute,"base-rows") == 0)
4370             {
4371               if (image != (Image *) NULL)
4372                 s=newSViv((ssize_t) image->magick_rows);
4373               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4374               continue;
4375             }
4376           if (LocaleCompare(attribute,"base-width") == 0)
4377             {
4378               if (image != (Image *) NULL)
4379                 s=newSViv((ssize_t) image->magick_columns);
4380               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4381               continue;
4382             }
4383           if (LocaleCompare(attribute,"bias") == 0)
4384             {
4385               if (image != (Image *) NULL)
4386                 s=newSVnv(image->bias);
4387               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4388               continue;
4389             }
4390           if (LocaleCompare(attribute,"blue-primary") == 0)
4391             {
4392               if (image == (Image *) NULL)
4393                 break;
4394               (void) FormatMagickString(color,MaxTextExtent,"%.15g,%.15g",
4395                 image->chromaticity.blue_primary.x,
4396                 image->chromaticity.blue_primary.y);
4397               s=newSVpv(color,0);
4398               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4399               continue;
4400             }
4401           if (LocaleCompare(attribute,"bordercolor") == 0)
4402             {
4403               if (image == (Image *) NULL)
4404                 break;
4405               (void) FormatMagickString(color,MaxTextExtent,QuantumFormat ","
4406                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4407                 image->border_color.red,image->border_color.green,
4408                 image->border_color.blue,image->border_color.opacity);
4409               s=newSVpv(color,0);
4410               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4411               continue;
4412             }
4413           if (LocaleCompare(attribute,"bounding-box") == 0)
4414             {
4415               char
4416                 geometry[MaxTextExtent];
4417
4418               RectangleInfo
4419                 page;
4420
4421               if (image == (Image *) NULL)
4422                 break;
4423               page=GetImageBoundingBox(image,&image->exception);
4424               (void) FormatMagickString(geometry,MaxTextExtent,
4425                 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4426                 page.height,(double) page.x,(double) page.y);
4427               s=newSVpv(geometry,0);
4428               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4429               continue;
4430             }
4431           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4432             attribute);
4433           break;
4434         }
4435         case 'C':
4436         case 'c':
4437         {
4438           if (LocaleCompare(attribute,"class") == 0)
4439             {
4440               if (image == (Image *) NULL)
4441                 break;
4442               s=newSViv(image->storage_class);
4443               (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4444                 image->storage_class));
4445               SvIOK_on(s);
4446               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4447               continue;
4448             }
4449           if (LocaleCompare(attribute,"clip-mask") == 0)
4450             {
4451               if (image != (Image *) NULL)
4452                 {
4453                   SV
4454                     *sv;
4455
4456                   sv=NULL;
4457                   if (image->mask == (Image *) NULL)
4458                     ClipImage(image);
4459                   if (image->mask != (Image *) NULL)
4460                     {
4461                       AddImageToRegistry(sv,image->mask);
4462                       s=sv_bless(newRV(sv),SvSTASH(reference));
4463                     }
4464                 }
4465               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4466               continue;
4467             }
4468           if (LocaleCompare(attribute,"clip-path") == 0)
4469             {
4470               if (image != (Image *) NULL)
4471                 {
4472                   SV
4473                     *sv;
4474
4475                   sv=NULL;
4476                   if (image->clip_mask == (Image *) NULL)
4477                     ClipImage(image);
4478                   if (image->clip_mask != (Image *) NULL)
4479                     {
4480                       AddImageToRegistry(sv,image->clip_mask);
4481                       s=sv_bless(newRV(sv),SvSTASH(reference));
4482                     }
4483                 }
4484               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4485               continue;
4486             }
4487           if (LocaleCompare(attribute,"compression") == 0)
4488             {
4489               j=info ? info->image_info->compression : image ?
4490                 image->compression : UndefinedCompression;
4491               if (info)
4492                 if (info->image_info->compression == UndefinedCompression)
4493                   j=image->compression;
4494               s=newSViv(j);
4495               (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4496                 j));
4497               SvIOK_on(s);
4498               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4499               continue;
4500             }
4501           if (LocaleCompare(attribute,"colorspace") == 0)
4502             {
4503               j=image ? image->colorspace : RGBColorspace;
4504               s=newSViv(j);
4505               (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4506                 j));
4507               SvIOK_on(s);
4508               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4509               continue;
4510             }
4511           if (LocaleCompare(attribute,"colors") == 0)
4512             {
4513               if (image != (Image *) NULL)
4514                 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4515                   &image->exception));
4516               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4517               continue;
4518             }
4519           if (LocaleNCompare(attribute,"colormap",8) == 0)
4520             {
4521               int
4522                 items;
4523
4524               if (image == (Image *) NULL || !image->colormap)
4525                 break;
4526               j=0;
4527               items=sscanf(attribute,"%*[^[][%ld",&j);
4528               if (j > (ssize_t) image->colors)
4529                 j%=image->colors;
4530               (void) FormatMagickString(color,MaxTextExtent,QuantumFormat ","
4531                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4532                 image->colormap[j].red,image->colormap[j].green,
4533                 image->colormap[j].blue,image->colormap[j].opacity);
4534               s=newSVpv(color,0);
4535               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4536               continue;
4537             }
4538           if (LocaleCompare(attribute,"columns") == 0)
4539             {
4540               if (image != (Image *) NULL)
4541                 s=newSViv((ssize_t) image->columns);
4542               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4543               continue;
4544             }
4545           if (LocaleCompare(attribute,"comment") == 0)
4546             {
4547               const char
4548                 *value;
4549
4550               value=GetImageProperty(image,attribute);
4551               if (value != (const char *) NULL)
4552                 s=newSVpv(value,0);
4553               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4554               continue;
4555             }
4556           if (LocaleCompare(attribute,"copyright") == 0)
4557             {
4558               s=newSVpv(GetMagickCopyright(),0);
4559               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4560               continue;
4561             }
4562           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4563             attribute);
4564           break;
4565         }
4566         case 'D':
4567         case 'd':
4568         {
4569           if (LocaleCompare(attribute,"density") == 0)
4570             {
4571               char
4572                 geometry[MaxTextExtent];
4573
4574               if (image == (Image *) NULL)
4575                 break;
4576               (void) FormatMagickString(geometry,MaxTextExtent,"%.15gx%.15g",
4577                 image->x_resolution,image->y_resolution);
4578               s=newSVpv(geometry,0);
4579               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4580               continue;
4581             }
4582           if (LocaleCompare(attribute,"delay") == 0)
4583             {
4584               if (image != (Image *) NULL)
4585                 s=newSViv((ssize_t) image->delay);
4586               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4587               continue;
4588             }
4589           if (LocaleCompare(attribute,"depth") == 0)
4590             {
4591               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4592               if (image != (Image *) NULL)
4593                 s=newSViv((ssize_t) GetImageDepth(image,&image->exception));
4594               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4595               continue;
4596             }
4597           if (LocaleCompare(attribute,"directory") == 0)
4598             {
4599               if (image && image->directory)
4600                 s=newSVpv(image->directory,0);
4601               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4602               continue;
4603             }
4604           if (LocaleCompare(attribute,"dispose") == 0)
4605             {
4606               if (image == (Image *) NULL)
4607                 break;
4608
4609               s=newSViv(image->dispose);
4610               (void) sv_setpv(s,
4611                 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
4612               SvIOK_on(s);
4613               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4614               continue;
4615             }
4616           if (LocaleCompare(attribute,"disk") == 0)
4617             {
4618               s=newSViv(GetMagickResource(DiskResource));
4619               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4620               continue;
4621             }
4622           if (LocaleCompare(attribute,"dither") == 0)
4623             {
4624               if (info)
4625                 s=newSViv((ssize_t) info->image_info->dither);
4626               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4627               continue;
4628             }
4629           if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4630             {
4631               if (info && info->image_info->server_name)
4632                 s=newSVpv(info->image_info->server_name,0);
4633               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4634               continue;
4635             }
4636           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4637             attribute);
4638           break;
4639         }
4640         case 'E':
4641         case 'e':
4642         {
4643           if (LocaleCompare(attribute,"elapsed-time") == 0)
4644             {
4645               if (image != (Image *) NULL)
4646                 s=newSVnv(GetElapsedTime(&image->timer));
4647               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4648               continue;
4649             }
4650           if (LocaleCompare(attribute,"endian") == 0)
4651             {
4652               j=info ? info->image_info->endian : image ? image->endian :
4653                 UndefinedEndian;
4654               s=newSViv(j);
4655               (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
4656               SvIOK_on(s);
4657               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4658               continue;
4659             }
4660           if (LocaleCompare(attribute,"error") == 0)
4661             {
4662               if (image != (Image *) NULL)
4663                 s=newSVnv(image->error.mean_error_per_pixel);
4664               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4665               continue;
4666             }
4667           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4668             attribute);
4669           break;
4670         }
4671         case 'F':
4672         case 'f':
4673         {
4674           if (LocaleCompare(attribute,"filesize") == 0)
4675             {
4676               if (image != (Image *) NULL)
4677                 s=newSViv((ssize_t) GetBlobSize(image));
4678               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4679               continue;
4680             }
4681           if (LocaleCompare(attribute,"filename") == 0)
4682             {
4683               if (info && info->image_info->filename &&
4684                   *info->image_info->filename)
4685                 s=newSVpv(info->image_info->filename,0);
4686               if (image != (Image *) NULL)
4687                 s=newSVpv(image->filename,0);
4688               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4689               continue;
4690             }
4691           if (LocaleCompare(attribute,"filter") == 0)
4692             {
4693               s=image ? newSViv(image->filter) : newSViv(0);
4694               (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
4695                 image->filter));
4696               SvIOK_on(s);
4697               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4698               continue;
4699             }
4700           if (LocaleCompare(attribute,"font") == 0)
4701             {
4702               if (info && info->image_info->font)
4703                 s=newSVpv(info->image_info->font,0);
4704               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4705               continue;
4706             }
4707           if (LocaleCompare(attribute,"foreground") == 0)
4708             continue;
4709           if (LocaleCompare(attribute,"format") == 0)
4710             {
4711               const MagickInfo
4712                 *magick_info;
4713
4714               magick_info=(const MagickInfo *) NULL;
4715               if (info && (*info->image_info->magick != '\0'))
4716                 magick_info=GetMagickInfo(info->image_info->magick,exception);
4717               if (image != (Image *) NULL)
4718                 magick_info=GetMagickInfo(image->magick,&image->exception);
4719               if ((magick_info != (const MagickInfo *) NULL) &&
4720                   (*magick_info->description != '\0'))
4721                 s=newSVpv((char *) magick_info->description,0);
4722               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4723               continue;
4724             }
4725           if (LocaleCompare(attribute,"fuzz") == 0)
4726             {
4727               if (info)
4728                 s=newSVnv(info->image_info->fuzz);
4729               if (image != (Image *) NULL)
4730                 s=newSVnv(image->fuzz);
4731               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4732               continue;
4733             }
4734           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4735             attribute);
4736           break;
4737         }
4738         case 'G':
4739         case 'g':
4740         {
4741           if (LocaleCompare(attribute,"gamma") == 0)
4742             {
4743               if (image != (Image *) NULL)
4744                 s=newSVnv(image->gamma);
4745               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4746               continue;
4747             }
4748           if (LocaleCompare(attribute,"geometry") == 0)
4749             {
4750               if (image && image->geometry)
4751                 s=newSVpv(image->geometry,0);
4752               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4753               continue;
4754             }
4755           if (LocaleCompare(attribute,"gravity") == 0)
4756             {
4757               s=image ? newSViv(image->gravity) : newSViv(0);
4758               (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
4759                 image->gravity));
4760               SvIOK_on(s);
4761               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4762               continue;
4763             }
4764           if (LocaleCompare(attribute,"green-primary") == 0)
4765             {
4766               if (image == (Image *) NULL)
4767                 break;
4768               (void) FormatMagickString(color,MaxTextExtent,"%.15g,%.15g",
4769                 image->chromaticity.green_primary.x,
4770                 image->chromaticity.green_primary.y);
4771               s=newSVpv(color,0);
4772               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4773               continue;
4774             }
4775           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4776             attribute);
4777           break;
4778         }
4779         case 'H':
4780         case 'h':
4781         {
4782           if (LocaleCompare(attribute,"height") == 0)
4783             {
4784               if (image != (Image *) NULL)
4785                 s=newSViv((ssize_t) image->rows);
4786               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4787               continue;
4788             }
4789           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4790             attribute);
4791           break;
4792         }
4793         case 'I':
4794         case 'i':
4795         {
4796           if (LocaleCompare(attribute,"icc") == 0)
4797             {
4798               if (image != (Image *) NULL)
4799                 {
4800                   const StringInfo
4801                     *profile;
4802
4803                   profile=GetImageProfile(image,"icc");
4804                   if (profile != (StringInfo *) NULL)
4805                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4806                       GetStringInfoLength(profile));
4807                 }
4808               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4809               continue;
4810             }
4811           if (LocaleCompare(attribute,"icm") == 0)
4812             {
4813               if (image != (Image *) NULL)
4814                 {
4815                   const StringInfo
4816                     *profile;
4817
4818                   profile=GetImageProfile(image,"icm");
4819                   if (profile != (const StringInfo *) NULL)
4820                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4821                       GetStringInfoLength(profile));
4822                 }
4823               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4824               continue;
4825             }
4826           if (LocaleCompare(attribute,"id") == 0)
4827             {
4828               if (image != (Image *) NULL)
4829                 {
4830                   char
4831                     key[MaxTextExtent];
4832
4833                   MagickBooleanType
4834                     status;
4835
4836                   static ssize_t
4837                     id = 0;
4838
4839                   (void) FormatMagickString(key,MaxTextExtent,"%.20g\n",(double)
4840                     id);
4841                   status=SetImageRegistry(ImageRegistryType,key,image,
4842                     &image->exception);
4843                   s=newSViv(id++);
4844                 }
4845               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4846               continue;
4847             }
4848           if (LocaleNCompare(attribute,"index",5) == 0)
4849             {
4850               char
4851                 name[MaxTextExtent];
4852
4853               int
4854                 items;
4855
4856               long
4857                 x,
4858                 y;
4859
4860               register const IndexPacket
4861                 *indexes;
4862
4863               register const PixelPacket
4864                 *p;
4865
4866               CacheView
4867                 *image_view;
4868
4869               if (image == (Image *) NULL)
4870                 break;
4871               if (image->storage_class != PseudoClass)
4872                 break;
4873               x=0;
4874               y=0;
4875               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
4876               image_view=AcquireCacheView(image);
4877               p=GetCacheViewVirtualPixels(image_view,x,y,1,1,&image->exception);
4878               if (p != (const PixelPacket *) NULL)
4879                 {
4880                   indexes=GetCacheViewVirtualIndexQueue(image_view);
4881                   (void) FormatMagickString(name,MaxTextExtent,QuantumFormat,
4882                     GetIndexPixelComponent(indexes));
4883                   s=newSVpv(name,0);
4884                   PUSHs(s ? sv_2mortal(s) : &sv_undef);
4885                 }
4886               image_view=DestroyCacheView(image_view);
4887               continue;
4888             }
4889           if (LocaleCompare(attribute,"iptc") == 0)
4890             {
4891               if (image != (Image *) NULL)
4892                 {
4893                   const StringInfo
4894                     *profile;
4895
4896                   profile=GetImageProfile(image,"iptc");
4897                   if (profile != (const StringInfo *) NULL)
4898                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4899                       GetStringInfoLength(profile));
4900                 }
4901               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4902               continue;
4903             }
4904           if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
4905             {
4906               if (image != (Image *) NULL)
4907                 s=newSViv((ssize_t) image->iterations);
4908               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4909               continue;
4910             }
4911           if (LocaleCompare(attribute,"interlace") == 0)
4912             {
4913               j=info ? info->image_info->interlace : image ? image->interlace :
4914                 UndefinedInterlace;
4915               s=newSViv(j);
4916               (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
4917                 j));
4918               SvIOK_on(s);
4919               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4920               continue;
4921             }
4922           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4923             attribute);
4924           break;
4925         }
4926         case 'L':
4927         case 'l':
4928         {
4929           if (LocaleCompare(attribute,"label") == 0)
4930             {
4931               const char
4932                 *value;
4933
4934               if (image == (Image *) NULL)
4935                 break;
4936               value=GetImageProperty(image,"Label");
4937               if (value != (const char *) NULL)
4938                 s=newSVpv(value,0);
4939               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4940               continue;
4941             }
4942           if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
4943             {
4944               if (image != (Image *) NULL)
4945                 s=newSViv((ssize_t) image->iterations);
4946               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4947               continue;
4948             }
4949           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4950             attribute);
4951           break;
4952         }
4953         case 'M':
4954         case 'm':
4955         {
4956           if (LocaleCompare(attribute,"magick") == 0)
4957             {
4958               if (info && *info->image_info->magick)
4959                 s=newSVpv(info->image_info->magick,0);
4960               if (image != (Image *) NULL)
4961                 s=newSVpv(image->magick,0);
4962               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4963               continue;
4964             }
4965           if (LocaleCompare(attribute,"map") == 0)
4966             {
4967               s=newSViv(GetMagickResource(MapResource));
4968               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4969               continue;
4970             }
4971           if (LocaleCompare(attribute,"maximum-error") == 0)
4972             {
4973               if (image != (Image *) NULL)
4974                 s=newSVnv(image->error.normalized_maximum_error);
4975               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4976               continue;
4977             }
4978           if (LocaleCompare(attribute,"memory") == 0)
4979             {
4980               s=newSViv(GetMagickResource(MemoryResource));
4981               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4982               continue;
4983             }
4984           if (LocaleCompare(attribute,"mean-error") == 0)
4985             {
4986               if (image != (Image *) NULL)
4987                 s=newSVnv(image->error.normalized_mean_error);
4988               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4989               continue;
4990             }
4991           if (LocaleCompare(attribute,"mime") == 0)
4992             {
4993               if (info && *info->image_info->magick)
4994                 s=newSVpv(MagickToMime(info->image_info->magick),0);
4995               if (image != (Image *) NULL)
4996                 s=newSVpv(MagickToMime(image->magick),0);
4997               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4998               continue;
4999             }
5000           if (LocaleCompare(attribute,"mattecolor") == 0)
5001             {
5002               if (image == (Image *) NULL)
5003                 break;
5004               (void) FormatMagickString(color,MaxTextExtent,QuantumFormat ","
5005                 QuantumFormat "," QuantumFormat "," QuantumFormat,
5006                 image->matte_color.red,image->matte_color.green,
5007                 image->matte_color.blue,image->matte_color.opacity);
5008               s=newSVpv(color,0);
5009               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5010               continue;
5011             }
5012           if (LocaleCompare(attribute,"matte") == 0)
5013             {
5014               if (image != (Image *) NULL)
5015                 s=newSViv((ssize_t) image->matte);
5016               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5017               continue;
5018             }
5019           if (LocaleCompare(attribute,"mime") == 0)
5020             {
5021               const char
5022                 *magick;
5023
5024               magick=NULL;
5025               if (info && *info->image_info->magick)
5026                 magick=info->image_info->magick;
5027               if (image != (Image *) NULL)
5028                 magick=image->magick;
5029               if (magick)
5030                 {
5031                   char
5032                     *mime;
5033
5034                   mime=MagickToMime(magick);
5035                   s=newSVpv(mime,0);
5036                   mime=(char *) RelinquishMagickMemory(mime);
5037                 }
5038               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5039               continue;
5040             }
5041           if (LocaleCompare(attribute,"monochrome") == 0)
5042             {
5043               if (image == (Image *) NULL)
5044                 continue;
5045               j=info ? info->image_info->monochrome :
5046                 IsMonochromeImage(image,&image->exception);
5047               s=newSViv(j);
5048               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5049               continue;
5050             }
5051           if (LocaleCompare(attribute,"montage") == 0)
5052             {
5053               if (image && image->montage)
5054                 s=newSVpv(image->montage,0);
5055               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5056               continue;
5057             }
5058           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5059             attribute);
5060           break;
5061         }
5062         case 'O':
5063         case 'o':
5064         {
5065           if (LocaleCompare(attribute,"orientation") == 0)
5066             {
5067               j=info ? info->image_info->orientation : image ?
5068                 image->orientation : UndefinedOrientation;
5069               s=newSViv(j);
5070               (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5071                 j));
5072               SvIOK_on(s);
5073               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5074               continue;
5075             }
5076           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5077             attribute);
5078           break;
5079         }
5080         case 'P':
5081         case 'p':
5082         {
5083           if (LocaleCompare(attribute,"page") == 0)
5084             {
5085               if (info && info->image_info->page)
5086                 s=newSVpv(info->image_info->page,0);
5087               if (image != (Image *) NULL)
5088                 {
5089                   char
5090                     geometry[MaxTextExtent];
5091
5092                   (void) FormatMagickString(geometry,MaxTextExtent,
5093                     "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5094                     (double) image->page.height,(double) image->page.x,(double)
5095                     image->page.y);
5096                   s=newSVpv(geometry,0);
5097                 }
5098               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5099               continue;
5100             }
5101           if (LocaleCompare(attribute,"page.x") == 0)
5102             {
5103               if (image != (Image *) NULL)
5104                 s=newSViv((ssize_t) image->page.x);
5105               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5106               continue;
5107             }
5108           if (LocaleCompare(attribute,"page.y") == 0)
5109             {
5110               if (image != (Image *) NULL)
5111                 s=newSViv((ssize_t) image->page.y);
5112               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5113               continue;
5114             }
5115           if (LocaleNCompare(attribute,"pixel",5) == 0)
5116             {
5117               char
5118                 tuple[MaxTextExtent];
5119
5120               int
5121                 items;
5122
5123               long
5124                 x,
5125                 y;
5126
5127               register const PixelPacket
5128                 *p;
5129
5130               register const IndexPacket
5131                 *indexes;
5132
5133               if (image == (Image *) NULL)
5134                 break;
5135               x=0;
5136               y=0;
5137               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5138               p=GetVirtualPixels(image,x,y,1,1,exception);
5139               indexes=GetVirtualIndexQueue(image);
5140               if (image->colorspace != CMYKColorspace)
5141                 (void) FormatMagickString(tuple,MaxTextExtent,QuantumFormat ","
5142                   QuantumFormat "," QuantumFormat "," QuantumFormat,
5143                   GetRedPixelComponent(p),GetGreenPixelComponent(p),
5144                   GetBluePixelComponent(p),GetOpacityPixelComponent(p));
5145               else
5146                 (void) FormatMagickString(tuple,MaxTextExtent,QuantumFormat ","
5147                   QuantumFormat "," QuantumFormat "," QuantumFormat ","
5148                   QuantumFormat,GetRedPixelComponent(p),
5149                   GetGreenPixelComponent(p),GetBluePixelComponent(p),
5150                   GetIndexPixelComponent(indexes),GetOpacityPixelComponent(p));
5151               s=newSVpv(tuple,0);
5152               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5153               continue;
5154             }
5155           if (LocaleCompare(attribute,"pointsize") == 0)
5156             {
5157               if (info)
5158                 s=newSViv((ssize_t) info->image_info->pointsize);
5159               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5160               continue;
5161             }
5162           if (LocaleCompare(attribute,"preview") == 0)
5163             {
5164               s=newSViv(info->image_info->preview_type);
5165               (void) sv_setpv(s,CommandOptionToMnemonic(MagickPreviewOptions,
5166                 info->image_info->preview_type));
5167               SvIOK_on(s);
5168               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5169               continue;
5170             }
5171           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5172             attribute);
5173           break;
5174         }
5175         case 'Q':
5176         case 'q':
5177         {
5178           if (LocaleCompare(attribute,"quality") == 0)
5179             {
5180               if (info)
5181                 s=newSViv((ssize_t) info->image_info->quality);
5182               if (image != (Image *) NULL)
5183                 s=newSViv((ssize_t) image->quality);
5184               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5185               continue;
5186             }
5187           if (LocaleCompare(attribute,"quantum") == 0)
5188             {
5189               if (info)
5190                 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5191               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5192               continue;
5193             }
5194           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5195             attribute);
5196           break;
5197         }
5198         case 'R':
5199         case 'r':
5200         {
5201           if (LocaleCompare(attribute,"rendering-intent") == 0)
5202             {
5203               s=newSViv(image->rendering_intent);
5204               (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5205                 image->rendering_intent));
5206               SvIOK_on(s);
5207               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5208               continue;
5209             }
5210           if (LocaleCompare(attribute,"red-primary") == 0)
5211             {
5212               if (image == (Image *) NULL)
5213                 break;
5214               (void) FormatMagickString(color,MaxTextExtent,"%.15g,%.15g",
5215                 image->chromaticity.red_primary.x,
5216                 image->chromaticity.red_primary.y);
5217               s=newSVpv(color,0);
5218               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5219               continue;
5220             }
5221           if (LocaleCompare(attribute,"rows") == 0)
5222             {
5223               if (image != (Image *) NULL)
5224                 s=newSViv((ssize_t) image->rows);
5225               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5226               continue;
5227             }
5228           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5229             attribute);
5230           break;
5231         }
5232         case 'S':
5233         case 's':
5234         {
5235           if (LocaleCompare(attribute,"sampling-factor") == 0)
5236             {
5237               if (info && info->image_info->sampling_factor)
5238                 s=newSVpv(info->image_info->sampling_factor,0);
5239               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5240               continue;
5241             }
5242           if (LocaleCompare(attribute,"subimage") == 0)
5243             {
5244               if (info)
5245                 s=newSViv((ssize_t) info->image_info->subimage);
5246               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5247               continue;
5248             }
5249           if (LocaleCompare(attribute,"subrange") == 0)
5250             {
5251               if (info)
5252                 s=newSViv((ssize_t) info->image_info->subrange);
5253               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5254               continue;
5255             }
5256           if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5257             {
5258               if (info && info->image_info->server_name)
5259                 s=newSVpv(info->image_info->server_name,0);
5260               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5261               continue;
5262             }
5263           if (LocaleCompare(attribute,"size") == 0)
5264             {
5265               if (info && info->image_info->size)
5266                 s=newSVpv(info->image_info->size,0);
5267               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5268               continue;
5269             }
5270           if (LocaleCompare(attribute,"scene") == 0)
5271             {
5272               if (image != (Image *) NULL)
5273                 s=newSViv((ssize_t) image->scene);
5274               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5275               continue;
5276             }
5277           if (LocaleCompare(attribute,"scenes") == 0)
5278             {
5279               if (image != (Image *) NULL)
5280                 s=newSViv((ssize_t) info->image_info->number_scenes);
5281               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5282               continue;
5283             }
5284           if (LocaleCompare(attribute,"signature") == 0)
5285             {
5286               const char
5287                 *value;
5288
5289               if (image == (Image *) NULL)
5290                 break;
5291               (void) SignatureImage(image);
5292               value=GetImageProperty(image,"Signature");
5293               if (value != (const char *) NULL)
5294                 s=newSVpv(value,0);
5295               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5296               continue;
5297             }
5298           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5299             attribute);
5300           break;
5301         }
5302         case 'T':
5303         case 't':
5304         {
5305           if (LocaleCompare(attribute,"taint") == 0)
5306             {
5307               if (image != (Image *) NULL)
5308                 s=newSViv((ssize_t) IsTaintImage(image));
5309               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5310               continue;
5311             }
5312           if (LocaleCompare(attribute,"tile") == 0)
5313             {
5314               if (info && info->image_info->tile)
5315                 s=newSVpv(info->image_info->tile,0);
5316               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5317               continue;
5318             }
5319           if (LocaleCompare(attribute,"texture") == 0)
5320             {
5321               if (info && info->image_info->texture)
5322                 s=newSVpv(info->image_info->texture,0);
5323               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5324               continue;
5325             }
5326           if (LocaleCompare(attribute,"total-ink-density") == 0)
5327             {
5328               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5329               if (image != (Image *) NULL)
5330                 s=newSVnv(GetImageTotalInkDensity(image));
5331               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5332               continue;
5333             }
5334           if (LocaleCompare(attribute,"transparent-color") == 0)
5335             {
5336               if (image == (Image *) NULL)
5337                 break;
5338               (void) FormatMagickString(color,MaxTextExtent,QuantumFormat ","
5339                 QuantumFormat "," QuantumFormat "," QuantumFormat,
5340                 image->transparent_color.red,image->transparent_color.green,
5341                 image->transparent_color.blue,image->transparent_color.opacity);
5342               s=newSVpv(color,0);
5343               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5344               continue;
5345             }
5346           if (LocaleCompare(attribute,"type") == 0)
5347             {
5348               if (image == (Image *) NULL)
5349                 break;
5350               j=(ssize_t) GetImageType(image,&image->exception);
5351               s=newSViv(j);
5352               (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5353               SvIOK_on(s);
5354               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5355               continue;
5356             }
5357           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5358             attribute);
5359           break;
5360         }
5361         case 'U':
5362         case 'u':
5363         {
5364           if (LocaleCompare(attribute,"units") == 0)
5365             {
5366               j=info ? info->image_info->units : image ? image->units :
5367                 UndefinedResolution;
5368               if (info && (info->image_info->units == UndefinedResolution))
5369                 if (image)
5370                   j=image->units;
5371               if (j == UndefinedResolution)
5372                 s=newSVpv("undefined units",0);
5373               else
5374                 if (j == PixelsPerInchResolution)
5375                   s=newSVpv("pixels / inch",0);
5376                 else
5377                   s=newSVpv("pixels / centimeter",0);
5378               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5379               continue;
5380             }
5381           if (LocaleCompare(attribute,"user-time") == 0)
5382             {
5383               if (image != (Image *) NULL)
5384                 s=newSVnv(GetUserTime(&image->timer));
5385               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5386               continue;
5387             }
5388           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5389             attribute);
5390           break;
5391         }
5392         case 'V':
5393         case 'v':
5394         {
5395           if (LocaleCompare(attribute,"verbose") == 0)
5396             {
5397               if (info)
5398                 s=newSViv((ssize_t) info->image_info->verbose);
5399               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5400               continue;
5401             }
5402           if (LocaleCompare(attribute,"version") == 0)
5403             {
5404               s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5405               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5406               continue;
5407             }
5408           if (LocaleCompare(attribute,"view") == 0)
5409             {
5410               if (info && info->image_info->view)
5411                 s=newSVpv(info->image_info->view,0);
5412               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5413               continue;
5414             }
5415           if (LocaleCompare(attribute,"virtual-pixel") == 0)
5416             {
5417               if (image == (Image *) NULL)
5418                 break;
5419               j=(ssize_t) GetImageVirtualPixelMethod(image);
5420               s=newSViv(j);
5421               (void) sv_setpv(s,CommandOptionToMnemonic(
5422                 MagickVirtualPixelOptions,j));
5423               SvIOK_on(s);
5424               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5425               continue;
5426             }
5427           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5428             attribute);
5429           break;
5430         }
5431         case 'W':
5432         case 'w':
5433         {
5434           if (LocaleCompare(attribute,"white-point") == 0)
5435             {
5436               if (image == (Image *) NULL)
5437                 break;
5438               (void) FormatMagickString(color,MaxTextExtent,"%.15g,%.15g",
5439                 image->chromaticity.white_point.x,
5440                 image->chromaticity.white_point.y);
5441               s=newSVpv(color,0);
5442               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5443               continue;
5444             }
5445           if (LocaleCompare(attribute,"width") == 0)
5446             {
5447               if (image != (Image *) NULL)
5448                 s=newSViv((ssize_t) image->columns);
5449               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5450               continue;
5451             }
5452           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5453              attribute);
5454           break;
5455         }
5456         case 'X':
5457         case 'x':
5458         {
5459           if (LocaleCompare(attribute,"x-resolution") == 0)
5460             {
5461               if (image != (Image *) NULL)
5462                 s=newSVnv(image->x_resolution);
5463               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5464               continue;
5465             }
5466           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5467             attribute);
5468           break;
5469         }
5470         case 'Y':
5471         case 'y':
5472         {
5473           if (LocaleCompare(attribute,"y-resolution") == 0)
5474             {
5475               if (image != (Image *) NULL)
5476                 s=newSVnv(image->y_resolution);
5477               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5478               continue;
5479             }
5480           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5481             attribute);
5482           break;
5483         }
5484         default:
5485           break;
5486       }
5487       if (image == (Image *) NULL)
5488         ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5489           attribute)
5490       else
5491         {
5492           value=GetImageProperty(image,attribute);
5493           if (value != (const char *) NULL)
5494             {
5495               s=newSVpv(value,0);
5496               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5497             }
5498           else
5499             if (*attribute != '%')
5500               ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5501                 attribute)
5502             else
5503               {
5504                  char
5505                    *meta;
5506
5507                  meta=InterpretImageProperties(info ? info->image_info :
5508                    (ImageInfo *) NULL,image,attribute);
5509                  s=newSVpv(meta,0);
5510                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5511                  meta=(char *) RelinquishMagickMemory(meta);
5512               }
5513         }
5514     }
5515     exception=DestroyExceptionInfo(exception);
5516     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5517   }
5518 \f
5519 #
5520 ###############################################################################
5521 #                                                                             #
5522 #                                                                             #
5523 #                                                                             #
5524 #   G e t A u t h e n t i c P i x e l s                                       #
5525 #                                                                             #
5526 #                                                                             #
5527 #                                                                             #
5528 ###############################################################################
5529 #
5530 #
5531 void *
5532 GetAuthenticPixels(ref,...)
5533   Image::Magick ref = NO_INIT
5534   ALIAS:
5535     getauthenticpixels = 1
5536     GetImagePixels = 2
5537     getimagepixels = 3
5538   CODE:
5539   {
5540     char
5541       *attribute;
5542
5543     ExceptionInfo
5544       *exception;
5545
5546     Image
5547       *image;
5548
5549     RectangleInfo
5550       region;
5551
5552     ssize_t
5553       i;
5554
5555     struct PackageInfo
5556       *info;
5557
5558     SV
5559       *perl_exception,
5560       *reference;
5561
5562     void
5563       *blob = NULL;
5564
5565     PERL_UNUSED_VAR(ref);
5566     PERL_UNUSED_VAR(ix);
5567     exception=AcquireExceptionInfo();
5568     perl_exception=newSVpv("",0);
5569     if (sv_isobject(ST(0)) == 0)
5570       {
5571         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5572           PackageName);
5573         goto PerlException;
5574       }
5575     reference=SvRV(ST(0));
5576
5577     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5578     if (image == (Image *) NULL)
5579       {
5580         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5581           PackageName);
5582         goto PerlException;
5583       }
5584
5585     region.x=0;
5586     region.y=0;
5587     region.width=image->columns;
5588     region.height=1;
5589     if (items == 1)
5590       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5591     for (i=2; i < items; i+=2)
5592     {
5593       attribute=(char *) SvPV(ST(i-1),na);
5594       switch (*attribute)
5595       {
5596         case 'g':
5597         case 'G':
5598         {
5599           if (LocaleCompare(attribute,"geometry") == 0)
5600             {
5601               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5602               break;
5603             }
5604           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5605             attribute);
5606           break;
5607         }
5608         case 'H':
5609         case 'h':
5610         {
5611           if (LocaleCompare(attribute,"height") == 0)
5612             {
5613               region.height=SvIV(ST(i));
5614               continue;
5615             }
5616           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5617             attribute);
5618           break;
5619         }
5620         case 'X':
5621         case 'x':
5622         {
5623           if (LocaleCompare(attribute,"x") == 0)
5624             {
5625               region.x=SvIV(ST(i));
5626               continue;
5627             }
5628           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5629             attribute);
5630           break;
5631         }
5632         case 'Y':
5633         case 'y':
5634         {
5635           if (LocaleCompare(attribute,"y") == 0)
5636             {
5637               region.y=SvIV(ST(i));
5638               continue;
5639             }
5640           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5641             attribute);
5642           break;
5643         }
5644         case 'W':
5645         case 'w':
5646         {
5647           if (LocaleCompare(attribute,"width") == 0)
5648             {
5649               region.width=SvIV(ST(i));
5650               continue;
5651             }
5652           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5653             attribute);
5654           break;
5655         }
5656       }
5657     }
5658     blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5659       region.height,exception);
5660     if (blob != (void *) NULL)
5661       goto PerlEnd;
5662
5663   PerlException:
5664     InheritPerlException(exception,perl_exception);
5665     exception=DestroyExceptionInfo(exception);
5666     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5667
5668   PerlEnd:
5669     RETVAL = blob;
5670   }
5671   OUTPUT:
5672     RETVAL
5673 \f
5674 #
5675 ###############################################################################
5676 #                                                                             #
5677 #                                                                             #
5678 #                                                                             #
5679 #   G e t V i r t u a l P i x e l s                                           #
5680 #                                                                             #
5681 #                                                                             #
5682 #                                                                             #
5683 ###############################################################################
5684 #
5685 #
5686 void *
5687 GetVirtualPixels(ref,...)
5688   Image::Magick ref = NO_INIT
5689   ALIAS:
5690     getvirtualpixels = 1
5691     AcquireImagePixels = 2
5692     acquireimagepixels = 3
5693   CODE:
5694   {
5695     char
5696       *attribute;
5697
5698     const void
5699       *blob = NULL;
5700
5701     ExceptionInfo
5702       *exception;
5703
5704     Image
5705       *image;
5706
5707     RectangleInfo
5708       region;
5709
5710     ssize_t
5711       i;
5712
5713     struct PackageInfo
5714       *info;
5715
5716     SV
5717       *perl_exception,
5718       *reference;
5719
5720     PERL_UNUSED_VAR(ref);
5721     PERL_UNUSED_VAR(ix);
5722     exception=AcquireExceptionInfo();
5723     perl_exception=newSVpv("",0);
5724     if (sv_isobject(ST(0)) == 0)
5725       {
5726         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5727           PackageName);
5728         goto PerlException;
5729       }
5730     reference=SvRV(ST(0));
5731
5732     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5733     if (image == (Image *) NULL)
5734       {
5735         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5736           PackageName);
5737         goto PerlException;
5738       }
5739
5740     region.x=0;
5741     region.y=0;
5742     region.width=image->columns;
5743     region.height=1;
5744     if (items == 1)
5745       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5746     for (i=2; i < items; i+=2)
5747     {
5748       attribute=(char *) SvPV(ST(i-1),na);
5749       switch (*attribute)
5750       {
5751         case 'g':
5752         case 'G':
5753         {
5754           if (LocaleCompare(attribute,"geometry") == 0)
5755             {
5756               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5757               break;
5758             }
5759           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5760             attribute);
5761           break;
5762         }
5763         case 'H':
5764         case 'h':
5765         {
5766           if (LocaleCompare(attribute,"height") == 0)
5767             {
5768               region.height=SvIV(ST(i));
5769               continue;
5770             }
5771           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5772             attribute);
5773           break;
5774         }
5775         case 'X':
5776         case 'x':
5777         {
5778           if (LocaleCompare(attribute,"x") == 0)
5779             {
5780               region.x=SvIV(ST(i));
5781               continue;
5782             }
5783           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5784             attribute);
5785           break;
5786         }
5787         case 'Y':
5788         case 'y':
5789         {
5790           if (LocaleCompare(attribute,"y") == 0)
5791             {
5792               region.y=SvIV(ST(i));
5793               continue;
5794             }
5795           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5796             attribute);
5797           break;
5798         }
5799         case 'W':
5800         case 'w':
5801         {
5802           if (LocaleCompare(attribute,"width") == 0)
5803             {
5804               region.width=SvIV(ST(i));
5805               continue;
5806             }
5807           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5808             attribute);
5809           break;
5810         }
5811       }
5812     }
5813     blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
5814       region.height,exception);
5815     if (blob != (void *) NULL)
5816       goto PerlEnd;
5817
5818   PerlException:
5819     InheritPerlException(exception,perl_exception);
5820     exception=DestroyExceptionInfo(exception);
5821     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5822
5823   PerlEnd:
5824     RETVAL = (void *) blob;
5825   }
5826   OUTPUT:
5827     RETVAL
5828 \f
5829 #
5830 ###############################################################################
5831 #                                                                             #
5832 #                                                                             #
5833 #                                                                             #
5834 #   G e t A u t h e n t i c I n d e x Q u e u e                               #
5835 #                                                                             #
5836 #                                                                             #
5837 #                                                                             #
5838 ###############################################################################
5839 #
5840 #
5841 void *
5842 GetAuthenticIndexQueue(ref,...)
5843   Image::Magick ref = NO_INIT
5844   ALIAS:
5845     getauthenticindexqueue = 1
5846     GetIndexes = 2
5847     getindexes = 3
5848   CODE:
5849   {
5850     ExceptionInfo
5851       *exception;
5852
5853     Image
5854       *image;
5855
5856     struct PackageInfo
5857       *info;
5858
5859     SV
5860       *perl_exception,
5861       *reference;
5862
5863     void
5864       *blob = NULL;
5865
5866     PERL_UNUSED_VAR(ref);
5867     PERL_UNUSED_VAR(ix);
5868     exception=AcquireExceptionInfo();
5869     perl_exception=newSVpv("",0);
5870     if (sv_isobject(ST(0)) == 0)
5871       {
5872         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5873           PackageName);
5874         goto PerlException;
5875       }
5876     reference=SvRV(ST(0));
5877
5878     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5879     if (image == (Image *) NULL)
5880       {
5881         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5882           PackageName);
5883         goto PerlException;
5884       }
5885
5886     blob=(void *) GetAuthenticIndexQueue(image);
5887     if (blob != (void *) NULL)
5888       goto PerlEnd;
5889
5890   PerlException:
5891     InheritPerlException(exception,perl_exception);
5892     exception=DestroyExceptionInfo(exception);
5893     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5894
5895   PerlEnd:
5896     RETVAL = blob;
5897   }
5898   OUTPUT:
5899     RETVAL
5900 \f
5901 #
5902 ###############################################################################
5903 #                                                                             #
5904 #                                                                             #
5905 #                                                                             #
5906 #   G e t V i r t u a l I n d e x Q u e u e                                   #
5907 #                                                                             #
5908 #                                                                             #
5909 #                                                                             #
5910 ###############################################################################
5911 #
5912 #
5913 void *
5914 GetVirtualIndexQueue(ref,...)
5915   Image::Magick ref = NO_INIT
5916   ALIAS:
5917     getvirtualindexqueue = 1
5918   CODE:
5919   {
5920     ExceptionInfo
5921       *exception;
5922
5923     Image
5924       *image;
5925
5926     struct PackageInfo
5927       *info;
5928
5929     SV
5930       *perl_exception,
5931       *reference;
5932
5933     void
5934       *blob = NULL;
5935
5936     PERL_UNUSED_VAR(ref);
5937     PERL_UNUSED_VAR(ix);
5938     exception=AcquireExceptionInfo();
5939     perl_exception=newSVpv("",0);
5940     if (sv_isobject(ST(0)) == 0)
5941       {
5942         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5943           PackageName);
5944         goto PerlException;
5945       }
5946     reference=SvRV(ST(0));
5947
5948     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5949     if (image == (Image *) NULL)
5950       {
5951         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5952           PackageName);
5953         goto PerlException;
5954       }
5955
5956     blob=(void *) GetVirtualIndexQueue(image);
5957     if (blob != (void *) NULL)
5958       goto PerlEnd;
5959
5960   PerlException:
5961     InheritPerlException(exception,perl_exception);
5962     exception=DestroyExceptionInfo(exception);
5963     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5964
5965   PerlEnd:
5966     RETVAL = blob;
5967   }
5968   OUTPUT:
5969     RETVAL
5970 \f
5971 #
5972 ###############################################################################
5973 #                                                                             #
5974 #                                                                             #
5975 #                                                                             #
5976 #   H i s t o g r a m                                                         #
5977 #                                                                             #
5978 #                                                                             #
5979 #                                                                             #
5980 ###############################################################################
5981 #
5982 #
5983 void
5984 Histogram(ref,...)
5985   Image::Magick ref=NO_INIT
5986   ALIAS:
5987     HistogramImage = 1
5988     histogram      = 2
5989     histogramimage = 3
5990   PPCODE:
5991   {
5992     AV
5993       *av;
5994
5995     char
5996       message[MaxTextExtent];
5997
5998     ColorPacket
5999       *histogram;
6000
6001     ExceptionInfo
6002       *exception;
6003
6004     HV
6005       *hv;
6006
6007     Image
6008       *image;
6009
6010     register ssize_t
6011       i;
6012
6013     ssize_t
6014       count;
6015
6016     struct PackageInfo
6017       *info;
6018
6019     SV
6020       *av_reference,
6021       *perl_exception,
6022       *reference;
6023
6024     size_t
6025       number_colors;
6026
6027     PERL_UNUSED_VAR(ref);
6028     PERL_UNUSED_VAR(ix);
6029     exception=AcquireExceptionInfo();
6030     perl_exception=newSVpv("",0);
6031     av=NULL;
6032     if (sv_isobject(ST(0)) == 0)
6033       {
6034         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6035           PackageName);
6036         goto PerlException;
6037       }
6038     reference=SvRV(ST(0));
6039     hv=SvSTASH(reference);
6040     av=newAV();
6041     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
6042     SvREFCNT_dec(av);
6043     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6044     if (image == (Image *) NULL)
6045       {
6046         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6047           PackageName);
6048         goto PerlException;
6049       }
6050     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
6051     count=0;
6052     for ( ; image; image=image->next)
6053     {
6054       histogram=GetImageHistogram(image,&number_colors,&image->exception);
6055       if (histogram == (ColorPacket *) NULL)
6056         continue;
6057       count+=(ssize_t) number_colors;
6058       EXTEND(sp,6*count);
6059       for (i=0; i < (ssize_t) number_colors; i++)
6060       {
6061         (void) FormatMagickString(message,MaxTextExtent,QuantumFormat,
6062           histogram[i].pixel.red);
6063         PUSHs(sv_2mortal(newSVpv(message,0)));
6064         (void) FormatMagickString(message,MaxTextExtent,QuantumFormat,
6065           histogram[i].pixel.green);
6066         PUSHs(sv_2mortal(newSVpv(message,0)));
6067         (void) FormatMagickString(message,MaxTextExtent,QuantumFormat,
6068           histogram[i].pixel.blue);
6069         PUSHs(sv_2mortal(newSVpv(message,0)));
6070         if (image->colorspace == CMYKColorspace)
6071           {
6072             (void) FormatMagickString(message,MaxTextExtent,QuantumFormat,
6073               histogram[i].index);
6074             PUSHs(sv_2mortal(newSVpv(message,0)));
6075           }
6076         (void) FormatMagickString(message,MaxTextExtent,QuantumFormat,
6077           histogram[i].pixel.opacity);
6078         PUSHs(sv_2mortal(newSVpv(message,0)));
6079         (void) FormatMagickString(message,MaxTextExtent,"%.20g",(double)
6080           histogram[i].count);
6081         PUSHs(sv_2mortal(newSVpv(message,0)));
6082       }
6083       histogram=(ColorPacket *) RelinquishMagickMemory(histogram);
6084     }
6085
6086   PerlException:
6087     InheritPerlException(exception,perl_exception);
6088     exception=DestroyExceptionInfo(exception);
6089     SvREFCNT_dec(perl_exception);
6090   }
6091 \f
6092 #
6093 ###############################################################################
6094 #                                                                             #
6095 #                                                                             #
6096 #                                                                             #
6097 #   G e t P i x e l                                                           #
6098 #                                                                             #
6099 #                                                                             #
6100 #                                                                             #
6101 ###############################################################################
6102 #
6103 #
6104 void
6105 GetPixel(ref,...)
6106   Image::Magick ref=NO_INIT
6107   ALIAS:
6108     getpixel = 1
6109     getPixel = 2
6110   PPCODE:
6111   {
6112     AV
6113       *av;
6114
6115     char
6116       *attribute;
6117
6118     ChannelType
6119       channel;
6120
6121     ExceptionInfo
6122       *exception;
6123
6124     Image
6125       *image;
6126
6127     MagickBooleanType
6128       normalize;
6129
6130     RectangleInfo
6131       region;
6132
6133     register const IndexPacket
6134       *indexes;
6135
6136     register const PixelPacket
6137       *p;
6138
6139     register ssize_t
6140       i;
6141
6142     ssize_t
6143       option;
6144
6145     struct PackageInfo
6146       *info;
6147
6148     SV
6149       *perl_exception,
6150       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6151
6152     PERL_UNUSED_VAR(ref);
6153     PERL_UNUSED_VAR(ix);
6154     exception=AcquireExceptionInfo();
6155     perl_exception=newSVpv("",0);
6156     reference=SvRV(ST(0));
6157     av=(AV *) reference;
6158     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6159       exception);
6160     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6161     if (image == (Image *) NULL)
6162       {
6163         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6164           PackageName);
6165         goto PerlException;
6166       }
6167     channel=DefaultChannels;
6168     normalize=MagickTrue;
6169     region.x=0;
6170     region.y=0;
6171     region.width=image->columns;
6172     region.height=1;
6173     if (items == 1)
6174       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6175     for (i=2; i < items; i+=2)
6176     {
6177       attribute=(char *) SvPV(ST(i-1),na);
6178       switch (*attribute)
6179       {
6180         case 'C':
6181         case 'c':
6182         {
6183           if (LocaleCompare(attribute,"channel") == 0)
6184             {
6185               ssize_t
6186                 option;
6187
6188               option=ParseChannelOption(SvPV(ST(i),na));
6189               if (option < 0)
6190                 {
6191                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6192                     SvPV(ST(i),na));
6193                   return;
6194                 }
6195                channel=(ChannelType) option;
6196               break;
6197             }
6198           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6199             attribute);
6200           break;
6201         }
6202         case 'g':
6203         case 'G':
6204         {
6205           if (LocaleCompare(attribute,"geometry") == 0)
6206             {
6207               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6208               break;
6209             }
6210           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6211             attribute);
6212           break;
6213         }
6214         case 'N':
6215         case 'n':
6216         {
6217           if (LocaleCompare(attribute,"normalize") == 0)
6218             {
6219               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6220                 SvPV(ST(i),na));
6221               if (option < 0)
6222                 {
6223                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6224                     SvPV(ST(i),na));
6225                   break;
6226                 }
6227              normalize=option != 0 ? MagickTrue : MagickFalse;
6228              break;
6229             }
6230           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6231             attribute);
6232           break;
6233         }
6234         case 'x':
6235         case 'X':
6236         {
6237           if (LocaleCompare(attribute,"x") == 0)
6238             {
6239               region.x=SvIV(ST(i));
6240               break;
6241             }
6242           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6243             attribute);
6244           break;
6245         }
6246         case 'y':
6247         case 'Y':
6248         {
6249           if (LocaleCompare(attribute,"y") == 0)
6250             {
6251               region.y=SvIV(ST(i));
6252               break;
6253             }
6254           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6255             attribute);
6256           break;
6257         }
6258         default:
6259         {
6260           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6261             attribute);
6262           break;
6263         }
6264       }
6265     }
6266     p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6267     if (p == (const PixelPacket *) NULL)
6268       PUSHs(&sv_undef);
6269     else
6270       {
6271         double
6272           scale;
6273
6274         indexes=GetVirtualIndexQueue(image);
6275         scale=1.0;
6276         if (normalize != MagickFalse)
6277           scale=1.0/QuantumRange;
6278         if ((channel & RedChannel) != 0)
6279           PUSHs(sv_2mortal(newSVnv(scale*GetRedPixelComponent(p))));
6280         if ((channel & GreenChannel) != 0)
6281           PUSHs(sv_2mortal(newSVnv(scale*GetGreenPixelComponent(p))));
6282         if ((channel & BlueChannel) != 0)
6283           PUSHs(sv_2mortal(newSVnv(scale*GetBluePixelComponent(p))));
6284         if (((channel & IndexChannel) != 0) &&
6285             (image->colorspace == CMYKColorspace))
6286           PUSHs(sv_2mortal(newSVnv(scale*GetIndexPixelComponent(indexes))));
6287         if ((channel & OpacityChannel) != 0)
6288           PUSHs(sv_2mortal(newSVnv(scale*GetOpacityPixelComponent(p))));
6289       }
6290
6291   PerlException:
6292     InheritPerlException(exception,perl_exception);
6293     exception=DestroyExceptionInfo(exception);
6294     SvREFCNT_dec(perl_exception);
6295   }
6296 \f
6297 #
6298 ###############################################################################
6299 #                                                                             #
6300 #                                                                             #
6301 #                                                                             #
6302 #   G e t P i x e l s                                                         #
6303 #                                                                             #
6304 #                                                                             #
6305 #                                                                             #
6306 ###############################################################################
6307 #
6308 #
6309 void
6310 GetPixels(ref,...)
6311   Image::Magick ref=NO_INIT
6312   ALIAS:
6313     getpixels = 1
6314     getPixels = 2
6315   PPCODE:
6316   {
6317     AV
6318       *av;
6319
6320     char
6321       *attribute;
6322
6323     const char
6324       *map;
6325
6326     ExceptionInfo
6327       *exception;
6328
6329     Image
6330       *image;
6331
6332     MagickBooleanType
6333       normalize,
6334       status;
6335
6336     RectangleInfo
6337       region;
6338
6339     register ssize_t
6340       i;
6341
6342     ssize_t
6343       option;
6344
6345     struct PackageInfo
6346       *info;
6347
6348     SV
6349       *perl_exception,
6350       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6351
6352     PERL_UNUSED_VAR(ref);
6353     PERL_UNUSED_VAR(ix);
6354     exception=AcquireExceptionInfo();
6355     perl_exception=newSVpv("",0);
6356     reference=SvRV(ST(0));
6357     av=(AV *) reference;
6358     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6359       exception);
6360     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6361     if (image == (Image *) NULL)
6362       {
6363         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6364           PackageName);
6365         goto PerlException;
6366       }
6367     map="RGB";
6368     if (image->matte != MagickFalse)
6369       map="RGBA";
6370     if (image->colorspace == CMYKColorspace)
6371       {
6372         map="CMYK";
6373         if (image->matte != MagickFalse)
6374           map="CMYKA";
6375       }
6376     normalize=MagickFalse;
6377     region.x=0;
6378     region.y=0;
6379     region.width=image->columns;
6380     region.height=1;
6381     if (items == 1)
6382       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6383     for (i=2; i < items; i+=2)
6384     {
6385       attribute=(char *) SvPV(ST(i-1),na);
6386       switch (*attribute)
6387       {
6388         case 'g':
6389         case 'G':
6390         {
6391           if (LocaleCompare(attribute,"geometry") == 0)
6392             {
6393               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6394               break;
6395             }
6396           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6397             attribute);
6398           break;
6399         }
6400         case 'H':
6401         case 'h':
6402         {
6403           if (LocaleCompare(attribute,"height") == 0)
6404             {
6405               region.height=SvIV(ST(i));
6406               break;
6407             }
6408           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6409             attribute);
6410           break;
6411         }
6412         case 'M':
6413         case 'm':
6414         {
6415           if (LocaleCompare(attribute,"map") == 0)
6416             {
6417               map=SvPV(ST(i),na);
6418               break;
6419             }
6420           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6421             attribute);
6422           break;
6423         }
6424         case 'N':
6425         case 'n':
6426         {
6427           if (LocaleCompare(attribute,"normalize") == 0)
6428             {
6429               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6430                 SvPV(ST(i),na));
6431               if (option < 0)
6432                 {
6433                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6434                     SvPV(ST(i),na));
6435                   break;
6436                 }
6437              normalize=option != 0 ? MagickTrue : MagickFalse;
6438              break;
6439             }
6440           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6441             attribute);
6442           break;
6443         }
6444         case 'W':
6445         case 'w':
6446         {
6447           if (LocaleCompare(attribute,"width") == 0)
6448             {
6449               region.width=SvIV(ST(i));
6450               break;
6451             }
6452           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6453             attribute);
6454           break;
6455         }
6456         case 'x':
6457         case 'X':
6458         {
6459           if (LocaleCompare(attribute,"x") == 0)
6460             {
6461               region.x=SvIV(ST(i));
6462               break;
6463             }
6464           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6465             attribute);
6466           break;
6467         }
6468         case 'y':
6469         case 'Y':
6470         {
6471           if (LocaleCompare(attribute,"y") == 0)
6472             {
6473               region.y=SvIV(ST(i));
6474               break;
6475             }
6476           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6477             attribute);
6478           break;
6479         }
6480         default:
6481         {
6482           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6483             attribute);
6484           break;
6485         }
6486       }
6487     }
6488     if (normalize != MagickFalse)
6489       {
6490         float
6491           *pixels;
6492
6493         pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6494           region.height*sizeof(*pixels));
6495         if (pixels == (float *) NULL)
6496           {
6497             ThrowPerlException(exception,ResourceLimitError,
6498               "MemoryAllocationFailed",PackageName);
6499             goto PerlException;
6500           }
6501         status=ExportImagePixels(image,region.x,region.y,region.width,
6502           region.height,map,FloatPixel,pixels,exception);
6503         if (status == MagickFalse)
6504           PUSHs(&sv_undef);
6505         else
6506           {
6507             EXTEND(sp,strlen(map)*region.width*region.height);
6508             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6509               PUSHs(sv_2mortal(newSVnv(pixels[i])));
6510           }
6511         pixels=(float *) RelinquishMagickMemory(pixels);
6512       }
6513     else
6514       {
6515         Quantum
6516           *pixels;
6517
6518         pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6519           region.height*sizeof(*pixels));
6520         if (pixels == (Quantum *) NULL)
6521           {
6522             ThrowPerlException(exception,ResourceLimitError,
6523               "MemoryAllocationFailed",PackageName);
6524             goto PerlException;
6525           }
6526         status=ExportImagePixels(image,region.x,region.y,region.width,
6527           region.height,map,QuantumPixel,pixels,exception);
6528         if (status == MagickFalse)
6529           PUSHs(&sv_undef);
6530         else
6531           {
6532             EXTEND(sp,strlen(map)*region.width*region.height);
6533             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6534               PUSHs(sv_2mortal(newSViv(pixels[i])));
6535           }
6536         pixels=(Quantum *) RelinquishMagickMemory(pixels);
6537       }
6538
6539   PerlException:
6540     InheritPerlException(exception,perl_exception);
6541     exception=DestroyExceptionInfo(exception);
6542     SvREFCNT_dec(perl_exception);
6543   }
6544 \f
6545 #
6546 ###############################################################################
6547 #                                                                             #
6548 #                                                                             #
6549 #                                                                             #
6550 #   I m a g e T o B l o b                                                     #
6551 #                                                                             #
6552 #                                                                             #
6553 #                                                                             #
6554 ###############################################################################
6555 #
6556 #
6557 void
6558 ImageToBlob(ref,...)
6559   Image::Magick ref=NO_INIT
6560   ALIAS:
6561     ImageToBlob  = 1
6562     imagetoblob  = 2
6563     toblob       = 3
6564     blob         = 4
6565   PPCODE:
6566   {
6567     char
6568       filename[MaxTextExtent];
6569
6570     ExceptionInfo
6571       *exception;
6572
6573     Image
6574       *image,
6575       *next;
6576
6577     register ssize_t
6578       i;
6579
6580     struct PackageInfo
6581       *info,
6582       *package_info;
6583
6584     size_t
6585       length;
6586
6587     ssize_t
6588       scene;
6589
6590     SV
6591       *perl_exception,
6592       *reference;
6593
6594     void
6595       *blob;
6596
6597     PERL_UNUSED_VAR(ref);
6598     PERL_UNUSED_VAR(ix);
6599     exception=AcquireExceptionInfo();
6600     perl_exception=newSVpv("",0);
6601     package_info=(struct PackageInfo *) NULL;
6602     if (sv_isobject(ST(0)) == 0)
6603       {
6604         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6605           PackageName);
6606         goto PerlException;
6607       }
6608     reference=SvRV(ST(0));
6609     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6610     if (image == (Image *) NULL)
6611       {
6612         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6613           PackageName);
6614         goto PerlException;
6615       }
6616     package_info=ClonePackageInfo(info,exception);
6617     for (i=2; i < items; i+=2)
6618       SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6619     (void) CopyMagickString(filename,package_info->image_info->filename,
6620       MaxTextExtent);
6621     scene=0;
6622     for (next=image; next; next=next->next)
6623     {
6624       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
6625       next->scene=scene++;
6626     }
6627     SetImageInfo(package_info->image_info,(unsigned int)
6628       GetImageListLength(image),&image->exception);
6629     EXTEND(sp,(ssize_t) GetImageListLength(image));
6630     for ( ; image; image=image->next)
6631     {
6632       length=0;
6633       blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6634       if (blob != (char *) NULL)
6635         {
6636           PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6637           blob=(unsigned char *) RelinquishMagickMemory(blob);
6638         }
6639       if (package_info->image_info->adjoin)
6640         break;
6641     }
6642
6643   PerlException:
6644     if (package_info != (struct PackageInfo *) NULL)
6645       DestroyPackageInfo(package_info);
6646     InheritPerlException(exception,perl_exception);
6647     exception=DestroyExceptionInfo(exception);
6648     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6649   }
6650 \f
6651 #
6652 ###############################################################################
6653 #                                                                             #
6654 #                                                                             #
6655 #                                                                             #
6656 #   L a y e r s                                                               #
6657 #                                                                             #
6658 #                                                                             #
6659 #                                                                             #
6660 ###############################################################################
6661 #
6662 #
6663 void
6664 Layers(ref,...)
6665   Image::Magick ref=NO_INIT
6666   ALIAS:
6667     Layers                = 1
6668     layers           = 2
6669     OptimizeImageLayers   = 3
6670     optimizelayers        = 4
6671     optimizeimagelayers   = 5
6672   PPCODE:
6673   {
6674     AV
6675       *av;
6676
6677     char
6678       *attribute;
6679
6680     CompositeOperator
6681       compose;
6682
6683     ExceptionInfo
6684       *exception;
6685
6686     HV
6687       *hv;
6688
6689     Image
6690       *image,
6691       *layers;
6692
6693     MagickBooleanType
6694       dither;
6695
6696     ImageLayerMethod
6697       method;
6698
6699     register ssize_t
6700       i;
6701
6702     ssize_t
6703       option,
6704       sp;
6705
6706     struct PackageInfo
6707       *info;
6708
6709     SV
6710       *av_reference,
6711       *perl_exception,
6712       *reference,
6713       *rv,
6714       *sv;
6715
6716     PERL_UNUSED_VAR(ref);
6717     PERL_UNUSED_VAR(ix);
6718     exception=AcquireExceptionInfo();
6719     perl_exception=newSVpv("",0);
6720     sv=NULL;
6721     if (sv_isobject(ST(0)) == 0)
6722       {
6723         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6724           PackageName);
6725         goto PerlException;
6726       }
6727     reference=SvRV(ST(0));
6728     hv=SvSTASH(reference);
6729     av=newAV();
6730     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
6731     SvREFCNT_dec(av);
6732     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6733     if (image == (Image *) NULL)
6734       {
6735         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6736           PackageName);
6737         goto PerlException;
6738       }
6739     compose=image->compose;
6740     dither=MagickFalse;
6741     method=OptimizeLayer;
6742     for (i=2; i < items; i+=2)
6743     {
6744       attribute=(char *) SvPV(ST(i-1),na);
6745       switch (*attribute)
6746       {
6747         case 'C':
6748         case 'c':
6749         {
6750           if (LocaleCompare(attribute,"compose") == 0)
6751             {
6752               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
6753                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
6754               if (sp < 0)
6755                 {
6756                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6757                     SvPV(ST(i),na));
6758                   break;
6759                 }
6760               compose=(CompositeOperator) sp;
6761               break;
6762             }
6763           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6764             attribute);
6765           break;
6766         }
6767         case 'D':
6768         case 'd':
6769         {
6770           if (LocaleCompare(attribute,"dither") == 0)
6771             {
6772               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
6773                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
6774               if (sp < 0)
6775                 {
6776                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6777                     SvPV(ST(i),na));
6778                   break;
6779                 }
6780               dither=(MagickBooleanType) sp;
6781               break;
6782             }
6783           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6784             attribute);
6785           break;
6786         }
6787         case 'M':
6788         case 'm':
6789         {
6790           if (LocaleCompare(attribute,"method") == 0)
6791             {
6792               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
6793                 SvPV(ST(i),na));
6794               if (option < 0)
6795                 {
6796                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6797                     SvPV(ST(i),na));
6798                   break;
6799                 }
6800               method=(ImageLayerMethod) option;
6801               break;
6802             }
6803           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6804             attribute);
6805           break;
6806         }
6807         default:
6808         {
6809           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6810             attribute);
6811           break;
6812         }
6813       }
6814     }
6815     layers=(Image *) NULL;
6816     switch (method)
6817     {
6818       case CompareAnyLayer:
6819       case CompareClearLayer:
6820       case CompareOverlayLayer:
6821       default:
6822       {
6823         layers=CompareImageLayers(image,method,exception);
6824         break;
6825       }
6826       case MergeLayer:
6827       case FlattenLayer:
6828       case MosaicLayer:
6829       {
6830         layers=MergeImageLayers(image,method,exception);
6831         break;
6832       }
6833       case DisposeLayer:
6834       {
6835         layers=DisposeImages(image,exception);
6836         break;
6837       }
6838       case OptimizeImageLayer:
6839       {
6840         layers=OptimizeImageLayers(image,exception);
6841         break;
6842       }
6843       case OptimizePlusLayer:
6844       {
6845         layers=OptimizePlusImageLayers(image,exception);
6846         break;
6847       }
6848       case OptimizeTransLayer:
6849       {
6850         OptimizeImageTransparency(image,exception);
6851         InheritException(&(image->exception),exception);
6852         break;
6853       }
6854       case RemoveDupsLayer:
6855       {
6856         RemoveDuplicateLayers(&image,exception);
6857         InheritException(&(image->exception),exception);
6858         break;
6859       }
6860       case RemoveZeroLayer:
6861       {
6862         RemoveZeroDelayLayers(&image,exception);
6863         InheritException(&(image->exception),exception);
6864         break;
6865       }
6866       case OptimizeLayer:
6867       {
6868         QuantizeInfo
6869           *quantize_info;
6870
6871         /*
6872           General Purpose, GIF Animation Optimizer.
6873         */
6874         layers=CoalesceImages(image,exception);
6875         if (layers == (Image *) NULL)
6876           break;
6877         InheritException(&(layers->exception),exception);
6878         image=layers;
6879         layers=OptimizeImageLayers(image,exception);
6880         if (layers == (Image *) NULL)
6881           break;
6882         InheritException(&(layers->exception),exception);
6883         image=DestroyImageList(image);
6884         image=layers;
6885         layers=(Image *) NULL;
6886         OptimizeImageTransparency(image,exception);
6887         InheritException(&(image->exception),exception);
6888         quantize_info=AcquireQuantizeInfo(info->image_info);
6889         (void) RemapImages(quantize_info,image,(Image *) NULL);
6890         quantize_info=DestroyQuantizeInfo(quantize_info);
6891         break;
6892       }
6893       case CompositeLayer:
6894       {
6895         Image
6896           *source;
6897
6898         RectangleInfo
6899           geometry;
6900
6901         /*
6902           Split image sequence at the first 'NULL:' image.
6903         */
6904         source=image;
6905         while (source != (Image *) NULL)
6906         {
6907           source=GetNextImageInList(source);
6908           if ((source != (Image *) NULL) &&
6909               (LocaleCompare(source->magick,"NULL") == 0))
6910             break;
6911         }
6912         if (source != (Image *) NULL)
6913           {
6914             if ((GetPreviousImageInList(source) == (Image *) NULL) ||
6915                 (GetNextImageInList(source) == (Image *) NULL))
6916               source=(Image *) NULL;
6917             else
6918               {
6919                 /*
6920                   Separate the two lists, junk the null: image.
6921                 */
6922                 source=SplitImageList(source->previous);
6923                 DeleteImageFromList(&source);
6924               }
6925           }
6926         if (source == (Image *) NULL)
6927           {
6928             (void) ThrowMagickException(exception,GetMagickModule(),
6929               OptionError,"MissingNullSeparator","layers Composite");
6930             break;
6931           }
6932         /*
6933           Adjust offset with gravity and virtual canvas.
6934         */
6935         SetGeometry(image,&geometry);
6936         (void) ParseAbsoluteGeometry(image->geometry,&geometry);
6937         geometry.width=source->page.width != 0 ? source->page.width :
6938           source->columns;
6939         geometry.height=source->page.height != 0 ? source->page.height :
6940           source->rows;
6941         GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
6942           image->columns,image->page.height != 0 ? image->page.height :
6943           image->rows,image->gravity,&geometry);
6944         CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
6945         source=DestroyImageList(source);
6946         InheritException(&(image->exception),exception);
6947         break;
6948       }
6949     }
6950     if (layers != (Image *) NULL)
6951       {
6952         InheritException(&(layers->exception),exception);
6953         image=layers;
6954       }
6955     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
6956       goto PerlException;
6957     for ( ; image; image=image->next)
6958     {
6959       AddImageToRegistry(sv,image);
6960       rv=newRV(sv);
6961       av_push(av,sv_bless(rv,hv));
6962       SvREFCNT_dec(sv);
6963     }
6964     exception=DestroyExceptionInfo(exception);
6965     ST(0)=av_reference;
6966     SvREFCNT_dec(perl_exception);
6967     XSRETURN(1);
6968
6969   PerlException:
6970     InheritPerlException(exception,perl_exception);
6971     exception=DestroyExceptionInfo(exception);
6972     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
6973     SvPOK_on(perl_exception);
6974     ST(0)=sv_2mortal(perl_exception);
6975     XSRETURN(1);
6976   }
6977 \f
6978 #
6979 ###############################################################################
6980 #                                                                             #
6981 #                                                                             #
6982 #                                                                             #
6983 #   M a g i c k T o M i m e                                                   #
6984 #                                                                             #
6985 #                                                                             #
6986 #                                                                             #
6987 ###############################################################################
6988 #
6989 #
6990 SV *
6991 MagickToMime(ref,name)
6992   Image::Magick ref=NO_INIT
6993   char *name
6994   ALIAS:
6995     magicktomime = 1
6996   CODE:
6997   {
6998     char
6999       *mime;
7000
7001     PERL_UNUSED_VAR(ref);
7002     PERL_UNUSED_VAR(ix);
7003     mime=MagickToMime(name);
7004     RETVAL=newSVpv(mime,0);
7005     mime=(char *) RelinquishMagickMemory(mime);
7006   }
7007   OUTPUT:
7008     RETVAL
7009 \f
7010 #
7011 ###############################################################################
7012 #                                                                             #
7013 #                                                                             #
7014 #                                                                             #
7015 #   M o g r i f y                                                             #
7016 #                                                                             #
7017 #                                                                             #
7018 #                                                                             #
7019 ###############################################################################
7020 #
7021 #
7022 void
7023 Mogrify(ref,...)
7024   Image::Magick ref=NO_INIT
7025   ALIAS:
7026     Comment            =   1
7027     CommentImage       =   2
7028     Label              =   3
7029     LabelImage         =   4
7030     AddNoise           =   5
7031     AddNoiseImage      =   6
7032     Colorize           =   7
7033     ColorizeImage      =   8
7034     Border             =   9
7035     BorderImage        =  10
7036     Blur               =  11
7037     BlurImage          =  12
7038     Chop               =  13
7039     ChopImage          =  14
7040     Crop               =  15
7041     CropImage          =  16
7042     Despeckle          =  17
7043     DespeckleImage     =  18
7044     Edge               =  19
7045     EdgeImage          =  20
7046     Emboss             =  21
7047     EmbossImage        =  22
7048     Enhance            =  23
7049     EnhanceImage       =  24
7050     Flip               =  25
7051     FlipImage          =  26
7052     Flop               =  27
7053     FlopImage          =  28
7054     Frame              =  29
7055     FrameImage         =  30
7056     Implode            =  31
7057     ImplodeImage       =  32
7058     Magnify            =  33
7059     MagnifyImage       =  34
7060     MedianFilter       =  35
7061     MedianFilterImage  =  36
7062     Minify             =  37
7063     MinifyImage        =  38
7064     OilPaint           =  39
7065     OilPaintImage      =  40
7066     ReduceNoise        =  41
7067     ReduceNoiseImage   =  42
7068     Roll               =  43
7069     RollImage          =  44
7070     Rotate             =  45
7071     RotateImage        =  46
7072     Sample             =  47
7073     SampleImage        =  48
7074     Scale              =  49
7075     ScaleImage         =  50
7076     Shade              =  51
7077     ShadeImage         =  52
7078     Sharpen            =  53
7079     SharpenImage       =  54
7080     Shear              =  55
7081     ShearImage         =  56
7082     Spread             =  57
7083     SpreadImage        =  58
7084     Swirl              =  59
7085     SwirlImage         =  60
7086     Resize             =  61
7087     ResizeImage        =  62
7088     Zoom               =  63
7089     ZoomImage          =  64
7090     Annotate           =  65
7091     AnnotateImage      =  66
7092     ColorFloodfill     =  67
7093     ColorFloodfillImage=  68
7094     Composite          =  69
7095     CompositeImage     =  70
7096     Contrast           =  71
7097     ContrastImage      =  72
7098     CycleColormap      =  73
7099     CycleColormapImage =  74
7100     Draw               =  75
7101     DrawImage          =  76
7102     Equalize           =  77
7103     EqualizeImage      =  78
7104     Gamma              =  79
7105     GammaImage         =  80
7106     Map                =  81
7107     MapImage           =  82
7108     MatteFloodfill     =  83
7109     MatteFloodfillImage=  84
7110     Modulate           =  85
7111     ModulateImage      =  86
7112     Negate             =  87
7113     NegateImage        =  88
7114     Normalize          =  89
7115     NormalizeImage     =  90
7116     NumberColors       =  91
7117     NumberColorsImage  =  92
7118     Opaque             =  93
7119     OpaqueImage        =  94
7120     Quantize           =  95
7121     QuantizeImage      =  96
7122     Raise              =  97
7123     RaiseImage         =  98
7124     Segment            =  99
7125     SegmentImage       = 100
7126     Signature          = 101
7127     SignatureImage     = 102
7128     Solarize           = 103
7129     SolarizeImage      = 104
7130     Sync               = 105
7131     SyncImage          = 106
7132     Texture            = 107
7133     TextureImage       = 108
7134     Evaluate           = 109
7135     EvaluateImage      = 110
7136     Transparent        = 111
7137     TransparentImage   = 112
7138     Threshold          = 113
7139     ThresholdImage     = 114
7140     Charcoal           = 115
7141     CharcoalImage      = 116
7142     Trim               = 117
7143     TrimImage          = 118
7144     Wave               = 119
7145     WaveImage          = 120
7146     Separate           = 121
7147     SeparateImage      = 122
7148     Stereo             = 125
7149     StereoImage        = 126
7150     Stegano            = 127
7151     SteganoImage       = 128
7152     Deconstruct        = 129
7153     DeconstructImage   = 130
7154     GaussianBlur       = 131
7155     GaussianBlurImage  = 132
7156     Convolve           = 133
7157     ConvolveImage      = 134
7158     Profile            = 135
7159     ProfileImage       = 136
7160     UnsharpMask        = 137
7161     UnsharpMaskImage   = 138
7162     MotionBlur         = 139
7163     MotionBlurImage    = 140
7164     OrderedDither      = 141
7165     OrderedDitherImage = 142
7166     Shave              = 143
7167     ShaveImage         = 144
7168     Level              = 145
7169     LevelImage         = 146
7170     Clip               = 147
7171     ClipImage          = 148
7172     AffineTransform    = 149
7173     AffineTransformImage = 150
7174     Difference         = 151
7175     DifferenceImage    = 152
7176     AdaptiveThreshold  = 153
7177     AdaptiveThresholdImage = 154
7178     Resample           = 155
7179     ResampleImage      = 156
7180     Describe           = 157
7181     DescribeImage      = 158
7182     BlackThreshold     = 159
7183     BlackThresholdImage= 160
7184     WhiteThreshold     = 161
7185     WhiteThresholdImage= 162
7186     RadialBlur         = 163
7187     RadialBlurImage    = 164
7188     Thumbnail          = 165
7189     ThumbnailImage     = 166
7190     Strip              = 167
7191     StripImage         = 168
7192     Tint               = 169
7193     TintImage          = 170
7194     Channel            = 171
7195     ChannelImage       = 172
7196     Splice             = 173
7197     SpliceImage        = 174
7198     Posterize          = 175
7199     PosterizeImage     = 176
7200     Shadow             = 177
7201     ShadowImage        = 178
7202     Identify           = 179
7203     IdentifyImage      = 180
7204     SepiaTone          = 181
7205     SepiaToneImage     = 182
7206     SigmoidalContrast  = 183
7207     SigmoidalContrastImage = 184
7208     Extent             = 185
7209     ExtentImage        = 186
7210     Vignette           = 187
7211     VignetteImage      = 188
7212     ContrastStretch    = 189
7213     ContrastStretchImage = 190
7214     Sans0              = 191
7215     Sans0Image         = 192
7216     Sans1              = 193
7217     Sans1Image         = 194
7218     AdaptiveSharpen    = 195
7219     AdaptiveSharpenImage = 196
7220     Transpose          = 197
7221     TransposeImage     = 198
7222     Transverse         = 199
7223     TransverseImage    = 200
7224     AutoOrient         = 201
7225     AutoOrientImage    = 202
7226     AdaptiveBlur       = 203
7227     AdaptiveBlurImage  = 204
7228     Sketch             = 205
7229     SketchImage        = 206
7230     UniqueColors       = 207
7231     UniqueColorsImage  = 208
7232     AdaptiveResize     = 209
7233     AdaptiveResizeImage= 210
7234     ClipMask           = 211
7235     ClipMaskImage      = 212
7236     LinearStretch      = 213
7237     LinearStretchImage = 214
7238     RecolorImage       = 215
7239     Recolor            = 216
7240     Mask               = 217
7241     MaskImage          = 218
7242     Polaroid           = 219
7243     PolaroidImage      = 220
7244     FloodfillPaint     = 221
7245     FloodfillPaintImage= 222
7246     Distort            = 223
7247     DistortImage       = 224
7248     Clut               = 225
7249     ClutImage          = 226
7250     LiquidRescale      = 227
7251     LiquidRescaleImage = 228
7252     Encipher           = 229
7253     EncipherImage      = 230
7254     Decipher           = 231
7255     DecipherImage      = 232
7256     Deskew             = 233
7257     DeskewImage        = 234
7258     Remap              = 235
7259     RemapImage         = 236
7260     SparseColor        = 237
7261     SparseColorImage   = 238
7262     Function           = 239
7263     FunctionImage      = 240
7264     SelectiveBlur      = 241
7265     SelectiveBlurImage = 242
7266     HaldClut           = 243
7267     HaldClutImage      = 244
7268     BlueShift          = 245
7269     BlueShiftImage     = 246
7270     ForwardFourierTransform  = 247
7271     ForwardFourierTransformImage = 248
7272     InverseFourierTransform = 249
7273     InverseFourierTransformImage = 250
7274     ColorDecisionList  = 251
7275     ColorDecisionListImage = 252
7276     AutoGamma          = 253
7277     AutoGammaImage     = 254
7278     AutoLevel          = 255
7279     AutoLevelImage     = 256
7280     LevelColors        = 257
7281     LevelColorsImage   = 258
7282     Clamp              = 259
7283     ClampImage         = 260
7284     Filter             = 261
7285     FilterImage        = 262
7286     BrightnessContrast = 263
7287     BrightnessContrastImage = 264
7288     Morphology         = 265
7289     MorphologyImage    = 266
7290     ColorMatrix        = 267
7291     ColorMatrixImage   = 268
7292     Color              = 269
7293     ColorImage         = 270
7294     Mode               = 271
7295     ModeImage          = 272
7296     Statistic          = 273
7297     StatisticImage     = 274
7298     MogrifyRegion      = 666
7299   PPCODE:
7300   {
7301     AffineMatrix
7302       affine,
7303       current;
7304
7305     char
7306       attribute_flag[MaxArguments],
7307       message[MaxTextExtent];
7308
7309     ChannelType
7310       channel;
7311
7312     CompositeOperator
7313       compose;
7314
7315     const char
7316       *attribute,
7317       *value;
7318
7319     double
7320       angle;
7321
7322     ExceptionInfo
7323       *exception;
7324
7325     GeometryInfo
7326       geometry_info;
7327
7328     Image
7329       *image,
7330       *next,
7331       *region_image;
7332
7333     MagickBooleanType
7334       status;
7335
7336     MagickStatusType
7337       flags;
7338
7339     PixelPacket
7340       fill_color;
7341
7342     RectangleInfo
7343       geometry,
7344       region_info;
7345
7346     register ssize_t
7347       i;
7348
7349     ssize_t
7350       base,
7351       j,
7352       number_images;
7353
7354     struct Methods
7355       *rp;
7356
7357     struct PackageInfo
7358       *info;
7359
7360     SV
7361       *perl_exception,
7362       **pv,
7363       *reference,
7364       **reference_vector;
7365
7366     struct ArgumentList
7367       argument_list[MaxArguments];
7368
7369     PERL_UNUSED_VAR(ref);
7370     PERL_UNUSED_VAR(ix);
7371     exception=AcquireExceptionInfo();
7372     perl_exception=newSVpv("",0);
7373     reference_vector=NULL;
7374     region_image=NULL;
7375     number_images=0;
7376     base=2;
7377     if (sv_isobject(ST(0)) == 0)
7378       {
7379         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7380           PackageName);
7381         goto PerlException;
7382       }
7383     reference=SvRV(ST(0));
7384     region_info.width=0;
7385     region_info.height=0;
7386     region_info.x=0;
7387     region_info.y=0;
7388     region_image=(Image *) NULL;
7389     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7390     if (ix && (ix != 666))
7391       {
7392         /*
7393           Called as Method(...)
7394         */
7395         ix=(ix+1)/2;
7396         rp=(&Methods[ix-1]);
7397         attribute=rp->name;
7398       }
7399     else
7400       {
7401         /*
7402           Called as Mogrify("Method",...)
7403         */
7404         attribute=(char *) SvPV(ST(1),na);
7405         if (ix)
7406           {
7407             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7408             attribute=(char *) SvPV(ST(2),na);
7409             base++;
7410           }
7411         for (rp=Methods; ; rp++)
7412         {
7413           if (rp >= EndOf(Methods))
7414             {
7415               ThrowPerlException(exception,OptionError,
7416                 "UnrecognizedPerlMagickMethod",attribute);
7417               goto PerlException;
7418             }
7419           if (strEQcase(attribute,rp->name))
7420             break;
7421         }
7422         ix=rp-Methods+1;
7423         base++;
7424       }
7425     if (image == (Image *) NULL)
7426       {
7427         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7428         goto PerlException;
7429       }
7430     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7431     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7432     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7433     {
7434       Arguments
7435         *pp,
7436         *qq;
7437
7438       ssize_t
7439         ssize_test;
7440
7441       struct ArgumentList
7442         *al;
7443
7444       SV
7445         *sv;
7446
7447       sv=NULL;
7448       ssize_test=0;
7449       pp=(Arguments *) NULL;
7450       qq=rp->arguments;
7451       if (i == items)
7452         {
7453           pp=rp->arguments,
7454           sv=ST(i-1);
7455         }
7456       else
7457         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7458         {
7459           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7460             break;
7461           if (strEQcase(attribute,qq->method) > ssize_test)
7462             {
7463               pp=qq;
7464               ssize_test=strEQcase(attribute,qq->method);
7465             }
7466         }
7467       if (pp == (Arguments *) NULL)
7468         {
7469           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7470             attribute);
7471           goto continue_outer_loop;
7472         }
7473       al=(&argument_list[pp-rp->arguments]);
7474       switch (pp->type)
7475       {
7476         case ArrayReference:
7477         {
7478           if (SvTYPE(sv) != SVt_RV)
7479             {
7480               (void) FormatMagickString(message,MaxTextExtent,
7481                 "invalid %.60s value",pp->method);
7482               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7483               goto continue_outer_loop;
7484             }
7485           al->array_reference=SvRV(sv);
7486           break;
7487         }
7488         case RealReference:
7489         {
7490           al->real_reference=SvNV(sv);
7491           break;
7492         }
7493         case FileReference:
7494         {
7495           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7496           break;
7497         }
7498         case ImageReference:
7499         {
7500           if (!sv_isobject(sv) ||
7501               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7502                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7503             {
7504               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7505                 PackageName);
7506               goto PerlException;
7507             }
7508           break;
7509         }
7510         case IntegerReference:
7511         {
7512           al->integer_reference=SvIV(sv);
7513           break;
7514         }
7515         case StringReference:
7516         {
7517           al->string_reference=(char *) SvPV(sv,al->length);
7518           if (sv_isobject(sv))
7519             al->image_reference=SetupList(aTHX_ SvRV(sv),
7520               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7521           break;
7522         }
7523         default:
7524         {
7525           /*
7526             Is a string; look up name.
7527           */
7528           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7529             {
7530               al->string_reference=(char *) SvPV(sv,al->length);
7531               al->integer_reference=(-1);
7532               break;
7533             }
7534           al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7535             MagickFalse,SvPV(sv,na));
7536           if (pp->type == MagickChannelOptions)
7537             al->integer_reference=ParseChannelOption(SvPV(sv,na));
7538           if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7539             {
7540               (void) FormatMagickString(message,MaxTextExtent,
7541                 "invalid %.60s value",pp->method);
7542               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7543               goto continue_outer_loop;
7544             }
7545           break;
7546         }
7547       }
7548       attribute_flag[pp-rp->arguments]++;
7549       continue_outer_loop: ;
7550     }
7551     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7552     pv=reference_vector;
7553     SetGeometryInfo(&geometry_info);
7554     channel=DefaultChannels;
7555     for (next=image; next; next=next->next)
7556     {
7557       image=next;
7558       SetGeometry(image,&geometry);
7559       if ((region_info.width*region_info.height) != 0)
7560         {
7561           region_image=image;
7562           image=CropImage(image,&region_info,exception);
7563         }
7564       switch (ix)
7565       {
7566         default:
7567         {
7568           (void) FormatMagickString(message,MaxTextExtent,"%.20g",(double) ix);
7569           ThrowPerlException(exception,OptionError,
7570             "UnrecognizedPerlMagickMethod",message);
7571           goto PerlException;
7572         }
7573         case 1:  /* Comment */
7574         {
7575           if (attribute_flag[0] == 0)
7576             argument_list[0].string_reference=(char *) NULL;
7577           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7578             info ? info->image_info : (ImageInfo *) NULL,image,
7579             argument_list[0].string_reference));
7580           break;
7581         }
7582         case 2:  /* Label */
7583         {
7584           if (attribute_flag[0] == 0)
7585             argument_list[0].string_reference=(char *) NULL;
7586           (void) SetImageProperty(image,"label",InterpretImageProperties(
7587             info ? info->image_info : (ImageInfo *) NULL,image,
7588             argument_list[0].string_reference));
7589           break;
7590         }
7591         case 3:  /* AddNoise */
7592         {
7593           if (attribute_flag[0] == 0)
7594             argument_list[0].integer_reference=UniformNoise;
7595           if (attribute_flag[1] != 0)
7596             channel=(ChannelType) argument_list[1].integer_reference;
7597           image=AddNoiseImageChannel(image,channel,(NoiseType)
7598             argument_list[0].integer_reference,exception);
7599           break;
7600         }
7601         case 4:  /* Colorize */
7602         {
7603           PixelPacket
7604             target;
7605
7606           (void) GetOneVirtualPixel(image,0,0,&target,exception);
7607           if (attribute_flag[0] != 0)
7608             (void) QueryColorDatabase(argument_list[0].string_reference,&target,
7609               exception);
7610           if (attribute_flag[1] == 0)
7611             argument_list[1].string_reference="100%";
7612           image=ColorizeImage(image,argument_list[1].string_reference,target,
7613             exception);
7614           break;
7615         }
7616         case 5:  /* Border */
7617         {
7618           geometry.width=0;
7619           geometry.height=0;
7620           if (attribute_flag[0] != 0)
7621             {
7622               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7623                 &geometry,exception);
7624               if ((flags & HeightValue) == 0)
7625                 geometry.height=geometry.width;
7626             }
7627           if (attribute_flag[1] != 0)
7628             geometry.width=argument_list[1].integer_reference;
7629           if (attribute_flag[2] != 0)
7630             geometry.height=argument_list[2].integer_reference;
7631           if (attribute_flag[3] != 0)
7632             QueryColorDatabase(argument_list[3].string_reference,
7633               &image->border_color,exception);
7634           if (attribute_flag[4] != 0)
7635             QueryColorDatabase(argument_list[4].string_reference,
7636               &image->border_color,exception);
7637           if (attribute_flag[5] != 0)
7638             QueryColorDatabase(argument_list[5].string_reference,
7639               &image->border_color,exception);
7640           if (attribute_flag[6] != 0)
7641             image->compose=(CompositeOperator) argument_list[6].integer_reference;
7642           image=BorderImage(image,&geometry,exception);
7643           break;
7644         }
7645         case 6:  /* Blur */
7646         {
7647           if (attribute_flag[0] != 0)
7648             {
7649               flags=ParseGeometry(argument_list[0].string_reference,
7650                 &geometry_info);
7651               if ((flags & SigmaValue) == 0)
7652                 geometry_info.sigma=1.0;
7653             }
7654           if (attribute_flag[1] != 0)
7655             geometry_info.rho=argument_list[1].real_reference;
7656           if (attribute_flag[2] != 0)
7657             geometry_info.sigma=argument_list[2].real_reference;
7658           if (attribute_flag[3] != 0)
7659             channel=(ChannelType) argument_list[3].integer_reference;
7660           image=BlurImageChannel(image,channel,geometry_info.rho,
7661             geometry_info.sigma,exception);
7662           break;
7663         }
7664         case 7:  /* Chop */
7665         {
7666           if (attribute_flag[0] != 0)
7667             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7668               &geometry,exception);
7669           if (attribute_flag[1] != 0)
7670             geometry.width=argument_list[1].integer_reference;
7671           if (attribute_flag[2] != 0)
7672             geometry.height=argument_list[2].integer_reference;
7673           if (attribute_flag[3] != 0)
7674             geometry.x=argument_list[3].integer_reference;
7675           if (attribute_flag[4] != 0)
7676             geometry.y=argument_list[4].integer_reference;
7677           image=ChopImage(image,&geometry,exception);
7678           break;
7679         }
7680         case 8:  /* Crop */
7681         {
7682           if (attribute_flag[6] != 0)
7683             image->gravity=(GravityType) argument_list[6].integer_reference;
7684           if (attribute_flag[0] != 0)
7685             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7686               &geometry,exception);
7687           if (attribute_flag[1] != 0)
7688             geometry.width=argument_list[1].integer_reference;
7689           if (attribute_flag[2] != 0)
7690             geometry.height=argument_list[2].integer_reference;
7691           if (attribute_flag[3] != 0)
7692             geometry.x=argument_list[3].integer_reference;
7693           if (attribute_flag[4] != 0)
7694             geometry.y=argument_list[4].integer_reference;
7695           if (attribute_flag[5] != 0)
7696             image->fuzz=
7697               SiPrefixToDouble(argument_list[5].string_reference,QuantumRange);
7698           image=CropImage(image,&geometry,exception);
7699           break;
7700         }
7701         case 9:  /* Despeckle */
7702         {
7703           image=DespeckleImage(image,exception);
7704           break;
7705         }
7706         case 10:  /* Edge */
7707         {
7708           if (attribute_flag[0] != 0)
7709             geometry_info.rho=argument_list[0].real_reference;
7710           image=EdgeImage(image,geometry_info.rho,exception);
7711           break;
7712         }
7713         case 11:  /* Emboss */
7714         {
7715           if (attribute_flag[0] != 0)
7716             {
7717               flags=ParseGeometry(argument_list[0].string_reference,
7718                 &geometry_info);
7719               if ((flags & SigmaValue) == 0)
7720                 geometry_info.sigma=1.0;
7721             }
7722           if (attribute_flag[1] != 0)
7723             geometry_info.rho=argument_list[1].real_reference;
7724           if (attribute_flag[2] != 0)
7725             geometry_info.sigma=argument_list[2].real_reference;
7726           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
7727             exception);
7728           break;
7729         }
7730         case 12:  /* Enhance */
7731         {
7732           image=EnhanceImage(image,exception);
7733           break;
7734         }
7735         case 13:  /* Flip */
7736         {
7737           image=FlipImage(image,exception);
7738           break;
7739         }
7740         case 14:  /* Flop */
7741         {
7742           image=FlopImage(image,exception);
7743           break;
7744         }
7745         case 15:  /* Frame */
7746         {
7747           FrameInfo
7748             frame_info;
7749
7750           if (attribute_flag[0] != 0)
7751             {
7752               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7753                 &geometry,exception);
7754               if ((flags & HeightValue) == 0)
7755                 geometry.height=geometry.width;
7756               frame_info.width=geometry.width;
7757               frame_info.height=geometry.height;
7758               frame_info.outer_bevel=geometry.x;
7759               frame_info.inner_bevel=geometry.y;
7760             }
7761           if (attribute_flag[1] != 0)
7762             frame_info.width=argument_list[1].integer_reference;
7763           if (attribute_flag[2] != 0)
7764             frame_info.height=argument_list[2].integer_reference;
7765           if (attribute_flag[3] != 0)
7766             frame_info.inner_bevel=argument_list[3].integer_reference;
7767           if (attribute_flag[4] != 0)
7768             frame_info.outer_bevel=argument_list[4].integer_reference;
7769           if (attribute_flag[5] != 0)
7770             QueryColorDatabase(argument_list[5].string_reference,&fill_color,
7771               exception);
7772           if (attribute_flag[6] != 0)
7773             QueryColorDatabase(argument_list[6].string_reference,&fill_color,
7774               exception);
7775           frame_info.x=(ssize_t) frame_info.width;
7776           frame_info.y=(ssize_t) frame_info.height;
7777           frame_info.width=image->columns+2*frame_info.x;
7778           frame_info.height=image->rows+2*frame_info.y;
7779           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
7780             image->matte_color=fill_color;
7781           if (attribute_flag[7] != 0)
7782             image->compose=(CompositeOperator) argument_list[7].integer_reference;
7783           image=FrameImage(image,&frame_info,exception);
7784           break;
7785         }
7786         case 16:  /* Implode */
7787         {
7788           if (attribute_flag[0] == 0)
7789             argument_list[0].real_reference=0.5;
7790           if (attribute_flag[1] != 0)
7791             image->interpolate=(InterpolatePixelMethod)
7792               argument_list[1].integer_reference;
7793           image=ImplodeImage(image,argument_list[0].real_reference,
7794             exception);
7795           break;
7796         }
7797         case 17:  /* Magnify */
7798         {
7799           image=MagnifyImage(image,exception);
7800           break;
7801         }
7802         case 18:  /* MedianFilter */
7803         {
7804           if (attribute_flag[0] != 0)
7805             {
7806               flags=ParseGeometry(argument_list[0].string_reference,
7807                 &geometry_info);
7808               if ((flags & SigmaValue) == 0)
7809                 geometry_info.sigma=1.0;
7810             }
7811           if (attribute_flag[1] != 0)
7812             geometry_info.rho=argument_list[1].real_reference;
7813           if (attribute_flag[2] != 0)
7814             geometry_info.sigma=argument_list[2].real_reference;
7815           if (attribute_flag[3] != 0)
7816             channel=(ChannelType) argument_list[3].integer_reference;
7817           image=StatisticImageChannel(image,channel,MedianStatistic,
7818             (size_t) geometry_info.rho,(size_t) geometry_info.sigma,exception);
7819           break;
7820         }
7821         case 19:  /* Minify */
7822         {
7823           image=MinifyImage(image,exception);
7824           break;
7825         }
7826         case 20:  /* OilPaint */
7827         {
7828           if (attribute_flag[0] == 0)
7829             argument_list[0].real_reference=0.0;
7830           image=OilPaintImage(image,argument_list[0].real_reference,
7831             exception);
7832           break;
7833         }
7834         case 21:  /* ReduceNoise */
7835         {
7836           if (attribute_flag[0] != 0)
7837             {
7838               flags=ParseGeometry(argument_list[0].string_reference,
7839                 &geometry_info);
7840               if ((flags & SigmaValue) == 0)
7841                 geometry_info.sigma=1.0;
7842             }
7843           if (attribute_flag[1] != 0)
7844             geometry_info.rho=argument_list[1].real_reference;
7845           if (attribute_flag[2] != 0)
7846             geometry_info.sigma=argument_list[2].real_reference;
7847           if (attribute_flag[3] != 0)
7848             channel=(ChannelType) argument_list[3].integer_reference;
7849           image=StatisticImageChannel(image,channel,NonpeakStatistic,
7850             (size_t) geometry_info.rho,(size_t) geometry_info.sigma,exception);
7851           break;
7852         }
7853         case 22:  /* Roll */
7854         {
7855           if (attribute_flag[0] != 0)
7856             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7857               &geometry,exception);
7858           if (attribute_flag[1] != 0)
7859             geometry.x=argument_list[1].integer_reference;
7860           if (attribute_flag[2] != 0)
7861             geometry.y=argument_list[2].integer_reference;
7862           image=RollImage(image,geometry.x,geometry.y,exception);
7863           break;
7864         }
7865         case 23:  /* Rotate */
7866         {
7867           if (attribute_flag[0] == 0)
7868             argument_list[0].real_reference=90.0;
7869           if (attribute_flag[1] != 0)
7870             QueryColorDatabase(argument_list[1].string_reference,
7871               &image->background_color,exception);
7872           if (attribute_flag[2] != 0)
7873             QueryColorDatabase(argument_list[2].string_reference,
7874               &image->background_color,exception);
7875           if (attribute_flag[3] != 0)
7876             QueryColorDatabase(argument_list[3].string_reference,
7877               &image->background_color,exception);
7878           image=RotateImage(image,argument_list[0].real_reference,exception);
7879           break;
7880         }
7881         case 24:  /* Sample */
7882         {
7883           if (attribute_flag[0] != 0)
7884             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7885               &geometry,exception);
7886           if (attribute_flag[1] != 0)
7887             geometry.width=argument_list[1].integer_reference;
7888           if (attribute_flag[2] != 0)
7889             geometry.height=argument_list[2].integer_reference;
7890           image=SampleImage(image,geometry.width,geometry.height,exception);
7891           break;
7892         }
7893         case 25:  /* Scale */
7894         {
7895           if (attribute_flag[0] != 0)
7896             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7897               &geometry,exception);
7898           if (attribute_flag[1] != 0)
7899             geometry.width=argument_list[1].integer_reference;
7900           if (attribute_flag[2] != 0)
7901             geometry.height=argument_list[2].integer_reference;
7902           image=ScaleImage(image,geometry.width,geometry.height,exception);
7903           break;
7904         }
7905         case 26:  /* Shade */
7906         {
7907           if (attribute_flag[0] != 0)
7908             {
7909               flags=ParseGeometry(argument_list[0].string_reference,
7910                 &geometry_info);
7911               if ((flags & SigmaValue) == 0)
7912                 geometry_info.sigma=0.0;
7913             }
7914           if (attribute_flag[1] != 0)
7915             geometry_info.rho=argument_list[1].real_reference;
7916           if (attribute_flag[2] != 0)
7917             geometry_info.sigma=argument_list[2].real_reference;
7918           image=ShadeImage(image,
7919             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
7920             geometry_info.rho,geometry_info.sigma,exception);
7921           break;
7922         }
7923         case 27:  /* Sharpen */
7924         {
7925           if (attribute_flag[0] != 0)
7926             {
7927               flags=ParseGeometry(argument_list[0].string_reference,
7928                 &geometry_info);
7929               if ((flags & SigmaValue) == 0)
7930                 geometry_info.sigma=1.0;
7931             }
7932           if (attribute_flag[1] != 0)
7933             geometry_info.rho=argument_list[1].real_reference;
7934           if (attribute_flag[2] != 0)
7935             geometry_info.sigma=argument_list[2].real_reference;
7936           if (attribute_flag[3] != 0)
7937             channel=(ChannelType) argument_list[3].integer_reference;
7938           image=SharpenImageChannel(image,channel,geometry_info.rho,
7939             geometry_info.sigma,exception);
7940           break;
7941         }
7942         case 28:  /* Shear */
7943         {
7944           if (attribute_flag[0] != 0)
7945             {
7946               flags=ParseGeometry(argument_list[0].string_reference,
7947                 &geometry_info);
7948               if ((flags & SigmaValue) == 0)
7949                 geometry_info.sigma=geometry_info.rho;
7950             }
7951           if (attribute_flag[1] != 0)
7952             geometry_info.rho=argument_list[1].real_reference;
7953           if (attribute_flag[2] != 0)
7954             geometry_info.sigma=argument_list[2].real_reference;
7955           if (attribute_flag[3] != 0)
7956             QueryColorDatabase(argument_list[3].string_reference,
7957               &image->background_color,exception);
7958           if (attribute_flag[4] != 0)
7959             QueryColorDatabase(argument_list[4].string_reference,
7960               &image->background_color,exception);
7961           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
7962             exception);
7963           break;
7964         }
7965         case 29:  /* Spread */
7966         {
7967           if (attribute_flag[0] == 0)
7968             argument_list[0].real_reference=1.0;
7969           image=SpreadImage(image,argument_list[0].real_reference,exception);
7970           break;
7971         }
7972         case 30:  /* Swirl */
7973         {
7974           if (attribute_flag[0] == 0)
7975             argument_list[0].real_reference=50.0;
7976           if (attribute_flag[1] != 0)
7977             image->interpolate=(InterpolatePixelMethod)
7978               argument_list[1].integer_reference;
7979           image=SwirlImage(image,argument_list[0].real_reference,exception);
7980           break;
7981         }
7982         case 31:  /* Resize */
7983         case 32:  /* Zoom */
7984         {
7985           if (attribute_flag[0] != 0)
7986             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7987               &geometry,exception);
7988           if (attribute_flag[1] != 0)
7989             geometry.width=argument_list[1].integer_reference;
7990           if (attribute_flag[2] != 0)
7991             geometry.height=argument_list[2].integer_reference;
7992           if (attribute_flag[3] == 0)
7993             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
7994           if (attribute_flag[4] != 0)
7995             SetImageArtifact(image,"filter:support",
7996               argument_list[4].string_reference);
7997           if (attribute_flag[5] == 0)
7998             argument_list[5].real_reference=1.0;
7999           image=ResizeImage(image,geometry.width,geometry.height,
8000             (FilterTypes) argument_list[3].integer_reference,
8001             argument_list[5].real_reference,exception);
8002           break;
8003         }
8004         case 33:  /* Annotate */
8005         {
8006           DrawInfo
8007             *draw_info;
8008
8009           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8010             (DrawInfo *) NULL);
8011           if (attribute_flag[0] != 0)
8012             {
8013               char
8014                 *text;
8015
8016               text=InterpretImageProperties(info ? info->image_info :
8017                 (ImageInfo *) NULL,image,argument_list[0].string_reference);
8018               (void) CloneString(&draw_info->text,text);
8019               text=DestroyString(text);
8020             }
8021           if (attribute_flag[1] != 0)
8022             (void) CloneString(&draw_info->font,
8023               argument_list[1].string_reference);
8024           if (attribute_flag[2] != 0)
8025             draw_info->pointsize=argument_list[2].real_reference;
8026           if (attribute_flag[3] != 0)
8027             (void) CloneString(&draw_info->density,
8028               argument_list[3].string_reference);
8029           if (attribute_flag[4] != 0)
8030             (void) QueryColorDatabase(argument_list[4].string_reference,
8031               &draw_info->undercolor,exception);
8032           if (attribute_flag[5] != 0)
8033             {
8034               (void) QueryColorDatabase(argument_list[5].string_reference,
8035                 &draw_info->stroke,exception);
8036               if (argument_list[5].image_reference != (Image *) NULL)
8037                 draw_info->stroke_pattern=CloneImage(
8038                   argument_list[5].image_reference,0,0,MagickTrue,exception);
8039             }
8040           if (attribute_flag[6] != 0)
8041             {
8042               (void) QueryColorDatabase(argument_list[6].string_reference,
8043                 &draw_info->fill,exception);
8044               if (argument_list[6].image_reference != (Image *) NULL)
8045                 draw_info->fill_pattern=CloneImage(
8046                   argument_list[6].image_reference,0,0,MagickTrue,exception);
8047             }
8048           if (attribute_flag[7] != 0)
8049             {
8050               (void) CloneString(&draw_info->geometry,
8051                 argument_list[7].string_reference);
8052               flags=ParsePageGeometry(image,argument_list[7].string_reference,
8053                 &geometry,exception);
8054               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8055                 geometry_info.sigma=geometry_info.xi;
8056             }
8057           if (attribute_flag[8] != 0)
8058             (void) QueryColorDatabase(argument_list[8].string_reference,
8059               &draw_info->fill,exception);
8060           if (attribute_flag[11] != 0)
8061             draw_info->gravity=(GravityType) argument_list[11].integer_reference;
8062           if (attribute_flag[25] != 0)
8063             {
8064               AV
8065                 *av;
8066
8067               av=(AV *) argument_list[25].array_reference;
8068               if ((av_len(av) != 3) && (av_len(av) != 5))
8069                 {
8070                   ThrowPerlException(exception,OptionError,
8071                     "affine matrix must have 4 or 6 elements",PackageName);
8072                   goto PerlException;
8073                 }
8074               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8075               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8076               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8077               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8078               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8079                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8080                 {
8081                   ThrowPerlException(exception,OptionError,
8082                     "affine matrix is singular",PackageName);
8083                    goto PerlException;
8084                 }
8085               if (av_len(av) == 5)
8086                 {
8087                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8088                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8089                 }
8090             }
8091           for (j=12; j < 17; j++)
8092           {
8093             if (attribute_flag[j] == 0)
8094               continue;
8095             value=argument_list[j].string_reference;
8096             angle=argument_list[j].real_reference;
8097             current=draw_info->affine;
8098             GetAffineMatrix(&affine);
8099             switch (j)
8100             {
8101               case 12:
8102               {
8103                 /*
8104                   Translate.
8105                 */
8106                 flags=ParseGeometry(value,&geometry_info);
8107                 affine.tx=geometry_info.xi;
8108                 affine.ty=geometry_info.psi;
8109                 if ((flags & PsiValue) == 0)
8110                   affine.ty=affine.tx;
8111                 break;
8112               }
8113               case 13:
8114               {
8115                 /*
8116                   Scale.
8117                 */
8118                 flags=ParseGeometry(value,&geometry_info);
8119                 affine.sx=geometry_info.rho;
8120                 affine.sy=geometry_info.sigma;
8121                 if ((flags & SigmaValue) == 0)
8122                   affine.sy=affine.sx;
8123                 break;
8124               }
8125               case 14:
8126               {
8127                 /*
8128                   Rotate.
8129                 */
8130                 if (angle == 0.0)
8131                   break;
8132                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8133                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8134                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8135                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8136                 break;
8137               }
8138               case 15:
8139               {
8140                 /*
8141                   SkewX.
8142                 */
8143                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8144                 break;
8145               }
8146               case 16:
8147               {
8148                 /*
8149                   SkewY.
8150                 */
8151                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8152                 break;
8153               }
8154             }
8155             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8156             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8157             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8158             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8159             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8160               current.tx;
8161             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8162               current.ty;
8163           }
8164           if (attribute_flag[9] == 0)
8165             argument_list[9].real_reference=0.0;
8166           if (attribute_flag[10] == 0)
8167             argument_list[10].real_reference=0.0;
8168           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8169             {
8170               char
8171                 geometry[MaxTextExtent];
8172
8173               (void) FormatMagickString(geometry,MaxTextExtent,"%+f%+f",
8174                 (double) argument_list[9].real_reference+draw_info->affine.tx,
8175                 (double) argument_list[10].real_reference+draw_info->affine.ty);
8176               (void) CloneString(&draw_info->geometry,geometry);
8177             }
8178           if (attribute_flag[17] != 0)
8179             draw_info->stroke_width=argument_list[17].real_reference;
8180           if (attribute_flag[18] != 0)
8181             {
8182               draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8183                 MagickTrue : MagickFalse;
8184               draw_info->stroke_antialias=draw_info->text_antialias;
8185             }
8186           if (attribute_flag[19] != 0)
8187             (void) CloneString(&draw_info->family,
8188               argument_list[19].string_reference);
8189           if (attribute_flag[20] != 0)
8190             draw_info->style=(StyleType) argument_list[20].integer_reference;
8191           if (attribute_flag[21] != 0)
8192             draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8193           if (attribute_flag[22] != 0)
8194             draw_info->weight=argument_list[22].integer_reference;
8195           if (attribute_flag[23] != 0)
8196             draw_info->align=(AlignType) argument_list[23].integer_reference;
8197           if (attribute_flag[24] != 0)
8198             (void) CloneString(&draw_info->encoding,
8199               argument_list[24].string_reference);
8200           if (attribute_flag[25] != 0)
8201             draw_info->fill_pattern=CloneImage(
8202               argument_list[25].image_reference,0,0,MagickTrue,exception);
8203           if (attribute_flag[26] != 0)
8204             draw_info->fill_pattern=CloneImage(
8205               argument_list[26].image_reference,0,0,MagickTrue,exception);
8206           if (attribute_flag[27] != 0)
8207             draw_info->stroke_pattern=CloneImage(
8208               argument_list[27].image_reference,0,0,MagickTrue,exception);
8209           if (attribute_flag[29] != 0)
8210             draw_info->kerning=argument_list[29].real_reference;
8211           if (attribute_flag[30] != 0)
8212             draw_info->interline_spacing=argument_list[30].real_reference;
8213           if (attribute_flag[31] != 0)
8214             draw_info->interword_spacing=argument_list[31].real_reference;
8215           if (attribute_flag[32] != 0)
8216             draw_info->direction=(DirectionType)
8217               argument_list[32].integer_reference;
8218           (void) AnnotateImage(image,draw_info);
8219           draw_info=DestroyDrawInfo(draw_info);
8220           break;
8221         }
8222         case 34:  /* ColorFloodfill */
8223         {
8224           DrawInfo
8225             *draw_info;
8226
8227           MagickBooleanType
8228             invert;
8229
8230           MagickPixelPacket
8231             target;
8232
8233           draw_info=CloneDrawInfo(info ? info->image_info :
8234             (ImageInfo *) NULL,(DrawInfo *) NULL);
8235           if (attribute_flag[0] != 0)
8236             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8237               &geometry,exception);
8238           if (attribute_flag[1] != 0)
8239             geometry.x=argument_list[1].integer_reference;
8240           if (attribute_flag[2] != 0)
8241             geometry.y=argument_list[2].integer_reference;
8242           if (attribute_flag[3] != 0)
8243             (void) QueryColorDatabase(argument_list[3].string_reference,
8244               &draw_info->fill,exception);
8245           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
8246             exception);
8247           invert=MagickFalse;
8248           if (attribute_flag[4] != 0)
8249             {
8250               QueryMagickColor(argument_list[4].string_reference,&target,
8251                 exception);
8252               invert=MagickTrue;
8253             }
8254           if (attribute_flag[5] != 0)
8255             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
8256               QuantumRange);
8257           if (attribute_flag[6] != 0)
8258             invert=(MagickBooleanType) argument_list[6].integer_reference;
8259           (void) FloodfillPaintImage(image,DefaultChannels,draw_info,&target,
8260             geometry.x,geometry.y,invert);
8261           draw_info=DestroyDrawInfo(draw_info);
8262           break;
8263         }
8264         case 35:  /* Composite */
8265         {
8266           char
8267             composite_geometry[MaxTextExtent];
8268
8269           Image
8270             *composite_image,
8271             *rotate_image;
8272
8273           compose=OverCompositeOp;
8274           if (attribute_flag[0] != 0)
8275             composite_image=argument_list[0].image_reference;
8276           else
8277             {
8278               ThrowPerlException(exception,OptionError,
8279                 "CompositeImageRequired",PackageName);
8280               goto PerlException;
8281             }
8282           /*
8283             Parameter Handling used for BOTH normal and tiled composition.
8284           */
8285           if (attribute_flag[1] != 0) /* compose */
8286             compose=(CompositeOperator) argument_list[1].integer_reference;
8287           if (attribute_flag[6] != 0) /* opacity  */
8288             {
8289               if (compose != DissolveCompositeOp)
8290                 (void) SetImageOpacity(composite_image,(Quantum) (QuantumRange-
8291                   SiPrefixToDouble(argument_list[6].string_reference,
8292                   QuantumRange)));
8293               else
8294                 {
8295                   CacheView
8296                     *composite_view;
8297
8298                   double
8299                     opacity;
8300
8301                   MagickBooleanType
8302                     sync;
8303
8304                   register ssize_t
8305                     x;
8306
8307                   register PixelPacket
8308                     *q;
8309
8310                   ssize_t
8311                     y;
8312
8313                   /*
8314                     Handle dissolve composite operator (patch by
8315                     Kevin A. McGrail).
8316                   */
8317                   (void) CloneString(&image->geometry,
8318                     argument_list[6].string_reference);
8319                   opacity=(Quantum) (QuantumRange-SiPrefixToDouble(
8320                     argument_list[6].string_reference,QuantumRange));
8321                   if (composite_image->matte != MagickTrue)
8322                     (void) SetImageOpacity(composite_image,OpaqueOpacity);
8323                   composite_view=AcquireCacheView(composite_image);
8324                   for (y=0; y < (ssize_t) composite_image->rows ; y++)
8325                   {
8326                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8327                       composite_image->columns,1,exception);
8328                     for (x=0; x < (ssize_t) composite_image->columns; x++)
8329                     {
8330                       if (q->opacity == OpaqueOpacity)
8331                         q->opacity=ClampToQuantum(opacity);
8332                       q++;
8333                     }
8334                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8335                     if (sync == MagickFalse)
8336                       break;
8337                   }
8338                   composite_view=DestroyCacheView(composite_view);
8339                 }
8340             }
8341           if (attribute_flag[9] != 0)    /* "color=>" */
8342             QueryColorDatabase(argument_list[9].string_reference,
8343               &composite_image->background_color,exception);
8344           if (attribute_flag[12] != 0) /* "interpolate=>" */
8345             image->interpolate=(InterpolatePixelMethod)
8346               argument_list[12].integer_reference;
8347           if (attribute_flag[13] != 0)   /* "args=>" */
8348             (void) SetImageArtifact(composite_image,"compose:args",
8349               argument_list[13].string_reference);
8350           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8351             (void) SetImageArtifact(composite_image,"compose:args",
8352               argument_list[14].string_reference);
8353           /*
8354             Tiling Composition (with orthogonal rotate).
8355           */
8356           rotate_image=(Image *) NULL;
8357           if (attribute_flag[8] != 0)   /* "rotate=>" */
8358             {
8359                /*
8360                  Rotate image.
8361                */
8362                rotate_image=RotateImage(composite_image,
8363                  argument_list[8].real_reference,exception);
8364                if (rotate_image == (Image *) NULL)
8365                  break;
8366             }
8367           if (attribute_flag[7] && argument_list[7].integer_reference) /* tile */
8368             {
8369               ssize_t
8370                 x,
8371                 y;
8372
8373               /*
8374                 Tile the composite image.
8375               */
8376              if (attribute_flag[8] != 0)   /* "tile=>" */
8377                (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8378                  "false");
8379              else
8380                (void) SetImageArtifact(composite_image,
8381                  "compose:outside-overlay","false");
8382              for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8383                 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8384                 {
8385                   if (attribute_flag[8] != 0) /* rotate */
8386                     (void) CompositeImage(image,compose,rotate_image,x,y);
8387                   else
8388                     (void) CompositeImage(image,compose,composite_image,x,y);
8389                 }
8390               if (attribute_flag[8] != 0) /* rotate */
8391                 rotate_image=DestroyImage(rotate_image);
8392               break;
8393             }
8394           /*
8395             Parameter Handling used used ONLY for normal composition.
8396           */
8397           if (attribute_flag[5] != 0) /* gravity */
8398             image->gravity=(GravityType) argument_list[5].integer_reference;
8399           if (attribute_flag[2] != 0) /* geometry offset */
8400             {
8401               SetGeometry(image,&geometry);
8402               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8403                 &geometry);
8404               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8405                 &geometry);
8406             }
8407           if (attribute_flag[3] != 0) /* x offset */
8408             geometry.x=argument_list[3].integer_reference;
8409           if (attribute_flag[4] != 0) /* y offset */
8410             geometry.y=argument_list[4].integer_reference;
8411           if (attribute_flag[10] != 0) /* mask */
8412             {
8413               if ((image->compose == DisplaceCompositeOp) ||
8414                   (image->compose == DistortCompositeOp))
8415                 {
8416                   /*
8417                     Merge Y displacement into X displacement image.
8418                   */
8419                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8420                     &image->exception);
8421                   (void) CompositeImage(composite_image,CopyGreenCompositeOp,
8422                     argument_list[10].image_reference,0,0);
8423                 }
8424               else
8425                 {
8426                   /*
8427                     Set a blending mask for the composition.
8428                   */
8429                   image->mask=CloneImage(argument_list[10].image_reference,0,0,
8430                     MagickTrue,&image->exception);
8431                   (void) NegateImage(image->mask,MagickFalse);
8432                 }
8433             }
8434           if (attribute_flag[11] != 0) /* channel */
8435             channel=(ChannelType) argument_list[11].integer_reference;
8436           /*
8437             Composite two images (normal composition).
8438           */
8439           (void) FormatMagickString(composite_geometry,MaxTextExtent,
8440             "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8441             (double) composite_image->rows,(double) geometry.x,(double)
8442             geometry.y);
8443           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8444             exception);
8445           if (attribute_flag[8] == 0) /* no rotate */
8446             CompositeImageChannel(image,channel,compose,composite_image,
8447               geometry.x,geometry.y);
8448           else
8449             {
8450               /*
8451                 Position adjust rotated image then composite.
8452               */
8453               geometry.x-=(ssize_t) (rotate_image->columns-
8454                 composite_image->columns)/2;
8455               geometry.y-=(ssize_t) (rotate_image->rows-
8456                 composite_image->rows)/2;
8457               CompositeImageChannel(image,channel,compose,rotate_image,
8458                 geometry.x,geometry.y);
8459               rotate_image=DestroyImage(rotate_image);
8460             }
8461           if (attribute_flag[10] != 0) /* mask */
8462             {
8463               if ((image->compose == DisplaceCompositeOp) ||
8464                   (image->compose == DistortCompositeOp))
8465                 composite_image=DestroyImage(composite_image);
8466               else
8467                 image->mask=DestroyImage(image->mask);
8468             }
8469           break;
8470         }
8471         case 36:  /* Contrast */
8472         {
8473           if (attribute_flag[0] == 0)
8474             argument_list[0].integer_reference=0;
8475           (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8476             MagickTrue : MagickFalse);
8477           break;
8478         }
8479         case 37:  /* CycleColormap */
8480         {
8481           if (attribute_flag[0] == 0)
8482             argument_list[0].integer_reference=6;
8483           (void) CycleColormapImage(image,argument_list[0].integer_reference);
8484           break;
8485         }
8486         case 38:  /* Draw */
8487         {
8488           DrawInfo
8489             *draw_info;
8490
8491           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8492             (DrawInfo *) NULL);
8493           (void) CloneString(&draw_info->primitive,"point");
8494           if (attribute_flag[0] != 0)
8495             {
8496               if (argument_list[0].integer_reference < 0)
8497                 (void) CloneString(&draw_info->primitive,
8498                   argument_list[0].string_reference);
8499               else
8500                 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8501                   MagickPrimitiveOptions,argument_list[0].integer_reference));
8502             }
8503           if (attribute_flag[1] != 0)
8504             {
8505               if (LocaleCompare(draw_info->primitive,"path") == 0)
8506                 {
8507                   (void) ConcatenateString(&draw_info->primitive," '");
8508                   ConcatenateString(&draw_info->primitive,
8509                     argument_list[1].string_reference);
8510                   (void) ConcatenateString(&draw_info->primitive,"'");
8511                 }
8512               else
8513                 {
8514                   (void) ConcatenateString(&draw_info->primitive," ");
8515                   ConcatenateString(&draw_info->primitive,
8516                     argument_list[1].string_reference);
8517                 }
8518             }
8519           if (attribute_flag[2] != 0)
8520             {
8521               (void) ConcatenateString(&draw_info->primitive," ");
8522               (void) ConcatenateString(&draw_info->primitive,
8523                 CommandOptionToMnemonic(MagickMethodOptions,
8524                 argument_list[2].integer_reference));
8525             }
8526           if (attribute_flag[3] != 0)
8527             {
8528               (void) QueryColorDatabase(argument_list[3].string_reference,
8529                 &draw_info->stroke,exception);
8530               if (argument_list[3].image_reference != (Image *) NULL)
8531                 draw_info->stroke_pattern=CloneImage(
8532                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8533             }
8534           if (attribute_flag[4] != 0)
8535             {
8536               (void) QueryColorDatabase(argument_list[4].string_reference,
8537                 &draw_info->fill,exception);
8538               if (argument_list[4].image_reference != (Image *) NULL)
8539                 draw_info->fill_pattern=CloneImage(
8540                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8541             }
8542           if (attribute_flag[5] != 0)
8543             draw_info->stroke_width=argument_list[5].real_reference;
8544           if (attribute_flag[6] != 0)
8545             (void) CloneString(&draw_info->font,
8546               argument_list[6].string_reference);
8547           if (attribute_flag[7] != 0)
8548             (void) QueryColorDatabase(argument_list[7].string_reference,
8549               &draw_info->border_color,exception);
8550           if (attribute_flag[8] != 0)
8551             draw_info->affine.tx=argument_list[8].real_reference;
8552           if (attribute_flag[9] != 0)
8553             draw_info->affine.ty=argument_list[9].real_reference;
8554           if (attribute_flag[20] != 0)
8555             {
8556               AV
8557                 *av;
8558
8559               av=(AV *) argument_list[20].array_reference;
8560               if ((av_len(av) != 3) && (av_len(av) != 5))
8561                 {
8562                   ThrowPerlException(exception,OptionError,
8563                     "affine matrix must have 4 or 6 elements",PackageName);
8564                   goto PerlException;
8565                 }
8566               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8567               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8568               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8569               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8570               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8571                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8572                 {
8573                   ThrowPerlException(exception,OptionError,
8574                     "affine matrix is singular",PackageName);
8575                    goto PerlException;
8576                 }
8577               if (av_len(av) == 5)
8578                 {
8579                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8580                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8581                 }
8582             }
8583           for (j=10; j < 15; j++)
8584           {
8585             if (attribute_flag[j] == 0)
8586               continue;
8587             value=argument_list[j].string_reference;
8588             angle=argument_list[j].real_reference;
8589             current=draw_info->affine;
8590             GetAffineMatrix(&affine);
8591             switch (j)
8592             {
8593               case 10:
8594               {
8595                 /*
8596                   Translate.
8597                 */
8598                 flags=ParseGeometry(value,&geometry_info);
8599                 affine.tx=geometry_info.xi;
8600                 affine.ty=geometry_info.psi;
8601                 if ((flags & PsiValue) == 0)
8602                   affine.ty=affine.tx;
8603                 break;
8604               }
8605               case 11:
8606               {
8607                 /*
8608                   Scale.
8609                 */
8610                 flags=ParseGeometry(value,&geometry_info);
8611                 affine.sx=geometry_info.rho;
8612                 affine.sy=geometry_info.sigma;
8613                 if ((flags & SigmaValue) == 0)
8614                   affine.sy=affine.sx;
8615                 break;
8616               }
8617               case 12:
8618               {
8619                 /*
8620                   Rotate.
8621                 */
8622                 if (angle == 0.0)
8623                   break;
8624                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8625                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8626                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8627                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8628                 break;
8629               }
8630               case 13:
8631               {
8632                 /*
8633                   SkewX.
8634                 */
8635                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8636                 break;
8637               }
8638               case 14:
8639               {
8640                 /*
8641                   SkewY.
8642                 */
8643                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8644                 break;
8645               }
8646             }
8647             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8648             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8649             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8650             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8651             draw_info->affine.tx=
8652               current.sx*affine.tx+current.ry*affine.ty+current.tx;
8653             draw_info->affine.ty=
8654               current.rx*affine.tx+current.sy*affine.ty+current.ty;
8655           }
8656           if (attribute_flag[15] != 0)
8657             draw_info->fill_pattern=CloneImage(
8658               argument_list[15].image_reference,0,0,MagickTrue,exception);
8659           if (attribute_flag[16] != 0)
8660             draw_info->pointsize=argument_list[16].real_reference;
8661           if (attribute_flag[17] != 0)
8662             {
8663               draw_info->stroke_antialias=argument_list[17].integer_reference != 0
8664                 ? MagickTrue : MagickFalse;
8665               draw_info->text_antialias=draw_info->stroke_antialias;
8666             }
8667           if (attribute_flag[18] != 0)
8668             (void) CloneString(&draw_info->density,
8669               argument_list[18].string_reference);
8670           if (attribute_flag[19] != 0)
8671             draw_info->stroke_width=argument_list[19].real_reference;
8672           if (attribute_flag[21] != 0)
8673             draw_info->dash_offset=argument_list[21].real_reference;
8674           if (attribute_flag[22] != 0)
8675             {
8676               AV
8677                 *av;
8678
8679               av=(AV *) argument_list[22].array_reference;
8680               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
8681                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
8682               if (draw_info->dash_pattern != (double *) NULL)
8683                 {
8684                   for (i=0; i <= av_len(av); i++)
8685                     draw_info->dash_pattern[i]=(double)
8686                       SvNV(*(av_fetch(av,i,0)));
8687                   draw_info->dash_pattern[i]=0.0;
8688                 }
8689             }
8690           if (attribute_flag[23] != 0)
8691             image->interpolate=(InterpolatePixelMethod)
8692               argument_list[23].integer_reference;
8693           if ((attribute_flag[24] != 0) &&
8694               (draw_info->fill_pattern != (Image *) NULL))
8695             flags=ParsePageGeometry(draw_info->fill_pattern,
8696               argument_list[24].string_reference,
8697               &draw_info->fill_pattern->tile_offset,exception);
8698           if (attribute_flag[25] != 0)
8699             {
8700               (void) ConcatenateString(&draw_info->primitive," '");
8701               (void) ConcatenateString(&draw_info->primitive,
8702                 argument_list[25].string_reference);
8703               (void) ConcatenateString(&draw_info->primitive,"'");
8704             }
8705           if (attribute_flag[26] != 0)
8706             draw_info->fill_pattern=CloneImage(
8707               argument_list[26].image_reference,0,0,MagickTrue,exception);
8708           if (attribute_flag[27] != 0)
8709             draw_info->stroke_pattern=CloneImage(
8710               argument_list[27].image_reference,0,0,MagickTrue,exception);
8711           if (attribute_flag[28] != 0)
8712             (void) CloneString(&draw_info->primitive,
8713               argument_list[28].string_reference);
8714           if (attribute_flag[29] != 0)
8715             draw_info->kerning=argument_list[29].real_reference;
8716           if (attribute_flag[30] != 0)
8717             draw_info->interline_spacing=argument_list[30].real_reference;
8718           if (attribute_flag[31] != 0)
8719             draw_info->interword_spacing=argument_list[31].real_reference;
8720           if (attribute_flag[32] != 0)
8721             draw_info->direction=(DirectionType)
8722               argument_list[32].integer_reference;
8723           DrawImage(image,draw_info);
8724           draw_info=DestroyDrawInfo(draw_info);
8725           break;
8726         }
8727         case 39:  /* Equalize */
8728         {
8729           if (attribute_flag[0] != 0)
8730             channel=(ChannelType) argument_list[0].integer_reference;
8731           EqualizeImageChannel(image,channel);
8732           break;
8733         }
8734         case 40:  /* Gamma */
8735         {
8736           if (attribute_flag[1] != 0)
8737             channel=(ChannelType) argument_list[1].integer_reference;
8738           if (attribute_flag[2] == 0)
8739             argument_list[2].real_reference=1.0;
8740           if (attribute_flag[3] == 0)
8741             argument_list[3].real_reference=1.0;
8742           if (attribute_flag[4] == 0)
8743             argument_list[4].real_reference=1.0;
8744           if (attribute_flag[0] == 0)
8745             {
8746               (void) FormatMagickString(message,MaxTextExtent,
8747                 "%.15g,%.15g,%.15g",(double) argument_list[2].real_reference,
8748                 (double) argument_list[3].real_reference,
8749                 (double) argument_list[4].real_reference);
8750               argument_list[0].string_reference=message;
8751             }
8752           if (strchr(argument_list[0].string_reference,',') != (char *) NULL)
8753             (void) GammaImage(image,argument_list[0].string_reference);
8754           else
8755             (void) GammaImageChannel(image,channel,
8756               StringToDouble(argument_list[0].string_reference));
8757           break;
8758         }
8759         case 41:  /* Map */
8760         {
8761           QuantizeInfo
8762             *quantize_info;
8763
8764           if (attribute_flag[0] == 0)
8765             {
8766               ThrowPerlException(exception,OptionError,"MapImageRequired",
8767                 PackageName);
8768               goto PerlException;
8769             }
8770           quantize_info=AcquireQuantizeInfo(info->image_info);
8771           if (attribute_flag[1] != 0)
8772             quantize_info->dither=(MagickBooleanType)
8773               argument_list[1].integer_reference;
8774           if (attribute_flag[2] != 0)
8775             quantize_info->dither_method=(DitherMethod)
8776               argument_list[2].integer_reference;
8777           (void) RemapImages(quantize_info,image,
8778             argument_list[0].image_reference);
8779           quantize_info=DestroyQuantizeInfo(quantize_info);
8780           break;
8781         }
8782         case 42:  /* MatteFloodfill */
8783         {
8784           DrawInfo
8785             *draw_info;
8786
8787           MagickBooleanType
8788             invert;
8789
8790           MagickPixelPacket
8791             target;
8792
8793           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8794             (DrawInfo *) NULL);
8795           if (attribute_flag[0] != 0)
8796           if (attribute_flag[0] != 0)
8797             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8798               &geometry,exception);
8799           if (attribute_flag[1] != 0)
8800             geometry.x=argument_list[1].integer_reference;
8801           if (attribute_flag[2] != 0)
8802             geometry.y=argument_list[2].integer_reference;
8803           if (image->matte == MagickFalse)
8804             (void) SetImageOpacity(image,OpaqueOpacity);
8805           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
8806             exception);
8807           if (attribute_flag[4] != 0)
8808             QueryMagickColor(argument_list[4].string_reference,&target,
8809               exception);
8810           if (attribute_flag[3] != 0)
8811             target.opacity=SiPrefixToDouble(argument_list[3].string_reference,
8812               QuantumRange);
8813           if (attribute_flag[5] != 0)
8814             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
8815               QuantumRange);
8816           invert=MagickFalse;
8817           if (attribute_flag[6] != 0)
8818             invert=(MagickBooleanType) argument_list[6].integer_reference;
8819           (void) FloodfillPaintImage(image,OpacityChannel,draw_info,&target,
8820             geometry.x,geometry.y,invert);
8821           draw_info=DestroyDrawInfo(draw_info);
8822           break;
8823         }
8824         case 43:  /* Modulate */
8825         {
8826           char
8827             modulate[MaxTextExtent];
8828
8829           ColorspaceType
8830             colorspace;
8831
8832           colorspace=image->colorspace;
8833           geometry_info.rho=100.0;
8834           geometry_info.sigma=100.0;
8835           geometry_info.xi=100.0;
8836           if (attribute_flag[0] != 0)
8837             (void)ParseGeometry(argument_list[0].string_reference,
8838               &geometry_info);
8839           if (attribute_flag[1] != 0)
8840             geometry_info.xi=argument_list[1].real_reference;
8841           if (attribute_flag[2] != 0)
8842             geometry_info.sigma=argument_list[2].real_reference;
8843           if (attribute_flag[3] != 0)
8844             {
8845               (void) SetImageColorspace(image,HWBColorspace);
8846               geometry_info.sigma=argument_list[3].real_reference;
8847             }
8848           if (attribute_flag[4] != 0)
8849             geometry_info.rho=argument_list[4].real_reference;
8850           if (attribute_flag[5] != 0)
8851             {
8852               (void) SetImageColorspace(image,HSLColorspace);
8853               geometry_info.sigma=argument_list[5].real_reference;
8854             }
8855           if (attribute_flag[6] != 0)
8856             {
8857               (void) SetImageColorspace(image,HWBColorspace);
8858               geometry_info.rho=argument_list[6].real_reference;
8859             }
8860           (void) FormatMagickString(modulate,MaxTextExtent,"%.15g,%.15g,%.15g",
8861             geometry_info.rho,geometry_info.sigma,geometry_info.xi);
8862           (void) ModulateImage(image,modulate);
8863           (void) SetImageColorspace(image,colorspace);
8864           break;
8865         }
8866         case 44:  /* Negate */
8867         {
8868           if (attribute_flag[0] == 0)
8869             argument_list[0].integer_reference=0;
8870           if (attribute_flag[1] != 0)
8871             channel=(ChannelType) argument_list[1].integer_reference;
8872           (void) NegateImageChannel(image,channel,
8873             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse);
8874           break;
8875         }
8876         case 45:  /* Normalize */
8877         {
8878           if (attribute_flag[0] != 0)
8879             channel=(ChannelType) argument_list[0].integer_reference;
8880           NormalizeImageChannel(image,channel);
8881           break;
8882         }
8883         case 46:  /* NumberColors */
8884           break;
8885         case 47:  /* Opaque */
8886         {
8887           MagickBooleanType
8888             invert;
8889
8890           MagickPixelPacket
8891             fill_color,
8892             target;
8893
8894           (void) QueryMagickColor("none",&target,exception);
8895           (void) QueryMagickColor("none",&fill_color,exception);
8896           if (attribute_flag[0] != 0)
8897             (void) QueryMagickColor(argument_list[0].string_reference,
8898               &target,exception);
8899           if (attribute_flag[1] != 0)
8900             (void) QueryMagickColor(argument_list[1].string_reference,
8901               &fill_color,exception);
8902           if (attribute_flag[2] != 0)
8903             image->fuzz=SiPrefixToDouble(argument_list[2].string_reference,
8904               QuantumRange);
8905           if (attribute_flag[3] != 0)
8906             channel=(ChannelType) argument_list[3].integer_reference;
8907           invert=MagickFalse;
8908           if (attribute_flag[4] != 0)
8909             invert=(MagickBooleanType) argument_list[4].integer_reference;
8910           (void) OpaquePaintImageChannel(image,channel,&target,&fill_color,
8911             invert);
8912           break;
8913         }
8914         case 48:  /* Quantize */
8915         {
8916           QuantizeInfo
8917             *quantize_info;
8918
8919           quantize_info=AcquireQuantizeInfo(info->image_info);
8920           if (attribute_flag[0] != 0)
8921             quantize_info->number_colors=(size_t)
8922               argument_list[0].integer_reference;
8923           if (attribute_flag[1] != 0)
8924             quantize_info->tree_depth=(size_t)
8925               argument_list[1].integer_reference;
8926           if (attribute_flag[2] != 0)
8927             quantize_info->colorspace=(ColorspaceType)
8928               argument_list[2].integer_reference;
8929           if (attribute_flag[3] != 0)
8930             quantize_info->dither=argument_list[3].integer_reference != 0 ?
8931               MagickTrue : MagickFalse;
8932           if (attribute_flag[4] != 0)
8933             quantize_info->measure_error=
8934               argument_list[4].integer_reference != 0 ? MagickTrue : MagickFalse;
8935           if (attribute_flag[5] != 0)
8936             (void) QueryColorDatabase(argument_list[5].string_reference,
8937               &image->transparent_color,exception);
8938           if (attribute_flag[5] && argument_list[5].integer_reference)
8939             {
8940               (void) QuantizeImages(quantize_info,image);
8941               goto PerlException;
8942             }
8943           if (attribute_flag[6] != 0)
8944             quantize_info->dither_method=(DitherMethod)
8945               argument_list[6].integer_reference;
8946           if ((image->storage_class == DirectClass) ||
8947               (image->colors > quantize_info->number_colors) ||
8948               (quantize_info->colorspace == GRAYColorspace))
8949             (void) QuantizeImage(quantize_info,image);
8950           else
8951             CompressImageColormap(image);
8952           quantize_info=DestroyQuantizeInfo(quantize_info);
8953           break;
8954         }
8955         case 49:  /* Raise */
8956         {
8957           if (attribute_flag[0] != 0)
8958             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8959               &geometry,exception);
8960           if (attribute_flag[1] != 0)
8961             geometry.width=argument_list[1].integer_reference;
8962           if (attribute_flag[2] != 0)
8963             geometry.height=argument_list[2].integer_reference;
8964           if (attribute_flag[3] == 0)
8965             argument_list[3].integer_reference=1;
8966           (void) RaiseImage(image,&geometry,argument_list[3].integer_reference !=
8967             0 ? MagickTrue : MagickFalse);
8968           break;
8969         }
8970         case 50:  /* Segment */
8971         {
8972           ColorspaceType
8973             colorspace;
8974
8975           double
8976             cluster_threshold,
8977             smoothing_threshold;
8978
8979           MagickBooleanType
8980             verbose;
8981
8982           cluster_threshold=1.0;
8983           smoothing_threshold=1.5;
8984           colorspace=RGBColorspace;
8985           verbose=MagickFalse;
8986           if (attribute_flag[0] != 0)
8987             {
8988               flags=ParseGeometry(argument_list[0].string_reference,
8989                 &geometry_info);
8990               cluster_threshold=geometry_info.rho;
8991               if (flags & SigmaValue)
8992                 smoothing_threshold=geometry_info.sigma;
8993             }
8994           if (attribute_flag[1] != 0)
8995             cluster_threshold=argument_list[1].real_reference;
8996           if (attribute_flag[2] != 0)
8997             smoothing_threshold=argument_list[2].real_reference;
8998           if (attribute_flag[3] != 0)
8999             colorspace=(ColorspaceType) argument_list[3].integer_reference;
9000           if (attribute_flag[4] != 0)
9001             verbose=argument_list[4].integer_reference != 0 ?
9002               MagickTrue : MagickFalse;
9003           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
9004             smoothing_threshold);
9005           break;
9006         }
9007         case 51:  /* Signature */
9008         {
9009           (void) SignatureImage(image);
9010           break;
9011         }
9012         case 52:  /* Solarize */
9013         {
9014           geometry_info.rho=QuantumRange/2.0;
9015           if (attribute_flag[0] != 0)
9016             flags=ParseGeometry(argument_list[0].string_reference,
9017               &geometry_info);
9018           if (attribute_flag[1] != 0)
9019             geometry_info.rho=SiPrefixToDouble(argument_list[1].string_reference,
9020              QuantumRange);
9021           (void) SolarizeImage(image,geometry_info.rho);
9022           break;
9023         }
9024         case 53:  /* Sync */
9025         {
9026           (void) SyncImage(image);
9027           break;
9028         }
9029         case 54:  /* Texture */
9030         {
9031           if (attribute_flag[0] == 0)
9032             break;
9033           TextureImage(image,argument_list[0].image_reference);
9034           break;
9035         }
9036         case 55:  /* Evalute */
9037         {
9038           MagickEvaluateOperator
9039             op;
9040
9041           op=SetEvaluateOperator;
9042           if (attribute_flag[0] == MagickFalse)
9043             argument_list[0].real_reference=0.0;
9044           if (attribute_flag[1] != MagickFalse)
9045             op=(MagickEvaluateOperator) argument_list[1].integer_reference;
9046           if (attribute_flag[2] != MagickFalse)
9047             channel=(ChannelType) argument_list[2].integer_reference;
9048           (void) EvaluateImageChannel(image,channel,op,
9049             argument_list[0].real_reference,exception);
9050           break;
9051         }
9052         case 56:  /* Transparent */
9053         {
9054           double
9055             opacity;
9056
9057           MagickBooleanType
9058             invert;
9059
9060           MagickPixelPacket
9061             target;
9062
9063           (void) QueryMagickColor("none",&target,exception);
9064           if (attribute_flag[0] != 0)
9065             (void) QueryMagickColor(argument_list[0].string_reference,&target,
9066               exception);
9067           opacity=TransparentOpacity;
9068           if (attribute_flag[1] != 0)
9069             opacity=SiPrefixToDouble(argument_list[1].string_reference,
9070               QuantumRange);
9071           if (attribute_flag[2] != 0)
9072             image->fuzz=SiPrefixToDouble(argument_list[2].string_reference,
9073               QuantumRange);
9074           if (attribute_flag[3] == 0)
9075             argument_list[3].integer_reference=0;
9076           invert=MagickFalse;
9077           if (attribute_flag[3] != 0)
9078             invert=(MagickBooleanType) argument_list[3].integer_reference;
9079           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9080             invert);
9081           break;
9082         }
9083         case 57:  /* Threshold */
9084         {
9085           double
9086             threshold;
9087
9088           if (attribute_flag[0] == 0)
9089             argument_list[0].string_reference="50%";
9090           if (attribute_flag[1] != 0)
9091             channel=(ChannelType) argument_list[1].integer_reference;
9092           threshold=SiPrefixToDouble(argument_list[0].string_reference,
9093             QuantumRange);
9094           (void) BilevelImageChannel(image,channel,threshold);
9095           break;
9096         }
9097         case 58:  /* Charcoal */
9098         {
9099           if (attribute_flag[0] != 0)
9100             {
9101               flags=ParseGeometry(argument_list[0].string_reference,
9102                 &geometry_info);
9103               if ((flags & SigmaValue) == 0)
9104                 geometry_info.sigma=1.0;
9105             }
9106           if (attribute_flag[1] != 0)
9107             geometry_info.rho=argument_list[1].real_reference;
9108           if (attribute_flag[2] != 0)
9109             geometry_info.sigma=argument_list[2].real_reference;
9110           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9111             exception);
9112           break;
9113         }
9114         case 59:  /* Trim */
9115         {
9116           if (attribute_flag[0] != 0)
9117             image->fuzz=SiPrefixToDouble(argument_list[0].string_reference,
9118               QuantumRange);
9119           image=TrimImage(image,exception);
9120           break;
9121         }
9122         case 60:  /* Wave */
9123         {
9124           if (attribute_flag[0] != 0)
9125             {
9126               flags=ParseGeometry(argument_list[0].string_reference,
9127                 &geometry_info);
9128               if ((flags & SigmaValue) == 0)
9129                 geometry_info.sigma=1.0;
9130             }
9131           if (attribute_flag[1] != 0)
9132             geometry_info.rho=argument_list[1].real_reference;
9133           if (attribute_flag[2] != 0)
9134             geometry_info.sigma=argument_list[2].real_reference;
9135           if (attribute_flag[3] != 0)
9136             image->interpolate=(InterpolatePixelMethod)
9137               argument_list[3].integer_reference;
9138           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9139             exception);
9140           break;
9141         }
9142         case 61:  /* Separate */
9143         {
9144           if (attribute_flag[0] != 0)
9145             channel=(ChannelType) argument_list[0].integer_reference;
9146           (void) SeparateImageChannel(image,channel);
9147           break;
9148         }
9149         case 63:  /* Stereo */
9150         {
9151           if (attribute_flag[0] == 0)
9152             {
9153               ThrowPerlException(exception,OptionError,"StereoImageRequired",
9154                 PackageName);
9155               goto PerlException;
9156             }
9157           if (attribute_flag[1] != 0)
9158             geometry.x=argument_list[1].integer_reference;
9159           if (attribute_flag[2] != 0)
9160             geometry.y=argument_list[2].integer_reference;
9161           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9162             geometry.x,geometry.y,exception);
9163           break;
9164         }
9165         case 64:  /* Stegano */
9166         {
9167           if (attribute_flag[0] == 0)
9168             {
9169               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9170                 PackageName);
9171               goto PerlException;
9172             }
9173           if (attribute_flag[1] == 0)
9174             argument_list[1].integer_reference=0;
9175           image->offset=argument_list[1].integer_reference;
9176           image=SteganoImage(image,argument_list[0].image_reference,exception);
9177           break;
9178         }
9179         case 65:  /* Deconstruct */
9180         {
9181           image=DeconstructImages(image,exception);
9182           break;
9183         }
9184         case 66:  /* GaussianBlur */
9185         {
9186           if (attribute_flag[0] != 0)
9187             {
9188               flags=ParseGeometry(argument_list[0].string_reference,
9189                 &geometry_info);
9190               if ((flags & SigmaValue) == 0)
9191                 geometry_info.sigma=1.0;
9192             }
9193           if (attribute_flag[1] != 0)
9194             geometry_info.rho=argument_list[1].real_reference;
9195           if (attribute_flag[2] != 0)
9196             geometry_info.sigma=argument_list[2].real_reference;
9197           if (attribute_flag[3] != 0)
9198             channel=(ChannelType) argument_list[3].integer_reference;
9199           image=GaussianBlurImageChannel(image,channel,geometry_info.rho,
9200             geometry_info.sigma,exception);
9201           break;
9202         }
9203         case 67:  /* Convolve */
9204         {
9205           AV
9206             *av;
9207
9208           double
9209             *kernel;
9210
9211           size_t
9212             order;
9213
9214           if (attribute_flag[0] == 0)
9215             break;
9216           if (attribute_flag[1] != 0)
9217             channel=(ChannelType) argument_list[1].integer_reference;
9218           if (attribute_flag[2] != 0)
9219             image->bias=SiPrefixToDouble(argument_list[2].string_reference,
9220               QuantumRange);
9221           av=(AV *) argument_list[0].array_reference;
9222           order=(size_t) sqrt(av_len(av)+1);
9223           kernel=(double *) AcquireQuantumMemory(order,order*sizeof(*kernel));
9224           if (kernel == (double *) NULL)
9225             {
9226               ThrowPerlException(exception,ResourceLimitFatalError,
9227                 "MemoryAllocationFailed",PackageName);
9228               goto PerlException;
9229             }
9230           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9231             kernel[j]=(double) SvNV(*(av_fetch(av,j,0)));
9232           for ( ; j < (ssize_t) (order*order); j++)
9233             kernel[j]=0.0;
9234           image=ConvolveImageChannel(image,channel,order,kernel,exception);
9235           kernel=(double *) RelinquishMagickMemory(kernel);
9236           break;
9237         }
9238         case 68:  /* Profile */
9239         {
9240           const char
9241             *name;
9242
9243           Image
9244             *profile_image;
9245
9246           ImageInfo
9247             *profile_info;
9248
9249           StringInfo
9250             *profile;
9251
9252           name="*";
9253           if (attribute_flag[0] != 0)
9254             name=argument_list[0].string_reference;
9255           if (attribute_flag[2] != 0)
9256             image->rendering_intent=(RenderingIntent)
9257               argument_list[2].integer_reference;
9258           if (attribute_flag[3] != 0)
9259             image->black_point_compensation=
9260               argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9261           if (attribute_flag[1] != 0)
9262             {
9263               if (argument_list[1].length == 0)
9264                 {
9265                   /*
9266                     Remove a profile from the image.
9267                   */
9268                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9269                     MagickTrue);
9270                   break;
9271                 }
9272               /*
9273                 Associate user supplied profile with the image.
9274               */
9275               profile=AcquireStringInfo(argument_list[1].length);
9276               SetStringInfoDatum(profile,(const unsigned char *)
9277                 argument_list[1].string_reference);
9278               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9279                 (size_t) GetStringInfoLength(profile),MagickFalse);
9280               profile=DestroyStringInfo(profile);
9281               break;
9282             }
9283           /*
9284             Associate a profile with the image.
9285           */
9286           profile_info=
9287             CloneImageInfo(info ? info->image_info : (ImageInfo *) NULL);
9288           (void) CopyMagickString(profile_info->filename,name,MaxTextExtent);
9289           profile_image=ReadImages(profile_info,&image->exception);
9290           if (profile_image == (Image *) NULL)
9291             break;
9292           ResetImageProfileIterator(profile_image);
9293           name=GetNextImageProfile(profile_image);
9294           while (name != (const char *) NULL)
9295           {
9296             const StringInfo
9297               *profile;
9298
9299             profile=GetImageProfile(profile_image,name);
9300             if (profile != (const StringInfo *) NULL)
9301               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9302                 (size_t) GetStringInfoLength(profile),MagickFalse);
9303             name=GetNextImageProfile(profile_image);
9304           }
9305           profile_image=DestroyImage(profile_image);
9306           profile_info=DestroyImageInfo(profile_info);
9307           break;
9308         }
9309         case 69:  /* UnsharpMask */
9310         {
9311           if (attribute_flag[0] != 0)
9312             {
9313               flags=ParseGeometry(argument_list[0].string_reference,
9314                 &geometry_info);
9315               if ((flags & SigmaValue) == 0)
9316                 geometry_info.sigma=1.0;
9317               if ((flags & XiValue) == 0)
9318                 geometry_info.xi=1.0;
9319               if ((flags & PsiValue) == 0)
9320                 geometry_info.psi=0.5;
9321             }
9322           if (attribute_flag[1] != 0)
9323             geometry_info.rho=argument_list[1].real_reference;
9324           if (attribute_flag[2] != 0)
9325             geometry_info.sigma=argument_list[2].real_reference;
9326           if (attribute_flag[3] != 0)
9327             geometry_info.xi=argument_list[3].real_reference;
9328           if (attribute_flag[4] != 0)
9329             geometry_info.psi=argument_list[4].real_reference;
9330           if (attribute_flag[5] != 0)
9331             channel=(ChannelType) argument_list[5].integer_reference;
9332           image=UnsharpMaskImageChannel(image,channel,geometry_info.rho,
9333             geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
9334           break;
9335         }
9336         case 70:  /* MotionBlur */
9337         {
9338           if (attribute_flag[0] != 0)
9339             {
9340               flags=ParseGeometry(argument_list[0].string_reference,
9341                 &geometry_info);
9342               if ((flags & SigmaValue) == 0)
9343                 geometry_info.sigma=1.0;
9344               if ((flags & XiValue) == 0)
9345                 geometry_info.xi=1.0;
9346             }
9347           if (attribute_flag[1] != 0)
9348             geometry_info.rho=argument_list[1].real_reference;
9349           if (attribute_flag[2] != 0)
9350             geometry_info.sigma=argument_list[2].real_reference;
9351           if (attribute_flag[3] != 0)
9352             geometry_info.xi=argument_list[3].real_reference;
9353           if (attribute_flag[4] != 0)
9354             channel=(ChannelType) argument_list[4].integer_reference;
9355           image=MotionBlurImageChannel(image,channel,geometry_info.rho,
9356             geometry_info.sigma,geometry_info.xi,exception);
9357           break;
9358         }
9359         case 71:  /* OrderedDither */
9360         {
9361           if (attribute_flag[0] == 0)
9362             argument_list[0].string_reference="o8x8";
9363           if (attribute_flag[1] != 0)
9364             channel=(ChannelType) argument_list[1].integer_reference;
9365           (void) OrderedPosterizeImageChannel(image,channel,
9366             argument_list[0].string_reference,exception);
9367           break;
9368         }
9369         case 72:  /* Shave */
9370         {
9371           if (attribute_flag[0] != 0)
9372             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9373               &geometry,exception);
9374           if (attribute_flag[1] != 0)
9375             geometry.width=argument_list[1].integer_reference;
9376           if (attribute_flag[2] != 0)
9377             geometry.height=argument_list[2].integer_reference;
9378           image=ShaveImage(image,&geometry,exception);
9379           break;
9380         }
9381         case 73:  /* Level */
9382         {
9383           double
9384             black_point,
9385             gamma,
9386             white_point;
9387
9388           black_point=0.0;
9389           white_point=(MagickRealType) image->columns*image->rows;
9390           gamma=1.0;
9391           if (attribute_flag[0] != 0)
9392             {
9393               flags=ParseGeometry(argument_list[0].string_reference,
9394                 &geometry_info);
9395               black_point=geometry_info.rho;
9396               if ((flags & SigmaValue) != 0)
9397                 white_point=geometry_info.sigma;
9398               if ((flags & XiValue) != 0)
9399                 gamma=geometry_info.xi;
9400               if ((flags & PercentValue) != 0)
9401                 {
9402                   black_point*=(double) (QuantumRange/100.0);
9403                   white_point*=(double) (QuantumRange/100.0);
9404                 }
9405               if ((flags & SigmaValue) == 0)
9406                 white_point=(double) QuantumRange-black_point;
9407             }
9408           if (attribute_flag[1] != 0)
9409             black_point=argument_list[1].real_reference;
9410           if (attribute_flag[2] != 0)
9411             white_point=argument_list[2].real_reference;
9412           if (attribute_flag[3] != 0)
9413             gamma=argument_list[3].real_reference;
9414           if (attribute_flag[4] != 0)
9415             channel=(ChannelType) argument_list[4].integer_reference;
9416           if (attribute_flag[5] != 0)
9417             {
9418               argument_list[0].real_reference=argument_list[5].real_reference;
9419               attribute_flag[0]=attribute_flag[5];
9420             }
9421           (void) LevelImageChannel(image,channel,black_point,white_point,gamma);
9422           break;
9423         }
9424         case 74:  /* Clip */
9425         {
9426           if (attribute_flag[0] == 0)
9427             argument_list[0].string_reference="#1";
9428           if (attribute_flag[1] == 0)
9429             argument_list[1].integer_reference=MagickTrue;
9430           (void) ClipImagePath(image,argument_list[0].string_reference,
9431             argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse);
9432           break;
9433         }
9434         case 75:  /* AffineTransform */
9435         {
9436           DrawInfo
9437             *draw_info;
9438
9439           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9440             (DrawInfo *) NULL);
9441           if (attribute_flag[0] != 0)
9442             {
9443               AV
9444                 *av;
9445
9446               av=(AV *) argument_list[0].array_reference;
9447               if ((av_len(av) != 3) && (av_len(av) != 5))
9448                 {
9449                   ThrowPerlException(exception,OptionError,
9450                     "affine matrix must have 4 or 6 elements",PackageName);
9451                   goto PerlException;
9452                 }
9453               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9454               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9455               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9456               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9457               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9458                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9459                 {
9460                   ThrowPerlException(exception,OptionError,
9461                     "affine matrix is singular",PackageName);
9462                    goto PerlException;
9463                 }
9464               if (av_len(av) == 5)
9465                 {
9466                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9467                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9468                 }
9469             }
9470           for (j=1; j < 6; j++)
9471           {
9472             if (attribute_flag[j] == 0)
9473               continue;
9474             value=argument_list[j].string_reference;
9475             angle=argument_list[j].real_reference;
9476             current=draw_info->affine;
9477             GetAffineMatrix(&affine);
9478             switch (j)
9479             {
9480               case 1:
9481               {
9482                 /*
9483                   Translate.
9484                 */
9485                 flags=ParseGeometry(value,&geometry_info);
9486                 affine.tx=geometry_info.xi;
9487                 affine.ty=geometry_info.psi;
9488                 if ((flags & PsiValue) == 0)
9489                   affine.ty=affine.tx;
9490                 break;
9491               }
9492               case 2:
9493               {
9494                 /*
9495                   Scale.
9496                 */
9497                 flags=ParseGeometry(value,&geometry_info);
9498                 affine.sx=geometry_info.rho;
9499                 affine.sy=geometry_info.sigma;
9500                 if ((flags & SigmaValue) == 0)
9501                   affine.sy=affine.sx;
9502                 break;
9503               }
9504               case 3:
9505               {
9506                 /*
9507                   Rotate.
9508                 */
9509                 if (angle == 0.0)
9510                   break;
9511                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9512                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9513                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9514                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9515                 break;
9516               }
9517               case 4:
9518               {
9519                 /*
9520                   SkewX.
9521                 */
9522                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9523                 break;
9524               }
9525               case 5:
9526               {
9527                 /*
9528                   SkewY.
9529                 */
9530                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9531                 break;
9532               }
9533             }
9534             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9535             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9536             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9537             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9538             draw_info->affine.tx=
9539               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9540             draw_info->affine.ty=
9541               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9542           }
9543           if (attribute_flag[6] != 0)
9544             image->interpolate=(InterpolatePixelMethod)
9545               argument_list[6].integer_reference;
9546           if (attribute_flag[7] != 0)
9547             QueryColorDatabase(argument_list[7].string_reference,
9548               &image->background_color,exception);
9549           image=AffineTransformImage(image,&draw_info->affine,exception);
9550           draw_info=DestroyDrawInfo(draw_info);
9551           break;
9552         }
9553         case 76:  /* Difference */
9554         {
9555           if (attribute_flag[0] == 0)
9556             {
9557               ThrowPerlException(exception,OptionError,
9558                 "ReferenceImageRequired",PackageName);
9559               goto PerlException;
9560             }
9561           if (attribute_flag[1] != 0)
9562             image->fuzz=SiPrefixToDouble(argument_list[1].string_reference,
9563               QuantumRange);
9564           (void) IsImagesEqual(image,argument_list[0].image_reference);
9565           break;
9566         }
9567         case 77:  /* AdaptiveThreshold */
9568         {
9569           if (attribute_flag[0] != 0)
9570             {
9571               flags=ParseGeometry(argument_list[0].string_reference,
9572                 &geometry_info);
9573               if ((flags & PercentValue) != 0)
9574                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9575             }
9576           if (attribute_flag[1] != 0)
9577             geometry_info.rho=argument_list[1].integer_reference;
9578           if (attribute_flag[2] != 0)
9579             geometry_info.sigma=argument_list[2].integer_reference;
9580           if (attribute_flag[3] != 0)
9581             geometry_info.xi=argument_list[3].integer_reference;;
9582           image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
9583             (size_t) geometry_info.sigma,(ssize_t) geometry_info.xi,
9584             exception);
9585           break;
9586         }
9587         case 78:  /* Resample */
9588         {
9589           size_t
9590             height,
9591             width;
9592
9593           if (attribute_flag[0] != 0)
9594             {
9595               flags=ParseGeometry(argument_list[0].string_reference,
9596                 &geometry_info);
9597               if ((flags & SigmaValue) == 0)
9598                 geometry_info.sigma=geometry_info.rho;
9599             }
9600           if (attribute_flag[1] != 0)
9601             geometry_info.rho=argument_list[1].real_reference;
9602           if (attribute_flag[2] != 0)
9603             geometry_info.sigma=argument_list[2].real_reference;
9604           if (attribute_flag[3] == 0)
9605             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
9606           if (attribute_flag[4] == 0)
9607             SetImageArtifact(image,"filter:support",
9608               argument_list[4].string_reference);
9609           if (attribute_flag[5] != 0)
9610             argument_list[5].real_reference=1.0;
9611           width=(size_t) (geometry_info.rho*image->columns/
9612             (image->x_resolution == 0.0 ? 72.0 : image->x_resolution)+0.5);
9613           height=(size_t) (geometry_info.sigma*image->rows/
9614             (image->y_resolution == 0.0 ? 72.0 : image->y_resolution)+0.5);
9615           image=ResizeImage(image,width,height,(FilterTypes)
9616             argument_list[3].integer_reference,argument_list[5].real_reference,
9617             exception);
9618           if (image != (Image *) NULL)
9619             {
9620               image->x_resolution=geometry_info.rho;
9621               image->y_resolution=geometry_info.sigma;
9622             }
9623           break;
9624         }
9625         case 79:  /* Describe */
9626         {
9627           if (attribute_flag[0] == 0)
9628             argument_list[0].file_reference=(FILE *) NULL;
9629           if (attribute_flag[1] != 0)
9630             (void) SetImageArtifact(image,"identify:features",
9631               argument_list[1].string_reference);
9632           (void) IdentifyImage(image,argument_list[0].file_reference,
9633             MagickTrue);
9634           break;
9635         }
9636         case 80:  /* BlackThreshold */
9637         {
9638           if (attribute_flag[0] == 0)
9639             argument_list[0].string_reference="50%";
9640           if (attribute_flag[2] != 0)
9641             channel=(ChannelType) argument_list[2].integer_reference;
9642           BlackThresholdImageChannel(image,channel,
9643             argument_list[0].string_reference,exception);
9644           break;
9645         }
9646         case 81:  /* WhiteThreshold */
9647         {
9648           if (attribute_flag[0] == 0)
9649             argument_list[0].string_reference="50%";
9650           if (attribute_flag[2] != 0)
9651             channel=(ChannelType) argument_list[2].integer_reference;
9652           WhiteThresholdImageChannel(image,channel,
9653             argument_list[0].string_reference,exception);
9654           break;
9655         }
9656         case 82:  /* RadialBlur */
9657         {
9658           if (attribute_flag[0] != 0)
9659             {
9660               flags=ParseGeometry(argument_list[0].string_reference,
9661                 &geometry_info);
9662               if ((flags & SigmaValue) == 0)
9663                 geometry_info.sigma=1.0;
9664             }
9665           if (attribute_flag[1] != 0)
9666             geometry_info.rho=argument_list[1].real_reference;
9667           if (attribute_flag[2] != 0)
9668             channel=(ChannelType) argument_list[2].integer_reference;
9669           image=RadialBlurImageChannel(image,channel,geometry_info.rho,
9670             exception);
9671           break;
9672         }
9673         case 83:  /* Thumbnail */
9674         {
9675           if (attribute_flag[0] != 0)
9676             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
9677               &geometry,exception);
9678           if (attribute_flag[1] != 0)
9679             geometry.width=argument_list[1].integer_reference;
9680           if (attribute_flag[2] != 0)
9681             geometry.height=argument_list[2].integer_reference;
9682           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
9683           break;
9684         }
9685         case 84:  /* Strip */
9686         {
9687           (void) StripImage(image);
9688           break;
9689         }
9690         case 85:  /* Tint */
9691         {
9692           PixelPacket
9693             target;
9694
9695           (void) GetOneVirtualPixel(image,0,0,&target,exception);
9696           if (attribute_flag[0] != 0)
9697             (void) QueryColorDatabase(argument_list[0].string_reference,&target,
9698               exception);
9699           if (attribute_flag[1] == 0)
9700             argument_list[1].string_reference="100";
9701           image=TintImage(image,argument_list[1].string_reference,target,
9702             exception);
9703           break;
9704         }
9705         case 86:  /* Channel */
9706         {
9707           if (attribute_flag[0] != 0)
9708             channel=(ChannelType) argument_list[0].integer_reference;
9709           (void) SeparateImageChannel(image,channel);
9710           break;
9711         }
9712         case 87:  /* Splice */
9713         {
9714           if (attribute_flag[0] != 0)
9715             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
9716               &geometry,exception);
9717           if (attribute_flag[1] != 0)
9718             geometry.width=argument_list[1].integer_reference;
9719           if (attribute_flag[2] != 0)
9720             geometry.height=argument_list[2].integer_reference;
9721           if (attribute_flag[3] != 0)
9722             geometry.x=argument_list[3].integer_reference;
9723           if (attribute_flag[4] != 0)
9724             geometry.y=argument_list[4].integer_reference;
9725           if (attribute_flag[5] != 0)
9726             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
9727               QuantumRange);
9728           if (attribute_flag[6] != 0)
9729             (void) QueryColorDatabase(argument_list[6].string_reference,
9730               &image->background_color,exception);
9731           if (attribute_flag[7] != 0)
9732             image->gravity=(GravityType) argument_list[7].integer_reference;
9733           image=SpliceImage(image,&geometry,exception);
9734           break;
9735         }
9736         case 88:  /* Posterize */
9737         {
9738           if (attribute_flag[0] == 0)
9739             argument_list[0].integer_reference=3;
9740           if (attribute_flag[1] == 0)
9741             argument_list[1].integer_reference=0;
9742           (void) PosterizeImage(image,argument_list[0].integer_reference,
9743             argument_list[1].integer_reference ? MagickTrue : MagickFalse);
9744           break;
9745         }
9746         case 89:  /* Shadow */
9747         {
9748           if (attribute_flag[0] != 0)
9749             {
9750               flags=ParseGeometry(argument_list[0].string_reference,
9751                 &geometry_info);
9752               if ((flags & SigmaValue) == 0)
9753                 geometry_info.sigma=1.0;
9754               if ((flags & XiValue) == 0)
9755                 geometry_info.xi=4.0;
9756               if ((flags & PsiValue) == 0)
9757                 geometry_info.psi=4.0;
9758             }
9759           if (attribute_flag[1] != 0)
9760             geometry_info.rho=argument_list[1].real_reference;
9761           if (attribute_flag[2] != 0)
9762             geometry_info.sigma=argument_list[2].real_reference;
9763           if (attribute_flag[3] != 0)
9764             geometry_info.xi=argument_list[3].integer_reference;
9765           if (attribute_flag[4] != 0)
9766             geometry_info.psi=argument_list[4].integer_reference;
9767           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
9768             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-
9769             0.5),exception);
9770           break;
9771         }
9772         case 90:  /* Identify */
9773         {
9774           if (attribute_flag[0] == 0)
9775             argument_list[0].file_reference=(FILE *) NULL;
9776           if (attribute_flag[1] != 0)
9777             (void) SetImageArtifact(image,"identify:features",
9778               argument_list[1].string_reference);
9779           if ((attribute_flag[2] != 0) &&
9780               (argument_list[2].integer_reference != 0))
9781             (void) SetImageArtifact(image,"identify:unique","true");
9782           (void) IdentifyImage(image,argument_list[0].file_reference,
9783             MagickTrue);
9784           break;
9785         }
9786         case 91:  /* SepiaTone */
9787         {
9788           if (attribute_flag[0] == 0)
9789             argument_list[0].real_reference=80.0*QuantumRange/100.0;
9790           image=SepiaToneImage(image,argument_list[0].real_reference,
9791             exception);
9792           break;
9793         }
9794         case 92:  /* SigmoidalContrast */
9795         {
9796           MagickBooleanType
9797             sharpen;
9798
9799           if (attribute_flag[0] != 0)
9800             {
9801               flags=ParseGeometry(argument_list[0].string_reference,
9802                 &geometry_info);
9803               if ((flags & SigmaValue) == 0)
9804                 geometry_info.sigma=QuantumRange/2.0;
9805               if ((flags & PercentValue) != 0)
9806                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
9807             }
9808           if (attribute_flag[1] != 0)
9809             geometry_info.rho=argument_list[1].real_reference;
9810           if (attribute_flag[2] != 0)
9811             geometry_info.sigma=argument_list[2].real_reference;
9812           if (attribute_flag[3] != 0)
9813             channel=(ChannelType) argument_list[3].integer_reference;
9814           sharpen=MagickTrue;
9815           if (attribute_flag[4] != 0)
9816             sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
9817               MagickFalse;
9818           (void) SigmoidalContrastImageChannel(image,channel,sharpen,
9819             geometry_info.rho,geometry_info.sigma);
9820           break;
9821         }
9822         case 93:  /* Extent */
9823         {
9824           if (attribute_flag[7] != 0)
9825             image->gravity=(GravityType) argument_list[7].integer_reference;
9826           if (attribute_flag[0] != 0)
9827             {
9828               int
9829                 flags;
9830
9831               flags=ParseGravityGeometry(image,
9832                 argument_list[0].string_reference,&geometry,exception);
9833               if (geometry.width == 0)
9834                 geometry.width=image->columns;
9835               if (geometry.height == 0)
9836                 geometry.height=image->rows;
9837             }
9838           if (attribute_flag[1] != 0)
9839             geometry.width=argument_list[1].integer_reference;
9840           if (attribute_flag[2] != 0)
9841             geometry.height=argument_list[2].integer_reference;
9842           if (attribute_flag[3] != 0)
9843             geometry.x=argument_list[3].integer_reference;
9844           if (attribute_flag[4] != 0)
9845             geometry.y=argument_list[4].integer_reference;
9846           if (attribute_flag[5] != 0)
9847             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
9848               QuantumRange);
9849           if (attribute_flag[6] != 0)
9850             (void) QueryColorDatabase(argument_list[6].string_reference,
9851               &image->background_color,exception);
9852           image=ExtentImage(image,&geometry,exception);
9853           break;
9854         }
9855         case 94:  /* Vignette */
9856         {
9857           if (attribute_flag[0] != 0)
9858             {
9859               flags=ParseGeometry(argument_list[0].string_reference,
9860                 &geometry_info);
9861               if ((flags & SigmaValue) == 0)
9862                 geometry_info.sigma=1.0;
9863               if ((flags & XiValue) == 0)
9864                 geometry_info.xi=0.1*image->columns;
9865               if ((flags & PsiValue) == 0)
9866                 geometry_info.psi=0.1*image->rows;
9867             }
9868           if (attribute_flag[1] != 0)
9869             geometry_info.rho=argument_list[1].real_reference;
9870           if (attribute_flag[2] != 0)
9871             geometry_info.sigma=argument_list[2].real_reference;
9872           if (attribute_flag[3] != 0)
9873             geometry_info.xi=argument_list[3].integer_reference;
9874           if (attribute_flag[4] != 0)
9875             geometry_info.psi=argument_list[4].integer_reference;
9876           if (attribute_flag[5] != 0)
9877             (void) QueryColorDatabase(argument_list[5].string_reference,
9878               &image->background_color,exception);
9879           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
9880             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-
9881             0.5),exception);
9882           break;
9883         }
9884         case 95:  /* ContrastStretch */
9885         {
9886           double
9887             black_point,
9888             white_point;
9889
9890           black_point=0.0;
9891           white_point=(MagickRealType) image->columns*image->rows;
9892           if (attribute_flag[0] != 0)
9893             {
9894               flags=ParseGeometry(argument_list[0].string_reference,
9895                 &geometry_info);
9896               black_point=geometry_info.rho;
9897               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
9898                 black_point;
9899               if ((flags & PercentValue) != 0)
9900                 {
9901                   black_point*=(double) image->columns*image->rows/100.0;
9902                   white_point*=(double) image->columns*image->rows/100.0;
9903                 }
9904               white_point=(MagickRealType) image->columns*image->rows-
9905                 white_point;
9906             }
9907           if (attribute_flag[1] != 0)
9908             black_point=argument_list[1].real_reference;
9909           if (attribute_flag[2] != 0)
9910             white_point=argument_list[2].real_reference;
9911           if (attribute_flag[4] != 0)
9912             channel=(ChannelType) argument_list[4].integer_reference;
9913           (void) ContrastStretchImageChannel(image,channel,black_point,
9914             white_point);
9915           break;
9916         }
9917         case 96:  /* Sans0 */
9918         {
9919           break;
9920         }
9921         case 97:  /* Sans1 */
9922         {
9923           break;
9924         }
9925         case 98:  /* AdaptiveSharpen */
9926         {
9927           if (attribute_flag[0] != 0)
9928             {
9929               flags=ParseGeometry(argument_list[0].string_reference,
9930                 &geometry_info);
9931               if ((flags & SigmaValue) == 0)
9932                 geometry_info.sigma=1.0;
9933             }
9934           if (attribute_flag[1] != 0)
9935             geometry_info.rho=argument_list[1].real_reference;
9936           if (attribute_flag[2] != 0)
9937             geometry_info.sigma=argument_list[2].real_reference;
9938           if (attribute_flag[3] != 0)
9939             channel=(ChannelType) argument_list[3].integer_reference;
9940           image=AdaptiveSharpenImageChannel(image,channel,geometry_info.rho,
9941             geometry_info.sigma,exception);
9942           break;
9943         }
9944         case 99:  /* Transpose */
9945         {
9946           image=TransposeImage(image,exception);
9947           break;
9948         }
9949         case 100:  /* Tranverse */
9950         {
9951           image=TransverseImage(image,exception);
9952           break;
9953         }
9954         case 101:  /* AutoOrient */
9955         {
9956           switch (image->orientation)
9957           {
9958             case TopRightOrientation:
9959             {
9960               image=FlopImage(image,exception);
9961               break;
9962             }
9963             case BottomRightOrientation:
9964             {
9965               image=RotateImage(image,180.0,exception);
9966               break;
9967             }
9968             case BottomLeftOrientation:
9969             {
9970               image=FlipImage(image,exception);
9971               break;
9972             }
9973             case LeftTopOrientation:
9974             {
9975               image=TransposeImage(image,exception);
9976               break;
9977             }
9978             case RightTopOrientation:
9979             {
9980               image=RotateImage(image,90.0,exception);
9981               break;
9982             }
9983             case RightBottomOrientation:
9984             {
9985               image=TransverseImage(image,exception);
9986               break;
9987             }
9988             case LeftBottomOrientation:
9989             {
9990               image=RotateImage(image,270.0,exception);
9991               break;
9992             }
9993             default:
9994               break;
9995           }
9996           break;
9997         }
9998         case 102:  /* AdaptiveBlur */
9999         {
10000           if (attribute_flag[0] != 0)
10001             {
10002               flags=ParseGeometry(argument_list[0].string_reference,
10003                 &geometry_info);
10004               if ((flags & SigmaValue) == 0)
10005                 geometry_info.sigma=1.0;
10006             }
10007           if (attribute_flag[1] != 0)
10008             geometry_info.rho=argument_list[1].real_reference;
10009           if (attribute_flag[2] != 0)
10010             geometry_info.sigma=argument_list[2].real_reference;
10011           if (attribute_flag[3] != 0)
10012             channel=(ChannelType) argument_list[3].integer_reference;
10013           image=AdaptiveBlurImageChannel(image,channel,geometry_info.rho,
10014             geometry_info.sigma,exception);
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           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10035             geometry_info.xi,exception);
10036           break;
10037         }
10038         case 104:  /* UniqueColors */
10039         {
10040           image=UniqueImageColors(image,exception);
10041           break;
10042         }
10043         case 105:  /* AdaptiveResize */
10044         {
10045           if (attribute_flag[0] != 0)
10046             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10047               &geometry,exception);
10048           if (attribute_flag[1] != 0)
10049             geometry.width=argument_list[1].integer_reference;
10050           if (attribute_flag[2] != 0)
10051             geometry.height=argument_list[2].integer_reference;
10052           if (attribute_flag[3] != 0)
10053             image->filter=(FilterTypes) argument_list[4].integer_reference;
10054           if (attribute_flag[4] != 0)
10055             SetImageArtifact(image,"filter:support",
10056               argument_list[4].string_reference);
10057           if (attribute_flag[5] != 0)
10058             image->blur=argument_list[5].real_reference;
10059           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10060             exception);
10061           break;
10062         }
10063         case 106:  /* ClipMask */
10064         {
10065           if (attribute_flag[0] == 0)
10066             {
10067               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10068                 PackageName);
10069               goto PerlException;
10070             }
10071           image->clip_mask=CloneImage(argument_list[0].image_reference,0,0,
10072             MagickTrue,exception);
10073           (void) NegateImage(image->clip_mask,MagickFalse);
10074           break;
10075         }
10076         case 107:  /* LinearStretch */
10077         {
10078            double
10079              black_point,
10080              white_point;
10081
10082            black_point=0.0;
10083            white_point=(MagickRealType) image->columns*image->rows;
10084            if (attribute_flag[0] != 0)
10085              {
10086                flags=ParseGeometry(argument_list[0].string_reference,
10087                  &geometry_info);
10088                if ((flags & SigmaValue) != 0)
10089                   white_point=geometry_info.sigma;
10090                if ((flags & PercentValue) != 0)
10091                  {
10092                    black_point*=(double) image->columns*image->rows/100.0;
10093                    white_point*=(double) image->columns*image->rows/100.0;
10094                  }
10095                if ((flags & SigmaValue) == 0)
10096                  white_point=(double) image->columns*image->rows-black_point;
10097              }
10098           if (attribute_flag[1] != 0)
10099             black_point=argument_list[1].real_reference;
10100           if (attribute_flag[2] != 0)
10101             white_point=argument_list[2].real_reference;
10102           (void) LinearStretchImage(image,black_point,white_point);
10103           break;
10104         }
10105         case 109:  /* Mask */
10106         {
10107           if (attribute_flag[0] == 0)
10108             {
10109               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10110                 PackageName);
10111               goto PerlException;
10112             }
10113           image->mask=CloneImage(argument_list[0].image_reference,0,0,
10114             MagickTrue,exception);
10115           (void) NegateImage(image->mask,MagickFalse);
10116           break;
10117         }
10118         case 110:  /* Polaroid */
10119         {
10120           DrawInfo
10121             *draw_info;
10122
10123           double
10124             angle;
10125
10126           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10127             (DrawInfo *) NULL);
10128           if (attribute_flag[0] != 0)
10129             (void) SetImageProperty(image,"caption",InterpretImageProperties(
10130               info ? info->image_info : (ImageInfo *) NULL,image,
10131               argument_list[0].string_reference));
10132           angle=0.0;
10133           if (attribute_flag[1] != 0)
10134             angle=argument_list[1].real_reference;
10135           if (attribute_flag[2] != 0)
10136             (void) CloneString(&draw_info->font,
10137               argument_list[2].string_reference);
10138           if (attribute_flag[3] != 0)
10139             (void) QueryColorDatabase(argument_list[3].string_reference,
10140               &draw_info->stroke,exception);
10141           if (attribute_flag[4] != 0)
10142             (void) QueryColorDatabase(argument_list[4].string_reference,
10143               &draw_info->fill,exception);
10144           if (attribute_flag[5] != 0)
10145             draw_info->stroke_width=argument_list[5].real_reference;
10146           if (attribute_flag[6] != 0)
10147             draw_info->pointsize=argument_list[6].real_reference;
10148           if (attribute_flag[7] != 0)
10149             draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10150           if (attribute_flag[8] != 0)
10151             (void) QueryColorDatabase(argument_list[8].string_reference,
10152               &image->background_color,exception);
10153           image=PolaroidImage(image,draw_info,angle,exception);
10154           draw_info=DestroyDrawInfo(draw_info);
10155           break;
10156         }
10157         case 111:  /* FloodfillPaint */
10158         {
10159           DrawInfo
10160             *draw_info;
10161
10162           MagickBooleanType
10163             invert;
10164
10165           MagickPixelPacket
10166             target;
10167
10168           draw_info=CloneDrawInfo(info ? info->image_info :
10169             (ImageInfo *) NULL,(DrawInfo *) NULL);
10170           if (attribute_flag[0] != 0)
10171             flags=ParsePageGeometry(image,argument_list[0].string_reference,
10172               &geometry,exception);
10173           if (attribute_flag[1] != 0)
10174             geometry.x=argument_list[1].integer_reference;
10175           if (attribute_flag[2] != 0)
10176             geometry.y=argument_list[2].integer_reference;
10177           if (attribute_flag[3] != 0)
10178             (void) QueryColorDatabase(argument_list[3].string_reference,
10179               &draw_info->fill,exception);
10180           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
10181             exception);
10182           if (attribute_flag[4] != 0)
10183             QueryMagickColor(argument_list[4].string_reference,&target,
10184               exception);
10185           if (attribute_flag[5] != 0)
10186             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
10187               QuantumRange);
10188           if (attribute_flag[6] != 0)
10189             channel=(ChannelType) argument_list[6].integer_reference;
10190           invert=MagickFalse;
10191           if (attribute_flag[7] != 0)
10192             invert=(MagickBooleanType) argument_list[7].integer_reference;
10193           (void) FloodfillPaintImage(image,channel,draw_info,&target,geometry.x,
10194             geometry.y,invert);
10195           draw_info=DestroyDrawInfo(draw_info);
10196           break;
10197         }
10198         case 112:  /* Distort */
10199         {
10200           AV
10201             *av;
10202
10203           double
10204             *coordinates;
10205
10206           DistortImageMethod
10207             method;
10208
10209           size_t
10210             number_coordinates;
10211
10212           VirtualPixelMethod
10213             virtual_pixel;
10214
10215           if (attribute_flag[0] == 0)
10216             break;
10217           method=UndefinedDistortion;
10218           if (attribute_flag[1] != 0)
10219             method=(DistortImageMethod) argument_list[1].integer_reference;
10220           av=(AV *) argument_list[0].array_reference;
10221           number_coordinates=(size_t) av_len(av)+1;
10222           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10223             sizeof(*coordinates));
10224           if (coordinates == (double *) NULL)
10225             {
10226               ThrowPerlException(exception,ResourceLimitFatalError,
10227                 "MemoryAllocationFailed",PackageName);
10228               goto PerlException;
10229             }
10230           for (j=0; j < (ssize_t) number_coordinates; j++)
10231             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10232           virtual_pixel=UndefinedVirtualPixelMethod;
10233           if (attribute_flag[2] != 0)
10234             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10235               argument_list[2].integer_reference);
10236           image=DistortImage(image,method,number_coordinates,coordinates,
10237             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10238             exception);
10239           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10240             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10241           coordinates=(double *) RelinquishMagickMemory(coordinates);
10242           break;
10243         }
10244         case 113:  /* Clut */
10245         {
10246           if (attribute_flag[0] == 0)
10247             {
10248               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10249                 PackageName);
10250               goto PerlException;
10251             }
10252           if (attribute_flag[1] != 0)
10253             channel=(ChannelType) argument_list[1].integer_reference;
10254           (void) ClutImageChannel(image,channel,
10255             argument_list[0].image_reference);
10256           break;
10257         }
10258         case 114:  /* LiquidRescale */
10259         {
10260           if (attribute_flag[0] != 0)
10261             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10262               &geometry,exception);
10263           if (attribute_flag[1] != 0)
10264             geometry.width=argument_list[1].integer_reference;
10265           if (attribute_flag[2] != 0)
10266             geometry.height=argument_list[2].integer_reference;
10267           if (attribute_flag[3] == 0)
10268             argument_list[3].real_reference=1.0;
10269           if (attribute_flag[4] == 0)
10270             argument_list[4].real_reference=0.0;
10271           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10272             argument_list[3].real_reference,argument_list[4].real_reference,
10273             exception);
10274           break;
10275         }
10276         case 115:  /* EncipherImage */
10277         {
10278           (void) EncipherImage(image,argument_list[0].string_reference,
10279             exception);
10280           break;
10281         }
10282         case 116:  /* DecipherImage */
10283         {
10284           (void) DecipherImage(image,argument_list[0].string_reference,
10285             exception);
10286           break;
10287         }
10288         case 117:  /* Deskew */
10289         {
10290           geometry_info.rho=QuantumRange/2.0;
10291           if (attribute_flag[0] != 0)
10292             flags=ParseGeometry(argument_list[0].string_reference,
10293               &geometry_info);
10294           if (attribute_flag[1] != 0)
10295             geometry_info.rho=SiPrefixToDouble(
10296               argument_list[1].string_reference,QuantumRange);
10297           image=DeskewImage(image,geometry_info.rho,exception);
10298           break;
10299         }
10300         case 118:  /* Remap */
10301         {
10302           QuantizeInfo
10303             *quantize_info;
10304
10305           if (attribute_flag[0] == 0)
10306             {
10307               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10308                 PackageName);
10309               goto PerlException;
10310             }
10311           quantize_info=AcquireQuantizeInfo(info->image_info);
10312           if (attribute_flag[1] != 0)
10313             quantize_info->dither=(MagickBooleanType)
10314               argument_list[1].integer_reference;
10315           if (attribute_flag[2] != 0)
10316             quantize_info->dither_method=(DitherMethod)
10317               argument_list[2].integer_reference;
10318           (void) RemapImages(quantize_info,image,
10319             argument_list[0].image_reference);
10320           quantize_info=DestroyQuantizeInfo(quantize_info);
10321           break;
10322         }
10323         case 119:  /* SparseColor */
10324         {
10325           AV
10326             *av;
10327
10328           double
10329             *coordinates;
10330
10331           SparseColorMethod
10332             method;
10333
10334           size_t
10335             number_coordinates;
10336
10337           VirtualPixelMethod
10338             virtual_pixel;
10339
10340           if (attribute_flag[0] == 0)
10341             break;
10342           method=UndefinedColorInterpolate;
10343           if (attribute_flag[1] != 0)
10344             method=(SparseColorMethod) argument_list[1].integer_reference;
10345           av=(AV *) argument_list[0].array_reference;
10346           number_coordinates=(size_t) av_len(av)+1;
10347           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10348             sizeof(*coordinates));
10349           if (coordinates == (double *) NULL)
10350             {
10351               ThrowPerlException(exception,ResourceLimitFatalError,
10352                 "MemoryAllocationFailed",PackageName);
10353               goto PerlException;
10354             }
10355           for (j=0; j < (ssize_t) number_coordinates; j++)
10356             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10357           virtual_pixel=UndefinedVirtualPixelMethod;
10358           if (attribute_flag[2] != 0)
10359             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10360               argument_list[2].integer_reference);
10361           if (attribute_flag[3] != 0)
10362             channel=(ChannelType) argument_list[3].integer_reference;
10363           image=SparseColorImage(image,channel,method,number_coordinates,
10364             coordinates,exception);
10365           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10366             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10367           coordinates=(double *) RelinquishMagickMemory(coordinates);
10368           break;
10369         }
10370         case 120:  /* Function */
10371         {
10372           AV
10373             *av;
10374
10375           double
10376             *parameters;
10377
10378           MagickFunction
10379             function;
10380
10381           size_t
10382             number_parameters;
10383
10384           VirtualPixelMethod
10385             virtual_pixel;
10386
10387           if (attribute_flag[0] == 0)
10388             break;
10389           function=UndefinedFunction;
10390           if (attribute_flag[1] != 0)
10391             function=(MagickFunction) argument_list[1].integer_reference;
10392           av=(AV *) argument_list[0].array_reference;
10393           number_parameters=(size_t) av_len(av)+1;
10394           parameters=(double *) AcquireQuantumMemory(number_parameters,
10395             sizeof(*parameters));
10396           if (parameters == (double *) NULL)
10397             {
10398               ThrowPerlException(exception,ResourceLimitFatalError,
10399                 "MemoryAllocationFailed",PackageName);
10400               goto PerlException;
10401             }
10402           for (j=0; j < (ssize_t) number_parameters; j++)
10403             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10404           virtual_pixel=UndefinedVirtualPixelMethod;
10405           if (attribute_flag[2] != 0)
10406             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10407               argument_list[2].integer_reference);
10408           (void) FunctionImage(image,function,number_parameters,parameters,
10409             exception);
10410           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10411             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10412           parameters=(double *) RelinquishMagickMemory(parameters);
10413           break;
10414         }
10415         case 121:  /* SelectiveBlur */
10416         {
10417           if (attribute_flag[0] != 0)
10418             {
10419               flags=ParseGeometry(argument_list[0].string_reference,
10420                 &geometry_info);
10421               if ((flags & SigmaValue) == 0)
10422                 geometry_info.sigma=1.0;
10423               if ((flags & PercentValue) != 0)
10424                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10425             }
10426           if (attribute_flag[1] != 0)
10427             geometry_info.rho=argument_list[1].real_reference;
10428           if (attribute_flag[2] != 0)
10429             geometry_info.sigma=argument_list[2].real_reference;
10430           if (attribute_flag[3] != 0)
10431             geometry_info.xi=argument_list[3].integer_reference;;
10432           if (attribute_flag[4] != 0)
10433             channel=(ChannelType) argument_list[4].integer_reference;
10434           image=SelectiveBlurImageChannel(image,channel,geometry_info.rho,
10435             geometry_info.sigma,geometry_info.xi,exception);
10436           break;
10437         }
10438         case 122:  /* HaldClut */
10439         {
10440           if (attribute_flag[0] == 0)
10441             {
10442               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10443                 PackageName);
10444               goto PerlException;
10445             }
10446           if (attribute_flag[1] != 0)
10447             channel=(ChannelType) argument_list[1].integer_reference;
10448           (void) HaldClutImageChannel(image,channel,
10449             argument_list[0].image_reference);
10450           break;
10451         }
10452         case 123:  /* BlueShift */
10453         {
10454           if (attribute_flag[0] != 0)
10455             (void) ParseGeometry(argument_list[0].string_reference,
10456               &geometry_info);
10457           image=BlueShiftImage(image,geometry_info.rho,exception);
10458           break;
10459         }
10460         case 124:  /* ForwardFourierTransformImage */
10461         {
10462           image=ForwardFourierTransformImage(image,
10463             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10464             exception);
10465           break;
10466         }
10467         case 125:  /* InverseFourierTransformImage */
10468         {
10469           image=InverseFourierTransformImage(image,image->next,
10470             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10471             exception);
10472           break;
10473         }
10474         case 126:  /* ColorDecisionList */
10475         {
10476           if (attribute_flag[0] == 0)
10477             argument_list[0].string_reference=(char *) NULL;
10478           (void) ColorDecisionListImage(image,
10479             argument_list[0].string_reference);
10480           break;
10481         }
10482         case 127:  /* AutoGamma */
10483         {
10484           if (attribute_flag[0] != 0)
10485             channel=(ChannelType) argument_list[0].integer_reference;
10486           (void) AutoGammaImageChannel(image,channel);
10487           break;
10488         }
10489         case 128:  /* AutoLevel */
10490         {
10491           if (attribute_flag[0] != 0)
10492             channel=(ChannelType) argument_list[0].integer_reference;
10493           (void) AutoLevelImageChannel(image,channel);
10494           break;
10495         }
10496         case 129:  /* LevelColors */
10497         {
10498           MagickPixelPacket
10499             black_point,
10500             white_point;
10501
10502           (void) QueryMagickColor("#000000",&black_point,exception);
10503           (void) QueryMagickColor("#ffffff",&white_point,exception);
10504           if (attribute_flag[1] != 0)
10505              (void) QueryMagickColor(argument_list[1].string_reference,
10506                &black_point,exception);
10507           if (attribute_flag[2] != 0)
10508              (void) QueryMagickColor(argument_list[2].string_reference,
10509                &white_point,exception);
10510           if (attribute_flag[3] != 0)
10511             channel=(ChannelType) argument_list[3].integer_reference;
10512           (void) LevelColorsImageChannel(image,channel,&black_point,
10513             &white_point,argument_list[0].integer_reference != 0 ? MagickTrue :
10514             MagickFalse);
10515           break;
10516         }
10517         case 130:  /* Clamp */
10518         {
10519           if (attribute_flag[0] != 0)
10520             channel=(ChannelType) argument_list[0].integer_reference;
10521           (void) ClampImageChannel(image,channel);
10522           break;
10523         }
10524         case 131:  /* Filter */
10525         {
10526           KernelInfo
10527             *kernel;
10528
10529           if (attribute_flag[0] == 0)
10530             break;
10531           kernel=AcquireKernelInfo(argument_list[0].string_reference);
10532           if (kernel == (KernelInfo *) NULL)
10533             break;
10534           if (attribute_flag[1] != 0)
10535             channel=(ChannelType) argument_list[1].integer_reference;
10536           if (attribute_flag[2] != 0)
10537             image->bias=SiPrefixToDouble(argument_list[2].string_reference,
10538               QuantumRange);
10539           image=FilterImageChannel(image,channel,kernel,exception);
10540           kernel=DestroyKernelInfo(kernel);
10541           break;
10542         }
10543         case 132:  /* BrightnessContrast */
10544         {
10545           double
10546             brightness,
10547             contrast;
10548
10549           brightness=0.0;
10550           contrast=0.0;
10551           if (attribute_flag[0] != 0)
10552             {
10553               flags=ParseGeometry(argument_list[0].string_reference,
10554                 &geometry_info);
10555               brightness=geometry_info.rho;
10556               if ((flags & SigmaValue) == 0)
10557                 contrast=geometry_info.sigma;
10558             }
10559           if (attribute_flag[1] != 0)
10560             brightness=argument_list[1].real_reference;
10561           if (attribute_flag[2] != 0)
10562             contrast=argument_list[2].real_reference;
10563           if (attribute_flag[4] != 0)
10564             channel=(ChannelType) argument_list[4].integer_reference;
10565           (void) BrightnessContrastImageChannel(image,channel,brightness,
10566             contrast);
10567           break;
10568         }
10569         case 133:  /* Morphology */
10570         {
10571           KernelInfo
10572             *kernel;
10573
10574           MorphologyMethod
10575             method;
10576
10577           ssize_t
10578             iterations;
10579
10580           if (attribute_flag[0] == 0)
10581             break;
10582           kernel=AcquireKernelInfo(argument_list[0].string_reference);
10583           if (kernel == (KernelInfo *) NULL)
10584             break;
10585           if (attribute_flag[1] != 0)
10586             channel=(ChannelType) argument_list[1].integer_reference;
10587           method=UndefinedMorphology;
10588           if (attribute_flag[2] != 0)
10589             method=argument_list[2].integer_reference;
10590           iterations=1;
10591           if (attribute_flag[3] != 0)
10592             iterations=argument_list[4].integer_reference;
10593           image=MorphologyImageChannel(image,channel,method,iterations,kernel,
10594             exception);
10595           kernel=DestroyKernelInfo(kernel);
10596           break;
10597         }
10598         case 108:  /* Recolor */
10599         case 134:  /* ColorMatrix */
10600         {
10601           AV
10602             *av;
10603
10604           double
10605             *color_matrix;
10606
10607           KernelInfo
10608             *kernel_info;
10609
10610           size_t
10611             order;
10612
10613           if (attribute_flag[0] == 0)
10614             break;
10615           av=(AV *) argument_list[0].array_reference;
10616           order=(size_t) sqrt(av_len(av)+1);
10617           color_matrix=(double *) AcquireQuantumMemory(order,order*
10618             sizeof(*color_matrix));
10619           if (color_matrix == (double *) NULL)
10620             {
10621               ThrowPerlException(exception,ResourceLimitFatalError,
10622                 "MemoryAllocationFailed",PackageName);
10623               goto PerlException;
10624            }
10625           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10626             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10627           for ( ; j < (ssize_t) (order*order); j++)
10628             color_matrix[j]=0.0;
10629           kernel_info=AcquireKernelInfo("1");
10630           if (kernel_info == (KernelInfo *) NULL)
10631             break;
10632           kernel_info->width=order;
10633           kernel_info->height=order;
10634           kernel_info->values=color_matrix;
10635           image=ColorMatrixImage(image,kernel_info,exception);
10636           kernel_info->values=(double *) NULL;
10637           kernel_info=DestroyKernelInfo(kernel_info);
10638           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10639           break;
10640         }
10641         case 135:  /* Color */
10642         {
10643           MagickPixelPacket
10644             color;
10645
10646           (void) QueryMagickColor("none",&color,exception);
10647           if (attribute_flag[0] != 0)
10648             (void) QueryMagickColor(argument_list[0].string_reference,
10649               &color,exception);
10650           (void) SetImageColor(image,&color);
10651           break;
10652         }
10653         case 136:  /* Mode */
10654         {
10655           if (attribute_flag[0] != 0)
10656             {
10657               flags=ParseGeometry(argument_list[0].string_reference,
10658                 &geometry_info);
10659               if ((flags & SigmaValue) == 0)
10660                 geometry_info.sigma=1.0;
10661             }
10662           if (attribute_flag[1] != 0)
10663             geometry_info.rho=argument_list[1].real_reference;
10664           if (attribute_flag[2] != 0)
10665             geometry_info.sigma=argument_list[2].real_reference;
10666           if (attribute_flag[3] != 0)
10667             channel=(ChannelType) argument_list[3].integer_reference;
10668           image=StatisticImageChannel(image,channel,ModeStatistic,
10669             (size_t) geometry_info.rho,(size_t) geometry_info.sigma,exception);
10670           break;
10671         }
10672         case 137:  /* Statistic */
10673         {
10674           StatisticType
10675             statistic;
10676
10677           statistic=UndefinedStatistic;
10678           if (attribute_flag[0] != 0)
10679             {
10680               flags=ParseGeometry(argument_list[0].string_reference,
10681                 &geometry_info);
10682               if ((flags & SigmaValue) == 0)
10683                 geometry_info.sigma=1.0;
10684             }
10685           if (attribute_flag[1] != 0)
10686             geometry_info.rho=argument_list[1].real_reference;
10687           if (attribute_flag[2] != 0)
10688             geometry_info.sigma=argument_list[2].real_reference;
10689           if (attribute_flag[3] != 0)
10690             channel=(ChannelType) argument_list[3].integer_reference;
10691           if (attribute_flag[4] != 0)
10692             statistic=(StatisticType) argument_list[4].integer_reference;
10693           image=StatisticImageChannel(image,channel,statistic,
10694             (size_t) geometry_info.rho,(size_t) geometry_info.sigma,exception);
10695           break;
10696         }
10697       }
10698       if (next != (Image *) NULL)
10699         (void) CatchImageException(next);
10700       if (region_image != (Image *) NULL)
10701         {
10702           /*
10703             Composite region.
10704           */
10705           status=CompositeImage(region_image,CopyCompositeOp,image,
10706             region_info.x,region_info.y);
10707           (void) CatchImageException(region_image);
10708           image=DestroyImage(image);
10709           image=region_image;
10710         }
10711       if (image != (Image *) NULL)
10712         {
10713           number_images++;
10714           if (next && (next != image))
10715             {
10716               image->next=next->next;
10717               DeleteImageFromRegistry(*pv,next);
10718             }
10719           sv_setiv(*pv,(IV) image);
10720           next=image;
10721         }
10722       if (*pv)
10723         pv++;
10724     }
10725
10726   PerlException:
10727     if (reference_vector)
10728       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
10729     InheritPerlException(exception,perl_exception);
10730     exception=DestroyExceptionInfo(exception);
10731     sv_setiv(perl_exception,(IV) number_images);
10732     SvPOK_on(perl_exception);
10733     ST(0)=sv_2mortal(perl_exception);
10734     XSRETURN(1);
10735   }
10736 \f
10737 #
10738 ###############################################################################
10739 #                                                                             #
10740 #                                                                             #
10741 #                                                                             #
10742 #   M o n t a g e                                                             #
10743 #                                                                             #
10744 #                                                                             #
10745 #                                                                             #
10746 ###############################################################################
10747 #
10748 #
10749 void
10750 Montage(ref,...)
10751   Image::Magick ref=NO_INIT
10752   ALIAS:
10753     MontageImage  = 1
10754     montage       = 2
10755     montageimage  = 3
10756   PPCODE:
10757   {
10758     AV
10759       *av;
10760
10761     char
10762       *attribute;
10763
10764     ExceptionInfo
10765       *exception;
10766
10767     HV
10768       *hv;
10769
10770     Image
10771       *image,
10772       *next;
10773
10774     MagickPixelPacket
10775       transparent_color;
10776
10777     MontageInfo
10778       *montage_info;
10779
10780     register ssize_t
10781       i;
10782
10783     ssize_t
10784       sp;
10785
10786     struct PackageInfo
10787       *info;
10788
10789     SV
10790       *av_reference,
10791       *perl_exception,
10792       *reference,
10793       *rv,
10794       *sv;
10795
10796     PERL_UNUSED_VAR(ref);
10797     PERL_UNUSED_VAR(ix);
10798     exception=AcquireExceptionInfo();
10799     perl_exception=newSVpv("",0);
10800     sv=NULL;
10801     attribute=NULL;
10802     if (sv_isobject(ST(0)) == 0)
10803       {
10804         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
10805           PackageName);
10806         goto PerlException;
10807       }
10808     reference=SvRV(ST(0));
10809     hv=SvSTASH(reference);
10810     av=newAV();
10811     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
10812     SvREFCNT_dec(av);
10813     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
10814     if (image == (Image *) NULL)
10815       {
10816         ThrowPerlException(exception,OptionError,"NoImagesDefined",
10817           PackageName);
10818         goto PerlException;
10819       }
10820     /*
10821       Get options.
10822     */
10823     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
10824     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
10825     (void) QueryMagickColor("none",&transparent_color,exception);
10826     for (i=2; i < items; i+=2)
10827     {
10828       attribute=(char *) SvPV(ST(i-1),na);
10829       switch (*attribute)
10830       {
10831         case 'B':
10832         case 'b':
10833         {
10834           if (LocaleCompare(attribute,"background") == 0)
10835             {
10836               (void) QueryColorDatabase(SvPV(ST(i),na),
10837                 &montage_info->background_color,exception);
10838               for (next=image; next; next=next->next)
10839                 next->background_color=montage_info->background_color;
10840               break;
10841             }
10842           if (LocaleCompare(attribute,"border") == 0)
10843             {
10844               montage_info->border_width=SvIV(ST(i));
10845               break;
10846             }
10847           if (LocaleCompare(attribute,"bordercolor") == 0)
10848             {
10849               (void) QueryColorDatabase(SvPV(ST(i),na),
10850                 &montage_info->border_color,exception);
10851               for (next=image; next; next=next->next)
10852                 next->border_color=montage_info->border_color;
10853               break;
10854             }
10855           if (LocaleCompare(attribute,"borderwidth") == 0)
10856             {
10857               montage_info->border_width=SvIV(ST(i));
10858               break;
10859             }
10860           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10861             attribute);
10862           break;
10863         }
10864         case 'C':
10865         case 'c':
10866         {
10867           if (LocaleCompare(attribute,"compose") == 0)
10868             {
10869               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
10870                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
10871               if (sp < 0)
10872                 {
10873                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
10874                     SvPV(ST(i),na));
10875                   break;
10876                 }
10877               for (next=image; next; next=next->next)
10878                 next->compose=(CompositeOperator) sp;
10879               break;
10880             }
10881           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10882             attribute);
10883           break;
10884         }
10885         case 'F':
10886         case 'f':
10887         {
10888           if (LocaleCompare(attribute,"fill") == 0)
10889             {
10890               (void) QueryColorDatabase(SvPV(ST(i),na),&montage_info->fill,
10891                 exception);
10892               break;
10893             }
10894           if (LocaleCompare(attribute,"font") == 0)
10895             {
10896               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
10897               break;
10898             }
10899           if (LocaleCompare(attribute,"frame") == 0)
10900             {
10901               char
10902                 *p;
10903
10904               p=SvPV(ST(i),na);
10905               if (IsGeometry(p) == MagickFalse)
10906                 {
10907                   ThrowPerlException(exception,OptionError,"MissingGeometry",
10908                     p);
10909                   break;
10910                 }
10911               (void) CloneString(&montage_info->frame,p);
10912               if (*p == '\0')
10913                 montage_info->frame=(char *) NULL;
10914               break;
10915             }
10916           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10917             attribute);
10918           break;
10919         }
10920         case 'G':
10921         case 'g':
10922         {
10923           if (LocaleCompare(attribute,"geometry") == 0)
10924             {
10925               char
10926                 *p;
10927
10928               p=SvPV(ST(i),na);
10929               if (IsGeometry(p) == MagickFalse)
10930                 {
10931                   ThrowPerlException(exception,OptionError,"MissingGeometry",
10932                     p);
10933                   break;
10934                 }
10935              (void) CloneString(&montage_info->geometry,p);
10936              if (*p == '\0')
10937                montage_info->geometry=(char *) NULL;
10938              break;
10939            }
10940          if (LocaleCompare(attribute,"gravity") == 0)
10941            {
10942              ssize_t
10943                in;
10944
10945              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
10946                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
10947              if (in < 0)
10948                {
10949                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
10950                    SvPV(ST(i),na));
10951                  return;
10952                }
10953              montage_info->gravity=(GravityType) in;
10954              for (next=image; next; next=next->next)
10955                next->gravity=(GravityType) in;
10956              break;
10957            }
10958           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10959             attribute);
10960           break;
10961         }
10962         case 'L':
10963         case 'l':
10964         {
10965           if (LocaleCompare(attribute,"label") == 0)
10966             {
10967               for (next=image; next; next=next->next)
10968                 (void) SetImageProperty(next,"label",InterpretImageProperties(
10969                   info ? info->image_info : (ImageInfo *) NULL,next,
10970                   SvPV(ST(i),na)));
10971               break;
10972             }
10973           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10974             attribute);
10975           break;
10976         }
10977         case 'M':
10978         case 'm':
10979         {
10980           if (LocaleCompare(attribute,"mattecolor") == 0)
10981             {
10982               (void) QueryColorDatabase(SvPV(ST(i),na),
10983                 &montage_info->matte_color,exception);
10984               for (next=image; next; next=next->next)
10985                 next->matte_color=montage_info->matte_color;
10986               break;
10987             }
10988           if (LocaleCompare(attribute,"mode") == 0)
10989             {
10990               ssize_t
10991                 in;
10992
10993               in=!SvPOK(ST(i)) ? SvIV(ST(i)) :
10994                 ParseCommandOption(MagickModeOptions,MagickFalse,SvPV(ST(i),na));
10995               switch (in)
10996               {
10997                 default:
10998                 {
10999                   ThrowPerlException(exception,OptionError,
11000                     "UnrecognizedModeType",SvPV(ST(i),na));
11001                   break;
11002                 }
11003                 case FrameMode:
11004                 {
11005                   (void) CloneString(&montage_info->frame,"15x15+3+3");
11006                   montage_info->shadow=MagickTrue;
11007                   break;
11008                 }
11009                 case UnframeMode:
11010                 {
11011                   montage_info->frame=(char *) NULL;
11012                   montage_info->shadow=MagickFalse;
11013                   montage_info->border_width=0;
11014                   break;
11015                 }
11016                 case ConcatenateMode:
11017                 {
11018                   montage_info->frame=(char *) NULL;
11019                   montage_info->shadow=MagickFalse;
11020                   (void) CloneString(&montage_info->geometry,"+0+0");
11021                   montage_info->border_width=0;
11022                 }
11023               }
11024               break;
11025             }
11026           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11027             attribute);
11028           break;
11029         }
11030         case 'P':
11031         case 'p':
11032         {
11033           if (LocaleCompare(attribute,"pointsize") == 0)
11034             {
11035               montage_info->pointsize=SvIV(ST(i));
11036               break;
11037             }
11038           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11039             attribute);
11040           break;
11041         }
11042         case 'S':
11043         case 's':
11044         {
11045           if (LocaleCompare(attribute,"shadow") == 0)
11046             {
11047               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11048                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11049               if (sp < 0)
11050                 {
11051                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11052                     SvPV(ST(i),na));
11053                   break;
11054                 }
11055              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11056              break;
11057             }
11058           if (LocaleCompare(attribute,"stroke") == 0)
11059             {
11060               (void) QueryColorDatabase(SvPV(ST(i),na),&montage_info->stroke,
11061                 exception);
11062               break;
11063             }
11064           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11065             attribute);
11066           break;
11067         }
11068         case 'T':
11069         case 't':
11070         {
11071           if (LocaleCompare(attribute,"texture") == 0)
11072             {
11073               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11074               break;
11075             }
11076           if (LocaleCompare(attribute,"tile") == 0)
11077             {
11078               char *p=SvPV(ST(i),na);
11079               if (IsGeometry(p) == MagickFalse)
11080                 {
11081                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11082                     p);
11083                   break;
11084                 }
11085               (void) CloneString(&montage_info->tile,p);
11086               if (*p == '\0')
11087                 montage_info->tile=(char *) NULL;
11088               break;
11089             }
11090           if (LocaleCompare(attribute,"title") == 0)
11091             {
11092               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11093               break;
11094             }
11095           if (LocaleCompare(attribute,"transparent") == 0)
11096             {
11097               MagickPixelPacket
11098                 transparent_color;
11099
11100               QueryMagickColor(SvPV(ST(i),na),&transparent_color,exception);
11101               for (next=image; next; next=next->next)
11102                 (void) TransparentPaintImage(next,&transparent_color,
11103                   TransparentOpacity,MagickFalse);
11104               break;
11105             }
11106           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11107             attribute);
11108           break;
11109         }
11110         default:
11111         {
11112           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11113             attribute);
11114           break;
11115         }
11116       }
11117     }
11118     image=MontageImageList(info->image_info,montage_info,image,exception);
11119     montage_info=DestroyMontageInfo(montage_info);
11120     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11121       goto PerlException;
11122     if (transparent_color.opacity != TransparentOpacity)
11123       for (next=image; next; next=next->next)
11124         (void) TransparentPaintImage(next,&transparent_color,
11125           TransparentOpacity,MagickFalse);
11126     for (  ; image; image=image->next)
11127     {
11128       AddImageToRegistry(sv,image);
11129       rv=newRV(sv);
11130       av_push(av,sv_bless(rv,hv));
11131       SvREFCNT_dec(sv);
11132     }
11133     exception=DestroyExceptionInfo(exception);
11134     ST(0)=av_reference;
11135     SvREFCNT_dec(perl_exception);
11136     XSRETURN(1);
11137
11138   PerlException:
11139     InheritPerlException(exception,perl_exception);
11140     exception=DestroyExceptionInfo(exception);
11141     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11142     SvPOK_on(perl_exception);
11143     ST(0)=sv_2mortal(perl_exception);
11144     XSRETURN(1);
11145   }
11146 \f
11147 #
11148 ###############################################################################
11149 #                                                                             #
11150 #                                                                             #
11151 #                                                                             #
11152 #   M o r p h                                                                 #
11153 #                                                                             #
11154 #                                                                             #
11155 #                                                                             #
11156 ###############################################################################
11157 #
11158 #
11159 void
11160 Morph(ref,...)
11161   Image::Magick ref=NO_INIT
11162   ALIAS:
11163     MorphImage  = 1
11164     morph       = 2
11165     morphimage  = 3
11166   PPCODE:
11167   {
11168     AV
11169       *av;
11170
11171     char
11172       *attribute;
11173
11174     ExceptionInfo
11175       *exception;
11176
11177     HV
11178       *hv;
11179
11180     Image
11181       *image;
11182
11183     register ssize_t
11184       i;
11185
11186     ssize_t
11187       number_frames;
11188
11189     struct PackageInfo
11190       *info;
11191
11192     SV
11193       *av_reference,
11194       *perl_exception,
11195       *reference,
11196       *rv,
11197       *sv;
11198
11199     PERL_UNUSED_VAR(ref);
11200     PERL_UNUSED_VAR(ix);
11201     exception=AcquireExceptionInfo();
11202     perl_exception=newSVpv("",0);
11203     sv=NULL;
11204     av=NULL;
11205     attribute=NULL;
11206     if (sv_isobject(ST(0)) == 0)
11207       {
11208         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11209           PackageName);
11210         goto PerlException;
11211       }
11212     reference=SvRV(ST(0));
11213     hv=SvSTASH(reference);
11214     av=newAV();
11215     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11216     SvREFCNT_dec(av);
11217     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11218     if (image == (Image *) NULL)
11219       {
11220         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11221           PackageName);
11222         goto PerlException;
11223       }
11224     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11225     /*
11226       Get attribute.
11227     */
11228     number_frames=30;
11229     for (i=2; i < items; i+=2)
11230     {
11231       attribute=(char *) SvPV(ST(i-1),na);
11232       switch (*attribute)
11233       {
11234         case 'F':
11235         case 'f':
11236         {
11237           if (LocaleCompare(attribute,"frames") == 0)
11238             {
11239               number_frames=SvIV(ST(i));
11240               break;
11241             }
11242           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11243             attribute);
11244           break;
11245         }
11246         default:
11247         {
11248           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11249             attribute);
11250           break;
11251         }
11252       }
11253     }
11254     image=MorphImages(image,number_frames,exception);
11255     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11256       goto PerlException;
11257     for ( ; image; image=image->next)
11258     {
11259       AddImageToRegistry(sv,image);
11260       rv=newRV(sv);
11261       av_push(av,sv_bless(rv,hv));
11262       SvREFCNT_dec(sv);
11263     }
11264     exception=DestroyExceptionInfo(exception);
11265     ST(0)=av_reference;
11266     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11267     XSRETURN(1);
11268
11269   PerlException:
11270     InheritPerlException(exception,perl_exception);
11271     exception=DestroyExceptionInfo(exception);
11272     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11273     SvPOK_on(perl_exception);
11274     ST(0)=sv_2mortal(perl_exception);
11275     XSRETURN(1);
11276   }
11277 \f
11278 #
11279 ###############################################################################
11280 #                                                                             #
11281 #                                                                             #
11282 #                                                                             #
11283 #   M o s a i c                                                               #
11284 #                                                                             #
11285 #                                                                             #
11286 #                                                                             #
11287 ###############################################################################
11288 #
11289 #
11290 void
11291 Mosaic(ref)
11292   Image::Magick ref=NO_INIT
11293   ALIAS:
11294     MosaicImage   = 1
11295     mosaic        = 2
11296     mosaicimage   = 3
11297   PPCODE:
11298   {
11299     AV
11300       *av;
11301
11302     ExceptionInfo
11303       *exception;
11304
11305     HV
11306       *hv;
11307
11308     Image
11309       *image;
11310
11311     struct PackageInfo
11312       *info;
11313
11314     SV
11315       *perl_exception,
11316       *reference,
11317       *rv,
11318       *sv;
11319
11320     PERL_UNUSED_VAR(ref);
11321     PERL_UNUSED_VAR(ix);
11322     exception=AcquireExceptionInfo();
11323     perl_exception=newSVpv("",0);
11324     sv=NULL;
11325     if (sv_isobject(ST(0)) == 0)
11326       {
11327         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11328           PackageName);
11329         goto PerlException;
11330       }
11331     reference=SvRV(ST(0));
11332     hv=SvSTASH(reference);
11333     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11334     if (image == (Image *) NULL)
11335       {
11336         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11337           PackageName);
11338         goto PerlException;
11339       }
11340     image=MergeImageLayers(image,MosaicLayer,exception);
11341     /*
11342       Create blessed Perl array for the returned image.
11343     */
11344     av=newAV();
11345     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11346     SvREFCNT_dec(av);
11347     AddImageToRegistry(sv,image);
11348     rv=newRV(sv);
11349     av_push(av,sv_bless(rv,hv));
11350     SvREFCNT_dec(sv);
11351     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11352     (void) CopyMagickString(image->filename,info->image_info->filename,
11353       MaxTextExtent);
11354     SetImageInfo(info->image_info,0,&image->exception);
11355     exception=DestroyExceptionInfo(exception);
11356     SvREFCNT_dec(perl_exception);
11357     XSRETURN(1);
11358
11359   PerlException:
11360     InheritPerlException(exception,perl_exception);
11361     exception=DestroyExceptionInfo(exception);
11362     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11363     SvPOK_on(perl_exception);  /* return messages in string context */
11364     ST(0)=sv_2mortal(perl_exception);
11365     XSRETURN(1);
11366   }
11367 \f
11368 #
11369 ###############################################################################
11370 #                                                                             #
11371 #                                                                             #
11372 #                                                                             #
11373 #   P i n g                                                                   #
11374 #                                                                             #
11375 #                                                                             #
11376 #                                                                             #
11377 ###############################################################################
11378 #
11379 #
11380 void
11381 Ping(ref,...)
11382   Image::Magick ref=NO_INIT
11383   ALIAS:
11384     PingImage  = 1
11385     ping       = 2
11386     pingimage  = 3
11387   PPCODE:
11388   {
11389     AV
11390       *av;
11391
11392     char
11393       **keep,
11394       **list;
11395
11396     ExceptionInfo
11397       *exception;
11398
11399     HV
11400       *hv;
11401
11402     Image
11403       *image,
11404       *next;
11405
11406     int
11407       n;
11408
11409     MagickBooleanType
11410       status;
11411
11412     register char
11413       **p;
11414
11415     register ssize_t
11416       i;
11417
11418     ssize_t
11419       ac;
11420
11421     STRLEN
11422       *length;
11423
11424     struct PackageInfo
11425       *info,
11426       *package_info;
11427
11428     SV
11429       *perl_exception,
11430       *reference;
11431
11432     size_t
11433       count;
11434
11435     PERL_UNUSED_VAR(ref);
11436     PERL_UNUSED_VAR(ix);
11437     exception=AcquireExceptionInfo();
11438     perl_exception=newSVpv("",0);
11439     package_info=(struct PackageInfo *) NULL;
11440     ac=(items < 2) ? 1 : items-1;
11441     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
11442     keep=list;
11443     length=(STRLEN *) NULL;
11444     if (list == (char **) NULL)
11445       {
11446         ThrowPerlException(exception,ResourceLimitError,
11447           "MemoryAllocationFailed",PackageName);
11448         goto PerlException;
11449       }
11450     keep=list;
11451     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
11452     if (length == (STRLEN *) NULL)
11453       {
11454         ThrowPerlException(exception,ResourceLimitError,
11455           "MemoryAllocationFailed",PackageName);
11456         goto PerlException;
11457       }
11458     if (sv_isobject(ST(0)) == 0)
11459       {
11460         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11461           PackageName);
11462         goto PerlException;
11463       }
11464     reference=SvRV(ST(0));
11465     hv=SvSTASH(reference);
11466     if (SvTYPE(reference) != SVt_PVAV)
11467       {
11468         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11469           PackageName);
11470         goto PerlException;
11471       }
11472     av=(AV *) reference;
11473     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11474       exception);
11475     package_info=ClonePackageInfo(info,exception);
11476     n=1;
11477     if (items <= 1)
11478       *list=(char *) (*package_info->image_info->filename ?
11479         package_info->image_info->filename : "XC:black");
11480     else
11481       for (n=0, i=0; i < ac; i++)
11482       {
11483         list[n]=(char *) SvPV(ST(i+1),length[n]);
11484         if ((items >= 3) && strEQcase(list[n],"blob"))
11485           {
11486             void
11487               *blob;
11488
11489             i++;
11490             blob=(void *) (SvPV(ST(i+1),length[n]));
11491             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
11492           }
11493         if ((items >= 3) && strEQcase(list[n],"filename"))
11494           continue;
11495         if ((items >= 3) && strEQcase(list[n],"file"))
11496           {
11497             FILE
11498               *file;
11499
11500             PerlIO
11501               *io_info;
11502
11503             i++;
11504             io_info=IoIFP(sv_2io(ST(i+1)));
11505             if (io_info == (PerlIO *) NULL)
11506               {
11507                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11508                   PackageName);
11509                 continue;
11510               }
11511             file=PerlIO_findFILE(io_info);
11512             if (file == (FILE *) NULL)
11513               {
11514                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11515                   PackageName);
11516                 continue;
11517               }
11518             SetImageInfoFile(package_info->image_info,file);
11519           }
11520         if ((items >= 3) && strEQcase(list[n],"magick"))
11521           continue;
11522         n++;
11523       }
11524     list[n]=(char *) NULL;
11525     keep=list;
11526     status=ExpandFilenames(&n,&list);
11527     if (status == MagickFalse)
11528       {
11529         ThrowPerlException(exception,ResourceLimitError,
11530           "MemoryAllocationFailed",PackageName);
11531         goto PerlException;
11532       }
11533     count=0;
11534     for (i=0; i < n; i++)
11535     {
11536       (void) CopyMagickString(package_info->image_info->filename,list[i],
11537         MaxTextExtent);
11538       image=PingImage(package_info->image_info,exception);
11539       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11540         break;
11541       if ((package_info->image_info->file != (FILE *) NULL) ||
11542           (package_info->image_info->blob != (void *) NULL))
11543         DisassociateImageStream(image);
11544       count+=GetImageListLength(image);
11545       EXTEND(sp,4*count);
11546       for (next=image; next; next=next->next)
11547       {
11548         PUSHs(sv_2mortal(newSViv(next->columns)));
11549         PUSHs(sv_2mortal(newSViv(next->rows)));
11550         PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
11551         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
11552       }
11553       image=DestroyImageList(image);
11554     }
11555     /*
11556       Free resources.
11557     */
11558     for (i=0; i < n; i++)
11559       if (list[i] != (char *) NULL)
11560         for (p=keep; list[i] != *p++; )
11561           if (*p == NULL)
11562             {
11563               list[i]=(char *) RelinquishMagickMemory(list[i]);
11564               break;
11565             }
11566
11567   PerlException:
11568     if (package_info != (struct PackageInfo *) NULL)
11569       DestroyPackageInfo(package_info);
11570     if (list && (list != keep))
11571       list=(char **) RelinquishMagickMemory(list);
11572     if (keep)
11573       keep=(char **) RelinquishMagickMemory(keep);
11574     if (length)
11575       length=(STRLEN *) RelinquishMagickMemory(length);
11576     InheritPerlException(exception,perl_exception);
11577     exception=DestroyExceptionInfo(exception);
11578     SvREFCNT_dec(perl_exception);  /* throw away all errors */
11579   }
11580 \f
11581 #
11582 ###############################################################################
11583 #                                                                             #
11584 #                                                                             #
11585 #                                                                             #
11586 #   P r e v i e w                                                             #
11587 #                                                                             #
11588 #                                                                             #
11589 #                                                                             #
11590 ###############################################################################
11591 #
11592 #
11593 void
11594 Preview(ref,...)
11595   Image::Magick ref=NO_INIT
11596   ALIAS:
11597     PreviewImage = 1
11598     preview      = 2
11599     previewimage = 3
11600   PPCODE:
11601   {
11602     AV
11603       *av;
11604
11605     ExceptionInfo
11606       *exception;
11607
11608     HV
11609       *hv;
11610
11611     Image
11612       *image,
11613       *preview_image;
11614
11615     PreviewType
11616       preview_type;
11617
11618     struct PackageInfo
11619       *info;
11620
11621     SV
11622       *av_reference,
11623       *perl_exception,
11624       *reference,
11625       *rv,
11626       *sv;
11627
11628     PERL_UNUSED_VAR(ref);
11629     PERL_UNUSED_VAR(ix);
11630     exception=AcquireExceptionInfo();
11631     perl_exception=newSVpv("",0);
11632     sv=NULL;
11633     av=NULL;
11634     if (sv_isobject(ST(0)) == 0)
11635       {
11636         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11637           PackageName);
11638         goto PerlException;
11639       }
11640     reference=SvRV(ST(0));
11641     hv=SvSTASH(reference);
11642     av=newAV();
11643     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11644     SvREFCNT_dec(av);
11645     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11646     if (image == (Image *) NULL)
11647       {
11648         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11649           PackageName);
11650         goto PerlException;
11651       }
11652     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11653     preview_type=GammaPreview;
11654     if (items > 1)
11655       preview_type=(PreviewType)
11656         ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
11657     for ( ; image; image=image->next)
11658     {
11659       preview_image=PreviewImage(image,preview_type,exception);
11660       if (preview_image == (Image *) NULL)
11661         goto PerlException;
11662       AddImageToRegistry(sv,preview_image);
11663       rv=newRV(sv);
11664       av_push(av,sv_bless(rv,hv));
11665       SvREFCNT_dec(sv);
11666     }
11667     exception=DestroyExceptionInfo(exception);
11668     ST(0)=av_reference;
11669     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11670     XSRETURN(1);
11671
11672   PerlException:
11673     InheritPerlException(exception,perl_exception);
11674     exception=DestroyExceptionInfo(exception);
11675     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11676     SvPOK_on(perl_exception);
11677     ST(0)=sv_2mortal(perl_exception);
11678     XSRETURN(1);
11679   }
11680 \f
11681 #
11682 ###############################################################################
11683 #                                                                             #
11684 #                                                                             #
11685 #                                                                             #
11686 #   Q u e r y C o l o r                                                       #
11687 #                                                                             #
11688 #                                                                             #
11689 #                                                                             #
11690 ###############################################################################
11691 #
11692 #
11693 void
11694 QueryColor(ref,...)
11695   Image::Magick ref=NO_INIT
11696   ALIAS:
11697     querycolor = 1
11698   PPCODE:
11699   {
11700     char
11701       *name;
11702
11703     ExceptionInfo
11704       *exception;
11705
11706     MagickPixelPacket
11707       color;
11708
11709     register ssize_t
11710       i;
11711
11712     SV
11713       *perl_exception;
11714
11715     PERL_UNUSED_VAR(ref);
11716     PERL_UNUSED_VAR(ix);
11717     exception=AcquireExceptionInfo();
11718     perl_exception=newSVpv("",0);
11719     if (items == 1)
11720       {
11721         const ColorInfo
11722           **colorlist;
11723
11724         size_t
11725           colors;
11726
11727         colorlist=GetColorInfoList("*",&colors,exception);
11728         EXTEND(sp,colors);
11729         for (i=0; i < (ssize_t) colors; i++)
11730         {
11731           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
11732         }
11733         colorlist=(const ColorInfo **)
11734           RelinquishMagickMemory((ColorInfo **) colorlist);
11735         goto PerlException;
11736       }
11737     EXTEND(sp,5*items);
11738     for (i=1; i < items; i++)
11739     {
11740       name=(char *) SvPV(ST(i),na);
11741       if (QueryMagickColor(name,&color,exception) == MagickFalse)
11742         {
11743           PUSHs(&sv_undef);
11744           continue;
11745         }
11746       PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
11747       PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
11748       PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
11749       if (color.matte != MagickFalse)
11750         PUSHs(sv_2mortal(newSViv((size_t) floor(color.opacity+0.5))));
11751       if (color.colorspace == CMYKColorspace)
11752         PUSHs(sv_2mortal(newSViv((size_t) floor(color.index+0.5))));
11753     }
11754
11755   PerlException:
11756     InheritPerlException(exception,perl_exception);
11757     exception=DestroyExceptionInfo(exception);
11758     SvREFCNT_dec(perl_exception);
11759   }
11760 \f
11761 #
11762 ###############################################################################
11763 #                                                                             #
11764 #                                                                             #
11765 #                                                                             #
11766 #   Q u e r y C o l o r N a m e                                               #
11767 #                                                                             #
11768 #                                                                             #
11769 #                                                                             #
11770 ###############################################################################
11771 #
11772 #
11773 void
11774 QueryColorname(ref,...)
11775   Image::Magick ref=NO_INIT
11776   ALIAS:
11777     querycolorname = 1
11778   PPCODE:
11779   {
11780     AV
11781       *av;
11782
11783     char
11784       message[MaxTextExtent];
11785
11786     ExceptionInfo
11787       *exception;
11788
11789     Image
11790       *image;
11791
11792     PixelPacket
11793       target_color;
11794
11795     register ssize_t
11796       i;
11797
11798     struct PackageInfo
11799       *info;
11800
11801     SV
11802       *perl_exception,
11803       *reference;  /* reference is the SV* of ref=SvIV(reference) */
11804
11805     PERL_UNUSED_VAR(ref);
11806     PERL_UNUSED_VAR(ix);
11807     exception=AcquireExceptionInfo();
11808     perl_exception=newSVpv("",0);
11809     reference=SvRV(ST(0));
11810     av=(AV *) reference;
11811     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11812       exception);
11813     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11814     if (image == (Image *) NULL)
11815       {
11816         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11817           PackageName);
11818         goto PerlException;
11819       }
11820     EXTEND(sp,items);
11821     for (i=1; i < items; i++)
11822     {
11823       (void) QueryColorDatabase(SvPV(ST(i),na),&target_color,exception);
11824       (void) QueryColorname(image,&target_color,SVGCompliance,message,
11825         exception);
11826       PUSHs(sv_2mortal(newSVpv(message,0)));
11827     }
11828
11829   PerlException:
11830     InheritPerlException(exception,perl_exception);
11831     exception=DestroyExceptionInfo(exception);
11832     SvREFCNT_dec(perl_exception);
11833   }
11834 \f
11835 #
11836 ###############################################################################
11837 #                                                                             #
11838 #                                                                             #
11839 #                                                                             #
11840 #   Q u e r y F o n t                                                         #
11841 #                                                                             #
11842 #                                                                             #
11843 #                                                                             #
11844 ###############################################################################
11845 #
11846 #
11847 void
11848 QueryFont(ref,...)
11849   Image::Magick ref=NO_INIT
11850   ALIAS:
11851     queryfont = 1
11852   PPCODE:
11853   {
11854     char
11855       *name,
11856       message[MaxTextExtent];
11857
11858     ExceptionInfo
11859       *exception;
11860
11861     register ssize_t
11862       i;
11863
11864     SV
11865       *perl_exception;
11866
11867     volatile const TypeInfo
11868       *type_info;
11869
11870     PERL_UNUSED_VAR(ref);
11871     PERL_UNUSED_VAR(ix);
11872     exception=AcquireExceptionInfo();
11873     perl_exception=newSVpv("",0);
11874     if (items == 1)
11875       {
11876         const TypeInfo
11877           **typelist;
11878
11879         size_t
11880           types;
11881
11882         typelist=GetTypeInfoList("*",&types,exception);
11883         EXTEND(sp,types);
11884         for (i=0; i < (ssize_t) types; i++)
11885         {
11886           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
11887         }
11888         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
11889           typelist);
11890         goto PerlException;
11891       }
11892     EXTEND(sp,10*items);
11893     for (i=1; i < items; i++)
11894     {
11895       name=(char *) SvPV(ST(i),na);
11896       type_info=GetTypeInfo(name,exception);
11897       if (type_info == (TypeInfo *) NULL)
11898         {
11899           PUSHs(&sv_undef);
11900           continue;
11901         }
11902       if (type_info->name == (char *) NULL)
11903         PUSHs(&sv_undef);
11904       else
11905         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
11906       if (type_info->description == (char *) NULL)
11907         PUSHs(&sv_undef);
11908       else
11909         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
11910       if (type_info->family == (char *) NULL)
11911         PUSHs(&sv_undef);
11912       else
11913         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
11914       if (type_info->style == UndefinedStyle)
11915         PUSHs(&sv_undef);
11916       else
11917         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
11918           type_info->style),0)));
11919       if (type_info->stretch == UndefinedStretch)
11920         PUSHs(&sv_undef);
11921       else
11922         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
11923           type_info->stretch),0)));
11924       (void) FormatMagickString(message,MaxTextExtent,"%.20g",(double)
11925         type_info->weight);
11926       PUSHs(sv_2mortal(newSVpv(message,0)));
11927       if (type_info->encoding == (char *) NULL)
11928         PUSHs(&sv_undef);
11929       else
11930         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
11931       if (type_info->foundry == (char *) NULL)
11932         PUSHs(&sv_undef);
11933       else
11934         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
11935       if (type_info->format == (char *) NULL)
11936         PUSHs(&sv_undef);
11937       else
11938         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
11939       if (type_info->metrics == (char *) NULL)
11940         PUSHs(&sv_undef);
11941       else
11942         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
11943       if (type_info->glyphs == (char *) NULL)
11944         PUSHs(&sv_undef);
11945       else
11946         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
11947     }
11948
11949   PerlException:
11950     InheritPerlException(exception,perl_exception);
11951     exception=DestroyExceptionInfo(exception);
11952     SvREFCNT_dec(perl_exception);
11953   }
11954 \f
11955 #
11956 ###############################################################################
11957 #                                                                             #
11958 #                                                                             #
11959 #                                                                             #
11960 #   Q u e r y F o n t M e t r i c s                                           #
11961 #                                                                             #
11962 #                                                                             #
11963 #                                                                             #
11964 ###############################################################################
11965 #
11966 #
11967 void
11968 QueryFontMetrics(ref,...)
11969   Image::Magick ref=NO_INIT
11970   ALIAS:
11971     queryfontmetrics = 1
11972   PPCODE:
11973   {
11974     AffineMatrix
11975       affine,
11976       current;
11977
11978     AV
11979       *av;
11980
11981     char
11982       *attribute;
11983
11984     double
11985       x,
11986       y;
11987
11988     DrawInfo
11989       *draw_info;
11990
11991     ExceptionInfo
11992       *exception;
11993
11994     GeometryInfo
11995       geometry_info;
11996
11997     Image
11998       *image;
11999
12000     MagickBooleanType
12001       status;
12002
12003     MagickStatusType
12004       flags;
12005
12006     register ssize_t
12007       i;
12008
12009     ssize_t
12010       type;
12011
12012     struct PackageInfo
12013       *info,
12014       *package_info;
12015
12016     SV
12017       *perl_exception,
12018       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12019
12020     TypeMetric
12021       metrics;
12022
12023     PERL_UNUSED_VAR(ref);
12024     PERL_UNUSED_VAR(ix);
12025     exception=AcquireExceptionInfo();
12026     package_info=(struct PackageInfo *) NULL;
12027     perl_exception=newSVpv("",0);
12028     reference=SvRV(ST(0));
12029     av=(AV *) reference;
12030     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12031       exception);
12032     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12033     if (image == (Image *) NULL)
12034       {
12035         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12036           PackageName);
12037         goto PerlException;
12038       }
12039     package_info=ClonePackageInfo(info,exception);
12040     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12041     CloneString(&draw_info->text,"");
12042     current=draw_info->affine;
12043     GetAffineMatrix(&affine);
12044     x=0.0;
12045     y=0.0;
12046     EXTEND(sp,7*items);
12047     for (i=2; i < items; i+=2)
12048     {
12049       attribute=(char *) SvPV(ST(i-1),na);
12050       switch (*attribute)
12051       {
12052         case 'A':
12053         case 'a':
12054         {
12055           if (LocaleCompare(attribute,"antialias") == 0)
12056             {
12057               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12058                 SvPV(ST(i),na));
12059               if (type < 0)
12060                 {
12061                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12062                     SvPV(ST(i),na));
12063                   break;
12064                 }
12065               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12066               break;
12067             }
12068           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12069             attribute);
12070           break;
12071         }
12072         case 'd':
12073         case 'D':
12074         {
12075           if (LocaleCompare(attribute,"density") == 0)
12076             {
12077               CloneString(&draw_info->density,SvPV(ST(i),na));
12078               break;
12079             }
12080           if (LocaleCompare(attribute,"direction") == 0)
12081             {
12082               draw_info->direction=(DirectionType) ParseCommandOption(
12083                 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12084               break;
12085             }
12086           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12087             attribute);
12088           break;
12089         }
12090         case 'e':
12091         case 'E':
12092         {
12093           if (LocaleCompare(attribute,"encoding") == 0)
12094             {
12095               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12096               break;
12097             }
12098           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12099             attribute);
12100           break;
12101         }
12102         case 'f':
12103         case 'F':
12104         {
12105           if (LocaleCompare(attribute,"family") == 0)
12106             {
12107               CloneString(&draw_info->family,SvPV(ST(i),na));
12108               break;
12109             }
12110           if (LocaleCompare(attribute,"fill") == 0)
12111             {
12112               if (info)
12113                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->fill,
12114                   &image->exception);
12115               break;
12116             }
12117           if (LocaleCompare(attribute,"font") == 0)
12118             {
12119               CloneString(&draw_info->font,SvPV(ST(i),na));
12120               break;
12121             }
12122           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12123             attribute);
12124           break;
12125         }
12126         case 'g':
12127         case 'G':
12128         {
12129           if (LocaleCompare(attribute,"geometry") == 0)
12130             {
12131               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12132               break;
12133             }
12134           if (LocaleCompare(attribute,"gravity") == 0)
12135             {
12136               draw_info->gravity=(GravityType) ParseCommandOption(
12137                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12138               break;
12139             }
12140           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12141             attribute);
12142           break;
12143         }
12144         case 'i':
12145         case 'I':
12146         {
12147           if (LocaleCompare(attribute,"interline-spacing") == 0)
12148             {
12149               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12150               draw_info->interline_spacing=geometry_info.rho;
12151               break;
12152             }
12153           if (LocaleCompare(attribute,"interword-spacing") == 0)
12154             {
12155               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12156               draw_info->interword_spacing=geometry_info.rho;
12157               break;
12158             }
12159           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12160             attribute);
12161           break;
12162         }
12163         case 'k':
12164         case 'K':
12165         {
12166           if (LocaleCompare(attribute,"kerning") == 0)
12167             {
12168               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12169               draw_info->kerning=geometry_info.rho;
12170               break;
12171             }
12172           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12173             attribute);
12174           break;
12175         }
12176         case 'p':
12177         case 'P':
12178         {
12179           if (LocaleCompare(attribute,"pointsize") == 0)
12180             {
12181               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12182               draw_info->pointsize=geometry_info.rho;
12183               break;
12184             }
12185           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12186             attribute);
12187           break;
12188         }
12189         case 'r':
12190         case 'R':
12191         {
12192           if (LocaleCompare(attribute,"rotate") == 0)
12193             {
12194               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12195               affine.rx=geometry_info.rho;
12196               affine.ry=geometry_info.sigma;
12197               if ((flags & SigmaValue) == 0)
12198                 affine.ry=affine.rx;
12199               break;
12200             }
12201           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12202             attribute);
12203           break;
12204         }
12205         case 's':
12206         case 'S':
12207         {
12208           if (LocaleCompare(attribute,"scale") == 0)
12209             {
12210               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12211               affine.sx=geometry_info.rho;
12212               affine.sy=geometry_info.sigma;
12213               if ((flags & SigmaValue) == 0)
12214                 affine.sy=affine.sx;
12215               break;
12216             }
12217           if (LocaleCompare(attribute,"skew") == 0)
12218             {
12219               double
12220                 x_angle,
12221                 y_angle;
12222
12223               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12224               x_angle=geometry_info.rho;
12225               y_angle=geometry_info.sigma;
12226               if ((flags & SigmaValue) == 0)
12227                 y_angle=x_angle;
12228               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12229               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12230               break;
12231             }
12232           if (LocaleCompare(attribute,"stroke") == 0)
12233             {
12234               if (info)
12235                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->stroke,
12236                   &image->exception);
12237               break;
12238             }
12239           if (LocaleCompare(attribute,"style") == 0)
12240             {
12241               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12242                 SvPV(ST(i),na));
12243               if (type < 0)
12244                 {
12245                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12246                     SvPV(ST(i),na));
12247                   break;
12248                 }
12249               draw_info->style=(StyleType) type;
12250               break;
12251             }
12252           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12253             attribute);
12254           break;
12255         }
12256         case 't':
12257         case 'T':
12258         {
12259           if (LocaleCompare(attribute,"text") == 0)
12260             {
12261               CloneString(&draw_info->text,SvPV(ST(i),na));
12262               break;
12263             }
12264           if (LocaleCompare(attribute,"translate") == 0)
12265             {
12266               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12267               affine.tx=geometry_info.rho;
12268               affine.ty=geometry_info.sigma;
12269               if ((flags & SigmaValue) == 0)
12270                 affine.ty=affine.tx;
12271               break;
12272             }
12273           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12274             attribute);
12275           break;
12276         }
12277         case 'w':
12278         case 'W':
12279         {
12280           if (LocaleCompare(attribute,"weight") == 0)
12281             {
12282               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12283               draw_info->weight=(size_t) geometry_info.rho;
12284               break;
12285             }
12286           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12287             attribute);
12288           break;
12289         }
12290         case 'x':
12291         case 'X':
12292         {
12293           if (LocaleCompare(attribute,"x") == 0)
12294             {
12295               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12296               x=geometry_info.rho;
12297               break;
12298             }
12299           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12300             attribute);
12301           break;
12302         }
12303         case 'y':
12304         case 'Y':
12305         {
12306           if (LocaleCompare(attribute,"y") == 0)
12307             {
12308               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12309               y=geometry_info.rho;
12310               break;
12311             }
12312           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12313             attribute);
12314           break;
12315         }
12316         default:
12317         {
12318           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12319             attribute);
12320           break;
12321         }
12322       }
12323     }
12324     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12325     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12326     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12327     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12328     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12329     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12330     if (draw_info->geometry == (char *) NULL)
12331       {
12332         draw_info->geometry=AcquireString((char *) NULL);
12333         (void) FormatMagickString(draw_info->geometry,MaxTextExtent,
12334           "%.15g,%.15g",x,y);
12335       }
12336     status=GetTypeMetrics(image,draw_info,&metrics);
12337     (void) CatchImageException(image);
12338     if (status == MagickFalse)
12339       PUSHs(&sv_undef);
12340     else
12341       {
12342         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12343         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12344         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12345         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12346         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12347         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12348         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12349         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12350         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12351         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12352         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12353         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12354         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12355       }
12356     draw_info=DestroyDrawInfo(draw_info);
12357
12358   PerlException:
12359     if (package_info != (struct PackageInfo *) NULL)
12360       DestroyPackageInfo(package_info);
12361     InheritPerlException(exception,perl_exception);
12362     exception=DestroyExceptionInfo(exception);
12363     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12364   }
12365 \f
12366 #
12367 ###############################################################################
12368 #                                                                             #
12369 #                                                                             #
12370 #                                                                             #
12371 #   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                         #
12372 #                                                                             #
12373 #                                                                             #
12374 #                                                                             #
12375 ###############################################################################
12376 #
12377 #
12378 void
12379 QueryMultilineFontMetrics(ref,...)
12380   Image::Magick ref=NO_INIT
12381   ALIAS:
12382     querymultilinefontmetrics = 1
12383   PPCODE:
12384   {
12385     AffineMatrix
12386       affine,
12387       current;
12388
12389     AV
12390       *av;
12391
12392     char
12393       *attribute;
12394
12395     double
12396       x,
12397       y;
12398
12399     DrawInfo
12400       *draw_info;
12401
12402     ExceptionInfo
12403       *exception;
12404
12405     GeometryInfo
12406       geometry_info;
12407
12408     Image
12409       *image;
12410
12411     MagickBooleanType
12412       status;
12413
12414     MagickStatusType
12415       flags;
12416
12417     register ssize_t
12418       i;
12419
12420     ssize_t
12421       type;
12422
12423     struct PackageInfo
12424       *info,
12425       *package_info;
12426
12427     SV
12428       *perl_exception,
12429       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12430
12431     TypeMetric
12432       metrics;
12433
12434     PERL_UNUSED_VAR(ref);
12435     PERL_UNUSED_VAR(ix);
12436     exception=AcquireExceptionInfo();
12437     package_info=(struct PackageInfo *) NULL;
12438     perl_exception=newSVpv("",0);
12439     reference=SvRV(ST(0));
12440     av=(AV *) reference;
12441     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12442       exception);
12443     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12444     if (image == (Image *) NULL)
12445       {
12446         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12447           PackageName);
12448         goto PerlException;
12449       }
12450     package_info=ClonePackageInfo(info,exception);
12451     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12452     CloneString(&draw_info->text,"");
12453     current=draw_info->affine;
12454     GetAffineMatrix(&affine);
12455     x=0.0;
12456     y=0.0;
12457     EXTEND(sp,7*items);
12458     for (i=2; i < items; i+=2)
12459     {
12460       attribute=(char *) SvPV(ST(i-1),na);
12461       switch (*attribute)
12462       {
12463         case 'A':
12464         case 'a':
12465         {
12466           if (LocaleCompare(attribute,"antialias") == 0)
12467             {
12468               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12469                 SvPV(ST(i),na));
12470               if (type < 0)
12471                 {
12472                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12473                     SvPV(ST(i),na));
12474                   break;
12475                 }
12476               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12477               break;
12478             }
12479           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12480             attribute);
12481           break;
12482         }
12483         case 'd':
12484         case 'D':
12485         {
12486           if (LocaleCompare(attribute,"density") == 0)
12487             {
12488               CloneString(&draw_info->density,SvPV(ST(i),na));
12489               break;
12490             }
12491           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12492             attribute);
12493           break;
12494         }
12495         case 'e':
12496         case 'E':
12497         {
12498           if (LocaleCompare(attribute,"encoding") == 0)
12499             {
12500               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12501               break;
12502             }
12503           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12504             attribute);
12505           break;
12506         }
12507         case 'f':
12508         case 'F':
12509         {
12510           if (LocaleCompare(attribute,"family") == 0)
12511             {
12512               CloneString(&draw_info->family,SvPV(ST(i),na));
12513               break;
12514             }
12515           if (LocaleCompare(attribute,"fill") == 0)
12516             {
12517               if (info)
12518                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->fill,
12519                   &image->exception);
12520               break;
12521             }
12522           if (LocaleCompare(attribute,"font") == 0)
12523             {
12524               CloneString(&draw_info->font,SvPV(ST(i),na));
12525               break;
12526             }
12527           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12528             attribute);
12529           break;
12530         }
12531         case 'g':
12532         case 'G':
12533         {
12534           if (LocaleCompare(attribute,"geometry") == 0)
12535             {
12536               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12537               break;
12538             }
12539           if (LocaleCompare(attribute,"gravity") == 0)
12540             {
12541               draw_info->gravity=(GravityType) ParseCommandOption(
12542                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12543               break;
12544             }
12545           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12546             attribute);
12547           break;
12548         }
12549         case 'p':
12550         case 'P':
12551         {
12552           if (LocaleCompare(attribute,"pointsize") == 0)
12553             {
12554               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12555               draw_info->pointsize=geometry_info.rho;
12556               break;
12557             }
12558           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12559             attribute);
12560           break;
12561         }
12562         case 'r':
12563         case 'R':
12564         {
12565           if (LocaleCompare(attribute,"rotate") == 0)
12566             {
12567               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12568               affine.rx=geometry_info.rho;
12569               affine.ry=geometry_info.sigma;
12570               if ((flags & SigmaValue) == 0)
12571                 affine.ry=affine.rx;
12572               break;
12573             }
12574           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12575             attribute);
12576           break;
12577         }
12578         case 's':
12579         case 'S':
12580         {
12581           if (LocaleCompare(attribute,"scale") == 0)
12582             {
12583               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12584               affine.sx=geometry_info.rho;
12585               affine.sy=geometry_info.sigma;
12586               if ((flags & SigmaValue) == 0)
12587                 affine.sy=affine.sx;
12588               break;
12589             }
12590           if (LocaleCompare(attribute,"skew") == 0)
12591             {
12592               double
12593                 x_angle,
12594                 y_angle;
12595
12596               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12597               x_angle=geometry_info.rho;
12598               y_angle=geometry_info.sigma;
12599               if ((flags & SigmaValue) == 0)
12600                 y_angle=x_angle;
12601               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12602               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12603               break;
12604             }
12605           if (LocaleCompare(attribute,"stroke") == 0)
12606             {
12607               if (info)
12608                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->stroke,
12609                   &image->exception);
12610               break;
12611             }
12612           if (LocaleCompare(attribute,"style") == 0)
12613             {
12614               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12615                 SvPV(ST(i),na));
12616               if (type < 0)
12617                 {
12618                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12619                     SvPV(ST(i),na));
12620                   break;
12621                 }
12622               draw_info->style=(StyleType) type;
12623               break;
12624             }
12625           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12626             attribute);
12627           break;
12628         }
12629         case 't':
12630         case 'T':
12631         {
12632           if (LocaleCompare(attribute,"text") == 0)
12633             {
12634               CloneString(&draw_info->text,SvPV(ST(i),na));
12635               break;
12636             }
12637           if (LocaleCompare(attribute,"translate") == 0)
12638             {
12639               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12640               affine.tx=geometry_info.rho;
12641               affine.ty=geometry_info.sigma;
12642               if ((flags & SigmaValue) == 0)
12643                 affine.ty=affine.tx;
12644               break;
12645             }
12646           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12647             attribute);
12648           break;
12649         }
12650         case 'w':
12651         case 'W':
12652         {
12653           if (LocaleCompare(attribute,"weight") == 0)
12654             {
12655               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12656               draw_info->weight=(size_t) geometry_info.rho;
12657               break;
12658             }
12659           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12660             attribute);
12661           break;
12662         }
12663         case 'x':
12664         case 'X':
12665         {
12666           if (LocaleCompare(attribute,"x") == 0)
12667             {
12668               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12669               x=geometry_info.rho;
12670               break;
12671             }
12672           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12673             attribute);
12674           break;
12675         }
12676         case 'y':
12677         case 'Y':
12678         {
12679           if (LocaleCompare(attribute,"y") == 0)
12680             {
12681               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12682               y=geometry_info.rho;
12683               break;
12684             }
12685           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12686             attribute);
12687           break;
12688         }
12689         default:
12690         {
12691           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12692             attribute);
12693           break;
12694         }
12695       }
12696     }
12697     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12698     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12699     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12700     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12701     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12702     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12703     if (draw_info->geometry == (char *) NULL)
12704       {
12705         draw_info->geometry=AcquireString((char *) NULL);
12706         (void) FormatMagickString(draw_info->geometry,MaxTextExtent,
12707           "%.15g,%.15g",x,y);
12708       }
12709     status=GetMultilineTypeMetrics(image,draw_info,&metrics);
12710     (void) CatchImageException(image);
12711     if (status == MagickFalse)
12712       PUSHs(&sv_undef);
12713     else
12714       {
12715         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12716         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12717         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12718         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12719         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12720         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12721         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12722         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12723         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12724         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12725         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12726         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12727         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12728       }
12729     draw_info=DestroyDrawInfo(draw_info);
12730
12731   PerlException:
12732     if (package_info != (struct PackageInfo *) NULL)
12733       DestroyPackageInfo(package_info);
12734     InheritPerlException(exception,perl_exception);
12735     exception=DestroyExceptionInfo(exception);
12736     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12737   }
12738 \f
12739 #
12740 ###############################################################################
12741 #                                                                             #
12742 #                                                                             #
12743 #                                                                             #
12744 #   Q u e r y F o r m a t                                                     #
12745 #                                                                             #
12746 #                                                                             #
12747 #                                                                             #
12748 ###############################################################################
12749 #
12750 #
12751 void
12752 QueryFormat(ref,...)
12753   Image::Magick ref=NO_INIT
12754   ALIAS:
12755     queryformat = 1
12756   PPCODE:
12757   {
12758     char
12759       *name;
12760
12761     ExceptionInfo
12762       *exception;
12763
12764     register ssize_t
12765       i;
12766
12767     SV
12768       *perl_exception;
12769
12770     volatile const MagickInfo
12771       *magick_info;
12772
12773     PERL_UNUSED_VAR(ref);
12774     PERL_UNUSED_VAR(ix);
12775     exception=AcquireExceptionInfo();
12776     perl_exception=newSVpv("",0);
12777     if (items == 1)
12778       {
12779         char
12780           format[MaxTextExtent];
12781
12782         const MagickInfo
12783           **format_list;
12784
12785         size_t
12786           types;
12787
12788         format_list=GetMagickInfoList("*",&types,exception);
12789         EXTEND(sp,types);
12790         for (i=0; i < (ssize_t) types; i++)
12791         {
12792           (void) CopyMagickString(format,format_list[i]->name,MaxTextExtent);
12793           LocaleLower(format);
12794           PUSHs(sv_2mortal(newSVpv(format,0)));
12795         }
12796         format_list=(const MagickInfo **)
12797           RelinquishMagickMemory((MagickInfo *) format_list);
12798         goto PerlException;
12799       }
12800     EXTEND(sp,8*items);
12801     for (i=1; i < items; i++)
12802     {
12803       name=(char *) SvPV(ST(i),na);
12804       magick_info=GetMagickInfo(name,exception);
12805       if (magick_info == (const MagickInfo *) NULL)
12806         {
12807           PUSHs(&sv_undef);
12808           continue;
12809         }
12810       PUSHs(sv_2mortal(newSViv(magick_info->adjoin)));
12811       PUSHs(sv_2mortal(newSViv(magick_info->blob_support)));
12812       PUSHs(sv_2mortal(newSViv(magick_info->raw)));
12813       PUSHs(sv_2mortal(newSViv((long) magick_info->decoder)));
12814       PUSHs(sv_2mortal(newSViv((long) magick_info->encoder)));
12815       if (magick_info->description == (char *) NULL)
12816         PUSHs(&sv_undef);
12817       else
12818         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
12819       if (magick_info->module == (char *) NULL)
12820         PUSHs(&sv_undef);
12821       else
12822         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
12823     }
12824
12825   PerlException:
12826     InheritPerlException(exception,perl_exception);
12827     exception=DestroyExceptionInfo(exception);
12828     SvREFCNT_dec(perl_exception);
12829   }
12830 \f
12831 #
12832 ###############################################################################
12833 #                                                                             #
12834 #                                                                             #
12835 #                                                                             #
12836 #   Q u e r y O p t i o n                                                     #
12837 #                                                                             #
12838 #                                                                             #
12839 #                                                                             #
12840 ###############################################################################
12841 #
12842 #
12843 void
12844 QueryOption(ref,...)
12845   Image::Magick ref=NO_INIT
12846   ALIAS:
12847     queryoption = 1
12848   PPCODE:
12849   {
12850     char
12851       **options;
12852
12853     ExceptionInfo
12854       *exception;
12855
12856     register ssize_t
12857       i;
12858
12859     ssize_t
12860       j,
12861       option;
12862
12863     SV
12864       *perl_exception;
12865
12866     PERL_UNUSED_VAR(ref);
12867     PERL_UNUSED_VAR(ix);
12868     exception=AcquireExceptionInfo();
12869     perl_exception=newSVpv("",0);
12870     EXTEND(sp,8*items);
12871     for (i=1; i < items; i++)
12872     {
12873       option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
12874         SvPV(ST(i),na));
12875       options=GetCommandOptions((CommandOption) option);
12876       if (options == (char **) NULL)
12877         PUSHs(&sv_undef);
12878       else
12879         {
12880           for (j=0; options[j] != (char *) NULL; j++)
12881             PUSHs(sv_2mortal(newSVpv(options[j],0)));
12882           options=DestroyStringList(options);
12883         }
12884     }
12885
12886     InheritPerlException(exception,perl_exception);
12887     exception=DestroyExceptionInfo(exception);
12888     SvREFCNT_dec(perl_exception);
12889   }
12890 \f
12891 #
12892 ###############################################################################
12893 #                                                                             #
12894 #                                                                             #
12895 #                                                                             #
12896 #   R e a d                                                                   #
12897 #                                                                             #
12898 #                                                                             #
12899 #                                                                             #
12900 ###############################################################################
12901 #
12902 #
12903 void
12904 Read(ref,...)
12905   Image::Magick ref=NO_INIT
12906   ALIAS:
12907     ReadImage  = 1
12908     read       = 2
12909     readimage  = 3
12910   PPCODE:
12911   {
12912     AV
12913       *av;
12914
12915     char
12916       **keep,
12917       **list;
12918
12919     ExceptionInfo
12920       *exception;
12921
12922     HV
12923       *hv;
12924
12925     Image
12926       *image;
12927
12928     int
12929       n;
12930
12931     MagickBooleanType
12932       status;
12933
12934     register char
12935       **p;
12936
12937     register ssize_t
12938       i;
12939
12940     ssize_t
12941       ac,
12942       number_images;
12943
12944     STRLEN
12945       *length;
12946
12947     struct PackageInfo
12948       *info,
12949       *package_info;
12950
12951     SV
12952       *perl_exception,  /* Perl variable for storing messages */
12953       *reference,
12954       *rv,
12955       *sv;
12956
12957     PERL_UNUSED_VAR(ref);
12958     PERL_UNUSED_VAR(ix);
12959     exception=AcquireExceptionInfo();
12960     perl_exception=newSVpv("",0);
12961     sv=NULL;
12962     package_info=(struct PackageInfo *) NULL;
12963     number_images=0;
12964     ac=(items < 2) ? 1 : items-1;
12965     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
12966     keep=list;
12967     length=(STRLEN *) NULL;
12968     if (list == (char **) NULL)
12969       {
12970         ThrowPerlException(exception,ResourceLimitError,
12971           "MemoryAllocationFailed",PackageName);
12972         goto PerlException;
12973       }
12974     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
12975     if (length == (STRLEN *) NULL)
12976       {
12977         ThrowPerlException(exception,ResourceLimitError,
12978           "MemoryAllocationFailed",PackageName);
12979         goto PerlException;
12980       }
12981     if (sv_isobject(ST(0)) == 0)
12982       {
12983         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12984           PackageName);
12985         goto PerlException;
12986       }
12987     reference=SvRV(ST(0));
12988     hv=SvSTASH(reference);
12989     if (SvTYPE(reference) != SVt_PVAV)
12990       {
12991         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12992           PackageName);
12993         goto PerlException;
12994       }
12995     av=(AV *) reference;
12996     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12997       exception);
12998     package_info=ClonePackageInfo(info,exception);
12999     n=1;
13000     if (items <= 1)
13001       *list=(char *) (*package_info->image_info->filename ?
13002         package_info->image_info->filename : "XC:black");
13003     else
13004       for (n=0, i=0; i < ac; i++)
13005       {
13006         list[n]=(char *) SvPV(ST(i+1),length[n]);
13007         if ((items >= 3) && strEQcase(list[n],"blob"))
13008           {
13009             void
13010               *blob;
13011
13012             i++;
13013             blob=(void *) (SvPV(ST(i+1),length[n]));
13014             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13015           }
13016         if ((items >= 3) && strEQcase(list[n],"filename"))
13017           continue;
13018         if ((items >= 3) && strEQcase(list[n],"file"))
13019           {
13020             FILE
13021               *file;
13022
13023             PerlIO
13024               *io_info;
13025
13026             i++;
13027             io_info=IoIFP(sv_2io(ST(i+1)));
13028             if (io_info == (PerlIO *) NULL)
13029               {
13030                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13031                   PackageName);
13032                 continue;
13033               }
13034             file=PerlIO_findFILE(io_info);
13035             if (file == (FILE *) NULL)
13036               {
13037                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13038                   PackageName);
13039                 continue;
13040               }
13041             SetImageInfoFile(package_info->image_info,file);
13042           }
13043         if ((items >= 3) && strEQcase(list[n],"magick"))
13044           continue;
13045         n++;
13046       }
13047     list[n]=(char *) NULL;
13048     keep=list;
13049     status=ExpandFilenames(&n,&list);
13050     if (status == MagickFalse)
13051       {
13052         ThrowPerlException(exception,ResourceLimitError,
13053           "MemoryAllocationFailed",PackageName);
13054         goto PerlException;
13055       }
13056     number_images=0;
13057     for (i=0; i < n; i++)
13058     {
13059       if ((package_info->image_info->file != (FILE *) NULL) ||
13060           (package_info->image_info->blob != (void *) NULL))
13061         {
13062           image=ReadImages(package_info->image_info,exception);
13063           if (image != (Image *) NULL)
13064             DisassociateImageStream(image);
13065         }
13066       else
13067         {
13068           (void) CopyMagickString(package_info->image_info->filename,list[i],
13069             MaxTextExtent);
13070           image=ReadImages(package_info->image_info,exception);
13071         }
13072       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
13073         break;
13074       for ( ; image; image=image->next)
13075       {
13076         AddImageToRegistry(sv,image);
13077         rv=newRV(sv);
13078         av_push(av,sv_bless(rv,hv));
13079         SvREFCNT_dec(sv);
13080         number_images++;
13081       }
13082     }
13083     /*
13084       Free resources.
13085     */
13086     for (i=0; i < n; i++)
13087       if (list[i] != (char *) NULL)
13088         for (p=keep; list[i] != *p++; )
13089           if (*p == (char *) NULL)
13090             {
13091               list[i]=(char *) RelinquishMagickMemory(list[i]);
13092               break;
13093             }
13094
13095   PerlException:
13096     if (package_info != (struct PackageInfo *) NULL)
13097       DestroyPackageInfo(package_info);
13098     if (list && (list != keep))
13099       list=(char **) RelinquishMagickMemory(list);
13100     if (keep)
13101       keep=(char **) RelinquishMagickMemory(keep);
13102     if (length)
13103       length=(STRLEN *) RelinquishMagickMemory(length);
13104     InheritPerlException(exception,perl_exception);
13105     exception=DestroyExceptionInfo(exception);
13106     sv_setiv(perl_exception,(IV) number_images);
13107     SvPOK_on(perl_exception);
13108     ST(0)=sv_2mortal(perl_exception);
13109     XSRETURN(1);
13110   }
13111 \f
13112 #
13113 ###############################################################################
13114 #                                                                             #
13115 #                                                                             #
13116 #                                                                             #
13117 #   R e m o t e                                                               #
13118 #                                                                             #
13119 #                                                                             #
13120 #                                                                             #
13121 ###############################################################################
13122 #
13123 #
13124 void
13125 Remote(ref,...)
13126   Image::Magick ref=NO_INIT
13127   ALIAS:
13128     RemoteCommand  = 1
13129     remote         = 2
13130     remoteCommand  = 3
13131   PPCODE:
13132   {
13133     AV
13134       *av;
13135
13136     ExceptionInfo
13137       *exception;
13138
13139     register ssize_t
13140       i;
13141
13142     SV
13143       *perl_exception,
13144       *reference;
13145
13146     struct PackageInfo
13147       *info;
13148
13149     PERL_UNUSED_VAR(ref);
13150     PERL_UNUSED_VAR(ix);
13151     exception=AcquireExceptionInfo();
13152     perl_exception=newSVpv("",0);
13153     reference=SvRV(ST(0));
13154     av=(AV *) reference;
13155     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13156       exception);
13157     for (i=1; i < items; i++)
13158       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13159         SvPV(ST(i),na),exception);
13160     InheritPerlException(exception,perl_exception);
13161     exception=DestroyExceptionInfo(exception);
13162     SvREFCNT_dec(perl_exception);    /* throw away all errors */
13163   }
13164 \f
13165 #
13166 ###############################################################################
13167 #                                                                             #
13168 #                                                                             #
13169 #                                                                             #
13170 #   S e t                                                                     #
13171 #                                                                             #
13172 #                                                                             #
13173 #                                                                             #
13174 ###############################################################################
13175 #
13176 #
13177 void
13178 Set(ref,...)
13179   Image::Magick ref=NO_INIT
13180   ALIAS:
13181     SetAttributes  = 1
13182     SetAttribute   = 2
13183     set            = 3
13184     setattributes  = 4
13185     setattribute   = 5
13186   PPCODE:
13187   {
13188     ExceptionInfo
13189       *exception;
13190
13191     Image
13192       *image;
13193
13194     register ssize_t
13195       i;
13196
13197     struct PackageInfo
13198       *info;
13199
13200     SV
13201       *perl_exception,
13202       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13203
13204     PERL_UNUSED_VAR(ref);
13205     PERL_UNUSED_VAR(ix);
13206     exception=AcquireExceptionInfo();
13207     perl_exception=newSVpv("",0);
13208     if (sv_isobject(ST(0)) == 0)
13209       {
13210         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13211           PackageName);
13212         goto PerlException;
13213       }
13214     reference=SvRV(ST(0));
13215     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13216     if (items == 2)
13217       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13218     else
13219       for (i=2; i < items; i+=2)
13220         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13221
13222   PerlException:
13223     InheritPerlException(exception,perl_exception);
13224     exception=DestroyExceptionInfo(exception);
13225     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13226     SvPOK_on(perl_exception);
13227     ST(0)=sv_2mortal(perl_exception);
13228     XSRETURN(1);
13229   }
13230 \f
13231 #
13232 ###############################################################################
13233 #                                                                             #
13234 #                                                                             #
13235 #                                                                             #
13236 #   S e t P i x e l                                                           #
13237 #                                                                             #
13238 #                                                                             #
13239 #                                                                             #
13240 ###############################################################################
13241 #
13242 #
13243 void
13244 SetPixel(ref,...)
13245   Image::Magick ref=NO_INIT
13246   ALIAS:
13247     setpixel = 1
13248     setPixel = 2
13249   PPCODE:
13250   {
13251     AV
13252       *av;
13253
13254     char
13255       *attribute;
13256
13257     ChannelType
13258       channel;
13259
13260     ExceptionInfo
13261       *exception;
13262
13263     Image
13264       *image;
13265
13266     MagickBooleanType
13267       normalize;
13268
13269     RectangleInfo
13270       region;
13271
13272     register IndexPacket
13273       *indexes;
13274
13275     register ssize_t
13276       i;
13277
13278     register PixelPacket
13279       *q;
13280
13281     ssize_t
13282       option;
13283
13284     struct PackageInfo
13285       *info;
13286
13287     SV
13288       *perl_exception,
13289       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13290
13291     PERL_UNUSED_VAR(ref);
13292     PERL_UNUSED_VAR(ix);
13293     exception=AcquireExceptionInfo();
13294     perl_exception=newSVpv("",0);
13295     reference=SvRV(ST(0));
13296     av=(AV *) reference;
13297     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13298       exception);
13299     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13300     if (image == (Image *) NULL)
13301       {
13302         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13303           PackageName);
13304         goto PerlException;
13305       }
13306     av=(AV *) NULL;
13307     channel=DefaultChannels;
13308     normalize=MagickTrue;
13309     region.x=0;
13310     region.y=0;
13311     region.width=image->columns;
13312     region.height=1;
13313     if (items == 1)
13314       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13315     for (i=2; i < items; i+=2)
13316     {
13317       attribute=(char *) SvPV(ST(i-1),na);
13318       switch (*attribute)
13319       {
13320         case 'C':
13321         case 'c':
13322         {
13323           if (LocaleCompare(attribute,"channel") == 0)
13324             {
13325               ssize_t
13326                 option;
13327
13328               option=ParseChannelOption(SvPV(ST(i),na));
13329               if (option < 0)
13330                 {
13331                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13332                     SvPV(ST(i),na));
13333                   return;
13334                 }
13335                channel=(ChannelType) option;
13336               break;
13337             }
13338           if (LocaleCompare(attribute,"color") == 0)
13339             {
13340               if (SvTYPE(ST(i)) != SVt_RV)
13341                 {
13342                   char
13343                     message[MaxTextExtent];
13344
13345                   (void) FormatMagickString(message,MaxTextExtent,
13346                     "invalid %.60s value",attribute);
13347                   ThrowPerlException(exception,OptionError,message,
13348                     SvPV(ST(i),na));
13349                 }
13350               av=(AV *) SvRV(ST(i));
13351               break;
13352             }
13353           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13354             attribute);
13355           break;
13356         }
13357         case 'g':
13358         case 'G':
13359         {
13360           if (LocaleCompare(attribute,"geometry") == 0)
13361             {
13362               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
13363               break;
13364             }
13365           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13366             attribute);
13367           break;
13368         }
13369         case 'N':
13370         case 'n':
13371         {
13372           if (LocaleCompare(attribute,"normalize") == 0)
13373             {
13374               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13375                 SvPV(ST(i),na));
13376               if (option < 0)
13377                 {
13378                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13379                     SvPV(ST(i),na));
13380                   break;
13381                 }
13382              normalize=option != 0 ? MagickTrue : MagickFalse;
13383              break;
13384             }
13385           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13386             attribute);
13387           break;
13388         }
13389         case 'x':
13390         case 'X':
13391         {
13392           if (LocaleCompare(attribute,"x") == 0)
13393             {
13394               region.x=SvIV(ST(i));
13395               break;
13396             }
13397           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13398             attribute);
13399           break;
13400         }
13401         case 'y':
13402         case 'Y':
13403         {
13404           if (LocaleCompare(attribute,"y") == 0)
13405             {
13406               region.y=SvIV(ST(i));
13407               break;
13408             }
13409           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13410             attribute);
13411           break;
13412         }
13413         default:
13414         {
13415           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13416             attribute);
13417           break;
13418         }
13419       }
13420     }
13421     (void) SetImageStorageClass(image,DirectClass);
13422     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
13423     if ((q == (PixelPacket *) NULL) || (av == (AV *) NULL) ||
13424         (SvTYPE(av) != SVt_PVAV))
13425       PUSHs(&sv_undef);
13426     else
13427       {
13428         double
13429           scale;
13430
13431         register ssize_t
13432           i;
13433
13434         i=0;
13435         indexes=GetAuthenticIndexQueue(image);
13436         scale=1.0;
13437         if (normalize != MagickFalse)
13438           scale=QuantumRange;
13439         if (((channel & RedChannel) != 0) && (i <= av_len(av)))
13440           {
13441             SetRedPixelComponent(q,ClampToQuantum(QuantumRange*SvNV(*(
13442               av_fetch(av,i,0)))));
13443             i++;
13444           }
13445         if (((channel & GreenChannel) != 0) && (i <= av_len(av)))
13446           {
13447             SetGreenPixelComponent(q,ClampToQuantum(QuantumRange*SvNV(*(
13448               av_fetch(av,i,0)))));
13449             i++;
13450           }
13451         if (((channel & BlueChannel) != 0) && (i <= av_len(av)))
13452           {
13453             SetBluePixelComponent(q,ClampToQuantum(QuantumRange*SvNV(*(
13454               av_fetch(av,i,0)))));
13455             i++;
13456           }
13457         if ((((channel & IndexChannel) != 0) &&
13458             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
13459           {
13460             SetIndexPixelComponent(indexes,ClampToQuantum(QuantumRange*
13461               SvNV(*(av_fetch(av,i,0)))));
13462             i++;
13463           }
13464         if (((channel & OpacityChannel) != 0) && (i <= av_len(av)))
13465           {
13466             SetOpacityPixelComponent(q,ClampToQuantum(QuantumRange*
13467               SvNV(*(av_fetch(av,i,0)))));
13468             i++;
13469           }
13470         (void) SyncAuthenticPixels(image,exception);
13471       }
13472
13473   PerlException:
13474     InheritPerlException(exception,perl_exception);
13475     exception=DestroyExceptionInfo(exception);
13476     SvREFCNT_dec(perl_exception);
13477   }
13478 \f
13479 #
13480 ###############################################################################
13481 #                                                                             #
13482 #                                                                             #
13483 #                                                                             #
13484 #   S m u s h                                                                 #
13485 #                                                                             #
13486 #                                                                             #
13487 #                                                                             #
13488 ###############################################################################
13489 #
13490 #
13491 void
13492 Smush(ref,...)
13493   Image::Magick ref=NO_INIT
13494   ALIAS:
13495     SmushImage  = 1
13496     smush       = 2
13497     smushimage  = 3
13498   PPCODE:
13499   {
13500     AV
13501       *av;
13502
13503     char
13504       *attribute;
13505
13506     ExceptionInfo
13507       *exception;
13508
13509     HV
13510       *hv;
13511
13512     Image
13513       *image;
13514
13515     register ssize_t
13516       i;
13517
13518     ssize_t
13519       offset,
13520       stack;
13521
13522     struct PackageInfo
13523       *info;
13524
13525     SV
13526       *av_reference,
13527       *perl_exception,
13528       *reference,
13529       *rv,
13530       *sv;
13531
13532     PERL_UNUSED_VAR(ref);
13533     PERL_UNUSED_VAR(ix);
13534     exception=AcquireExceptionInfo();
13535     perl_exception=newSVpv("",0);
13536     sv=NULL;
13537     attribute=NULL;
13538     av=NULL;
13539     if (sv_isobject(ST(0)) == 0)
13540       {
13541         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13542           PackageName);
13543         goto PerlException;
13544       }
13545     reference=SvRV(ST(0));
13546     hv=SvSTASH(reference);
13547     av=newAV();
13548     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13549     SvREFCNT_dec(av);
13550     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13551     if (image == (Image *) NULL)
13552       {
13553         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13554           PackageName);
13555         goto PerlException;
13556       }
13557     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13558     /*
13559       Get options.
13560     */
13561     offset=0;
13562     stack=MagickTrue;
13563     for (i=2; i < items; i+=2)
13564     {
13565       attribute=(char *) SvPV(ST(i-1),na);
13566       switch (*attribute)
13567       {
13568         case 'O':
13569         case 'o':
13570         {
13571           if (LocaleCompare(attribute,"offset") == 0)
13572             {
13573               offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
13574               break;
13575             }
13576           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13577             attribute);
13578           break;
13579         }
13580         case 'S':
13581         case 's':
13582         {
13583           if (LocaleCompare(attribute,"stack") == 0)
13584             {
13585               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13586                 SvPV(ST(i),na));
13587               if (stack < 0)
13588                 {
13589                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13590                     SvPV(ST(i),na));
13591                   return;
13592                 }
13593               break;
13594             }
13595           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13596             attribute);
13597           break;
13598         }
13599         default:
13600         {
13601           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13602             attribute);
13603           break;
13604         }
13605       }
13606     }
13607     image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
13608       exception);
13609     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
13610       goto PerlException;
13611     for ( ; image; image=image->next)
13612     {
13613       AddImageToRegistry(sv,image);
13614       rv=newRV(sv);
13615       av_push(av,sv_bless(rv,hv));
13616       SvREFCNT_dec(sv);
13617     }
13618     exception=DestroyExceptionInfo(exception);
13619     ST(0)=av_reference;
13620     SvREFCNT_dec(perl_exception);
13621     XSRETURN(1);
13622
13623   PerlException:
13624     InheritPerlException(exception,perl_exception);
13625     exception=DestroyExceptionInfo(exception);
13626     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
13627     SvPOK_on(perl_exception);
13628     ST(0)=sv_2mortal(perl_exception);
13629     XSRETURN(1);
13630   }
13631 \f
13632 #
13633 ###############################################################################
13634 #                                                                             #
13635 #                                                                             #
13636 #                                                                             #
13637 #   S t a t i s t i c s                                                       #
13638 #                                                                             #
13639 #                                                                             #
13640 #                                                                             #
13641 ###############################################################################
13642 #
13643 #
13644 void
13645 Statistics(ref,...)
13646   Image::Magick ref=NO_INIT
13647   ALIAS:
13648     StatisticsImage = 1
13649     statistics      = 2
13650     statisticsimage = 3
13651   PPCODE:
13652   {
13653 #define ChannelStatistics(channel) \
13654 { \
13655   (void) FormatMagickString(message,MaxTextExtent,"%.20g", \
13656     (double) channel_statistics[channel].depth); \
13657   PUSHs(sv_2mortal(newSVpv(message,0))); \
13658   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
13659     channel_statistics[channel].minima/scale); \
13660   PUSHs(sv_2mortal(newSVpv(message,0))); \
13661   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
13662     channel_statistics[channel].maxima/scale); \
13663   PUSHs(sv_2mortal(newSVpv(message,0))); \
13664   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
13665     channel_statistics[channel].mean/scale); \
13666   PUSHs(sv_2mortal(newSVpv(message,0))); \
13667   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
13668     channel_statistics[channel].standard_deviation/scale); \
13669   PUSHs(sv_2mortal(newSVpv(message,0))); \
13670   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
13671     channel_statistics[channel].kurtosis); \
13672   PUSHs(sv_2mortal(newSVpv(message,0))); \
13673   (void) FormatMagickString(message,MaxTextExtent,"%.15g", \
13674     channel_statistics[channel].skewness); \
13675   PUSHs(sv_2mortal(newSVpv(message,0))); \
13676 }
13677
13678     AV
13679       *av;
13680
13681     char
13682       message[MaxTextExtent];
13683
13684     ChannelStatistics
13685       *channel_statistics;
13686
13687     double
13688       scale;
13689
13690     ExceptionInfo
13691       *exception;
13692
13693     HV
13694       *hv;
13695
13696     Image
13697       *image;
13698
13699     ssize_t
13700       count;
13701
13702     struct PackageInfo
13703       *info;
13704
13705     SV
13706       *av_reference,
13707       *perl_exception,
13708       *reference;
13709
13710     PERL_UNUSED_VAR(ref);
13711     PERL_UNUSED_VAR(ix);
13712     exception=AcquireExceptionInfo();
13713     perl_exception=newSVpv("",0);
13714     av=NULL;
13715     if (sv_isobject(ST(0)) == 0)
13716       {
13717         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13718           PackageName);
13719         goto PerlException;
13720       }
13721     reference=SvRV(ST(0));
13722     hv=SvSTASH(reference);
13723     av=newAV();
13724     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13725     SvREFCNT_dec(av);
13726     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13727     if (image == (Image *) NULL)
13728       {
13729         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13730           PackageName);
13731         goto PerlException;
13732       }
13733     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13734     count=0;
13735     for ( ; image; image=image->next)
13736     {
13737       channel_statistics=GetImageChannelStatistics(image,&image->exception);
13738       if (channel_statistics == (ChannelStatistics *) NULL)
13739         continue;
13740       count++;
13741       EXTEND(sp,35*count);
13742       scale=(double) QuantumRange;
13743       ChannelStatistics(RedChannel);
13744       ChannelStatistics(GreenChannel);
13745       ChannelStatistics(BlueChannel);
13746       if (image->colorspace == CMYKColorspace)
13747         ChannelStatistics(IndexChannel);
13748       if (image->matte != MagickFalse)
13749         ChannelStatistics(OpacityChannel);
13750       channel_statistics=(ChannelStatistics *)
13751         RelinquishMagickMemory(channel_statistics);
13752     }
13753
13754   PerlException:
13755     InheritPerlException(exception,perl_exception);
13756     exception=DestroyExceptionInfo(exception);
13757     SvREFCNT_dec(perl_exception);
13758   }
13759 \f
13760 #
13761 ###############################################################################
13762 #                                                                             #
13763 #                                                                             #
13764 #                                                                             #
13765 #   S y n c A u t h e n t i c P i x e l s                                     #
13766 #                                                                             #
13767 #                                                                             #
13768 #                                                                             #
13769 ###############################################################################
13770 #
13771 #
13772 void
13773 SyncAuthenticPixels(ref,...)
13774   Image::Magick ref = NO_INIT
13775   ALIAS:
13776     Syncauthenticpixels = 1
13777     SyncImagePixels = 2
13778     syncimagepixels = 3
13779   CODE:
13780   {
13781     ExceptionInfo
13782       *exception;
13783
13784     Image
13785       *image;
13786
13787     MagickBooleanType
13788       status;
13789
13790     struct PackageInfo
13791       *info;
13792
13793     SV
13794       *perl_exception,
13795       *reference;
13796
13797     PERL_UNUSED_VAR(ref);
13798     PERL_UNUSED_VAR(ix);
13799     exception=AcquireExceptionInfo();
13800     perl_exception=newSVpv("",0);
13801     if (sv_isobject(ST(0)) == 0)
13802       {
13803         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13804           PackageName);
13805         goto PerlException;
13806       }
13807
13808     reference=SvRV(ST(0));
13809     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13810     if (image == (Image *) NULL)
13811       {
13812         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13813           PackageName);
13814         goto PerlException;
13815       }
13816
13817     status=SyncAuthenticPixels(image,exception);
13818     if (status != MagickFalse)
13819       return;
13820     InheritException(exception,&image->exception);
13821
13822   PerlException:
13823     InheritPerlException(exception,perl_exception);
13824     exception=DestroyExceptionInfo(exception);
13825     SvREFCNT_dec(perl_exception);  /* throw away all errors */
13826   }
13827 \f
13828 #
13829 ###############################################################################
13830 #                                                                             #
13831 #                                                                             #
13832 #                                                                             #
13833 #   T r a n s f o r m                                                         #
13834 #                                                                             #
13835 #                                                                             #
13836 #                                                                             #
13837 ###############################################################################
13838 #
13839 #
13840 void
13841 Transform(ref,...)
13842   Image::Magick ref=NO_INIT
13843   ALIAS:
13844     TransformImage = 1
13845     transform      = 2
13846     transformimage = 3
13847   PPCODE:
13848   {
13849     AV
13850       *av;
13851
13852     char
13853       *attribute,
13854       *crop_geometry,
13855       *geometry;
13856
13857     ExceptionInfo
13858       *exception;
13859
13860     HV
13861       *hv;
13862
13863     Image
13864       *clone,
13865       *image;
13866
13867     register ssize_t
13868       i;
13869
13870     struct PackageInfo
13871       *info;
13872
13873     SV
13874       *av_reference,
13875       *perl_exception,
13876       *reference,
13877       *rv,
13878       *sv;
13879
13880     PERL_UNUSED_VAR(ref);
13881     PERL_UNUSED_VAR(ix);
13882     exception=AcquireExceptionInfo();
13883     perl_exception=newSVpv("",0);
13884     sv=NULL;
13885     av=NULL;
13886     attribute=NULL;
13887     if (sv_isobject(ST(0)) == 0)
13888       {
13889         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13890           PackageName);
13891         goto PerlException;
13892       }
13893     reference=SvRV(ST(0));
13894     hv=SvSTASH(reference);
13895     av=newAV();
13896     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13897     SvREFCNT_dec(av);
13898     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13899     if (image == (Image *) NULL)
13900       {
13901         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13902           PackageName);
13903         goto PerlException;
13904       }
13905     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13906     /*
13907       Get attribute.
13908     */
13909     crop_geometry=(char *) NULL;
13910     geometry=(char *) NULL;
13911     for (i=2; i < items; i+=2)
13912     {
13913       attribute=(char *) SvPV(ST(i-1),na);
13914       switch (*attribute)
13915       {
13916         case 'c':
13917         case 'C':
13918         {
13919           if (LocaleCompare(attribute,"crop") == 0)
13920             {
13921               crop_geometry=SvPV(ST(i),na);
13922               break;
13923             }
13924           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13925             attribute);
13926           break;
13927         }
13928         case 'g':
13929         case 'G':
13930         {
13931           if (LocaleCompare(attribute,"geometry") == 0)
13932             {
13933               geometry=SvPV(ST(i),na);
13934               break;
13935             }
13936          if (LocaleCompare(attribute,"gravity") == 0)
13937            {
13938              Image
13939                *next;
13940
13941              ssize_t
13942                in;
13943
13944              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
13945                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13946              if (in < 0)
13947                {
13948                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
13949                    SvPV(ST(i),na));
13950                  return;
13951                }
13952              for (next=image; next; next=next->next)
13953                next->gravity=(GravityType) in;
13954              break;
13955            }
13956           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13957             attribute);
13958           break;
13959         }
13960         default:
13961         {
13962           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13963             attribute);
13964           break;
13965         }
13966       }
13967     }
13968     for ( ; image; image=image->next)
13969     {
13970       clone=CloneImage(image,0,0,MagickTrue,exception);
13971       if ((clone == (Image *) NULL) || (exception->severity >= ErrorException))
13972         goto PerlException;
13973       TransformImage(&clone,crop_geometry,geometry);
13974       for ( ; clone; clone=clone->next)
13975       {
13976         AddImageToRegistry(sv,clone);
13977         rv=newRV(sv);
13978         av_push(av,sv_bless(rv,hv));
13979         SvREFCNT_dec(sv);
13980       }
13981     }
13982     exception=DestroyExceptionInfo(exception);
13983     ST(0)=av_reference;
13984     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13985     XSRETURN(1);
13986
13987   PerlException:
13988     InheritPerlException(exception,perl_exception);
13989     exception=DestroyExceptionInfo(exception);
13990     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
13991     SvPOK_on(perl_exception);
13992     ST(0)=sv_2mortal(perl_exception);
13993     XSRETURN(1);
13994   }
13995 \f
13996 #
13997 ###############################################################################
13998 #                                                                             #
13999 #                                                                             #
14000 #                                                                             #
14001 #   W r i t e                                                                 #
14002 #                                                                             #
14003 #                                                                             #
14004 #                                                                             #
14005 ###############################################################################
14006 #
14007 #
14008 void
14009 Write(ref,...)
14010   Image::Magick ref=NO_INIT
14011   ALIAS:
14012     WriteImage    = 1
14013     write         = 2
14014     writeimage    = 3
14015   PPCODE:
14016   {
14017     char
14018       filename[MaxTextExtent];
14019
14020     ExceptionInfo
14021       *exception;
14022
14023     Image
14024       *image,
14025       *next;
14026
14027     register ssize_t
14028       i;
14029
14030     ssize_t
14031       number_images,
14032       scene;
14033
14034     struct PackageInfo
14035       *info,
14036       *package_info;
14037
14038     SV
14039       *perl_exception,
14040       *reference;
14041
14042     PERL_UNUSED_VAR(ref);
14043     PERL_UNUSED_VAR(ix);
14044     exception=AcquireExceptionInfo();
14045     perl_exception=newSVpv("",0);
14046     number_images=0;
14047     package_info=(struct PackageInfo *) NULL;
14048     if (sv_isobject(ST(0)) == 0)
14049       {
14050         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14051           PackageName);
14052         goto PerlException;
14053       }
14054     reference=SvRV(ST(0));
14055     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14056     if (image == (Image *) NULL)
14057       {
14058         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14059           PackageName);
14060         goto PerlException;
14061       }
14062     package_info=ClonePackageInfo(info,exception);
14063     if (items == 2)
14064       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14065     else
14066       if (items > 2)
14067         for (i=2; i < items; i+=2)
14068           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14069             exception);
14070     (void) CopyMagickString(filename,package_info->image_info->filename,
14071       MaxTextExtent);
14072     scene=0;
14073     for (next=image; next; next=next->next)
14074     {
14075       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
14076       next->scene=scene++;
14077     }
14078     SetImageInfo(package_info->image_info,(unsigned int)
14079       GetImageListLength(image),&image->exception);
14080     for (next=image; next; next=next->next)
14081     {
14082       (void) WriteImage(package_info->image_info,next);
14083       if (next->exception.severity >= ErrorException)
14084         InheritException(exception,&next->exception);
14085       GetImageException(next,exception);
14086       number_images++;
14087       if (package_info->image_info->adjoin)
14088         break;
14089     }
14090
14091   PerlException:
14092     if (package_info != (struct PackageInfo *) NULL)
14093       DestroyPackageInfo(package_info);
14094     InheritPerlException(exception,perl_exception);
14095     exception=DestroyExceptionInfo(exception);
14096     sv_setiv(perl_exception,(IV) number_images);
14097     SvPOK_on(perl_exception);
14098     ST(0)=sv_2mortal(perl_exception);
14099     XSRETURN(1);
14100   }